You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by mi...@apache.org on 2015/12/30 23:15:41 UTC
[20/51] [partial] hbase-site git commit: Published site at
07b623670647686084f8f5fd2038e2bafcfdac54.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/e5c3dcd1/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/RSRpcServices.RegionScannerCloseCallBack.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/RSRpcServices.RegionScannerCloseCallBack.html b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/RSRpcServices.RegionScannerCloseCallBack.html
index be615ae..9d47569 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/RSRpcServices.RegionScannerCloseCallBack.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/RSRpcServices.RegionScannerCloseCallBack.html
@@ -2526,324 +2526,327 @@
<span class="sourceLineNo">2518</span> }<a name="line.2518"></a>
<span class="sourceLineNo">2519</span> assert scanner != null;<a name="line.2519"></a>
<span class="sourceLineNo">2520</span> if (request.hasRenew() && request.getRenew()) {<a name="line.2520"></a>
-<span class="sourceLineNo">2521</span> lease = regionServer.leases.removeLease(scannerName);<a name="line.2521"></a>
-<span class="sourceLineNo">2522</span> if (lease != null && scanners.containsKey(scannerName)) {<a name="line.2522"></a>
-<span class="sourceLineNo">2523</span> regionServer.leases.addLease(lease);<a name="line.2523"></a>
-<span class="sourceLineNo">2524</span> }<a name="line.2524"></a>
-<span class="sourceLineNo">2525</span> return builder.build();<a name="line.2525"></a>
-<span class="sourceLineNo">2526</span> }<a name="line.2526"></a>
-<span class="sourceLineNo">2527</span> RpcCallContext context = RpcServer.getCurrentCall();<a name="line.2527"></a>
-<span class="sourceLineNo">2528</span> Object lastBlock = null;<a name="line.2528"></a>
-<span class="sourceLineNo">2529</span><a name="line.2529"></a>
-<span class="sourceLineNo">2530</span> quota = getQuotaManager().checkQuota(region, OperationQuota.OperationType.SCAN);<a name="line.2530"></a>
-<span class="sourceLineNo">2531</span> long maxQuotaResultSize = Math.min(maxScannerResultSize, quota.getReadAvailable());<a name="line.2531"></a>
+<span class="sourceLineNo">2521</span> rsh = scanners.get(scannerName);<a name="line.2521"></a>
+<span class="sourceLineNo">2522</span> lease = regionServer.leases.removeLease(scannerName);<a name="line.2522"></a>
+<span class="sourceLineNo">2523</span> if (lease != null && rsh != null) {<a name="line.2523"></a>
+<span class="sourceLineNo">2524</span> regionServer.leases.addLease(lease);<a name="line.2524"></a>
+<span class="sourceLineNo">2525</span> // Increment the nextCallSeq value which is the next expected from client.<a name="line.2525"></a>
+<span class="sourceLineNo">2526</span> rsh.incNextCallSeq();<a name="line.2526"></a>
+<span class="sourceLineNo">2527</span> }<a name="line.2527"></a>
+<span class="sourceLineNo">2528</span> return builder.build();<a name="line.2528"></a>
+<span class="sourceLineNo">2529</span> }<a name="line.2529"></a>
+<span class="sourceLineNo">2530</span> RpcCallContext context = RpcServer.getCurrentCall();<a name="line.2530"></a>
+<span class="sourceLineNo">2531</span> Object lastBlock = null;<a name="line.2531"></a>
<span class="sourceLineNo">2532</span><a name="line.2532"></a>
-<span class="sourceLineNo">2533</span> if (rows > 0) {<a name="line.2533"></a>
-<span class="sourceLineNo">2534</span> // if nextCallSeq does not match throw Exception straight away. This needs to be<a name="line.2534"></a>
-<span class="sourceLineNo">2535</span> // performed even before checking of Lease.<a name="line.2535"></a>
-<span class="sourceLineNo">2536</span> // See HBASE-5974<a name="line.2536"></a>
-<span class="sourceLineNo">2537</span> if (request.hasNextCallSeq()) {<a name="line.2537"></a>
-<span class="sourceLineNo">2538</span> if (rsh != null) {<a name="line.2538"></a>
-<span class="sourceLineNo">2539</span> if (request.getNextCallSeq() != rsh.getNextCallSeq()) {<a name="line.2539"></a>
-<span class="sourceLineNo">2540</span> throw new OutOfOrderScannerNextException(<a name="line.2540"></a>
-<span class="sourceLineNo">2541</span> "Expected nextCallSeq: " + rsh.getNextCallSeq()<a name="line.2541"></a>
-<span class="sourceLineNo">2542</span> + " But the nextCallSeq got from client: " + request.getNextCallSeq() +<a name="line.2542"></a>
-<span class="sourceLineNo">2543</span> "; request=" + TextFormat.shortDebugString(request));<a name="line.2543"></a>
-<span class="sourceLineNo">2544</span> }<a name="line.2544"></a>
-<span class="sourceLineNo">2545</span> // Increment the nextCallSeq value which is the next expected from client.<a name="line.2545"></a>
-<span class="sourceLineNo">2546</span> rsh.incNextCallSeq();<a name="line.2546"></a>
-<span class="sourceLineNo">2547</span> }<a name="line.2547"></a>
-<span class="sourceLineNo">2548</span> }<a name="line.2548"></a>
-<span class="sourceLineNo">2549</span> try {<a name="line.2549"></a>
-<span class="sourceLineNo">2550</span> // Remove lease while its being processed in server; protects against case<a name="line.2550"></a>
-<span class="sourceLineNo">2551</span> // where processing of request takes > lease expiration time.<a name="line.2551"></a>
-<span class="sourceLineNo">2552</span> lease = regionServer.leases.removeLease(scannerName);<a name="line.2552"></a>
-<span class="sourceLineNo">2553</span> List<Result> results = new ArrayList<Result>();<a name="line.2553"></a>
-<span class="sourceLineNo">2554</span><a name="line.2554"></a>
-<span class="sourceLineNo">2555</span> boolean done = false;<a name="line.2555"></a>
-<span class="sourceLineNo">2556</span> // Call coprocessor. Get region info from scanner.<a name="line.2556"></a>
-<span class="sourceLineNo">2557</span> if (region != null && region.getCoprocessorHost() != null) {<a name="line.2557"></a>
-<span class="sourceLineNo">2558</span> Boolean bypass = region.getCoprocessorHost().preScannerNext(<a name="line.2558"></a>
-<span class="sourceLineNo">2559</span> scanner, results, rows);<a name="line.2559"></a>
-<span class="sourceLineNo">2560</span> if (!results.isEmpty()) {<a name="line.2560"></a>
-<span class="sourceLineNo">2561</span> for (Result r : results) {<a name="line.2561"></a>
-<span class="sourceLineNo">2562</span> lastBlock = addSize(context, r, lastBlock);<a name="line.2562"></a>
-<span class="sourceLineNo">2563</span> }<a name="line.2563"></a>
-<span class="sourceLineNo">2564</span> }<a name="line.2564"></a>
-<span class="sourceLineNo">2565</span> if (bypass != null && bypass.booleanValue()) {<a name="line.2565"></a>
-<span class="sourceLineNo">2566</span> done = true;<a name="line.2566"></a>
+<span class="sourceLineNo">2533</span> quota = getQuotaManager().checkQuota(region, OperationQuota.OperationType.SCAN);<a name="line.2533"></a>
+<span class="sourceLineNo">2534</span> long maxQuotaResultSize = Math.min(maxScannerResultSize, quota.getReadAvailable());<a name="line.2534"></a>
+<span class="sourceLineNo">2535</span><a name="line.2535"></a>
+<span class="sourceLineNo">2536</span> if (rows > 0) {<a name="line.2536"></a>
+<span class="sourceLineNo">2537</span> // if nextCallSeq does not match throw Exception straight away. This needs to be<a name="line.2537"></a>
+<span class="sourceLineNo">2538</span> // performed even before checking of Lease.<a name="line.2538"></a>
+<span class="sourceLineNo">2539</span> // See HBASE-5974<a name="line.2539"></a>
+<span class="sourceLineNo">2540</span> if (request.hasNextCallSeq()) {<a name="line.2540"></a>
+<span class="sourceLineNo">2541</span> if (rsh != null) {<a name="line.2541"></a>
+<span class="sourceLineNo">2542</span> if (request.getNextCallSeq() != rsh.getNextCallSeq()) {<a name="line.2542"></a>
+<span class="sourceLineNo">2543</span> throw new OutOfOrderScannerNextException(<a name="line.2543"></a>
+<span class="sourceLineNo">2544</span> "Expected nextCallSeq: " + rsh.getNextCallSeq()<a name="line.2544"></a>
+<span class="sourceLineNo">2545</span> + " But the nextCallSeq got from client: " + request.getNextCallSeq() +<a name="line.2545"></a>
+<span class="sourceLineNo">2546</span> "; request=" + TextFormat.shortDebugString(request));<a name="line.2546"></a>
+<span class="sourceLineNo">2547</span> }<a name="line.2547"></a>
+<span class="sourceLineNo">2548</span> // Increment the nextCallSeq value which is the next expected from client.<a name="line.2548"></a>
+<span class="sourceLineNo">2549</span> rsh.incNextCallSeq();<a name="line.2549"></a>
+<span class="sourceLineNo">2550</span> }<a name="line.2550"></a>
+<span class="sourceLineNo">2551</span> }<a name="line.2551"></a>
+<span class="sourceLineNo">2552</span> try {<a name="line.2552"></a>
+<span class="sourceLineNo">2553</span> // Remove lease while its being processed in server; protects against case<a name="line.2553"></a>
+<span class="sourceLineNo">2554</span> // where processing of request takes > lease expiration time.<a name="line.2554"></a>
+<span class="sourceLineNo">2555</span> lease = regionServer.leases.removeLease(scannerName);<a name="line.2555"></a>
+<span class="sourceLineNo">2556</span> List<Result> results = new ArrayList<Result>();<a name="line.2556"></a>
+<span class="sourceLineNo">2557</span><a name="line.2557"></a>
+<span class="sourceLineNo">2558</span> boolean done = false;<a name="line.2558"></a>
+<span class="sourceLineNo">2559</span> // Call coprocessor. Get region info from scanner.<a name="line.2559"></a>
+<span class="sourceLineNo">2560</span> if (region != null && region.getCoprocessorHost() != null) {<a name="line.2560"></a>
+<span class="sourceLineNo">2561</span> Boolean bypass = region.getCoprocessorHost().preScannerNext(<a name="line.2561"></a>
+<span class="sourceLineNo">2562</span> scanner, results, rows);<a name="line.2562"></a>
+<span class="sourceLineNo">2563</span> if (!results.isEmpty()) {<a name="line.2563"></a>
+<span class="sourceLineNo">2564</span> for (Result r : results) {<a name="line.2564"></a>
+<span class="sourceLineNo">2565</span> lastBlock = addSize(context, r, lastBlock);<a name="line.2565"></a>
+<span class="sourceLineNo">2566</span> }<a name="line.2566"></a>
<span class="sourceLineNo">2567</span> }<a name="line.2567"></a>
-<span class="sourceLineNo">2568</span> }<a name="line.2568"></a>
-<span class="sourceLineNo">2569</span><a name="line.2569"></a>
-<span class="sourceLineNo">2570</span> if (!done) {<a name="line.2570"></a>
-<span class="sourceLineNo">2571</span> long maxResultSize = Math.min(scanner.getMaxResultSize(), maxQuotaResultSize);<a name="line.2571"></a>
-<span class="sourceLineNo">2572</span> if (maxResultSize <= 0) {<a name="line.2572"></a>
-<span class="sourceLineNo">2573</span> maxResultSize = maxQuotaResultSize;<a name="line.2573"></a>
-<span class="sourceLineNo">2574</span> }<a name="line.2574"></a>
-<span class="sourceLineNo">2575</span> // This is cells inside a row. Default size is 10 so if many versions or many cfs,<a name="line.2575"></a>
-<span class="sourceLineNo">2576</span> // then we'll resize. Resizings show in profiler. Set it higher than 10. For now<a name="line.2576"></a>
-<span class="sourceLineNo">2577</span> // arbitrary 32. TODO: keep record of general size of results being returned.<a name="line.2577"></a>
-<span class="sourceLineNo">2578</span> List<Cell> values = new ArrayList<Cell>(32);<a name="line.2578"></a>
-<span class="sourceLineNo">2579</span> region.startRegionOperation(Operation.SCAN);<a name="line.2579"></a>
-<span class="sourceLineNo">2580</span> try {<a name="line.2580"></a>
-<span class="sourceLineNo">2581</span> int i = 0;<a name="line.2581"></a>
-<span class="sourceLineNo">2582</span> synchronized(scanner) {<a name="line.2582"></a>
-<span class="sourceLineNo">2583</span> boolean stale = (region.getRegionInfo().getReplicaId() != 0);<a name="line.2583"></a>
-<span class="sourceLineNo">2584</span> boolean clientHandlesPartials =<a name="line.2584"></a>
-<span class="sourceLineNo">2585</span> request.hasClientHandlesPartials() && request.getClientHandlesPartials();<a name="line.2585"></a>
-<span class="sourceLineNo">2586</span> boolean clientHandlesHeartbeats =<a name="line.2586"></a>
-<span class="sourceLineNo">2587</span> request.hasClientHandlesHeartbeats() && request.getClientHandlesHeartbeats();<a name="line.2587"></a>
-<span class="sourceLineNo">2588</span><a name="line.2588"></a>
-<span class="sourceLineNo">2589</span> // On the server side we must ensure that the correct ordering of partial results is<a name="line.2589"></a>
-<span class="sourceLineNo">2590</span> // returned to the client to allow them to properly reconstruct the partial results.<a name="line.2590"></a>
-<span class="sourceLineNo">2591</span> // If the coprocessor host is adding to the result list, we cannot guarantee the<a name="line.2591"></a>
-<span class="sourceLineNo">2592</span> // correct ordering of partial results and so we prevent partial results from being<a name="line.2592"></a>
-<span class="sourceLineNo">2593</span> // formed.<a name="line.2593"></a>
-<span class="sourceLineNo">2594</span> boolean serverGuaranteesOrderOfPartials = results.isEmpty();<a name="line.2594"></a>
-<span class="sourceLineNo">2595</span> boolean allowPartialResults =<a name="line.2595"></a>
-<span class="sourceLineNo">2596</span> clientHandlesPartials && serverGuaranteesOrderOfPartials && !isSmallScan;<a name="line.2596"></a>
-<span class="sourceLineNo">2597</span> boolean moreRows = false;<a name="line.2597"></a>
-<span class="sourceLineNo">2598</span><a name="line.2598"></a>
-<span class="sourceLineNo">2599</span> // Heartbeat messages occur when the processing of the ScanRequest is exceeds a<a name="line.2599"></a>
-<span class="sourceLineNo">2600</span> // certain time threshold on the server. When the time threshold is exceeded, the<a name="line.2600"></a>
-<span class="sourceLineNo">2601</span> // server stops the scan and sends back whatever Results it has accumulated within<a name="line.2601"></a>
-<span class="sourceLineNo">2602</span> // that time period (may be empty). Since heartbeat messages have the potential to<a name="line.2602"></a>
-<span class="sourceLineNo">2603</span> // create partial Results (in the event that the timeout occurs in the middle of a<a name="line.2603"></a>
-<span class="sourceLineNo">2604</span> // row), we must only generate heartbeat messages when the client can handle both<a name="line.2604"></a>
-<span class="sourceLineNo">2605</span> // heartbeats AND partials<a name="line.2605"></a>
-<span class="sourceLineNo">2606</span> boolean allowHeartbeatMessages = clientHandlesHeartbeats && allowPartialResults;<a name="line.2606"></a>
-<span class="sourceLineNo">2607</span><a name="line.2607"></a>
-<span class="sourceLineNo">2608</span> // Default value of timeLimit is negative to indicate no timeLimit should be<a name="line.2608"></a>
-<span class="sourceLineNo">2609</span> // enforced.<a name="line.2609"></a>
-<span class="sourceLineNo">2610</span> long timeLimit = -1;<a name="line.2610"></a>
-<span class="sourceLineNo">2611</span><a name="line.2611"></a>
-<span class="sourceLineNo">2612</span> // Set the time limit to be half of the more restrictive timeout value (one of the<a name="line.2612"></a>
-<span class="sourceLineNo">2613</span> // timeout values must be positive). In the event that both values are positive, the<a name="line.2613"></a>
-<span class="sourceLineNo">2614</span> // more restrictive of the two is used to calculate the limit.<a name="line.2614"></a>
-<span class="sourceLineNo">2615</span> if (allowHeartbeatMessages && (scannerLeaseTimeoutPeriod > 0 || rpcTimeout > 0)) {<a name="line.2615"></a>
-<span class="sourceLineNo">2616</span> long timeLimitDelta;<a name="line.2616"></a>
-<span class="sourceLineNo">2617</span> if (scannerLeaseTimeoutPeriod > 0 && rpcTimeout > 0) {<a name="line.2617"></a>
-<span class="sourceLineNo">2618</span> timeLimitDelta = Math.min(scannerLeaseTimeoutPeriod, rpcTimeout);<a name="line.2618"></a>
-<span class="sourceLineNo">2619</span> } else {<a name="line.2619"></a>
-<span class="sourceLineNo">2620</span> timeLimitDelta =<a name="line.2620"></a>
-<span class="sourceLineNo">2621</span> scannerLeaseTimeoutPeriod > 0 ? scannerLeaseTimeoutPeriod : rpcTimeout;<a name="line.2621"></a>
-<span class="sourceLineNo">2622</span> }<a name="line.2622"></a>
-<span class="sourceLineNo">2623</span> // Use half of whichever timeout value was more restrictive... But don't allow<a name="line.2623"></a>
-<span class="sourceLineNo">2624</span> // the time limit to be less than the allowable minimum (could cause an<a name="line.2624"></a>
-<span class="sourceLineNo">2625</span> // immediatate timeout before scanning any data).<a name="line.2625"></a>
-<span class="sourceLineNo">2626</span> timeLimitDelta = Math.max(timeLimitDelta / 2, minimumScanTimeLimitDelta);<a name="line.2626"></a>
-<span class="sourceLineNo">2627</span> timeLimit = System.currentTimeMillis() + timeLimitDelta;<a name="line.2627"></a>
-<span class="sourceLineNo">2628</span> }<a name="line.2628"></a>
-<span class="sourceLineNo">2629</span><a name="line.2629"></a>
-<span class="sourceLineNo">2630</span> final LimitScope sizeScope =<a name="line.2630"></a>
-<span class="sourceLineNo">2631</span> allowPartialResults ? LimitScope.BETWEEN_CELLS : LimitScope.BETWEEN_ROWS;<a name="line.2631"></a>
-<span class="sourceLineNo">2632</span> final LimitScope timeScope =<a name="line.2632"></a>
-<span class="sourceLineNo">2633</span> allowHeartbeatMessages ? LimitScope.BETWEEN_CELLS : LimitScope.BETWEEN_ROWS;<a name="line.2633"></a>
-<span class="sourceLineNo">2634</span><a name="line.2634"></a>
-<span class="sourceLineNo">2635</span> boolean trackMetrics =<a name="line.2635"></a>
-<span class="sourceLineNo">2636</span> request.hasTrackScanMetrics() && request.getTrackScanMetrics();<a name="line.2636"></a>
+<span class="sourceLineNo">2568</span> if (bypass != null && bypass.booleanValue()) {<a name="line.2568"></a>
+<span class="sourceLineNo">2569</span> done = true;<a name="line.2569"></a>
+<span class="sourceLineNo">2570</span> }<a name="line.2570"></a>
+<span class="sourceLineNo">2571</span> }<a name="line.2571"></a>
+<span class="sourceLineNo">2572</span><a name="line.2572"></a>
+<span class="sourceLineNo">2573</span> if (!done) {<a name="line.2573"></a>
+<span class="sourceLineNo">2574</span> long maxResultSize = Math.min(scanner.getMaxResultSize(), maxQuotaResultSize);<a name="line.2574"></a>
+<span class="sourceLineNo">2575</span> if (maxResultSize <= 0) {<a name="line.2575"></a>
+<span class="sourceLineNo">2576</span> maxResultSize = maxQuotaResultSize;<a name="line.2576"></a>
+<span class="sourceLineNo">2577</span> }<a name="line.2577"></a>
+<span class="sourceLineNo">2578</span> // This is cells inside a row. Default size is 10 so if many versions or many cfs,<a name="line.2578"></a>
+<span class="sourceLineNo">2579</span> // then we'll resize. Resizings show in profiler. Set it higher than 10. For now<a name="line.2579"></a>
+<span class="sourceLineNo">2580</span> // arbitrary 32. TODO: keep record of general size of results being returned.<a name="line.2580"></a>
+<span class="sourceLineNo">2581</span> List<Cell> values = new ArrayList<Cell>(32);<a name="line.2581"></a>
+<span class="sourceLineNo">2582</span> region.startRegionOperation(Operation.SCAN);<a name="line.2582"></a>
+<span class="sourceLineNo">2583</span> try {<a name="line.2583"></a>
+<span class="sourceLineNo">2584</span> int i = 0;<a name="line.2584"></a>
+<span class="sourceLineNo">2585</span> synchronized(scanner) {<a name="line.2585"></a>
+<span class="sourceLineNo">2586</span> boolean stale = (region.getRegionInfo().getReplicaId() != 0);<a name="line.2586"></a>
+<span class="sourceLineNo">2587</span> boolean clientHandlesPartials =<a name="line.2587"></a>
+<span class="sourceLineNo">2588</span> request.hasClientHandlesPartials() && request.getClientHandlesPartials();<a name="line.2588"></a>
+<span class="sourceLineNo">2589</span> boolean clientHandlesHeartbeats =<a name="line.2589"></a>
+<span class="sourceLineNo">2590</span> request.hasClientHandlesHeartbeats() && request.getClientHandlesHeartbeats();<a name="line.2590"></a>
+<span class="sourceLineNo">2591</span><a name="line.2591"></a>
+<span class="sourceLineNo">2592</span> // On the server side we must ensure that the correct ordering of partial results is<a name="line.2592"></a>
+<span class="sourceLineNo">2593</span> // returned to the client to allow them to properly reconstruct the partial results.<a name="line.2593"></a>
+<span class="sourceLineNo">2594</span> // If the coprocessor host is adding to the result list, we cannot guarantee the<a name="line.2594"></a>
+<span class="sourceLineNo">2595</span> // correct ordering of partial results and so we prevent partial results from being<a name="line.2595"></a>
+<span class="sourceLineNo">2596</span> // formed.<a name="line.2596"></a>
+<span class="sourceLineNo">2597</span> boolean serverGuaranteesOrderOfPartials = results.isEmpty();<a name="line.2597"></a>
+<span class="sourceLineNo">2598</span> boolean allowPartialResults =<a name="line.2598"></a>
+<span class="sourceLineNo">2599</span> clientHandlesPartials && serverGuaranteesOrderOfPartials && !isSmallScan;<a name="line.2599"></a>
+<span class="sourceLineNo">2600</span> boolean moreRows = false;<a name="line.2600"></a>
+<span class="sourceLineNo">2601</span><a name="line.2601"></a>
+<span class="sourceLineNo">2602</span> // Heartbeat messages occur when the processing of the ScanRequest is exceeds a<a name="line.2602"></a>
+<span class="sourceLineNo">2603</span> // certain time threshold on the server. When the time threshold is exceeded, the<a name="line.2603"></a>
+<span class="sourceLineNo">2604</span> // server stops the scan and sends back whatever Results it has accumulated within<a name="line.2604"></a>
+<span class="sourceLineNo">2605</span> // that time period (may be empty). Since heartbeat messages have the potential to<a name="line.2605"></a>
+<span class="sourceLineNo">2606</span> // create partial Results (in the event that the timeout occurs in the middle of a<a name="line.2606"></a>
+<span class="sourceLineNo">2607</span> // row), we must only generate heartbeat messages when the client can handle both<a name="line.2607"></a>
+<span class="sourceLineNo">2608</span> // heartbeats AND partials<a name="line.2608"></a>
+<span class="sourceLineNo">2609</span> boolean allowHeartbeatMessages = clientHandlesHeartbeats && allowPartialResults;<a name="line.2609"></a>
+<span class="sourceLineNo">2610</span><a name="line.2610"></a>
+<span class="sourceLineNo">2611</span> // Default value of timeLimit is negative to indicate no timeLimit should be<a name="line.2611"></a>
+<span class="sourceLineNo">2612</span> // enforced.<a name="line.2612"></a>
+<span class="sourceLineNo">2613</span> long timeLimit = -1;<a name="line.2613"></a>
+<span class="sourceLineNo">2614</span><a name="line.2614"></a>
+<span class="sourceLineNo">2615</span> // Set the time limit to be half of the more restrictive timeout value (one of the<a name="line.2615"></a>
+<span class="sourceLineNo">2616</span> // timeout values must be positive). In the event that both values are positive, the<a name="line.2616"></a>
+<span class="sourceLineNo">2617</span> // more restrictive of the two is used to calculate the limit.<a name="line.2617"></a>
+<span class="sourceLineNo">2618</span> if (allowHeartbeatMessages && (scannerLeaseTimeoutPeriod > 0 || rpcTimeout > 0)) {<a name="line.2618"></a>
+<span class="sourceLineNo">2619</span> long timeLimitDelta;<a name="line.2619"></a>
+<span class="sourceLineNo">2620</span> if (scannerLeaseTimeoutPeriod > 0 && rpcTimeout > 0) {<a name="line.2620"></a>
+<span class="sourceLineNo">2621</span> timeLimitDelta = Math.min(scannerLeaseTimeoutPeriod, rpcTimeout);<a name="line.2621"></a>
+<span class="sourceLineNo">2622</span> } else {<a name="line.2622"></a>
+<span class="sourceLineNo">2623</span> timeLimitDelta =<a name="line.2623"></a>
+<span class="sourceLineNo">2624</span> scannerLeaseTimeoutPeriod > 0 ? scannerLeaseTimeoutPeriod : rpcTimeout;<a name="line.2624"></a>
+<span class="sourceLineNo">2625</span> }<a name="line.2625"></a>
+<span class="sourceLineNo">2626</span> // Use half of whichever timeout value was more restrictive... But don't allow<a name="line.2626"></a>
+<span class="sourceLineNo">2627</span> // the time limit to be less than the allowable minimum (could cause an<a name="line.2627"></a>
+<span class="sourceLineNo">2628</span> // immediatate timeout before scanning any data).<a name="line.2628"></a>
+<span class="sourceLineNo">2629</span> timeLimitDelta = Math.max(timeLimitDelta / 2, minimumScanTimeLimitDelta);<a name="line.2629"></a>
+<span class="sourceLineNo">2630</span> timeLimit = System.currentTimeMillis() + timeLimitDelta;<a name="line.2630"></a>
+<span class="sourceLineNo">2631</span> }<a name="line.2631"></a>
+<span class="sourceLineNo">2632</span><a name="line.2632"></a>
+<span class="sourceLineNo">2633</span> final LimitScope sizeScope =<a name="line.2633"></a>
+<span class="sourceLineNo">2634</span> allowPartialResults ? LimitScope.BETWEEN_CELLS : LimitScope.BETWEEN_ROWS;<a name="line.2634"></a>
+<span class="sourceLineNo">2635</span> final LimitScope timeScope =<a name="line.2635"></a>
+<span class="sourceLineNo">2636</span> allowHeartbeatMessages ? LimitScope.BETWEEN_CELLS : LimitScope.BETWEEN_ROWS;<a name="line.2636"></a>
<span class="sourceLineNo">2637</span><a name="line.2637"></a>
-<span class="sourceLineNo">2638</span> // Configure with limits for this RPC. Set keep progress true since size progress<a name="line.2638"></a>
-<span class="sourceLineNo">2639</span> // towards size limit should be kept between calls to nextRaw<a name="line.2639"></a>
-<span class="sourceLineNo">2640</span> ScannerContext.Builder contextBuilder = ScannerContext.newBuilder(true);<a name="line.2640"></a>
-<span class="sourceLineNo">2641</span> contextBuilder.setSizeLimit(sizeScope, maxResultSize);<a name="line.2641"></a>
-<span class="sourceLineNo">2642</span> contextBuilder.setBatchLimit(scanner.getBatch());<a name="line.2642"></a>
-<span class="sourceLineNo">2643</span> contextBuilder.setTimeLimit(timeScope, timeLimit);<a name="line.2643"></a>
-<span class="sourceLineNo">2644</span> contextBuilder.setTrackMetrics(trackMetrics);<a name="line.2644"></a>
-<span class="sourceLineNo">2645</span> ScannerContext scannerContext = contextBuilder.build();<a name="line.2645"></a>
-<span class="sourceLineNo">2646</span> boolean limitReached = false;<a name="line.2646"></a>
-<span class="sourceLineNo">2647</span> while (i < rows) {<a name="line.2647"></a>
-<span class="sourceLineNo">2648</span> // Reset the batch progress to 0 before every call to RegionScanner#nextRaw. The<a name="line.2648"></a>
-<span class="sourceLineNo">2649</span> // batch limit is a limit on the number of cells per Result. Thus, if progress is<a name="line.2649"></a>
-<span class="sourceLineNo">2650</span> // being tracked (i.e. scannerContext.keepProgress() is true) then we need to<a name="line.2650"></a>
-<span class="sourceLineNo">2651</span> // reset the batch progress between nextRaw invocations since we don't want the<a name="line.2651"></a>
-<span class="sourceLineNo">2652</span> // batch progress from previous calls to affect future calls<a name="line.2652"></a>
-<span class="sourceLineNo">2653</span> scannerContext.setBatchProgress(0);<a name="line.2653"></a>
-<span class="sourceLineNo">2654</span><a name="line.2654"></a>
-<span class="sourceLineNo">2655</span> // Collect values to be returned here<a name="line.2655"></a>
-<span class="sourceLineNo">2656</span> moreRows = scanner.nextRaw(values, scannerContext);<a name="line.2656"></a>
+<span class="sourceLineNo">2638</span> boolean trackMetrics =<a name="line.2638"></a>
+<span class="sourceLineNo">2639</span> request.hasTrackScanMetrics() && request.getTrackScanMetrics();<a name="line.2639"></a>
+<span class="sourceLineNo">2640</span><a name="line.2640"></a>
+<span class="sourceLineNo">2641</span> // Configure with limits for this RPC. Set keep progress true since size progress<a name="line.2641"></a>
+<span class="sourceLineNo">2642</span> // towards size limit should be kept between calls to nextRaw<a name="line.2642"></a>
+<span class="sourceLineNo">2643</span> ScannerContext.Builder contextBuilder = ScannerContext.newBuilder(true);<a name="line.2643"></a>
+<span class="sourceLineNo">2644</span> contextBuilder.setSizeLimit(sizeScope, maxResultSize);<a name="line.2644"></a>
+<span class="sourceLineNo">2645</span> contextBuilder.setBatchLimit(scanner.getBatch());<a name="line.2645"></a>
+<span class="sourceLineNo">2646</span> contextBuilder.setTimeLimit(timeScope, timeLimit);<a name="line.2646"></a>
+<span class="sourceLineNo">2647</span> contextBuilder.setTrackMetrics(trackMetrics);<a name="line.2647"></a>
+<span class="sourceLineNo">2648</span> ScannerContext scannerContext = contextBuilder.build();<a name="line.2648"></a>
+<span class="sourceLineNo">2649</span> boolean limitReached = false;<a name="line.2649"></a>
+<span class="sourceLineNo">2650</span> while (i < rows) {<a name="line.2650"></a>
+<span class="sourceLineNo">2651</span> // Reset the batch progress to 0 before every call to RegionScanner#nextRaw. The<a name="line.2651"></a>
+<span class="sourceLineNo">2652</span> // batch limit is a limit on the number of cells per Result. Thus, if progress is<a name="line.2652"></a>
+<span class="sourceLineNo">2653</span> // being tracked (i.e. scannerContext.keepProgress() is true) then we need to<a name="line.2653"></a>
+<span class="sourceLineNo">2654</span> // reset the batch progress between nextRaw invocations since we don't want the<a name="line.2654"></a>
+<span class="sourceLineNo">2655</span> // batch progress from previous calls to affect future calls<a name="line.2655"></a>
+<span class="sourceLineNo">2656</span> scannerContext.setBatchProgress(0);<a name="line.2656"></a>
<span class="sourceLineNo">2657</span><a name="line.2657"></a>
-<span class="sourceLineNo">2658</span> if (!values.isEmpty()) {<a name="line.2658"></a>
-<span class="sourceLineNo">2659</span> final boolean partial = scannerContext.partialResultFormed();<a name="line.2659"></a>
-<span class="sourceLineNo">2660</span> Result r = Result.create(values, null, stale, partial);<a name="line.2660"></a>
-<span class="sourceLineNo">2661</span> lastBlock = addSize(context, r, lastBlock);<a name="line.2661"></a>
-<span class="sourceLineNo">2662</span> results.add(r);<a name="line.2662"></a>
-<span class="sourceLineNo">2663</span> i++;<a name="line.2663"></a>
-<span class="sourceLineNo">2664</span> }<a name="line.2664"></a>
-<span class="sourceLineNo">2665</span><a name="line.2665"></a>
-<span class="sourceLineNo">2666</span> boolean sizeLimitReached = scannerContext.checkSizeLimit(LimitScope.BETWEEN_ROWS);<a name="line.2666"></a>
-<span class="sourceLineNo">2667</span> boolean timeLimitReached = scannerContext.checkTimeLimit(LimitScope.BETWEEN_ROWS);<a name="line.2667"></a>
-<span class="sourceLineNo">2668</span> boolean rowLimitReached = i >= rows;<a name="line.2668"></a>
-<span class="sourceLineNo">2669</span> limitReached = sizeLimitReached || timeLimitReached || rowLimitReached;<a name="line.2669"></a>
-<span class="sourceLineNo">2670</span><a name="line.2670"></a>
-<span class="sourceLineNo">2671</span> if (limitReached || !moreRows) {<a name="line.2671"></a>
-<span class="sourceLineNo">2672</span> if (LOG.isTraceEnabled()) {<a name="line.2672"></a>
-<span class="sourceLineNo">2673</span> LOG.trace("Done scanning. limitReached: " + limitReached + " moreRows: "<a name="line.2673"></a>
-<span class="sourceLineNo">2674</span> + moreRows + " scannerContext: " + scannerContext);<a name="line.2674"></a>
-<span class="sourceLineNo">2675</span> }<a name="line.2675"></a>
-<span class="sourceLineNo">2676</span> // We only want to mark a ScanResponse as a heartbeat message in the event that<a name="line.2676"></a>
-<span class="sourceLineNo">2677</span> // there are more values to be read server side. If there aren't more values,<a name="line.2677"></a>
-<span class="sourceLineNo">2678</span> // marking it as a heartbeat is wasteful because the client will need to issue<a name="line.2678"></a>
-<span class="sourceLineNo">2679</span> // another ScanRequest only to realize that they already have all the values<a name="line.2679"></a>
-<span class="sourceLineNo">2680</span> if (moreRows) {<a name="line.2680"></a>
-<span class="sourceLineNo">2681</span> // Heartbeat messages occur when the time limit has been reached.<a name="line.2681"></a>
-<span class="sourceLineNo">2682</span> builder.setHeartbeatMessage(timeLimitReached);<a name="line.2682"></a>
-<span class="sourceLineNo">2683</span> }<a name="line.2683"></a>
-<span class="sourceLineNo">2684</span> break;<a name="line.2684"></a>
-<span class="sourceLineNo">2685</span> }<a name="line.2685"></a>
-<span class="sourceLineNo">2686</span> values.clear();<a name="line.2686"></a>
-<span class="sourceLineNo">2687</span> }<a name="line.2687"></a>
-<span class="sourceLineNo">2688</span><a name="line.2688"></a>
-<span class="sourceLineNo">2689</span> if (limitReached || moreRows) {<a name="line.2689"></a>
-<span class="sourceLineNo">2690</span> // We stopped prematurely<a name="line.2690"></a>
-<span class="sourceLineNo">2691</span> builder.setMoreResultsInRegion(true);<a name="line.2691"></a>
-<span class="sourceLineNo">2692</span> } else {<a name="line.2692"></a>
-<span class="sourceLineNo">2693</span> // We didn't get a single batch<a name="line.2693"></a>
-<span class="sourceLineNo">2694</span> builder.setMoreResultsInRegion(false);<a name="line.2694"></a>
-<span class="sourceLineNo">2695</span> }<a name="line.2695"></a>
-<span class="sourceLineNo">2696</span><a name="line.2696"></a>
-<span class="sourceLineNo">2697</span> // Check to see if the client requested that we track metrics server side. If the<a name="line.2697"></a>
-<span class="sourceLineNo">2698</span> // client requested metrics, retrieve the metrics from the scanner context.<a name="line.2698"></a>
-<span class="sourceLineNo">2699</span> if (trackMetrics) {<a name="line.2699"></a>
-<span class="sourceLineNo">2700</span> Map<String, Long> metrics = scannerContext.getMetrics().getMetricsMap();<a name="line.2700"></a>
-<span class="sourceLineNo">2701</span> ScanMetrics.Builder metricBuilder = ScanMetrics.newBuilder();<a name="line.2701"></a>
-<span class="sourceLineNo">2702</span> NameInt64Pair.Builder pairBuilder = NameInt64Pair.newBuilder();<a name="line.2702"></a>
-<span class="sourceLineNo">2703</span><a name="line.2703"></a>
-<span class="sourceLineNo">2704</span> for (Entry<String, Long> entry : metrics.entrySet()) {<a name="line.2704"></a>
-<span class="sourceLineNo">2705</span> pairBuilder.setName(entry.getKey());<a name="line.2705"></a>
-<span class="sourceLineNo">2706</span> pairBuilder.setValue(entry.getValue());<a name="line.2706"></a>
-<span class="sourceLineNo">2707</span> metricBuilder.addMetrics(pairBuilder.build());<a name="line.2707"></a>
-<span class="sourceLineNo">2708</span> }<a name="line.2708"></a>
-<span class="sourceLineNo">2709</span><a name="line.2709"></a>
-<span class="sourceLineNo">2710</span> builder.setScanMetrics(metricBuilder.build());<a name="line.2710"></a>
-<span class="sourceLineNo">2711</span> }<a name="line.2711"></a>
-<span class="sourceLineNo">2712</span> }<a name="line.2712"></a>
-<span class="sourceLineNo">2713</span> region.updateReadRequestsCount(i);<a name="line.2713"></a>
-<span class="sourceLineNo">2714</span> long responseCellSize = context != null ? context.getResponseCellSize() : 0;<a name="line.2714"></a>
-<span class="sourceLineNo">2715</span> region.getMetrics().updateScanNext(responseCellSize);<a name="line.2715"></a>
-<span class="sourceLineNo">2716</span> if (regionServer.metricsRegionServer != null) {<a name="line.2716"></a>
-<span class="sourceLineNo">2717</span> regionServer.metricsRegionServer.updateScannerNext(responseCellSize);<a name="line.2717"></a>
-<span class="sourceLineNo">2718</span> }<a name="line.2718"></a>
-<span class="sourceLineNo">2719</span> } finally {<a name="line.2719"></a>
-<span class="sourceLineNo">2720</span> region.closeRegionOperation();<a name="line.2720"></a>
-<span class="sourceLineNo">2721</span> }<a name="line.2721"></a>
-<span class="sourceLineNo">2722</span> // coprocessor postNext hook<a name="line.2722"></a>
-<span class="sourceLineNo">2723</span> if (region != null && region.getCoprocessorHost() != null) {<a name="line.2723"></a>
-<span class="sourceLineNo">2724</span> region.getCoprocessorHost().postScannerNext(scanner, results, rows, true);<a name="line.2724"></a>
-<span class="sourceLineNo">2725</span> }<a name="line.2725"></a>
-<span class="sourceLineNo">2726</span> }<a name="line.2726"></a>
-<span class="sourceLineNo">2727</span><a name="line.2727"></a>
-<span class="sourceLineNo">2728</span> quota.addScanResult(results);<a name="line.2728"></a>
-<span class="sourceLineNo">2729</span><a name="line.2729"></a>
-<span class="sourceLineNo">2730</span> // If the scanner's filter - if any - is done with the scan<a name="line.2730"></a>
-<span class="sourceLineNo">2731</span> // and wants to tell the client to stop the scan. This is done by passing<a name="line.2731"></a>
-<span class="sourceLineNo">2732</span> // a null result, and setting moreResults to false.<a name="line.2732"></a>
-<span class="sourceLineNo">2733</span> if (scanner.isFilterDone() && results.isEmpty()) {<a name="line.2733"></a>
-<span class="sourceLineNo">2734</span> moreResults = false;<a name="line.2734"></a>
-<span class="sourceLineNo">2735</span> results = null;<a name="line.2735"></a>
-<span class="sourceLineNo">2736</span> } else {<a name="line.2736"></a>
-<span class="sourceLineNo">2737</span> addResults(builder, results, controller,<a name="line.2737"></a>
-<span class="sourceLineNo">2738</span> RegionReplicaUtil.isDefaultReplica(region.getRegionInfo()),<a name="line.2738"></a>
-<span class="sourceLineNo">2739</span> isClientCellBlockSupport(context));<a name="line.2739"></a>
-<span class="sourceLineNo">2740</span> }<a name="line.2740"></a>
-<span class="sourceLineNo">2741</span> } catch (IOException e) {<a name="line.2741"></a>
-<span class="sourceLineNo">2742</span> // if we have an exception on scanner next and we are using the callSeq<a name="line.2742"></a>
-<span class="sourceLineNo">2743</span> // we should rollback because the client will retry with the same callSeq<a name="line.2743"></a>
-<span class="sourceLineNo">2744</span> // and get an OutOfOrderScannerNextException if we don't do so.<a name="line.2744"></a>
-<span class="sourceLineNo">2745</span> if (rsh != null && request.hasNextCallSeq()) {<a name="line.2745"></a>
-<span class="sourceLineNo">2746</span> rsh.rollbackNextCallSeq();<a name="line.2746"></a>
-<span class="sourceLineNo">2747</span> }<a name="line.2747"></a>
-<span class="sourceLineNo">2748</span> throw e;<a name="line.2748"></a>
-<span class="sourceLineNo">2749</span> } finally {<a name="line.2749"></a>
-<span class="sourceLineNo">2750</span> if (context != null) {<a name="line.2750"></a>
-<span class="sourceLineNo">2751</span> context.setCallBack(rsh.shippedCallback);<a name="line.2751"></a>
-<span class="sourceLineNo">2752</span> }<a name="line.2752"></a>
-<span class="sourceLineNo">2753</span> // Adding resets expiration time on lease.<a name="line.2753"></a>
-<span class="sourceLineNo">2754</span> if (scanners.containsKey(scannerName)) {<a name="line.2754"></a>
-<span class="sourceLineNo">2755</span> ttl = this.scannerLeaseTimeoutPeriod;<a name="line.2755"></a>
-<span class="sourceLineNo">2756</span> // When context != null, adding back the lease will be done in callback set above.<a name="line.2756"></a>
-<span class="sourceLineNo">2757</span> if (context == null) {<a name="line.2757"></a>
-<span class="sourceLineNo">2758</span> if (lease != null) regionServer.leases.addLease(lease);<a name="line.2758"></a>
-<span class="sourceLineNo">2759</span> }<a name="line.2759"></a>
-<span class="sourceLineNo">2760</span> }<a name="line.2760"></a>
-<span class="sourceLineNo">2761</span> }<a name="line.2761"></a>
-<span class="sourceLineNo">2762</span> }<a name="line.2762"></a>
-<span class="sourceLineNo">2763</span><a name="line.2763"></a>
-<span class="sourceLineNo">2764</span> if (!moreResults || closeScanner) {<a name="line.2764"></a>
-<span class="sourceLineNo">2765</span> ttl = 0;<a name="line.2765"></a>
-<span class="sourceLineNo">2766</span> moreResults = false;<a name="line.2766"></a>
-<span class="sourceLineNo">2767</span> if (region != null && region.getCoprocessorHost() != null) {<a name="line.2767"></a>
-<span class="sourceLineNo">2768</span> if (region.getCoprocessorHost().preScannerClose(scanner)) {<a name="line.2768"></a>
-<span class="sourceLineNo">2769</span> return builder.build(); // bypass<a name="line.2769"></a>
-<span class="sourceLineNo">2770</span> }<a name="line.2770"></a>
-<span class="sourceLineNo">2771</span> }<a name="line.2771"></a>
-<span class="sourceLineNo">2772</span> rsh = scanners.remove(scannerName);<a name="line.2772"></a>
-<span class="sourceLineNo">2773</span> if (rsh != null) {<a name="line.2773"></a>
-<span class="sourceLineNo">2774</span> if (context != null) {<a name="line.2774"></a>
-<span class="sourceLineNo">2775</span> context.setCallBack(rsh.closeCallBack);<a name="line.2775"></a>
-<span class="sourceLineNo">2776</span> } else {<a name="line.2776"></a>
-<span class="sourceLineNo">2777</span> rsh.s.close();<a name="line.2777"></a>
-<span class="sourceLineNo">2778</span> }<a name="line.2778"></a>
-<span class="sourceLineNo">2779</span> try {<a name="line.2779"></a>
-<span class="sourceLineNo">2780</span> regionServer.leases.cancelLease(scannerName);<a name="line.2780"></a>
-<span class="sourceLineNo">2781</span> } catch (LeaseException le) {<a name="line.2781"></a>
-<span class="sourceLineNo">2782</span> // No problem, ignore<a name="line.2782"></a>
-<span class="sourceLineNo">2783</span> if (LOG.isTraceEnabled()) {<a name="line.2783"></a>
-<span class="sourceLineNo">2784</span> LOG.trace("Un-able to cancel lease of scanner. It could already be closed.");<a name="line.2784"></a>
-<span class="sourceLineNo">2785</span> }<a name="line.2785"></a>
-<span class="sourceLineNo">2786</span> }<a name="line.2786"></a>
-<span class="sourceLineNo">2787</span> if (region != null && region.getCoprocessorHost() != null) {<a name="line.2787"></a>
-<span class="sourceLineNo">2788</span> region.getCoprocessorHost().postScannerClose(scanner);<a name="line.2788"></a>
+<span class="sourceLineNo">2658</span> // Collect values to be returned here<a name="line.2658"></a>
+<span class="sourceLineNo">2659</span> moreRows = scanner.nextRaw(values, scannerContext);<a name="line.2659"></a>
+<span class="sourceLineNo">2660</span><a name="line.2660"></a>
+<span class="sourceLineNo">2661</span> if (!values.isEmpty()) {<a name="line.2661"></a>
+<span class="sourceLineNo">2662</span> final boolean partial = scannerContext.partialResultFormed();<a name="line.2662"></a>
+<span class="sourceLineNo">2663</span> Result r = Result.create(values, null, stale, partial);<a name="line.2663"></a>
+<span class="sourceLineNo">2664</span> lastBlock = addSize(context, r, lastBlock);<a name="line.2664"></a>
+<span class="sourceLineNo">2665</span> results.add(r);<a name="line.2665"></a>
+<span class="sourceLineNo">2666</span> i++;<a name="line.2666"></a>
+<span class="sourceLineNo">2667</span> }<a name="line.2667"></a>
+<span class="sourceLineNo">2668</span><a name="line.2668"></a>
+<span class="sourceLineNo">2669</span> boolean sizeLimitReached = scannerContext.checkSizeLimit(LimitScope.BETWEEN_ROWS);<a name="line.2669"></a>
+<span class="sourceLineNo">2670</span> boolean timeLimitReached = scannerContext.checkTimeLimit(LimitScope.BETWEEN_ROWS);<a name="line.2670"></a>
+<span class="sourceLineNo">2671</span> boolean rowLimitReached = i >= rows;<a name="line.2671"></a>
+<span class="sourceLineNo">2672</span> limitReached = sizeLimitReached || timeLimitReached || rowLimitReached;<a name="line.2672"></a>
+<span class="sourceLineNo">2673</span><a name="line.2673"></a>
+<span class="sourceLineNo">2674</span> if (limitReached || !moreRows) {<a name="line.2674"></a>
+<span class="sourceLineNo">2675</span> if (LOG.isTraceEnabled()) {<a name="line.2675"></a>
+<span class="sourceLineNo">2676</span> LOG.trace("Done scanning. limitReached: " + limitReached + " moreRows: "<a name="line.2676"></a>
+<span class="sourceLineNo">2677</span> + moreRows + " scannerContext: " + scannerContext);<a name="line.2677"></a>
+<span class="sourceLineNo">2678</span> }<a name="line.2678"></a>
+<span class="sourceLineNo">2679</span> // We only want to mark a ScanResponse as a heartbeat message in the event that<a name="line.2679"></a>
+<span class="sourceLineNo">2680</span> // there are more values to be read server side. If there aren't more values,<a name="line.2680"></a>
+<span class="sourceLineNo">2681</span> // marking it as a heartbeat is wasteful because the client will need to issue<a name="line.2681"></a>
+<span class="sourceLineNo">2682</span> // another ScanRequest only to realize that they already have all the values<a name="line.2682"></a>
+<span class="sourceLineNo">2683</span> if (moreRows) {<a name="line.2683"></a>
+<span class="sourceLineNo">2684</span> // Heartbeat messages occur when the time limit has been reached.<a name="line.2684"></a>
+<span class="sourceLineNo">2685</span> builder.setHeartbeatMessage(timeLimitReached);<a name="line.2685"></a>
+<span class="sourceLineNo">2686</span> }<a name="line.2686"></a>
+<span class="sourceLineNo">2687</span> break;<a name="line.2687"></a>
+<span class="sourceLineNo">2688</span> }<a name="line.2688"></a>
+<span class="sourceLineNo">2689</span> values.clear();<a name="line.2689"></a>
+<span class="sourceLineNo">2690</span> }<a name="line.2690"></a>
+<span class="sourceLineNo">2691</span><a name="line.2691"></a>
+<span class="sourceLineNo">2692</span> if (limitReached || moreRows) {<a name="line.2692"></a>
+<span class="sourceLineNo">2693</span> // We stopped prematurely<a name="line.2693"></a>
+<span class="sourceLineNo">2694</span> builder.setMoreResultsInRegion(true);<a name="line.2694"></a>
+<span class="sourceLineNo">2695</span> } else {<a name="line.2695"></a>
+<span class="sourceLineNo">2696</span> // We didn't get a single batch<a name="line.2696"></a>
+<span class="sourceLineNo">2697</span> builder.setMoreResultsInRegion(false);<a name="line.2697"></a>
+<span class="sourceLineNo">2698</span> }<a name="line.2698"></a>
+<span class="sourceLineNo">2699</span><a name="line.2699"></a>
+<span class="sourceLineNo">2700</span> // Check to see if the client requested that we track metrics server side. If the<a name="line.2700"></a>
+<span class="sourceLineNo">2701</span> // client requested metrics, retrieve the metrics from the scanner context.<a name="line.2701"></a>
+<span class="sourceLineNo">2702</span> if (trackMetrics) {<a name="line.2702"></a>
+<span class="sourceLineNo">2703</span> Map<String, Long> metrics = scannerContext.getMetrics().getMetricsMap();<a name="line.2703"></a>
+<span class="sourceLineNo">2704</span> ScanMetrics.Builder metricBuilder = ScanMetrics.newBuilder();<a name="line.2704"></a>
+<span class="sourceLineNo">2705</span> NameInt64Pair.Builder pairBuilder = NameInt64Pair.newBuilder();<a name="line.2705"></a>
+<span class="sourceLineNo">2706</span><a name="line.2706"></a>
+<span class="sourceLineNo">2707</span> for (Entry<String, Long> entry : metrics.entrySet()) {<a name="line.2707"></a>
+<span class="sourceLineNo">2708</span> pairBuilder.setName(entry.getKey());<a name="line.2708"></a>
+<span class="sourceLineNo">2709</span> pairBuilder.setValue(entry.getValue());<a name="line.2709"></a>
+<span class="sourceLineNo">2710</span> metricBuilder.addMetrics(pairBuilder.build());<a name="line.2710"></a>
+<span class="sourceLineNo">2711</span> }<a name="line.2711"></a>
+<span class="sourceLineNo">2712</span><a name="line.2712"></a>
+<span class="sourceLineNo">2713</span> builder.setScanMetrics(metricBuilder.build());<a name="line.2713"></a>
+<span class="sourceLineNo">2714</span> }<a name="line.2714"></a>
+<span class="sourceLineNo">2715</span> }<a name="line.2715"></a>
+<span class="sourceLineNo">2716</span> region.updateReadRequestsCount(i);<a name="line.2716"></a>
+<span class="sourceLineNo">2717</span> long responseCellSize = context != null ? context.getResponseCellSize() : 0;<a name="line.2717"></a>
+<span class="sourceLineNo">2718</span> region.getMetrics().updateScanNext(responseCellSize);<a name="line.2718"></a>
+<span class="sourceLineNo">2719</span> if (regionServer.metricsRegionServer != null) {<a name="line.2719"></a>
+<span class="sourceLineNo">2720</span> regionServer.metricsRegionServer.updateScannerNext(responseCellSize);<a name="line.2720"></a>
+<span class="sourceLineNo">2721</span> }<a name="line.2721"></a>
+<span class="sourceLineNo">2722</span> } finally {<a name="line.2722"></a>
+<span class="sourceLineNo">2723</span> region.closeRegionOperation();<a name="line.2723"></a>
+<span class="sourceLineNo">2724</span> }<a name="line.2724"></a>
+<span class="sourceLineNo">2725</span> // coprocessor postNext hook<a name="line.2725"></a>
+<span class="sourceLineNo">2726</span> if (region != null && region.getCoprocessorHost() != null) {<a name="line.2726"></a>
+<span class="sourceLineNo">2727</span> region.getCoprocessorHost().postScannerNext(scanner, results, rows, true);<a name="line.2727"></a>
+<span class="sourceLineNo">2728</span> }<a name="line.2728"></a>
+<span class="sourceLineNo">2729</span> }<a name="line.2729"></a>
+<span class="sourceLineNo">2730</span><a name="line.2730"></a>
+<span class="sourceLineNo">2731</span> quota.addScanResult(results);<a name="line.2731"></a>
+<span class="sourceLineNo">2732</span><a name="line.2732"></a>
+<span class="sourceLineNo">2733</span> // If the scanner's filter - if any - is done with the scan<a name="line.2733"></a>
+<span class="sourceLineNo">2734</span> // and wants to tell the client to stop the scan. This is done by passing<a name="line.2734"></a>
+<span class="sourceLineNo">2735</span> // a null result, and setting moreResults to false.<a name="line.2735"></a>
+<span class="sourceLineNo">2736</span> if (scanner.isFilterDone() && results.isEmpty()) {<a name="line.2736"></a>
+<span class="sourceLineNo">2737</span> moreResults = false;<a name="line.2737"></a>
+<span class="sourceLineNo">2738</span> results = null;<a name="line.2738"></a>
+<span class="sourceLineNo">2739</span> } else {<a name="line.2739"></a>
+<span class="sourceLineNo">2740</span> addResults(builder, results, controller,<a name="line.2740"></a>
+<span class="sourceLineNo">2741</span> RegionReplicaUtil.isDefaultReplica(region.getRegionInfo()),<a name="line.2741"></a>
+<span class="sourceLineNo">2742</span> isClientCellBlockSupport(context));<a name="line.2742"></a>
+<span class="sourceLineNo">2743</span> }<a name="line.2743"></a>
+<span class="sourceLineNo">2744</span> } catch (IOException e) {<a name="line.2744"></a>
+<span class="sourceLineNo">2745</span> // if we have an exception on scanner next and we are using the callSeq<a name="line.2745"></a>
+<span class="sourceLineNo">2746</span> // we should rollback because the client will retry with the same callSeq<a name="line.2746"></a>
+<span class="sourceLineNo">2747</span> // and get an OutOfOrderScannerNextException if we don't do so.<a name="line.2747"></a>
+<span class="sourceLineNo">2748</span> if (rsh != null && request.hasNextCallSeq()) {<a name="line.2748"></a>
+<span class="sourceLineNo">2749</span> rsh.rollbackNextCallSeq();<a name="line.2749"></a>
+<span class="sourceLineNo">2750</span> }<a name="line.2750"></a>
+<span class="sourceLineNo">2751</span> throw e;<a name="line.2751"></a>
+<span class="sourceLineNo">2752</span> } finally {<a name="line.2752"></a>
+<span class="sourceLineNo">2753</span> if (context != null) {<a name="line.2753"></a>
+<span class="sourceLineNo">2754</span> context.setCallBack(rsh.shippedCallback);<a name="line.2754"></a>
+<span class="sourceLineNo">2755</span> }<a name="line.2755"></a>
+<span class="sourceLineNo">2756</span> // Adding resets expiration time on lease.<a name="line.2756"></a>
+<span class="sourceLineNo">2757</span> if (scanners.containsKey(scannerName)) {<a name="line.2757"></a>
+<span class="sourceLineNo">2758</span> ttl = this.scannerLeaseTimeoutPeriod;<a name="line.2758"></a>
+<span class="sourceLineNo">2759</span> // When context != null, adding back the lease will be done in callback set above.<a name="line.2759"></a>
+<span class="sourceLineNo">2760</span> if (context == null) {<a name="line.2760"></a>
+<span class="sourceLineNo">2761</span> if (lease != null) regionServer.leases.addLease(lease);<a name="line.2761"></a>
+<span class="sourceLineNo">2762</span> }<a name="line.2762"></a>
+<span class="sourceLineNo">2763</span> }<a name="line.2763"></a>
+<span class="sourceLineNo">2764</span> }<a name="line.2764"></a>
+<span class="sourceLineNo">2765</span> }<a name="line.2765"></a>
+<span class="sourceLineNo">2766</span><a name="line.2766"></a>
+<span class="sourceLineNo">2767</span> if (!moreResults || closeScanner) {<a name="line.2767"></a>
+<span class="sourceLineNo">2768</span> ttl = 0;<a name="line.2768"></a>
+<span class="sourceLineNo">2769</span> moreResults = false;<a name="line.2769"></a>
+<span class="sourceLineNo">2770</span> if (region != null && region.getCoprocessorHost() != null) {<a name="line.2770"></a>
+<span class="sourceLineNo">2771</span> if (region.getCoprocessorHost().preScannerClose(scanner)) {<a name="line.2771"></a>
+<span class="sourceLineNo">2772</span> return builder.build(); // bypass<a name="line.2772"></a>
+<span class="sourceLineNo">2773</span> }<a name="line.2773"></a>
+<span class="sourceLineNo">2774</span> }<a name="line.2774"></a>
+<span class="sourceLineNo">2775</span> rsh = scanners.remove(scannerName);<a name="line.2775"></a>
+<span class="sourceLineNo">2776</span> if (rsh != null) {<a name="line.2776"></a>
+<span class="sourceLineNo">2777</span> if (context != null) {<a name="line.2777"></a>
+<span class="sourceLineNo">2778</span> context.setCallBack(rsh.closeCallBack);<a name="line.2778"></a>
+<span class="sourceLineNo">2779</span> } else {<a name="line.2779"></a>
+<span class="sourceLineNo">2780</span> rsh.s.close();<a name="line.2780"></a>
+<span class="sourceLineNo">2781</span> }<a name="line.2781"></a>
+<span class="sourceLineNo">2782</span> try {<a name="line.2782"></a>
+<span class="sourceLineNo">2783</span> regionServer.leases.cancelLease(scannerName);<a name="line.2783"></a>
+<span class="sourceLineNo">2784</span> } catch (LeaseException le) {<a name="line.2784"></a>
+<span class="sourceLineNo">2785</span> // No problem, ignore<a name="line.2785"></a>
+<span class="sourceLineNo">2786</span> if (LOG.isTraceEnabled()) {<a name="line.2786"></a>
+<span class="sourceLineNo">2787</span> LOG.trace("Un-able to cancel lease of scanner. It could already be closed.");<a name="line.2787"></a>
+<span class="sourceLineNo">2788</span> }<a name="line.2788"></a>
<span class="sourceLineNo">2789</span> }<a name="line.2789"></a>
-<span class="sourceLineNo">2790</span> }<a name="line.2790"></a>
-<span class="sourceLineNo">2791</span> }<a name="line.2791"></a>
-<span class="sourceLineNo">2792</span><a name="line.2792"></a>
-<span class="sourceLineNo">2793</span> if (ttl > 0) {<a name="line.2793"></a>
-<span class="sourceLineNo">2794</span> builder.setTtl(ttl);<a name="line.2794"></a>
-<span class="sourceLineNo">2795</span> }<a name="line.2795"></a>
-<span class="sourceLineNo">2796</span> builder.setScannerId(scannerId);<a name="line.2796"></a>
-<span class="sourceLineNo">2797</span> builder.setMoreResults(moreResults);<a name="line.2797"></a>
-<span class="sourceLineNo">2798</span> return builder.build();<a name="line.2798"></a>
-<span class="sourceLineNo">2799</span> } catch (IOException ie) {<a name="line.2799"></a>
-<span class="sourceLineNo">2800</span> if (scannerName != null && ie instanceof NotServingRegionException) {<a name="line.2800"></a>
-<span class="sourceLineNo">2801</span> RegionScannerHolder rsh = scanners.remove(scannerName);<a name="line.2801"></a>
-<span class="sourceLineNo">2802</span> if (rsh != null) {<a name="line.2802"></a>
-<span class="sourceLineNo">2803</span> try {<a name="line.2803"></a>
-<span class="sourceLineNo">2804</span> RegionScanner scanner = rsh.s;<a name="line.2804"></a>
-<span class="sourceLineNo">2805</span> LOG.warn(scannerName + " encountered " + ie.getMessage() + ", closing ...");<a name="line.2805"></a>
-<span class="sourceLineNo">2806</span> scanner.close();<a name="line.2806"></a>
-<span class="sourceLineNo">2807</span> regionServer.leases.cancelLease(scannerName);<a name="line.2807"></a>
-<span class="sourceLineNo">2808</span> } catch (IOException e) {<a name="line.2808"></a>
-<span class="sourceLineNo">2809</span> LOG.warn("Getting exception closing " + scannerName, e);<a name="line.2809"></a>
-<span class="sourceLineNo">2810</span> }<a name="line.2810"></a>
-<span class="sourceLineNo">2811</span> }<a name="line.2811"></a>
-<span class="sourceLineNo">2812</span> }<a name="line.2812"></a>
-<span class="sourceLineNo">2813</span> throw new ServiceException(ie);<a name="line.2813"></a>
-<span class="sourceLineNo">2814</span> } finally {<a name="line.2814"></a>
-<span class="sourceLineNo">2815</span> if (quota != null) {<a name="line.2815"></a>
-<span class="sourceLineNo">2816</span> quota.close();<a name="line.2816"></a>
-<span class="sourceLineNo">2817</span> }<a name="line.2817"></a>
-<span class="sourceLineNo">2818</span> }<a name="line.2818"></a>
-<span class="sourceLineNo">2819</span> }<a name="line.2819"></a>
-<span class="sourceLineNo">2820</span><a name="line.2820"></a>
-<span class="sourceLineNo">2821</span> @Override<a name="line.2821"></a>
-<span class="sourceLineNo">2822</span> public CoprocessorServiceResponse execRegionServerService(RpcController controller,<a name="line.2822"></a>
-<span class="sourceLineNo">2823</span> CoprocessorServiceRequest request) throws ServiceException {<a name="line.2823"></a>
-<span class="sourceLineNo">2824</span> return regionServer.execRegionServerService(controller, request);<a name="line.2824"></a>
-<span class="sourceLineNo">2825</span> }<a name="line.2825"></a>
-<span class="sourceLineNo">2826</span><a name="line.2826"></a>
-<span class="sourceLineNo">2827</span> @Override<a name="line.2827"></a>
-<span class="sourceLineNo">2828</span> public UpdateConfigurationResponse updateConfiguration(<a name="line.2828"></a>
-<span class="sourceLineNo">2829</span> RpcController controller, UpdateConfigurationRequest request)<a name="line.2829"></a>
-<span class="sourceLineNo">2830</span> throws ServiceException {<a name="line.2830"></a>
-<span class="sourceLineNo">2831</span> try {<a name="line.2831"></a>
-<span class="sourceLineNo">2832</span> this.regionServer.updateConfiguration();<a name="line.2832"></a>
-<span class="sourceLineNo">2833</span> } catch (Exception e) {<a name="line.2833"></a>
-<span class="sourceLineNo">2834</span> throw new ServiceException(e);<a name="line.2834"></a>
-<span class="sourceLineNo">2835</span> }<a name="line.2835"></a>
-<span class="sourceLineNo">2836</span> return UpdateConfigurationResponse.getDefaultInstance();<a name="line.2836"></a>
-<span class="sourceLineNo">2837</span> }<a name="line.2837"></a>
-<span class="sourceLineNo">2838</span>}<a name="line.2838"></a>
+<span class="sourceLineNo">2790</span> if (region != null && region.getCoprocessorHost() != null) {<a name="line.2790"></a>
+<span class="sourceLineNo">2791</span> region.getCoprocessorHost().postScannerClose(scanner);<a name="line.2791"></a>
+<span class="sourceLineNo">2792</span> }<a name="line.2792"></a>
+<span class="sourceLineNo">2793</span> }<a name="line.2793"></a>
+<span class="sourceLineNo">2794</span> }<a name="line.2794"></a>
+<span class="sourceLineNo">2795</span><a name="line.2795"></a>
+<span class="sourceLineNo">2796</span> if (ttl > 0) {<a name="line.2796"></a>
+<span class="sourceLineNo">2797</span> builder.setTtl(ttl);<a name="line.2797"></a>
+<span class="sourceLineNo">2798</span> }<a name="line.2798"></a>
+<span class="sourceLineNo">2799</span> builder.setScannerId(scannerId);<a name="line.2799"></a>
+<span class="sourceLineNo">2800</span> builder.setMoreResults(moreResults);<a name="line.2800"></a>
+<span class="sourceLineNo">2801</span> return builder.build();<a name="line.2801"></a>
+<span class="sourceLineNo">2802</span> } catch (IOException ie) {<a name="line.2802"></a>
+<span class="sourceLineNo">2803</span> if (scannerName != null && ie instanceof NotServingRegionException) {<a name="line.2803"></a>
+<span class="sourceLineNo">2804</span> RegionScannerHolder rsh = scanners.remove(scannerName);<a name="line.2804"></a>
+<span class="sourceLineNo">2805</span> if (rsh != null) {<a name="line.2805"></a>
+<span class="sourceLineNo">2806</span> try {<a name="line.2806"></a>
+<span class="sourceLineNo">2807</span> RegionScanner scanner = rsh.s;<a name="line.2807"></a>
+<span class="sourceLineNo">2808</span> LOG.warn(scannerName + " encountered " + ie.getMessage() + ", closing ...");<a name="line.2808"></a>
+<span class="sourceLineNo">2809</span> scanner.close();<a name="line.2809"></a>
+<span class="sourceLineNo">2810</span> regionServer.leases.cancelLease(scannerName);<a name="line.2810"></a>
+<span class="sourceLineNo">2811</span> } catch (IOException e) {<a name="line.2811"></a>
+<span class="sourceLineNo">2812</span> LOG.warn("Getting exception closing " + scannerName, e);<a name="line.2812"></a>
+<span class="sourceLineNo">2813</span> }<a name="line.2813"></a>
+<span class="sourceLineNo">2814</span> }<a name="line.2814"></a>
+<span class="sourceLineNo">2815</span> }<a name="line.2815"></a>
+<span class="sourceLineNo">2816</span> throw new ServiceException(ie);<a name="line.2816"></a>
+<span class="sourceLineNo">2817</span> } finally {<a name="line.2817"></a>
+<span class="sourceLineNo">2818</span> if (quota != null) {<a name="line.2818"></a>
+<span class="sourceLineNo">2819</span> quota.close();<a name="line.2819"></a>
+<span class="sourceLineNo">2820</span> }<a name="line.2820"></a>
+<span class="sourceLineNo">2821</span> }<a name="line.2821"></a>
+<span class="sourceLineNo">2822</span> }<a name="line.2822"></a>
+<span class="sourceLineNo">2823</span><a name="line.2823"></a>
+<span class="sourceLineNo">2824</span> @Override<a name="line.2824"></a>
+<span class="sourceLineNo">2825</span> public CoprocessorServiceResponse execRegionServerService(RpcController controller,<a name="line.2825"></a>
+<span class="sourceLineNo">2826</span> CoprocessorServiceRequest request) throws ServiceException {<a name="line.2826"></a>
+<span class="sourceLineNo">2827</span> return regionServer.execRegionServerService(controller, request);<a name="line.2827"></a>
+<span class="sourceLineNo">2828</span> }<a name="line.2828"></a>
+<span class="sourceLineNo">2829</span><a name="line.2829"></a>
+<span class="sourceLineNo">2830</span> @Override<a name="line.2830"></a>
+<span class="sourceLineNo">2831</span> public UpdateConfigurationResponse updateConfiguration(<a name="line.2831"></a>
+<span class="sourceLineNo">2832</span> RpcController controller, UpdateConfigurationRequest request)<a name="line.2832"></a>
+<span class="sourceLineNo">2833</span> throws ServiceException {<a name="line.2833"></a>
+<span class="sourceLineNo">2834</span> try {<a name="line.2834"></a>
+<span class="sourceLineNo">2835</span> this.regionServer.updateConfiguration();<a name="line.2835"></a>
+<span class="sourceLineNo">2836</span> } catch (Exception e) {<a name="line.2836"></a>
+<span class="sourceLineNo">2837</span> throw new ServiceException(e);<a name="line.2837"></a>
+<span class="sourceLineNo">2838</span> }<a name="line.2838"></a>
+<span class="sourceLineNo">2839</span> return UpdateConfigurationResponse.getDefaultInstance();<a name="line.2839"></a>
+<span class="sourceLineNo">2840</span> }<a name="line.2840"></a>
+<span class="sourceLineNo">2841</span>}<a name="line.2841"></a>