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 738f095..20036d7 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 @@ -25,7 +25,7 @@ import org.apache.hadoop.hbase.shaded.com.google.common.annotations.VisibleForTe import java.io.IOException; import java.io.InterruptedIOException; -import java.util.LinkedList; +import java.util.ArrayDeque; import java.util.Queue; import java.util.concurrent.ExecutorService; @@ -294,25 +294,30 @@ public abstract class ClientScanner extends AbstractClientScanner { } protected void initSyncCache() { - cache = new LinkedList<>(); + cache = new ArrayDeque<>(); } protected Result nextWithSyncCache() throws IOException { - // If the scanner is closed and there's nothing left in the cache, next is a no-op. - if (cache.isEmpty() && this.closed) { - return null; + Result result = cache.poll(); + if (result != null) { + return result; } - if (cache.isEmpty()) { - loadCache(); + // If there is nothing left in the cache and the scanner is closed, + // return a no-op + if (this.closed) { + return null; } - if (cache.size() > 0) { - return cache.poll(); - } + loadCache(); + + // try again to load from cache + result = cache.poll(); // if we exhausted this scanner before calling close, write out the scan metrics - writeScanMetrics(); - return null; + if (result == null) { + writeScanMetrics(); + } + return result; } @VisibleForTesting @@ -491,10 +496,8 @@ public abstract class ClientScanner extends AbstractClientScanner { // processing of the scan is taking a long time server side. Rather than continue to // loop until a limit (e.g. size or caching) is reached, break out early to avoid causing // unnecesary delays to the caller - if (LOG.isTraceEnabled()) { - LOG.trace("Heartbeat message received and cache contains Results." + - " Breaking out of scan loop"); - } + LOG.trace("Heartbeat message received and cache contains Results. " + + "Breaking out of scan loop"); // we know that the region has not been exhausted yet so just break without calling // closeScannerIfExhausted break; @@ -560,9 +563,7 @@ public abstract class ClientScanner extends AbstractClientScanner { // We used to catch this error, interpret, and rethrow. However, we // have since decided that it's not nice for a scanner's close to // throw exceptions. Chances are it was just due to lease time out. - if (LOG.isDebugEnabled()) { - LOG.debug("scanner failed to close", e); - } + LOG.debug("scanner failed to close", e); } catch (IOException e) { /* An exception other than UnknownScanner is unexpected. */ LOG.warn("scanner failed to close.", e); @@ -574,19 +575,20 @@ public abstract class ClientScanner extends AbstractClientScanner { @Override public boolean renewLease() { - if (callable != null) { - // do not return any rows, do not advance the scanner - callable.setRenew(true); - try { - this.caller.callWithoutRetries(callable, this.scannerTimeout); - } catch (Exception e) { - return false; - } finally { - callable.setRenew(false); - } + if (callable == null) { + return false; + } + // do not return any rows, do not advance the scanner + callable.setRenew(true); + try { + this.caller.callWithoutRetries(callable, this.scannerTimeout); return true; + } catch (Exception e) { + LOG.debug("scanner failed to renew lease", e); + return false; + } finally { + callable.setRenew(false); } - return false; } protected void initCache() {