You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by nk...@apache.org on 2014/03/04 10:06:27 UTC

svn commit: r1573949 - in /hbase/trunk: hbase-client/src/main/java/org/apache/hadoop/hbase/client/ hbase-server/src/test/java/org/apache/hadoop/hbase/client/

Author: nkeywal
Date: Tue Mar  4 09:06:27 2014
New Revision: 1573949

URL: http://svn.apache.org/r1573949
Log:
HBASE-9999 Add support for small reverse scan

Modified:
    hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java
    hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientSmallScanner.java
    hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java
    hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedClientScanner.java
    hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedScannerCallable.java
    hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java

Modified: hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java?rev=1573949&r1=1573948&r2=1573949&view=diff
==============================================================================
--- hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java (original)
+++ hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java Tue Mar  4 09:06:27 2014
@@ -39,7 +39,6 @@ import org.apache.hadoop.hbase.protobuf.
 import org.apache.hadoop.hbase.protobuf.generated.MapReduceProtos;
 import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;
 import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.hadoop.hbase.util.ExceptionUtil;
 
 /**
  * Implements the scanner interface for the HBase client.

Modified: hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientSmallScanner.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientSmallScanner.java?rev=1573949&r1=1573948&r2=1573949&view=diff
==============================================================================
--- hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientSmallScanner.java (original)
+++ hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientSmallScanner.java Tue Mar  4 09:06:27 2014
@@ -153,21 +153,23 @@ public class ClientSmallScanner extends 
       LOG.trace("Advancing internal small scanner to startKey at '"
           + Bytes.toStringBinary(localStartKey) + "'");
     }
-    smallScanCallable = getSmallScanCallable(localStartKey, cacheNum);
+    smallScanCallable = getSmallScanCallable(
+        scan, getConnection(), getTable(), localStartKey, cacheNum);
     if (this.scanMetrics != null && skipRowOfFirstResult == null) {
       this.scanMetrics.countOfRegions.incrementAndGet();
     }
     return true;
   }
 
-  private RegionServerCallable<Result[]> getSmallScanCallable(
+  static RegionServerCallable<Result[]> getSmallScanCallable(
+      final Scan sc, HConnection connection, TableName table,
       byte[] localStartKey, final int cacheNum) {
-    this.scan.setStartRow(localStartKey);
+    sc.setStartRow(localStartKey);
     RegionServerCallable<Result[]> callable = new RegionServerCallable<Result[]>(
-        getConnection(), getTable(), scan.getStartRow()) {
+        connection, table, sc.getStartRow()) {
       public Result[] call(int callTimeout) throws IOException {
         ScanRequest request = RequestConverter.buildScanRequest(getLocation()
-            .getRegionInfo().getRegionName(), scan, cacheNum, true);
+            .getRegionInfo().getRegionName(), sc, cacheNum, true);
         PayloadCarryingRpcController controller = new PayloadCarryingRpcController();
         controller.setPriority(getTableName());
         controller.setCallTimeout(callTimeout);

Modified: hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java?rev=1573949&r1=1573948&r2=1573949&view=diff
==============================================================================
--- hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java (original)
+++ hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java Tue Mar  4 09:06:27 2014
@@ -742,15 +742,24 @@ public class HTable implements HTableInt
     if (scan.getCaching() <= 0) {
       scan.setCaching(getScannerCaching());
     }
-    if (scan.isSmall() && !scan.isReversed()) {
+
+    if (scan.isReversed()) {
+      if (scan.isSmall()) {
+        return new ClientSmallReversedScanner(getConfiguration(), scan, getName(),
+            this.connection);
+      } else {
+        return new ReversedClientScanner(getConfiguration(), scan, getName(),
+            this.connection);
+      }
+    }
+
+    if (scan.isSmall()) {
       return new ClientSmallScanner(getConfiguration(), scan, getName(),
-          this.connection);
-    } else if (scan.isReversed()) {
-      return new ReversedClientScanner(getConfiguration(), scan, getName(),
-          this.connection);
+          this.connection, this.rpcCallerFactory);
+    } else {
+      return new ClientScanner(getConfiguration(), scan,
+          getName(), this.connection);
     }
-    return new ClientScanner(getConfiguration(), scan,
-        getName(), this.connection);
   }
 
   /**

Modified: hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedClientScanner.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedClientScanner.java?rev=1573949&r1=1573948&r2=1573949&view=diff
==============================================================================
--- hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedClientScanner.java (original)
+++ hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedClientScanner.java Tue Mar  4 09:06:27 2014
@@ -29,6 +29,7 @@ import org.apache.hadoop.conf.Configurat
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.ExceptionUtil;
 
 /**
  * A reversed client scanner which support backward scanning
@@ -114,6 +115,7 @@ public class ReversedClientScanner exten
         this.scanMetrics.countOfRegions.incrementAndGet();
       }
     } catch (IOException e) {
+      ExceptionUtil.rethrowIfInterrupt(e);
       close();
       throw e;
     }
@@ -151,7 +153,7 @@ public class ReversedClientScanner exten
    * @param row
    * @return a new byte array which is the closest front row of the specified one
    */
