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.LinkedBlockingQueue;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.Abortable;
27  import org.apache.hadoop.hbase.HBaseInterfaceAudience;
28  import org.apache.hadoop.hbase.classification.InterfaceAudience;
29  import org.apache.hadoop.hbase.classification.InterfaceStability;
30  import org.apache.hadoop.hbase.util.ReflectionUtils;
31  
32  /**
33   * An {@link RpcExecutor} that will balance requests evenly across all its queues, but still remains
34   * efficient with a single queue via an inlinable queue balancing mechanism. Defaults to FIFO but
35   * you can pass an alternate queue class to use.
36   */
37  @InterfaceAudience.LimitedPrivate({ HBaseInterfaceAudience.COPROC, HBaseInterfaceAudience.PHOENIX })
38  @InterfaceStability.Evolving
39  public class BalancedQueueRpcExecutor extends RpcExecutor {
40    private static final Log LOG = LogFactory.getLog(BalancedQueueRpcExecutor.class);
41  
42    private final QueueBalancer balancer;
43  
44    public BalancedQueueRpcExecutor(final String name, final int handlerCount,
45        final int maxQueueLength, final PriorityFunction priority, final Configuration conf,
46        final Abortable abortable) {
47      this(name, handlerCount, conf.get(CALL_QUEUE_TYPE_CONF_KEY, CALL_QUEUE_TYPE_CONF_DEFAULT),
48          maxQueueLength, priority, conf, abortable);
49    }
50  
51    public BalancedQueueRpcExecutor(final String name, final int handlerCount,
52        final String callQueueType, final int maxQueueLength, final PriorityFunction priority,
53        final Configuration conf, final Abortable abortable) {
54      super(name, handlerCount, callQueueType, maxQueueLength, priority, conf, abortable);
55      this.balancer = getBalancer(this.numCallQueues);
56      initializeQueues(this.numCallQueues);
57    }
58  
59    @Deprecated
60    public BalancedQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
61        final int maxQueueLength) {
62      this(name, handlerCount, numQueues, maxQueueLength, null, null);
63    }
64  
65    @Deprecated
66    public BalancedQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
67        final int maxQueueLength, final Configuration conf, final Abortable abortable) {
68      this(name, handlerCount, numQueues, conf, abortable, LinkedBlockingQueue.class, maxQueueLength);
69    }
70  
71    @Deprecated
72    public BalancedQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
73        final Class<? extends BlockingQueue> queueClass, Object... initargs) {
74      this(name, handlerCount, numQueues, null, null,  queueClass, initargs);
75    }
76  
77    @Deprecated
78    public BalancedQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
79        final Configuration conf, final Abortable abortable,
80        final Class<? extends BlockingQueue> queueClass, Object... initargs) {
81      super(name, Math.max(handlerCount, numQueues), numQueues, conf, abortable);
82      this.balancer = getBalancer(numQueues);
83      initializeQueues(numQueues, queueClass, initargs);
84      LOG.debug(name + " queues=" + numQueues + " handlerCount=" + handlerCount);
85    }
86  
87    @Deprecated
88    protected void initializeQueues(final int numQueues,
89        final Class<? extends BlockingQueue> queueClass, Object... initargs) {
90      if (initargs.length > 0) {
91        currentQueueLimit = (int) initargs[0];
92        initargs[0] = Math.max((int) initargs[0], DEFAULT_CALL_QUEUE_SIZE_HARD_LIMIT);
93      }
94      for (int i = 0; i < numQueues; ++i) {
95        queues.add((BlockingQueue<CallRunner>) ReflectionUtils.newInstance(queueClass, initargs));
96      }
97    }
98  
99    @Override
100   public boolean dispatch(final CallRunner callTask) throws InterruptedException {
101     int queueIndex = balancer.getNextQueue();
102     BlockingQueue<CallRunner> queue = queues.get(queueIndex);
103     // that means we can overflow by at most <num reader> size (5), that's ok
104     if (queue.size() >= currentQueueLimit) {
105       return false;
106     }
107     return queue.offer(callTask);
108   }
109 }