You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by te...@apache.org on 2012/11/14 11:58:05 UTC

svn commit: r1409148 - in /hbase/trunk/hbase-common/src: main/java/org/apache/hadoop/hbase/util/Bytes.java test/java/org/apache/hadoop/hbase/util/TestBytes.java

Author: tedyu
Date: Wed Nov 14 10:58:04 2012
New Revision: 1409148

URL: http://svn.apache.org/viewvc?rev=1409148&view=rev
Log:
HBASE-7137 Improve Bytes to accept byte buffers which don't allow us to directly access their backing arrays (Hiroshi)


Modified:
    hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
    hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java

Modified: hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java?rev=1409148&r1=1409147&r2=1409148&view=diff
==============================================================================
--- hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java (original)
+++ hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java Wed Nov 14 10:58:04 2012
@@ -242,14 +242,24 @@ public class Bytes {
   }
 
   /**
-   * Returns a new byte array, copied from the passed ByteBuffer.
-   * @param bb A ByteBuffer
+   * Returns a new byte array, copied from the given {@code buf},
+   * from the index 0 (inclusive) to the limit (exclusive),
+   * regardless of the current position.
+   * The position and the other index parameters are not changed.
+   *
+   * @param buf a byte buffer
    * @return the byte array
+   * @see #getBytes(ByteBuffer)
    */
-  public static byte[] toBytes(ByteBuffer bb) {
-    int length = bb.limit();
-    byte [] result = new byte[length];
-    System.arraycopy(bb.array(), bb.arrayOffset(), result, 0, length);
+  public static byte[] toBytes(ByteBuffer buf) {
+    ByteBuffer dup = buf.duplicate();
+    dup.position(0);
+    return readBytes(dup);
+  }
+
+  private static byte[] readBytes(ByteBuffer buf) {
+    byte [] result = new byte[buf.remaining()];
+    buf.get(result);
     return result;
   }
 
@@ -309,16 +319,23 @@ public class Bytes {
   }
 
   /**
-   * Converts the given byte buffer, from its array offset to its limit, to
-   * a string. The position and the mark are ignored.
+   * Converts the given byte buffer to a printable representation,
+   * from the index 0 (inclusive) to the limit (exclusive),
+   * regardless of the current position.
+   * The position and the other index parameters are not changed.
    *
    * @param buf a byte buffer
    * @return a string representation of the buffer's binary contents
+   * @see #toBytes(ByteBuffer)
+   * @see #getBytes(ByteBuffer)
    */
   public static String toStringBinary(ByteBuffer buf) {
     if (buf == null)
       return "null";
-    return toStringBinary(buf.array(), buf.arrayOffset(), buf.limit());
+    if (buf.hasArray()) {
+      return toStringBinary(buf.array(), buf.arrayOffset(), buf.limit());
+    }
+    return toStringBinary(toBytes(buf));
   }
 
   /**
@@ -737,17 +754,16 @@ public class Bytes {
   }
 
   /**
-   * This method will get a sequence of bytes from pos -> limit,
-   * but will restore pos after.
-   * @param buf
-   * @return byte array
+   * Returns a new byte array, copied from the given {@code buf},
+   * from the position (inclusive) to the limit (exclusive).
+   * The position and the other index parameters are not changed.
+   *
+   * @param buf a byte buffer
+   * @return the byte array
+   * @see #toBytes(ByteBuffer)
    */
   public static byte[] getBytes(ByteBuffer buf) {
-    int savedPos = buf.position();
-    byte [] newBytes = new byte[buf.remaining()];
-    buf.get(newBytes);
-    buf.position(savedPos);
-    return newBytes;
+    return readBytes(buf.duplicate());
   }
 
   /**

Modified: hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java?rev=1409148&r1=1409147&r2=1409148&view=diff
==============================================================================
--- hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java (original)
+++ hbase/trunk/hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java Wed Nov 14 10:58:04 2012
@@ -23,6 +23,7 @@ import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.math.BigDecimal;
+import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Random;
 
@@ -172,6 +173,69 @@ public class TestBytes extends TestCase 
     return result;
   }
 
+  public void testToBytesForByteBuffer() {
+    byte[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    ByteBuffer target = ByteBuffer.wrap(array);
+    target.position(2);
+    target.limit(7);
+
+    byte[] actual = Bytes.toBytes(target);
+    byte[] expected = { 0, 1, 2, 3, 4, 5, 6 };
+    assertTrue(Arrays.equals(expected,  actual));
+    assertEquals(2, target.position());
+    assertEquals(7, target.limit());
+
+    ByteBuffer target2 = target.slice();
+    assertEquals(0, target2.position());
+    assertEquals(5, target2.limit());
+
+    byte[] actual2 = Bytes.toBytes(target2);
+    byte[] expected2 = { 2, 3, 4, 5, 6 };
+    assertTrue(Arrays.equals(expected2, actual2));
+    assertEquals(0, target2.position());
+    assertEquals(5, target2.limit());
+  }
+
+  public void testGetBytesForByteBuffer() {
+    byte[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    ByteBuffer target = ByteBuffer.wrap(array);
+    target.position(2);
+    target.limit(7);
+
+    byte[] actual = Bytes.getBytes(target);
+    byte[] expected = { 2, 3, 4, 5, 6 };
+    assertTrue(Arrays.equals(expected,  actual));
+    assertEquals(2, target.position());
+    assertEquals(7, target.limit());
+  }
+
+  public void testToStringBinaryForBytes() {
+    byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
+    String actual = Bytes.toStringBinary(array);
+    String expected = "09azAZ@\\x01";
+    assertEquals(expected, actual);
+
+    String actual2 = Bytes.toStringBinary(array, 2, 3);
+    String expected2 = "azA";
+    assertEquals(expected2, actual2);
+  }
+
+  public void testToStringBinaryForArrayBasedByteBuffer() {
+    byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
+    ByteBuffer target = ByteBuffer.wrap(array);
+    String actual = Bytes.toStringBinary(target);
+    String expected = "09azAZ@\\x01";
+    assertEquals(expected, actual);
+  }
+
+  public void testToStringBinaryForReadOnlyByteBuffer() {
+    byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
+    ByteBuffer target = ByteBuffer.wrap(array).asReadOnlyBuffer();
+    String actual = Bytes.toStringBinary(target);
+    String expected = "09azAZ@\\x01";
+    assertEquals(expected, actual);
+  }
+
   public void testBinarySearch() throws Exception {
     byte [][] arr = {
         {1},