From 550a5a8f58ec71ab6caee677fc1be87efbda8b55 Mon Sep 17 00:00:00 2001 From: zhangduo Date: Tue, 23 May 2017 21:50:30 +0800 Subject: [PATCH] HBASE-18042 Client Compatibility breaks between versions 1.2 and 1.3 --- .../hadoop/hbase/regionserver/RSRpcServices.java | 40 ++++++++++++++++------ 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java index b3ca94d..8ca2a3d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java @@ -19,6 +19,8 @@ package org.apache.hadoop.hbase.regionserver; import com.google.common.annotations.VisibleForTesting; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import java.io.FileNotFoundException; import java.io.IOException; @@ -27,10 +29,20 @@ import java.net.BindException; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.LongAdder; @@ -194,7 +206,6 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos.ScanMet import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaSnapshotsRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaSnapshotsResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaSnapshotsResponse.TableQuotaSnapshot; -import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceViolationPolicy; import org.apache.hadoop.hbase.shaded.protobuf.generated.RPCProtos.RequestHeader; import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.BulkLoadDescriptor; import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.CompactionDescriptor; @@ -265,7 +276,10 @@ public class RSRpcServices implements HBaseRPCErrorHandler, private final AtomicLong scannerIdGen = new AtomicLong(0L); private final ConcurrentMap scanners = new ConcurrentHashMap<>(); - + // Hold the name of a closed scanner for a while. This is used to keep compatible for old clients + // which may send next or close request to a region scanner which has already been exhausted. The + // entries will be removed automatically after scannerLeaseTimeoutPeriod. + private final Cache closedScanners; /** * The lease timeout period for client scanners (milliseconds). */ @@ -1168,6 +1182,9 @@ public class RSRpcServices implements HBaseRPCErrorHandler, isa = new InetSocketAddress(initialIsa.getHostName(), address.getPort()); rpcServer.setErrorHandler(this); rs.setName(name); + + closedScanners = CacheBuilder.newBuilder() + .expireAfterAccess(scannerLeaseTimeoutPeriod, TimeUnit.MILLISECONDS).build(); } @Override @@ -2790,18 +2807,18 @@ public class RSRpcServices implements HBaseRPCErrorHandler, String scannerName = Long.toString(request.getScannerId()); RegionScannerHolder rsh = scanners.get(scannerName); if (rsh == null) { - // just ignore the close request if scanner does not exists. - if (request.hasCloseScanner() && request.getCloseScanner()) { + // just ignore the next or close request if scanner does not exists. + if (closedScanners.getIfPresent(scannerName) != null) { throw SCANNER_ALREADY_CLOSED; } else { LOG.warn("Client tried to access missing scanner " + scannerName); throw new UnknownScannerException( - "Unknown scanner '" + scannerName + "'. This can happen due to any of the following " - + "reasons: a) Scanner id given is wrong, b) Scanner lease expired because of " - + "long wait between consecutive client checkins, c) Server may be closing down, " - + "d) RegionServer restart during upgrade.\nIf the issue is due to reason (b), a " - + "possible fix would be increasing the value of" - + "'hbase.client.scanner.timeout.period' configuration."); + "Unknown scanner '" + scannerName + "'. This can happen due to any of the following " + + "reasons: a) Scanner id given is wrong, b) Scanner lease expired because of " + + "long wait between consecutive client checkins, c) Server may be closing down, " + + "d) RegionServer restart during upgrade.\nIf the issue is due to reason (b), a " + + "possible fix would be increasing the value of" + + "'hbase.client.scanner.timeout.period' configuration."); } } HRegionInfo hri = rsh.s.getRegionInfo(); @@ -3353,6 +3370,7 @@ public class RSRpcServices implements HBaseRPCErrorHandler, if (region.getCoprocessorHost() != null) { region.getCoprocessorHost().postScannerClose(scanner); } + closedScanners.put(scannerName, scannerName); } } -- 2.7.4