Index: src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (revision 1410836) +++ src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (working copy) @@ -3412,6 +3412,10 @@ this(scan, null); } + @Override + public long getReadPt() { + return this.readPt; + } /** * Reset both the filter and the old filter. */ @@ -3442,22 +3446,28 @@ // This could be a new thread from the last time we called next(). MultiVersionConsistencyControl.setThreadReadPoint(this.readPt); - results.clear(); - - boolean returnResult = nextInternal(limit, metric); - - outResults.addAll(results); - resetFilters(); - if (isFilterDone()) { - return false; - } - return returnResult; + return innerRegionNext(outResults, limit, metric); } finally { closeRegionOperation(); } } @Override + public synchronized boolean innerRegionNext(List outResults, int limit, + String metric) throws IOException { + results.clear(); + + boolean returnResult = nextInternal(limit, metric); + + outResults.addAll(results); + resetFilters(); + if (isFilterDone()) { + return false; + } + return returnResult; + } + + @Override public synchronized boolean next(List outResults) throws IOException { // apply the batching limit by default @@ -5120,7 +5130,7 @@ * Acquires a read lock and checks if the region is closing or closed. * @throws NotServingRegionException when the region is closing or closed */ - private void startRegionOperation() throws NotServingRegionException { + public void startRegionOperation() throws NotServingRegionException { if (this.closing.get()) { throw new NotServingRegionException(regionInfo.getRegionNameAsString() + " is closing"); @@ -5137,7 +5147,7 @@ * Closes the lock. This needs to be called in the finally block corresponding * to the try block of #startRegionOperation */ - private void closeRegionOperation(){ + public void closeRegionOperation(){ lock.readLock().unlock(); } Index: src/main/java/org/apache/hadoop/hbase/regionserver/RegionScanner.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/RegionScanner.java (revision 1410836) +++ src/main/java/org/apache/hadoop/hbase/regionserver/RegionScanner.java (working copy) @@ -20,7 +20,10 @@ package org.apache.hadoop.hbase.regionserver; import java.io.IOException; +import java.util.List; + import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.KeyValue; /** * RegionScanner describes iterators over rows in an HRegion. @@ -49,4 +52,20 @@ */ public boolean reseek(byte[] row) throws IOException; + /** + * @return The Scanner's readPt + */ + public long getReadPt(); + + /** + * Grab the next row's worth of values with a limit on the number of values + * to return. + * This is a special method to be called from coprocessor hooks to avoid expensive setup + * @param result return output array + * @param limit limit on row count to get + * @param metric the metric name + * @return true if more rows exist after this one, false if scanner is done + * @throws IOException e + */ + public boolean innerRegionNext(List result, int limit, String metric) throws IOException; } Index: src/test/java/org/apache/hadoop/hbase/coprocessor/TestCoprocessorInterface.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/coprocessor/TestCoprocessorInterface.java (revision 1410836) +++ src/test/java/org/apache/hadoop/hbase/coprocessor/TestCoprocessorInterface.java (working copy) @@ -85,6 +85,12 @@ } @Override + public boolean innerRegionNext(List result, int limit, String metric) + throws IOException { + return delegate.innerRegionNext(result, limit, metric); + } + + @Override public void close() throws IOException { delegate.close(); } @@ -104,6 +110,10 @@ return false; } + @Override + public long getReadPt() { + return delegate.getReadPt(); + } } public static class CoprocessorImpl extends BaseRegionObserver {