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  
19  package org.apache.hadoop.hbase.ipc;
20  
21  import java.lang.reflect.Constructor;
22  import java.lang.reflect.InvocationTargetException;
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import javax.net.SocketFactory;
27  
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.hbase.HConstants;
30  
31  /**
32   * Cache a client using its socket factory as the hash key.
33   * Enables reuse/sharing of clients on a per SocketFactory basis. A client 
34   * establishes certain configuration dependent characteristics like timeouts, 
35   * tcp-keepalive (true or false), etc. For more details on the characteristics,
36   * look at {@link HBaseClient#HBaseClient(Configuration, SocketFactory)}
37   * Creation of dynamic proxies to protocols creates the clients (and increments
38   * reference count once created), and stopping of the proxies leads to clearing
39   * out references and when the reference drops to zero, the cache mapping is 
40   * cleared. 
41   */
42  class ClientCache {
43    private Map<SocketFactory, HBaseClient> clients =
44      new HashMap<SocketFactory, HBaseClient>();
45  
46    protected ClientCache() {}
47  
48    /**
49     * Construct & cache an IPC client with the user-provided SocketFactory
50     * if no cached client exists.
51     *
52     * @param conf Configuration
53     * @param factory socket factory
54     * @return an IPC client
55     */
56    @SuppressWarnings("unchecked")
57    protected synchronized HBaseClient getClient(Configuration conf, SocketFactory factory) {
58  
59      HBaseClient client = clients.get(factory);
60      if (client == null) {
61        Class<? extends HBaseClient> hbaseClientClass = (Class<? extends HBaseClient>) conf
62            .getClass(HConstants.HBASECLIENT_IMPL, HBaseClient.class);
63  
64        // Make an hbase client instead of hadoop Client.
65        try {
66          Constructor<? extends HBaseClient> cst = hbaseClientClass.getConstructor(
67              Configuration.class, SocketFactory.class);
68          client = cst.newInstance(conf, factory);
69        } catch (InvocationTargetException e) {
70          throw new RuntimeException(e);
71        } catch (InstantiationException e) {
72          throw new RuntimeException(e);
73        } catch (IllegalAccessException e) {
74          throw new RuntimeException(e);
75        } catch (NoSuchMethodException e) {
76          throw new RuntimeException("No matching constructor in "+hbaseClientClass.getName(), e);
77        }
78  
79        clients.put(factory, client);
80      } else {
81        client.incCount();
82      }
83      return client;
84    }
85  
86    /**
87     * Stop a RPC client connection
88     * A RPC client is closed only when its reference count becomes zero.
89     * @param client client to stop
90     */
91    protected void stopClient(HBaseClient client) {
92      synchronized (this) {
93        client.decCount();
94        if (client.isZeroReference()) {
95          clients.remove(client.getSocketFactory());
96        }
97      }
98      if (client.isZeroReference()) {
99        client.stop();
100     }
101   }
102 }