diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/MultiByteBuff.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/MultiByteBuff.java index a25791e5ce8..f9000ed953a 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/MultiByteBuff.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/MultiByteBuff.java @@ -181,6 +181,9 @@ public class MultiByteBuff extends ByteBuff { * Returns in which sub ByteBuffer, the given element index will be available. */ private int getItemIndex(int elemIndex) { + if (elemIndex < 0) { + throw new IndexOutOfBoundsException(); + } int index = 1; while (elemIndex >= this.itemBeginPos[index]) { index++; @@ -721,15 +724,16 @@ public class MultiByteBuff extends ByteBuff { } /** - * Writes a byte to this MBB at the given index - * @param index - * @param b + * Writes a byte to this MBB at the given index and won't affect the position of any of the + * buffers. * @return this object + * @throws IndexOutOfBoundsException If index is negative or not smaller than the + * {@link MultiByteBuff#limit} */ @Override public MultiByteBuff put(int index, byte b) { checkRefCount(); - int itemIndex = getItemIndex(limit); + int itemIndex = getItemIndex(index); ByteBuffer item = items[itemIndex]; item.put(index - itemBeginPos[itemIndex], b); return this; diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/nio/TestMultiByteBuff.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/nio/TestMultiByteBuff.java index 563f82a1cd9..b40ac0c22a8 100644 --- a/hbase-common/src/test/java/org/apache/hadoop/hbase/nio/TestMultiByteBuff.java +++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/nio/TestMultiByteBuff.java @@ -594,4 +594,58 @@ public class TestMultiByteBuff { assertTrue(e != null); } } + + @Test + public void testPositionalPutByte() throws Exception { + ByteBuffer bb1 = ByteBuffer.allocate(50); + ByteBuffer bb2 = ByteBuffer.allocate(50); + ByteBuffer bb3 = ByteBuffer.allocate(50); + ByteBuffer bb4 = ByteBuffer.allocate(50); + MultiByteBuff srcMultiByteBuff = new MultiByteBuff(bb1, bb2, bb3, bb4); + for (int i = 1; i <= 200; i++) { + srcMultiByteBuff.put((byte) 0xff); + } + + srcMultiByteBuff.put(20, (byte) 0); + byte val = srcMultiByteBuff.get(20); + assertTrue(val == 0); + + srcMultiByteBuff.put(50, (byte) 0); + val = srcMultiByteBuff.get(50); + assertTrue(val == 0); + + srcMultiByteBuff.put(80, (byte) 0); + val = srcMultiByteBuff.get(80); + assertTrue(val == 0); + + srcMultiByteBuff.put(100, (byte) 0); + val = srcMultiByteBuff.get(100); + assertTrue(val == 0); + + srcMultiByteBuff.put(121, (byte) 0); + val = srcMultiByteBuff.get(121); + assertTrue(val == 0); + + srcMultiByteBuff.put(150, (byte) 0); + val = srcMultiByteBuff.get(150); + assertTrue(val == 0); + + srcMultiByteBuff.put(180, (byte) 0); + val = srcMultiByteBuff.get(180); + assertTrue(val == 0); + + try { + srcMultiByteBuff.put(200, (byte) 0); + fail(); + } catch (IndexOutOfBoundsException e) { + assertTrue(e != null); + } + + try { + srcMultiByteBuff.put(260, (byte) 0); + fail(); + } catch (IndexOutOfBoundsException e) { + assertTrue(e != null); + } + } } diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestOrderedBytes.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestOrderedBytes.java index 45b8e3547ce..c8e0381969b 100644 --- a/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestOrderedBytes.java +++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestOrderedBytes.java @@ -1263,26 +1263,44 @@ public class TestOrderedBytes { int cnt = 0; PositionedByteRange buff = new SimplePositionedMutableByteRange(1024); for (Order ord : new Order[] { Order.ASCENDING, Order.DESCENDING }) { - int o; - o = OrderedBytes.encodeNull(buff, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, negInf, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, negLarge, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, negMed, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, negSmall, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, zero, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, posSmall, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, posMed, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, posLarge, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, posInf, ord); cnt++; - o = OrderedBytes.encodeNumeric(buff, nan, ord); cnt++; - o = OrderedBytes.encodeInt8(buff, int8, ord); cnt++; - o = OrderedBytes.encodeInt16(buff, int16, ord); cnt++; - o = OrderedBytes.encodeInt32(buff, int32, ord); cnt++; - o = OrderedBytes.encodeInt64(buff, int64, ord); cnt++; - o = OrderedBytes.encodeFloat32(buff, float32, ord); cnt++; - o = OrderedBytes.encodeFloat64(buff, float64, ord); cnt++; - o = OrderedBytes.encodeString(buff, text, ord); cnt++; - o = OrderedBytes.encodeBlobVar(buff, blobVar, ord); cnt++; + OrderedBytes.encodeNull(buff, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, negInf, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, negLarge, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, negMed, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, negSmall, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, zero, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, posSmall, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, posMed, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, posLarge, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, posInf, ord); + cnt++; + OrderedBytes.encodeNumeric(buff, nan, ord); + cnt++; + OrderedBytes.encodeInt8(buff, int8, ord); + cnt++; + OrderedBytes.encodeInt16(buff, int16, ord); + cnt++; + OrderedBytes.encodeInt32(buff, int32, ord); + cnt++; + OrderedBytes.encodeInt64(buff, int64, ord); + cnt++; + OrderedBytes.encodeFloat32(buff, float32, ord); + cnt++; + OrderedBytes.encodeFloat64(buff, float64, ord); + cnt++; + OrderedBytes.encodeString(buff, text, ord); + cnt++; + OrderedBytes.encodeBlobVar(buff, blobVar, ord); + cnt++; } buff.setPosition(0);