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>The following logic and API will be removed in the future:
48   * <p>This class has a static Map of {@link HConnection} instances keyed by
49   * {@link Configuration}; all invocations of {@link #getConnection(Configuration)}
50   * that pass the same {@link Configuration} instance will be returned the same
51   * {@link  HConnection} instance (Adding properties to a Configuration
52   * instance does not change its object identity; for more on how this is done see
53   * {@link HConnectionKey}).  Sharing {@link HConnection}
54   * instances is usually what you want; all clients of the {@link HConnection}
55   * instances share the HConnections' cache of Region locations rather than each
56   * having to discover for itself the location of meta, etc.  It makes
57   * sense for the likes of the pool of HTables class {@link HTablePool}, for
58   * instance (If concerned that a single {@link HConnection} is insufficient
59   * for sharing amongst clients in say an heavily-multithreaded environment,
60   * in practise its not proven to be an issue.  Besides, {@link HConnection} is
61   * implemented atop Hadoop RPC and as of this writing, Hadoop RPC does a
62   * connection per cluster-member, exclusively).
63   *
64   * <p>But sharing connections makes clean up of {@link HConnection} instances a little awkward.
65   * Currently, clients cleanup by calling {@link #deleteConnection(Configuration)}. This will
66   * shutdown the zookeeper connection the HConnection was using and clean up all
67   * HConnection resources as well as stopping proxies to servers out on the
68   * cluster. Not running the cleanup will not end the world; it'll
69   * just stall the closeup some and spew some zookeeper connection failed
70   * messages into the log.  Running the cleanup on a {@link HConnection} that is
71   * subsequently used by another will cause breakage so be careful running
72   * cleanup.
73   * <p>To create a {@link HConnection} that is not shared by others, you can
74   * create a new {@link Configuration} instance, pass this new instance to
75   * {@link #getConnection(Configuration)}, and then when done, close it up by
76   * doing something like the following:
77   * <pre>
78   * {@code
79   * Configuration newConfig = new Configuration(originalConf);
80   * HConnection connection = HConnectionManager.getConnection(newConfig);
81   * // Use the connection to your hearts' delight and then when done...
82   * HConnectionManager.deleteConnection(newConfig, true);
83   * }
84   * </pre>
85   * <p>Cleanup used to be done inside in a shutdown hook.  On startup we'd
86   * register a shutdown hook that called {@link #deleteAllConnections()}
87   * on its way out but the order in which shutdown hooks run is not defined so
88   * were problematic for clients of HConnection that wanted to register their
89   * own shutdown hooks so we removed ours though this shifts the onus for
90   * cleanup to the client.
91   */
92  @SuppressWarnings("serial")
93  @InterfaceAudience.Public
94  @InterfaceStability.Evolving
95  public class HConnectionManager {
96  
97    @Deprecated
98    public static final String RETRIES_BY_SERVER_KEY =
99        ConnectionManager.RETRIES_BY_SERVER_KEY;
100 
101   @Deprecated
102   public static final int MAX_CACHED_CONNECTION_INSTANCES =
103       ConnectionManager.MAX_CACHED_CONNECTION_INSTANCES;
104 
105   /*
106    * Non-instantiable.
107    */
108   private HConnectionManager() {
109     super();
110   }
111 
112   /**
113    * Get the connection that goes with the passed <code>conf</code> configuration instance.
114    * If no current connection exists, method creates a new connection and keys it using
115    * connection-specific properties from the passed {@link Configuration}; see
116    * {@link HConnectionKey}.
117    * @param conf configuration
118    * @return HConnection object for <code>conf</code>
119    * @throws ZooKeeperConnectionException
120    */
121   public static HConnection getConnection(final Configuration conf) throws IOException {
122     return ConnectionManager.getConnectionInternal(conf);
123   }
124 
125   /**
126    * Create a new HConnection instance using the passed <code>conf</code> instance.
127    * <p>Note: This bypasses the usual HConnection life cycle management done by
128    * {@link #getConnection(Configuration)}. The caller is responsible for
129    * calling {@link HConnection#close()} on the returned connection instance.
130    *
131    * This is the recommended way to create HConnections.
132    * {@code
133    * HConnection connection = HConnectionManager.createConnection(conf);
134    * HTableInterface table = connection.getTable("mytable");
135    * table.get(...);
136    * ...
137    * table.close();
138    * connection.close();
139    * }
140    *
141    * @param conf configuration
142    * @return HConnection object for <code>conf</code>
143    * @throws ZooKeeperConnectionException
144    */
145   public static HConnection createConnection(Configuration conf) throws IOException {
146     return ConnectionManager.createConnectionInternal(conf);
147   }
148 
149 
150   /**
151    * Create a new HConnection instance using the passed <code>conf</code> instance.
152    * <p>Note: This bypasses the usual HConnection life cycle management done by
153    * {@link #getConnection(Configuration)}. The caller is responsible for
154    * calling {@link HConnection#close()} on the returned connection instance.
155    * This is the recommended way to create HConnections.
156    * {@code
157    * ExecutorService pool = ...;
158    * HConnection connection = HConnectionManager.createConnection(conf, pool);
159    * HTableInterface table = connection.getTable("mytable");
160    * table.get(...);
161    * ...
162    * table.close();
163    * connection.close();
164    * }
165    * @param conf configuration
166    * @param pool the thread pool to use for batch operation in HTables used via this HConnection
167    * @return HConnection object for <code>conf</code>
168    * @throws ZooKeeperConnectionException
169    */
170   public static HConnection createConnection(Configuration conf, ExecutorService pool)
171       throws IOException {
172     return ConnectionManager.createConnection(conf, pool);
173   }
174 
175   /**
176    * Create a new HConnection instance using the passed <code>conf</code> instance.
177    * <p>Note: This bypasses the usual HConnection life cycle management done by
178    * {@link #getConnection(Configuration)}. The caller is responsible for
179    * calling {@link HConnection#close()} on the returned connection instance.
180    * This is the recommended way to create HConnections.
181    * {@code
182    * ExecutorService pool = ...;
183    * HConnection connection = HConnectionManager.createConnection(conf, pool);
184    * HTableInterface table = connection.getTable("mytable");
185    * table.get(...);
186    * ...
187    * table.close();
188    * connection.close();
189    * }
190    * @param conf configuration
191    * @param user the user the connection is for
192    * @return HConnection object for <code>conf</code>
193    * @throws ZooKeeperConnectionException
194    */
195   public static HConnection createConnection(Configuration conf, User user)
196   throws IOException {
197     return ConnectionManager.createConnection(conf, user);
198   }
199 
200   /**
201    * Create a new HConnection instance using the passed <code>conf</code> instance.
202    * <p>Note: This bypasses the usual HConnection life cycle management done by
203    * {@link #getConnection(Configuration)}. The caller is responsible for
204    * calling {@link HConnection#close()} on the returned connection instance.
205    * This is the recommended way to create HConnections.
206    * {@code
207    * ExecutorService pool = ...;
208    * HConnection connection = HConnectionManager.createConnection(conf, pool);
209    * HTableInterface table = connection.getTable("mytable");
210    * table.get(...);
211    * ...
212    * table.close();
213    * connection.close();
214    * }
215    * @param conf configuration
216    * @param pool the thread pool to use for batch operation in HTables used via this HConnection
217    * @param user the user the connection is for
218    * @return HConnection object for <code>conf</code>
219    * @throws ZooKeeperConnectionException
220    */
221   public static HConnection createConnection(Configuration conf, ExecutorService pool, User user)
222   throws IOException {
223     return ConnectionManager.createConnection(conf, pool, user);
224   }
225 
226   @Deprecated
227   static HConnection createConnection(final Configuration conf, final boolean managed)
228       throws IOException {
229     return ConnectionManager.createConnection(conf, managed);
230   }
231 
232   @Deprecated
233   static ClusterConnection createConnection(final Configuration conf, final boolean managed,
234       final ExecutorService pool, final User user) throws IOException {
235     return ConnectionManager.createConnection(conf, managed, pool, user);
236   }
237 
238   /**
239    * Delete connection information for the instance specified by passed configuration.
240    * If there are no more references to the designated connection connection, this method will
241    * then close connection to the zookeeper ensemble and let go of all associated resources.
242    *
243    * @param conf configuration whose identity is used to find {@link HConnection} instance.
244    * @deprecated
245    */
246   public static void deleteConnection(Configuration conf) {
247     ConnectionManager.deleteConnection(conf);
248   }
249 
250   /**
251    * Cleanup a known stale connection.
252    * This will then close connection to the zookeeper ensemble and let go of all resources.
253    *
254    * @param connection
255    * @deprecated
256    */
257   public static void deleteStaleConnection(HConnection connection) {
258     ConnectionManager.deleteStaleConnection(connection);
259   }
260 
261   /**
262    * Delete information for all connections. Close or not the connection, depending on the
263    *  staleConnection boolean and the ref count. By default, you should use it with
264    *  staleConnection to true.
265    * @deprecated
266    */
267   public static void deleteAllConnections(boolean staleConnection) {
268     ConnectionManager.deleteAllConnections(staleConnection);
269   }
270 
271   /**
272    * Delete information for all connections..
273    * @deprecated kept for backward compatibility, but the behavior is broken. HBASE-8983
274    */
275   @Deprecated
276   public static void deleteAllConnections() {
277     ConnectionManager.deleteAllConnections();
278   }
279 
280   /**
281    * This convenience method invokes the given {@link HConnectable#connect}
282    * implementation using a {@link HConnection} instance that lasts just for the
283    * duration of the invocation.
284    *
285    * @param <T> the return type of the connect method
286    * @param connectable the {@link HConnectable} instance
287    * @return the value returned by the connect method
288    * @throws IOException
289    * @deprecated Internal method, do not use thru HConnectionManager.
290    */
291   @InterfaceAudience.Private
292   @Deprecated
293   public static <T> T execute(HConnectable<T> connectable) throws IOException {
294     return ConnectionManager.execute(connectable);
295   }
296 
297   /**
298    * Set the number of retries to use serverside when trying to communicate
299    * with another server over {@link HConnection}.  Used updating catalog
300    * tables, etc.  Call this method before we create any Connections.
301    * @param c The Configuration instance to set the retries into.
302    * @param log Used to log what we set in here.
303    * @deprecated Internal method, do not use.
304    */
305   @InterfaceAudience.Private
306   @Deprecated
307   public static void setServerSideHConnectionRetries(
308       final Configuration c, final String sn, final Log log) {
309     ConnectionUtils.setServerSideHConnectionRetriesConfig(c, sn, log);
310   }
311 }