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 }