Repository: hbase
Updated Branches:
  refs/heads/master 5bfc5745a -> e83ac38d6


HBASE-20078 MultiByteBuff : bug in reading primitives when individual buffers 
are too small.


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/e83ac38d
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/e83ac38d
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/e83ac38d

Branch: refs/heads/master
Commit: e83ac38d68baa5f142afbe2e2f30e23161943eb0
Parents: 5bfc574
Author: anoopsamjohn <anoopsamj...@gmail.com>
Authored: Wed Mar 14 12:07:57 2018 +0530
Committer: anoopsamjohn <anoopsamj...@gmail.com>
Committed: Wed Mar 14 12:07:57 2018 +0530

----------------------------------------------------------------------
 .../apache/hadoop/hbase/nio/MultiByteBuff.java  | 84 +++-----------------
 .../hadoop/hbase/nio/TestMultiByteBuff.java     | 31 ++++++++
 2 files changed, 40 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/e83ac38d/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/MultiByteBuff.java
----------------------------------------------------------------------
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 847e2eb..97f5141 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
@@ -260,16 +260,10 @@ public class MultiByteBuff extends ByteBuff {
       // means cur item is the last one and we wont be able to read a int. 
Throw exception
       throw new BufferUnderflowException();
     }
-    ByteBuffer nextItem = items[itemIndex + 1];
-    // Get available bytes from this item and remaining from next
     int l = 0;
-    for (int i = offsetInItem; i < item.capacity(); i++) {
-      l <<= 8;
-      l ^= ByteBufferUtils.toByte(item, i) & 0xFF;
-    }
-    for (int i = 0; i < Bytes.SIZEOF_INT - remainingLen; i++) {
+    for (int i = 0; i < Bytes.SIZEOF_INT; i++) {
       l <<= 8;
-      l ^= ByteBufferUtils.toByte(nextItem, i) & 0xFF;
+      l ^= get(index + i) & 0xFF;
     }
     return l;
   }
@@ -310,16 +304,10 @@ public class MultiByteBuff extends ByteBuff {
       // means cur item is the last one and we wont be able to read a long. 
Throw exception
       throw new BufferUnderflowException();
     }
-    ByteBuffer nextItem = items[itemIndex + 1];
-    // Get available bytes from this item and remaining from next
     long l = 0;
-    for (int i = offsetInItem; i < item.capacity(); i++) {
-      l <<= 8;
-      l ^= ByteBufferUtils.toByte(item, i) & 0xFF;
-    }
-    for (int i = 0; i < Bytes.SIZEOF_LONG - remainingLen; i++) {
+    for (int i = 0; i < Bytes.SIZEOF_LONG; i++) {
       l <<= 8;
-      l ^= ByteBufferUtils.toByte(nextItem, i) & 0xFF;
+      l ^= get(index + i) & 0xFF;
     }
     return l;
   }
@@ -339,28 +327,7 @@ public class MultiByteBuff extends ByteBuff {
     } else {
       itemIndex = getItemIndex(index);
     }
-    ByteBuffer item = items[itemIndex];
-    int offsetInItem = index - this.itemBeginPos[itemIndex];
-    int remainingLen = item.limit() - offsetInItem;
-    if (remainingLen >= Bytes.SIZEOF_LONG) {
-      return ByteBufferUtils.toLong(item, offsetInItem);
-    }
-    if (items.length - 1 == itemIndex) {
-      // means cur item is the last one and we wont be able to read a long. 
Throw exception
-      throw new BufferUnderflowException();
-    }
-    ByteBuffer nextItem = items[itemIndex + 1];
-    // Get available bytes from this item and remaining from next
-    long l = 0;
-    for (int i = offsetInItem; i < item.capacity(); i++) {
-      l <<= 8;
-      l ^= ByteBufferUtils.toByte(item, i) & 0xFF;
-    }
-    for (int i = 0; i < Bytes.SIZEOF_LONG - remainingLen; i++) {
-      l <<= 8;
-      l ^= ByteBufferUtils.toByte(nextItem, i) & 0xFF;
-    }
-    return l;
+    return getLong(index, itemIndex);
   }
 
   @Override
