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.ArrayList;
21  import java.util.List;
22  import java.util.Random;
23  import java.util.concurrent.BlockingQueue;
24  import java.util.concurrent.LinkedBlockingQueue;
25  
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  import org.apache.hadoop.hbase.classification.InterfaceStability;
28  import org.apache.hadoop.hbase.HBaseInterfaceAudience;
29  import org.apache.hadoop.hbase.util.ReflectionUtils;
30  
31  /**
32   * An {@link RpcExecutor} that will balance requests evenly across all its queues, but still remains
33   * efficient with a single queue via an inlinable queue balancing mechanism.
34   */
35  @InterfaceAudience.LimitedPrivate({ HBaseInterfaceAudience.COPROC, HBaseInterfaceAudience.PHOENIX })
36  @InterfaceStability.Evolving
37  public class BalancedQueueRpcExecutor extends RpcExecutor {
38  
39    protected final List<BlockingQueue<CallRunner>> queues;
40    private final QueueBalancer balancer;
41  
42    public BalancedQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
43        final int maxQueueLength) {
44      this(name, handlerCount, numQueues, LinkedBlockingQueue.class, maxQueueLength);
45    }
46  
47    public BalancedQueueRpcExecutor(final String name, final int handlerCount, final int numQueues,
48        final Class<? extends BlockingQueue> queueClass, Object... initargs) {
49      super(name, Math.max(handlerCount, numQueues));
50      queues = new ArrayList<BlockingQueue<CallRunner>>(numQueues);
51      this.balancer = getBalancer(numQueues);
52      initializeQueues(numQueues, queueClass, initargs);
53    }
54  
55    protected void initializeQueues(final int numQueues,
56        final Class<? extends BlockingQueue> queueClass, Object... initargs) {
57      for (int i = 0; i < numQueues; ++i) {
58        queues.add((BlockingQueue<CallRunner>) ReflectionUtils.newInstance(queueClass, initargs));
59      }
60    }
61  
62    @Override
63    public void dispatch(final CallRunner callTask) throws InterruptedException {
64      int queueIndex = balancer.getNextQueue();
65      queues.get(queueIndex).put(callTask);
66    }
67  
68    @Override
69    public int getQueueLength() {
70      int length = 0;
71      for (final BlockingQueue<CallRunner> queue : queues) {
72        length += queue.size();
73      }
74      return length;
75    }
76  
77    @Override
78    public List<BlockingQueue<CallRunner>> getQueues() {
79      return queues;
80    }
81  }