diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AbstractClientScanner.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AbstractClientScanner.java index 54c97d7..1137626 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AbstractClientScanner.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AbstractClientScanner.java @@ -121,4 +121,11 @@ public abstract class AbstractClientScanner implements ResultScanner { } }; } + /** + * Allow the client to renew the scanner's lease on the server. + * @return true if the lease was successfully renewed, false otherwise. + */ + // Note that this method should be on ResultScanner, but that is marked stable. + // Callers have to cast their instance of ResultScanner to AbstractClientScanner to use this. + public abstract boolean renewLease(); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java index d77f2df..e9f21a8 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ClientScanner.java @@ -468,4 +468,21 @@ public class ClientScanner extends AbstractClientScanner { } closed = true; } + + @Override + public boolean renewLease() { + if (callable != null) { + // do not return any rows, do not advance the scanner + callable.setCaching(0); + try { + this.caller.callWithoutRetries(callable, this.scannerTimeout); + } catch (Exception e) { + return false; + } finally { + callable.setCaching(this.caching); + } + return true; + } + return false; + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/ClientSideRegionScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/ClientSideRegionScanner.java index 587eff7..584d434 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/ClientSideRegionScanner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/ClientSideRegionScanner.java @@ -113,4 +113,9 @@ public class ClientSideRegionScanner extends AbstractClientScanner { } } } + + @Override + public boolean renewLease() { + throw new UnsupportedOperationException(); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java index 2928f26..4737ee7 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java @@ -202,4 +202,9 @@ public class TableSnapshotScanner extends AbstractClientScanner { } } + @Override + public boolean renewLease() { + throw new UnsupportedOperationException(); + } + } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java index 7080f09..900b40a 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide3.java @@ -22,6 +22,7 @@ package org.apache.hadoop.hbase.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; import java.util.ArrayList; @@ -431,4 +432,29 @@ public class TestFromClientSide3 { assertTrue(Arrays.equals(res.getValue(FAMILY, COL_QUAL), VAL_BYTES)); table.close(); } + + @Test + public void testLeaseRenewal() throws Exception { + HTable table = TEST_UTIL.createTable( + Bytes.toBytes("testLeaseRenewal"), FAMILY); + Put p = new Put(ROW_BYTES); + p.add(FAMILY, COL_QUAL, VAL_BYTES); + table.put(p); + p = new Put(ANOTHERROW); + p.add(FAMILY, COL_QUAL, VAL_BYTES); + table.put(p); + Scan s = new Scan(); + s.setCaching(1); + ResultScanner rs = table.getScanner(s); + // make sure that calling renewLease does not impact the scan results + assertTrue(((AbstractClientScanner)rs).renewLease()); + assertTrue(Arrays.equals(rs.next().getRow(), ANOTHERROW)); + assertTrue(((AbstractClientScanner)rs).renewLease()); + assertTrue(Arrays.equals(rs.next().getRow(), ROW_BYTES)); + assertTrue(((AbstractClientScanner)rs).renewLease()); + assertNull(rs.next()); + assertFalse(((AbstractClientScanner)rs).renewLease()); + rs.close(); + table.close(); + } }