View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.client;
20  
21  import java.io.IOException;
22  import java.util.concurrent.ExecutorService;
23  import org.apache.commons.logging.Log;
24  import org.apache.hadoop.classification.InterfaceAudience;
25  import org.apache.hadoop.classification.InterfaceStability;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.ZooKeeperConnectionException;
28  import org.apache.hadoop.hbase.security.User;
29  
30  /**
31   * A non-instantiable class that manages creation of {@link HConnection}s.
32   * <p>The simplest way to use this class is by using {@link #createConnection(Configuration)}.
33   * This creates a new {@link HConnection} to the cluster that is managed by the caller.
34   * From this {@link HConnection} {@link HTableInterface} implementations are retrieved
35   * with {@link HConnection#getTable(byte[])}. Example:
36   * <pre>
37   * {@code
38   * HConnection connection = HConnectionManager.createConnection(config);
39   * HTableInterface table = connection.getTable("table1");
40   * try {
41   *   // Use the table as needed, for a single operation and a single thread
42   * } finally {
43   *   table.close();
44   *   connection.close();
45   * }
46   * }</pre>
47   * <p>This class has a static Map of {@link HConnection} instances keyed by
48   * {@link HConnectionKey}; A {@link HConnectionKey} is identified by a set of
49   * {@link Configuration} properties. Invocations of {@link #getConnection(Configuration)}
50   * that pass the same {@link Configuration} instance will return the same
51   * {@link  HConnection} instance ONLY WHEN the set of properties are the same
52   * (i.e. if you change properties in your {@link Configuration} instance, such as RPC timeout,
53   * the codec used, HBase will create a new {@link HConnection} instance. For more details on
54   * how this is done see {@link HConnectionKey}).
55   * <p>Sharing {@link HConnection} instances is usually what you want; all clients
56   * of the {@link HConnection} instances share the HConnections' cache of Region
57   * locations rather than each having to discover for itself the location of meta, etc.
58   * But sharing connections makes clean up of {@link HConnection} instances a little awkward.
59   * Currently, clients cleanup by calling {@link #deleteConnection(Configuration)}. This will
60   * shutdown the zookeeper connection the HConnection was using and clean up all
61   * HConnection resources as well as stopping proxies to servers out on the
62   * cluster. Not running the cleanup will not end the world; it'll
63   * just stall the closeup some and spew some zookeeper connection failed
64   * messages into the log.  Running the cleanup on a {@link HConnection} that is
65   * subsequently used by another will cause breakage so be careful running
66   * cleanup.
67   * <p>To create a {@link HConnection} that is not shared by others, you can
68   * set property "hbase.client.instance.id" to a unique value for your {@link Configuration}
69   * instance, like the following:
70   * <pre>
71   * {@code
72   * conf.set("hbase.client.instance.id", "12345");
73   * HConnection connection = HConnectionManager.getConnection(conf);
74   * // Use the connection to your hearts' delight and then when done...
75   * conf.set("hbase.client.instance.id", "12345");
76   * HConnectionManager.deleteConnection(conf, true);
77   * }
78   * </pre>
79   * <p>Cleanup used to be done inside in a shutdown hook.  On startup we'd
80   * register a shutdown hook that called {@link #deleteAllConnections()}
81   * on its way out but the order in which shutdown hooks run is not defined so
82   * were problematic for clients of HConnection that wanted to register their
83   * own shutdown hooks so we removed ours though this shifts the onus for
84   * cleanup to the client.
85   */
86  @SuppressWarnings("serial")
87  @InterfaceAudience.Public
88  @InterfaceStability.Evolving
89  public class HConnectionManager {
90  
91    @Deprecated
92    public static final String RETRIES_BY_SERVER_KEY =
93        ConnectionManager.RETRIES_BY_SERVER_KEY;
94  
95    @Deprecated
96    public static final int MAX_CACHED_CONNECTION_INSTANCES =
97        ConnectionManager.MAX_CACHED_CONNECTION_INSTANCES;
98  
99    /*
100    * Non-instantiable.
101    */
102   private HConnectionManager() {
103     super();
104   }
105 
106   /**
107    * Get the connection that goes with the passed <code>conf</code> configuration instance.
108    * If no current connection exists, method creates a new connection and keys it using
109    * connection-specific properties from the passed {@link Configuration}; see
110    * {@link HConnectionKey}.
111    * @param conf configuration
112    * @return HConnection object for <code>conf</code>
113    * @throws ZooKeeperConnectionException
114    */
115   public static HConnection getConnection(final Configuration conf) throws IOException {
116     return ConnectionManager.getConnectionInternal(conf);
117   }
118 
119   /**
120    * Create a new HConnection instance using the passed <code>conf</code> instance.
121    * <p>Note: This bypasses the usual HConnection life cycle management done by
122    * {@link #getConnection(Configuration)}. The caller is responsible for
123    * calling {@link HConnection#close()} on the returned connection instance.
124    *
125    * This is the recommended way to create HConnections.
126    * {@code
127    * HConnection connection = HConnectionManager.createConnection(conf);
128    * HTableInterface table = connection.getTable("mytable");
129    * table.get(...);
130    * ...
131    * table.close();
132    * connection.close();
133    * }
134    *
135    * @param conf configuration
136    * @return HConnection object for <code>conf</code>
137    * @throws ZooKeeperConnectionException
138    */
139   public static HConnection createConnection(Configuration conf) throws IOException {
140     return ConnectionManager.createConnectionInternal(conf);
141   }
142 
143 
144   /**
145    * Create a new HConnection instance using the passed <code>conf</code> instance.
146    * <p>Note: This bypasses the usual HConnection life cycle management done by
147    * {@link #getConnection(Configuration)}. The caller is responsible for
148    * calling {@link HConnection#close()} on the returned connection instance.
149    * This is the recommended way to create HConnections.
150    * {@code
151    * ExecutorService pool = ...;
152    * HConnection connection = HConnectionManager.createConnection(conf, pool);
153    * HTableInterface table = connection.getTable("mytable");
154    * table.get(...);
155    * ...
156    * table.close();
157    * connection.close();
158    * }
159    * @param conf configuration
160    * @param pool the thread pool to use for batch operation in HTables used via this HConnection
161    * @return HConnection object for <code>conf</code>
162    * @throws ZooKeeperConnectionException
163    */
164   public static HConnection createConnection(Configuration conf, ExecutorService pool)
165       throws IOException {
166     return ConnectionManager.createConnection(conf, pool);
167   }
168 
169   /**
170    * Create a new HConnection instance using the passed <code>conf</code> instance.
171    * <p>Note: This bypasses the usual HConnection life cycle management done by
172    * {@link #getConnection(Configuration)}. The caller is responsible for
173    * calling {@link HConnection#close()} on the returned connection instance.
174    * This is the recommended way to create HConnections.
175    * {@code
176    * ExecutorService pool = ...;
177    * HConnection connection = HConnectionManager.createConnection(conf, pool);
178    * HTableInterface table = connection.getTable("mytable");
179    * table.get(...);
180    * ...
181    * table.close();
182    * connection.close();
183    * }
184    * @param conf configuration
185    * @param user the user the connection is for
186    * @return HConnection object for <code>conf</code>
187    * @throws ZooKeeperConnectionException
188    */
189   public static HConnection createConnection(Configuration conf, User user)
190   throws IOException {
191     return ConnectionManager.createConnection(conf, user);
192   }
193 
194   /**
195    * Create a new HConnection instance using the passed <code>conf</code> instance.
196    * <p>Note: This bypasses the usual HConnection life cycle management done by
197    * {@link #getConnection(Configuration)}. The caller is responsible for
198    * calling {@link HConnection#close()} on the returned connection instance.
199    * This is the recommended way to create HConnections.
200    * {@code
201    * ExecutorService pool = ...;
202    * HConnection connection = HConnectionManager.createConnection(conf, pool);
203    * HTableInterface table = connection.getTable("mytable");
204    * table.get(...);
205    * ...
206    * table.close();
207    * connection.close();
208    * }
209    * @param conf configuration
210    * @param pool the thread pool to use for batch operation in HTables used via this HConnection
211    * @param user the user the connection is for
212    * @return HConnection object for <code>conf</code>
213    * @throws ZooKeeperConnectionException
214    */
215   public static HConnection createConnection(Configuration conf, ExecutorService pool, User user)
216   throws IOException {
217     return ConnectionManager.createConnection(conf, pool, user);
218   }
219 
220   @Deprecated
221   static HConnection createConnection(final Configuration conf, final boolean managed)
222       throws IOException {
223     return ConnectionManager.createConnection(conf, managed);
224   }
225 
226   @Deprecated
227   static ClusterConnection createConnection(final Configuration conf, final boolean managed,
228       final ExecutorService pool, final User user) throws IOException {
229     return ConnectionManager.createConnection(conf, managed, pool, user);
230   }
231 
232   /**
233    * Delete connection information for the instance specified by passed configuration.
234    * If there are no more references to the designated connection connection, this method will
235    * then close connection to the zookeeper ensemble and let go of all associated resources.
236    *
237    * @param conf configuration whose identity is used to find {@link HConnection} instance.
238    * @deprecated
239    */
240   @Deprecated
241   public static void deleteConnection(Configuration conf) {
242     ConnectionManager.deleteConnection(conf);
243   }
244 
245   /**
246    * Cleanup a known stale connection.
247    * This will then close connection to the zookeeper ensemble and let go of all resources.
248    *
249    * @param connection
250    * @deprecated
251    */
252   @Deprecated
253   public static void deleteStaleConnection(HConnection connection) {
254     ConnectionManager.deleteStaleConnection(connection);
255   }
256 
257   /**
258    * Delete information for all connections. Close or not the connection, depending on the
259    *  staleConnection boolean and the ref count. By default, you should use it with
260    *  staleConnection to true.
261    * @deprecated
262    */
263   @Deprecated
264   public static void deleteAllConnections(boolean staleConnection) {
265     ConnectionManager.deleteAllConnections(staleConnection);
266   }
267 
268   /**
269    * Delete information for all connections..
270    * @deprecated kept for backward compatibility, but the behavior is broken. HBASE-8983
271    */
272   @Deprecated
273   public static void deleteAllConnections() {
274     ConnectionManager.deleteAllConnections();
275   }
276 
277   /**
278    * This convenience method invokes the given {@link HConnectable#connect}
279    * implementation using a {@link HConnection} instance that lasts just for the
280    * duration of the invocation.
281    *
282    * @param <T> the return type of the connect method
283    * @param connectable the {@link HConnectable} instance
284    * @return the value returned by the connect method
285    * @throws IOException
286    * @deprecated Internal method, do not use thru HConnectionManager.
287    */
288   @InterfaceAudience.Private
289   @Deprecated
290   public static <T> T execute(HConnectable<T> connectable) throws IOException {
291     return ConnectionManager.execute(connectable);
292   }
293 
294   /**
295    * Set the number of retries to use serverside when trying to communicate
296    * with another server over {@link HConnection}.  Used updating catalog
297    * tables, etc.  Call this method before we create any Connections.
298    * @param c The Configuration instance to set the retries into.
299    * @param log Used to log what we set in here.
300    * @deprecated Internal method, do not use.
301    */
302   @InterfaceAudience.Private
303   @Deprecated
304   public static void setServerSideHConnectionRetries(
305       final Configuration c, final String sn, final Log log) {
306     ConnectionUtils.setServerSideHConnectionRetriesConfig(c, sn, log);
307   }
308 }