View Javadoc

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.ipc;
19  
20  import java.util.concurrent.BlockingQueue;
21  import java.util.concurrent.atomic.AtomicInteger;
22  import org.apache.hadoop.hbase.Abortable;
23  import org.apache.hadoop.hbase.classification.InterfaceAudience;
24  import org.apache.hadoop.hbase.monitoring.MonitoredRPCHandler;
25  import org.apache.hadoop.util.StringUtils;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  /**
30   * Thread to handle rpc call.
31   * Should only be used in {@link RpcExecutor} and its sub-classes.
32   */
33  @InterfaceAudience.Private
34  public class RpcHandler extends Thread {
35    private static final Logger LOG = LoggerFactory.getLogger(RpcHandler.class);
36  
37    /**
38     * Q to find CallRunners to run in.
39     */
40    final BlockingQueue<CallRunner> q;
41  
42    final int handlerCount;
43    final double handlerFailureThreshhold;
44  
45    // metrics (shared with other handlers)
46    final AtomicInteger activeHandlerCount;
47    final AtomicInteger failedHandlerCount;
48  
49    // The up-level RpcServer.
50    final Abortable abortable;
51  
52    private boolean running;
53  
54    RpcHandler(final String name, final double handlerFailureThreshhold, final int handlerCount,
55        final BlockingQueue<CallRunner> q, final AtomicInteger activeHandlerCount,
56        final AtomicInteger failedHandlerCount, final Abortable abortable) {
57      super(name);
58      setDaemon(true);
59      this.q = q;
60      this.handlerFailureThreshhold = handlerFailureThreshhold;
61      this.activeHandlerCount = activeHandlerCount;
62      this.failedHandlerCount = failedHandlerCount;
63      this.handlerCount = handlerCount;
64      this.abortable = abortable;
65    }
66  
67    /**
68     * @return A {@link CallRunner}
69     * @throws InterruptedException Throws by {@link BlockingQueue#take()}
70     */
71    protected CallRunner getCallRunner() throws InterruptedException {
72      return this.q.take();
73    }
74  
75    public void stopRunning() {
76      running = false;
77    }
78  
79    @Override
80    public void run() {
81      boolean interrupted = false;
82      running = true;
83      try {
84        while (running) {
85          try {
86            run(getCallRunner());
87          } catch (InterruptedException e) {
88            interrupted = true;
89          }
90        }
91      } catch (Exception e) {
92        LOG.warn(e.toString(), e);
93        throw e;
94      } finally {
95        if (interrupted) {
96          Thread.currentThread().interrupt();
97        }
98      }
99    }
100 
101   private void run(CallRunner cr) {
102     MonitoredRPCHandler status = RpcServer.getStatus();
103     cr.setStatus(status);
104     try {
105       this.activeHandlerCount.incrementAndGet();
106       cr.run();
107     } catch (Throwable e) {
108       if (e instanceof Error) {
109         int failedCount = failedHandlerCount.incrementAndGet();
110         if (this.handlerFailureThreshhold >= 0
111           && failedCount > handlerCount * this.handlerFailureThreshhold) {
112           String message = "Number of failed RpcServer handler runs exceeded threshhold "
113             + this.handlerFailureThreshhold + "; reason: " + StringUtils.stringifyException(e);
114           if (abortable != null) {
115             abortable.abort(message, e);
116           } else {
117             LOG.error("Error but can't abort because abortable is null: "
118               + StringUtils.stringifyException(e));
119             throw e;
120           }
121         } else {
122           LOG.warn("Handler errors " + StringUtils.stringifyException(e));
123         }
124       } else {
125         LOG.warn("Handler exception " + StringUtils.stringifyException(e));
126       }
127     } finally {
128       this.activeHandlerCount.decrementAndGet();
129     }
130   }
131 }