Repository: hbase
Updated Branches:
  refs/heads/0.98 c5522961c -> 084186836


HBASE-11865 Result implements CellScannable; rather it should BE a CellScanner


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

Branch: refs/heads/0.98
Commit: 084186836318bf0cc93da611c98cb9c63b687d0b
Parents: c552296
Author: stack <[email protected]>
Authored: Sun Aug 31 00:11:35 2014 -0700
Committer: stack <[email protected]>
Committed: Sun Aug 31 00:14:37 2014 -0700

----------------------------------------------------------------------
 .../org/apache/hadoop/hbase/client/Result.java  | 60 ++++++++++++++------
 .../apache/hadoop/hbase/client/TestResult.java  | 27 +++++++++
 2 files changed, 69 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/08418683/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java
----------------------------------------------------------------------
diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java
index 8abbcf7..68d2416 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java
@@ -58,20 +58,23 @@ import org.apache.hadoop.hbase.util.Bytes;
  *
  * To get the latest value for a specific family and qualifier use {@link 
#getValue(byte[], byte[])}.
  *
- * A Result is backed by an array of {@link KeyValue} objects, each 
representing
+ * A Result is backed by an array of {@link Cell} objects, each representing
  * an HBase cell defined by the row, family, qualifier, timestamp, and 
value.<p>
  *
- * The underlying {@link KeyValue} objects can be accessed through the method 
{@link #listCells()}.
- * Each KeyValue can then be accessed through
- * {@link KeyValue#getRow()}, {@link KeyValue#getFamily()}, {@link 
KeyValue#getQualifier()},
- * {@link KeyValue#getTimestamp()}, and {@link KeyValue#getValue()}.<p>
+ * The underlying {@link Cell} objects can be accessed through the method 
{@link #listCells()}.
+ * This will create a List from the internal Cell []. Better is to exploit the 
fact that
+ * a new Result instance is a primed {@link CellScanner}; just call {@link 
#advance()} and
+ * {@link #current()} to iterate over Cells as you would any {@link 
CellScanner}.
+ * Call {@link #cellScanner()} to reset should you need to iterate the same 
Result over again
+ * ({@link CellScanner}s are one-shot).
  *
- * If you need to overwrite a Result with another Result instance -- as in the 
old 'mapred' RecordReader next
- * invocations -- then create an empty Result with the null constructor and in 
then use {@link #copyFrom(Result)}
+ * If you need to overwrite a Result with another Result instance -- as in the 
old 'mapred'
+ * RecordReader next invocations -- then create an empty Result with the null 
constructor and
+ * in then use {@link #copyFrom(Result)}
  */
 @InterfaceAudience.Public
 @InterfaceStability.Stable
-public class Result implements CellScannable {
+public class Result implements CellScannable, CellScanner {
   private Cell[] cells;
   private Boolean exists; // if the query was just to check existence.
   // We're not using java serialization.  Transient here is just a marker to 
say
@@ -85,6 +88,13 @@ public class Result implements CellScannable {
   private static final int PAD_WIDTH = 128;
   public static final Result EMPTY_RESULT = new Result();
 
+  private final static int INITIAL_CELLSCANNER_INDEX = -1;
+
+  /**
+   * Index for where we are when Result is acting as a {@link CellScanner}.
+   */
+  private int cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
+
   /**
    * Creates an empty Result w/ no KeyValue payload; returns null if you call 
{@link #rawCells()}.
    * Use this to represent no results if <code>null</code> won't do or in old 
'mapred' as oppposed to 'mapreduce' package
@@ -180,13 +190,13 @@ public class Result implements CellScannable {
   }
 
   /**
-   * Return an cells of a Result as an array of KeyValues 
-   * 
+   * Return an cells of a Result as an array of KeyValues
+   *
    * WARNING do not use, expensive.  This does an arraycopy of the cell[]'s 
value.
    *
    * Added to ease transition from  0.94 -> 0.96.
-   * 
-   * @deprecated as of 0.96, use {@link #rawCells()}  
+   *
+   * @deprecated as of 0.96, use {@link #rawCells()}
    * @return array of KeyValues, empty array if nothing in result.
    */
   @Deprecated
@@ -208,15 +218,15 @@ public class Result implements CellScannable {
   public List<Cell> listCells() {
     return isEmpty()? null: Arrays.asList(rawCells());
   }
-  
+
   /**
-   * Return an cells of a Result as an array of KeyValues 
-   * 
+   * Return an cells of a Result as an array of KeyValues
+   *
    * WARNING do not use, expensive.  This does  an arraycopy of the cell[]'s 
value.
    *
    * Added to ease transition from  0.94 -> 0.96.
-   * 
-   * @deprecated as of 0.96, use {@link #listCells()}  
+   *
+   * @deprecated as of 0.96, use {@link #listCells()}
    * @return all sorted List of KeyValues; can be null if no cells in the 
result
    */
   @Deprecated
@@ -803,7 +813,21 @@ public class Result implements CellScannable {
 
   @Override
   public CellScanner cellScanner() {
-    return CellUtil.createCellScanner(this.cells);
+    // Reset
+    this.cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
+    return this;
+  }
+
+  @Override
+  public Cell current() {
+    if (cells == null) return null;
+    return (cellScannerIndex < 0)? null: this.cells[cellScannerIndex];
+  }
+
+  @Override
+  public boolean advance() {
+    if (cells == null) return false;
+    return ++cellScannerIndex < this.cells.length;
   }
 
   public Boolean getExists() {

http://git-wip-us.apache.org/repos/asf/hbase/blob/08418683/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestResult.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestResult.java 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestResult.java
index 74563f0..a0e1a45 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestResult.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestResult.java
@@ -21,6 +21,7 @@ package org.apache.hadoop.hbase.client;
 
 import static org.apache.hadoop.hbase.HBaseTestCase.assertByteEquals;
 
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.List;
@@ -30,6 +31,7 @@ import junit.framework.TestCase;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellScanner;
 import org.apache.hadoop.hbase.CellUtil;
 import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.SmallTests;
@@ -60,6 +62,31 @@ public class TestResult extends TestCase {
   static final byte [] family = Bytes.toBytes("family");
   static final byte [] value = Bytes.toBytes("value");
 
+  /**
+   * Run some tests to ensure Result acts like a proper CellScanner.
+   * @throws IOException
+   */
+  public void testResultAsCellScanner() throws IOException {
+    Cell [] cells = genKVs(row, family, value, 1, 10);
+    Arrays.sort(cells, KeyValue.COMPARATOR);
+    Result r = Result.create(cells);
+    assertSame(r, cells);
+    // Assert I run over same result multiple times.
+    assertSame(r.cellScanner(), cells);
+    assertSame(r.cellScanner(), cells);
+    // Assert we are not creating new object when doing cellscanner
+    assertTrue(r == r.cellScanner());
+  }
+
+  private void assertSame(final CellScanner cellScanner, final Cell [] cells) 
throws IOException {
+    int count = 0;
+    while (cellScanner.advance()) {
+      assertTrue(cells[count].equals(cellScanner.current()));
+      count++;
+    }
+    assertEquals(cells.length, count);
+  }
+
   public void testBasicGetColumn() throws Exception {
     KeyValue [] kvs = genKVs(row, family, value, 1, 100);
 

Reply via email to