-  private byte[] createClosestRowBefore(byte[] row) {
+  protected byte[] createClosestRowBefore(byte[] row) {
     if (row == null) {
       throw new IllegalArgumentException("The passed row is empty");
     }

Modified: hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedScannerCallable.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedScannerCallable.java?rev=1573949&r1=1573948&r2=1573949&view=diff
==============================================================================
--- hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedScannerCallable.java (original)
+++ hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ReversedScannerCallable.java Tue Mar  4 09:06:27 2014
@@ -70,7 +70,7 @@ public class ReversedScannerCallable ext
         this.location = connection.getRegionLocation(tableName, row, reload);
         if (this.location == null) {
           throw new IOException("Failed to find location, tableName="
-              + tableName + ", row=" + Bytes.toString(row) + ", reload="
+              + tableName + ", row=" + Bytes.toStringBinary(row) + ", reload="
               + reload);
         }
       } else {

Modified: hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java?rev=1573949&r1=1573948&r2=1573949&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java (original)
+++ hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java Tue Mar  4 09:06:27 2014
@@ -6061,4 +6061,170 @@ public class TestFromClientSide {
     assertEquals(insertNum, count);
     table.close();
   }
+
+
+  /**
+   * Tests reversed scan under multi regions
+   */
+  @Test
+  public void testSmallReversedScanUnderMultiRegions() throws Exception {
+    // Test Initialization.
+    byte[] TABLE = Bytes.toBytes("testSmallReversedScanUnderMultiRegions");
+    byte[][] splitRows = new byte[][]{
+        Bytes.toBytes("000"), Bytes.toBytes("002"), Bytes.toBytes("004"),
+        Bytes.toBytes("006"), Bytes.toBytes("008"), Bytes.toBytes("010")};
+    HTable table = TEST_UTIL.createTable(TABLE, FAMILY, splitRows);
+    TEST_UTIL.waitUntilAllRegionsAssigned(table.getName());
+
+    assertEquals(splitRows.length + 1, table.getRegionLocations().size());
+    for (byte[] splitRow : splitRows) {
+      Put put = new Put(splitRow);
+      put.add(FAMILY, QUALIFIER, VALUE);
+      table.put(put);
+
+      byte[] nextRow = Bytes.copy(splitRow);
+      nextRow[nextRow.length - 1]++;
+
+      put = new Put(nextRow);
+      put.add(FAMILY, QUALIFIER, VALUE);
+      table.put(put);
+    }
+
+    // scan forward
+    ResultScanner scanner = table.getScanner(new Scan());
+    int count = 0;
+    for (Result r : scanner) {
+      assertTrue(!r.isEmpty());
+      count++;
+    }
+    assertEquals(12, count);
+
+    reverseScanTest(table, false);
+    reverseScanTest(table, true);
+
+    table.close();
+  }
+
+  private void reverseScanTest(HTable table, boolean small) throws IOException {
+    // scan backward
+    Scan scan = new Scan();
+    scan.setReversed(true);
+    ResultScanner scanner = table.getScanner(scan);
+    int count = 0;
+    byte[] lastRow = null;
+    for (Result r : scanner) {
+      assertTrue(!r.isEmpty());
+      count++;
+      byte[] thisRow = r.getRow();
+      if (lastRow != null) {
+        assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
+            + ",this row=" + Bytes.toString(thisRow),
+            Bytes.compareTo(thisRow, lastRow) < 0);
+      }
+      lastRow = thisRow;
+    }
+    assertEquals(12, count);
+
+    scan = new Scan();
+    scan.setSmall(small);
+    scan.setReversed(true);
+    scan.setStartRow(Bytes.toBytes("002"));
+    scanner = table.getScanner(scan);
+    count = 0;
+    lastRow = null;
+    for (Result r : scanner) {
+      assertTrue(!r.isEmpty());
+      count++;
+      byte[] thisRow = r.getRow();
+      if (lastRow != null) {
+        assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
+            + ",this row=" + Bytes.toString(thisRow),
+            Bytes.compareTo(thisRow, lastRow) < 0);
+      }
+      lastRow = thisRow;
+    }
+    assertEquals(3, count); // 000 001 002
+
+    scan = new Scan();
+    scan.setSmall(small);
+    scan.setReversed(true);
+    scan.setStartRow(Bytes.toBytes("002"));
+    scan.setStopRow(Bytes.toBytes("000"));
+    scanner = table.getScanner(scan);
+    count = 0;
+    lastRow = null;
+    for (Result r : scanner) {
+      assertTrue(!r.isEmpty());
+      count++;
+      byte[] thisRow = r.getRow();
+      if (lastRow != null) {
+        assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
+            + ",this row=" + Bytes.toString(thisRow),
+            Bytes.compareTo(thisRow, lastRow) < 0);
+      }
+      lastRow = thisRow;
+    }
+    assertEquals(2, count); // 001 002
+
+    scan = new Scan();
+    scan.setSmall(small);
+    scan.setReversed(true);
+    scan.setStartRow(Bytes.toBytes("001"));
+    scanner = table.getScanner(scan);
+    count = 0;
+    lastRow = null;
+    for (Result r : scanner) {
+      assertTrue(!r.isEmpty());
+      count++;
+      byte[] thisRow = r.getRow();
+      if (lastRow != null) {
+        assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
+            + ",this row=" + Bytes.toString(thisRow),
+            Bytes.compareTo(thisRow, lastRow) < 0);
+      }
+      lastRow = thisRow;
+    }
+    assertEquals(2, count); // 000 001
+
+    scan = new Scan();
+    scan.setSmall(small);
+    scan.setReversed(true);
+    scan.setStartRow(Bytes.toBytes("000"));
+    scanner = table.getScanner(scan);
+    count = 0;
+    lastRow = null;
+    for (Result r : scanner) {
+      assertTrue(!r.isEmpty());
+      count++;
+      byte[] thisRow = r.getRow();
+      if (lastRow != null) {
+        assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
+            + ",this row=" + Bytes.toString(thisRow),
+            Bytes.compareTo(thisRow, lastRow) < 0);
+      }
+      lastRow = thisRow;
+    }
+    assertEquals(1, count); // 000
+
+    scan = new Scan();
+    scan.setSmall(small);
+    scan.setReversed(true);
+    scan.setStartRow(Bytes.toBytes("006"));
+    scan.setStopRow(Bytes.toBytes("002"));
+    scanner = table.getScanner(scan);
+    count = 0;
+    lastRow = null;
+    for (Result r : scanner) {
+      assertTrue(!r.isEmpty());
+      count++;
+      byte[] thisRow = r.getRow();
+      if (lastRow != null) {
+        assertTrue("Error scan order, last row= " + Bytes.toString(lastRow)
+            + ",this row=" + Bytes.toString(thisRow),
+            Bytes.compareTo(thisRow, lastRow) < 0);
+      }
+      lastRow = thisRow;
+    }
+    assertEquals(4, count); // 003 004 005 006
+  }
 }