@@ -513,15 +480,6 @@ public class MultiByteBuff extends ByteBuff {
     if (remaining >= Bytes.SIZEOF_SHORT) {
       return this.curItem.getShort();
     }
-    if (remaining == 0) {
-      if (items.length - 1 == this.curItemIndex) {
-        // means cur item is the last one and we wont be able to read a long. 
Throw exception
-        throw new BufferUnderflowException();
-      }
-      this.curItemIndex++;
-      this.curItem = this.items[this.curItemIndex];
-      return this.curItem.getShort();
-    }
     short n = 0;
     n = (short) (n ^ (get() & 0xFF));
     n = (short) (n << 8);
@@ -540,16 +498,6 @@ public class MultiByteBuff extends ByteBuff {
     if (remaining >= Bytes.SIZEOF_INT) {
       return this.curItem.getInt();
     }
-    if (remaining == 0) {
-      if (items.length - 1 == this.curItemIndex) {
-        // means cur item is the last one and we wont be able to read a long. 
Throw exception
-        throw new BufferUnderflowException();
-      }
-      this.curItemIndex++;
-      this.curItem = this.items[this.curItemIndex];
-      return this.curItem.getInt();
-    }
-    // Get available bytes from this item and remaining from next
     int n = 0;
     for (int i = 0; i < Bytes.SIZEOF_INT; i++) {
       n <<= 8;
@@ -570,16 +518,6 @@ public class MultiByteBuff extends ByteBuff {
     if (remaining >= Bytes.SIZEOF_LONG) {
       return this.curItem.getLong();
     }
-    if (remaining == 0) {
-      if (items.length - 1 == this.curItemIndex) {
-        // means cur item is the last one and we wont be able to read a long. 
Throw exception
-        throw new BufferUnderflowException();
-      }
-      this.curItemIndex++;
-      this.curItem = this.items[this.curItemIndex];
-      return this.curItem.getLong();
-    }
-    // Get available bytes from this item and remaining from next
     long l = 0;
     for (int i = 0; i < Bytes.SIZEOF_LONG; i++) {
       l <<= 8;
@@ -613,8 +551,7 @@ public class MultiByteBuff extends ByteBuff {
           toRead);
       this.curItem.position(this.curItem.position() + toRead);
       length -= toRead;
-      if (length == 0)
-        break;
+      if (length == 0) break;
       this.curItemIndex++;
       this.curItem = this.items[this.curItemIndex];
       offset += toRead;
@@ -631,8 +568,7 @@ public class MultiByteBuff extends ByteBuff {
       ByteBufferUtils.copyFromBufferToArray(dst, item, sourceOffset, offset,
           toRead);
       length -= toRead;
-      if (length == 0)
-        break;
+      if (length == 0) break;
       itemIndex++;
       item = this.items[itemIndex];
       offset += toRead;
@@ -985,8 +921,7 @@ public class MultiByteBuff extends ByteBuff {
       ByteBufferUtils
           .copyFromBufferToArray(dupB, locCurItem, locCurItem.position(), 
offset, toRead);
       length -= toRead;
-      if (length == 0)
-        break;
+      if (length == 0) break;
       locCurItemIndex++;
       locCurItem = this.items[locCurItemIndex];
       offset += toRead;
@@ -1090,8 +1025,7 @@ public class MultiByteBuff extends ByteBuff {
         // doing more reads from Channel. Only this much there for now.
         break;
       } else {
-        if (this.curItemIndex >= this.limitedItemIndex)
-          break;
+        if (this.curItemIndex >= this.limitedItemIndex) break;
         this.curItemIndex++;
         this.curItem = this.items[this.curItemIndex];
       }

http://git-wip-us.apache.org/repos/asf/hbase/blob/e83ac38d/hbase-common/src/test/java/org/apache/hadoop/hbase/nio/TestMultiByteBuff.java
----------------------------------------------------------------------
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 95c088e..84cf7a4 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
@@ -426,4 +426,35 @@ public class TestMultiByteBuff {
     mbb1.get(); // Now we have reached the limit
     assertFalse(mbb1.hasRemaining());
   }
+
+  @Test
+  public void testGetPrimitivesWithSmallIndividualBBs() {
+    short s = 45;
+    int i = 2345;
+    long l = 75681526L;
+    ByteBuffer bb = ByteBuffer.allocate(14);
+    bb.putShort(s);
+    bb.putInt(i);
+    bb.putLong(l);
+
+    ByteBuffer bb1 = ((ByteBuffer) 
bb.duplicate().position(0).limit(1)).slice();
+    ByteBuffer bb2 = ((ByteBuffer) 
bb.duplicate().position(1).limit(3)).slice();
+    ByteBuffer bb3 = ((ByteBuffer) 
bb.duplicate().position(3).limit(5)).slice();
+    ByteBuffer bb4 = ((ByteBuffer) 
bb.duplicate().position(5).limit(11)).slice();
+    ByteBuffer bb5 = ((ByteBuffer) 
bb.duplicate().position(11).limit(12)).slice();
+    ByteBuffer bb6 = ((ByteBuffer) 
bb.duplicate().position(12).limit(14)).slice();
+    MultiByteBuff mbb = new MultiByteBuff(bb1, bb2, bb3, bb4, bb5, bb6);
+    assertEquals(s, mbb.getShortAfterPosition(0));
+    assertEquals(i, mbb.getIntAfterPosition(2));
+    assertEquals(l, mbb.getLongAfterPosition(6));
+
+    assertEquals(s, mbb.getShort(0));
+    assertEquals(i, mbb.getInt(2));
+    assertEquals(l, mbb.getLong(6));
+
+    mbb.position(0);
+    assertEquals(s, mbb.getShort());
+    assertEquals(i, mbb.getInt());
+    assertEquals(l, mbb.getLong());
+  }
 }

Reply via email to