1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package org.apache.hadoop.hbase.client;
19 
20 import org.apache.hadoop.hbase.HRegionLocation;
21 import org.apache.hadoop.hbase.classification.InterfaceAudience;
22 
23 import java.io.IOException;
24 
25 /**
26  * An {@link RpcRetryingCaller} that will update the per-region stats for the call on return,
27  * if stats are available
28  */
29 @InterfaceAudience.Private
30 public class StatsTrackingRpcRetryingCaller<T> extends RpcRetryingCaller<T> {
31   private final ServerStatisticTracker stats;
32 
StatsTrackingRpcRetryingCaller(long pause, int retries, int startLogErrorsCnt, ServerStatisticTracker stats)33   public StatsTrackingRpcRetryingCaller(long pause, int retries, int startLogErrorsCnt,
34       ServerStatisticTracker stats) {
35     super(pause, retries, startLogErrorsCnt);
36     this.stats = stats;
37   }
38 
StatsTrackingRpcRetryingCaller(long pause, int retries, RetryingCallerInterceptor interceptor, int startLogErrorsCnt, ServerStatisticTracker stats)39   public StatsTrackingRpcRetryingCaller(long pause, int retries,
40       RetryingCallerInterceptor interceptor, int startLogErrorsCnt,
41       ServerStatisticTracker stats) {
42     super(pause, retries, interceptor, startLogErrorsCnt);
43     this.stats = stats;
44   }
45 
46   @Override
callWithRetries(RetryingCallable<T> callable, int callTimeout)47   public T callWithRetries(RetryingCallable<T> callable, int callTimeout)
48       throws IOException, RuntimeException {
49     T result = super.callWithRetries(callable, callTimeout);
50     return updateStatsAndUnwrap(result, callable);
51   }
52 
53   @Override
callWithoutRetries(RetryingCallable<T> callable, int callTimeout)54   public T callWithoutRetries(RetryingCallable<T> callable, int callTimeout)
55       throws IOException, RuntimeException {
56     T result = super.callWithRetries(callable, callTimeout);
57     return updateStatsAndUnwrap(result, callable);
58   }
59 
updateStatsAndUnwrap(T result, RetryingCallable<T> callable)60   private T updateStatsAndUnwrap(T result, RetryingCallable<T> callable) {
61     // don't track stats about requests that aren't to regionservers
62     if (!(callable instanceof RegionServerCallable)) {
63       return result;
64     }
65 
66     // mutli-server callables span multiple regions, so they don't have a location,
67     // but they are region server callables, so we have to handle them when we process the
68     // result in AsyncProcess#receiveMultiAction, not in here
69     if (callable instanceof MultiServerCallable) {
70       return result;
71     }
72 
73     // update the stats for the single server callable
74     RegionServerCallable<T> regionCallable = (RegionServerCallable) callable;
75     HRegionLocation location = regionCallable.getLocation();
76     return ResultStatsUtil.updateStats(result, stats, location);
77   }
78 }