1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.pool2;
18
19 import java.io.Closeable;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.NoSuchElementException;
24
25 /**
26 * A "keyed" pooling interface.
27 * <p>
28 * A keyed pool maintains a pool of instances for each key value.
29 * </p>
30 * <p>
31 * Example of use:
32 * </p>
33 * <pre style="border:solid thin; padding: 1ex;"
34 * > Object obj = <code style="color:#00C">null</code>;
35 * Object key = <code style="color:#C00">"Key"</code>;
36 *
37 * <code style="color:#00C">try</code> {
38 * obj = pool.borrowObject(key);
39 * <code style="color:#0C0">//...use the object...</code>
40 * } <code style="color:#00C">catch</code> (Exception e) {
41 * <code style="color:#0C0">// invalidate the object</code>
42 * pool.invalidateObject(key, obj);
43 * <code style="color:#0C0">// do not return the object to the pool twice</code>
44 * obj = <code style="color:#00C">null</code>;
45 * } <code style="color:#00C">finally</code> {
46 * <code style="color:#0C0">// make sure the object is returned to the pool</code>
47 * <code style="color:#00C">if</code> (<code style="color:#00C">null</code> != obj) {
48 * pool.returnObject(key, obj);
49 * }
50 * }</pre>
51 * <p>
52 * {@link KeyedObjectPool} implementations <em>may</em> choose to store at most
53 * one instance per key value, or may choose to maintain a pool of instances
54 * for each key (essentially creating a {@link java.util.Map Map} of
55 * {@link ObjectPool pools}).
56 * </p>
57 * <p>
58 * See {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool
59 * GenericKeyedObjectPool} for an implementation.
60 * </p>
61 *
62 * @param <K> The type of keys maintained by this pool.
63 * @param <V> Type of element pooled in this pool.
64 *
65 *
66 * @see KeyedPooledObjectFactory
67 * @see ObjectPool
68 * @see org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool
69 * @since 2.0
70 */
71 public interface KeyedObjectPool<K, V> extends Closeable {
72
73 /**
74 * Creates an object using the {@link KeyedPooledObjectFactory factory} or
75 * other implementation dependent mechanism, passivate it, and then place it
76 * in the idle object pool. {@code addObject} is useful for
77 * "pre-loading" a pool with idle objects (Optional operation).
78 *
79 * @param key the key a new instance should be added to
80 * @throws Exception
81 * when {@link KeyedPooledObjectFactory#makeObject} fails.
82 * @throws IllegalStateException
83 * after {@link #close} has been called on this pool.
84 * @throws UnsupportedOperationException
85 * when this pool cannot add new idle objects.
86 */
87 void addObject(K key) throws Exception;
88
89 /**
90 * Calls {@link KeyedObjectPool#addObject(Object)} with each
91 * key in {@code keys} for {@code count} number of times. This has
92 * the same effect as calling {@link #addObjects(Object, int)}
93 * for each key in the {@code keys} collection.
94 *
95 * @param keys
96 * {@link Collection} of keys to add objects for.
97 * @param count
98 * the number of idle objects to add for each {@code key}.
99 * @throws Exception
100 * when {@link KeyedObjectPool#addObject(Object)} fails.
101 * @throws IllegalArgumentException
102 * when {@code keyedPool}, {@code keys}, or any value
103 * in {@code keys} is {@code null}.
104 * @see #addObjects(Object, int)
105 */
106 default void addObjects(final Collection<K> keys, final int count) throws Exception {
107 if (keys == null) {
108 throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEYS);
109 }
110 for (final K key : keys) {
111 addObjects(key, count);
112 }
113 }
114
115 /**
116 * Calls {@link KeyedObjectPool#addObject(Object)}
117 * {@code key} {@code count} number of times.
118 *
119 * @param key
120 * the key to add objects for.
121 * @param count
122 * the number of idle objects to add for {@code key}.
123 * @throws Exception
124 * when {@link KeyedObjectPool#addObject(Object)} fails.
125 * @throws IllegalArgumentException
126 * when {@code key} is {@code null}.
127 * @since 2.8.0
128 */
129 default void addObjects(final K key, final int count) throws Exception {
130 if (key == null) {
131 throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEY);
132 }
133 for (int i = 0; i < count; i++) {
134 addObject(key);
135 }
136 }
137
138 /**
139 * Borrows an instance from this pool for the specified {@code key}.
140 * <p>
141 * Instances returned from this method will have been either newly created
142 * with {@link KeyedPooledObjectFactory#makeObject makeObject} or will be
143 * a previously idle object and have been activated with
144 * {@link KeyedPooledObjectFactory#activateObject activateObject} and then
145 * (optionally) validated with
146 * {@link KeyedPooledObjectFactory#validateObject validateObject}.
147 * </p>
148 * <p>
149 * By contract, clients <strong>must</strong> return the borrowed object
150 * using {@link #returnObject returnObject},
151 * {@link #invalidateObject invalidateObject}, or a related method as
152 * defined in an implementation or sub-interface, using a {@code key}
153 * that is {@link Object#equals equivalent} to the one used to borrow the
154 * instance in the first place.
155 * </p>
156 * <p>
157 * The behavior of this method when the pool has been exhausted is not
158 * strictly specified (although it may be specified by implementations).
159 * </p>
160 *
161 * @param key the key used to obtain the object
162 * @return an instance from this pool.
163 * @throws IllegalStateException
164 * after {@link #close close} has been called on this pool
165 * @throws Exception
166 * when {@link KeyedPooledObjectFactory#makeObject
167 * makeObject} throws an exception
168 * @throws NoSuchElementException
169 * when the pool is exhausted and cannot or will not return
170 * another instance
171 */
172 V borrowObject(K key) throws Exception;
173
174 /**
175 * Clears the pool, removing all pooled instances (optional operation).
176 *
177 * @throws UnsupportedOperationException when this implementation doesn't
178 * support the operation
179 *
180 * @throws Exception if the pool cannot be cleared
181 */
182 void clear() throws Exception;
183
184 /**
185 * Clears the specified pool, removing all pooled instances corresponding to
186 * the given {@code key} (optional operation).
187 *
188 * @param key the key to clear
189 * @throws UnsupportedOperationException when this implementation doesn't
190 * support the operation
191 *
192 * @throws Exception if the key cannot be cleared
193 */
194 void clear(K key) throws Exception;
195
196 /**
197 * Closes this pool, and free any resources associated with it.
198 * <p>
199 * Calling {@link #addObject addObject} or
200 * {@link #borrowObject borrowObject} after invoking this method on a pool
201 * will cause them to throw an {@link IllegalStateException}.
202 * </p>
203 * <p>
204 * Implementations should silently fail if not all resources can be freed.
205 * </p>
206 */
207 @Override
208 void close();
209
210 /**
211 * Gets a copy of the pool key list.
212 * <p>
213 * Note: The default implementation returns an empty list.
214 * Implementations should override this method.
215 * </p>
216 *
217 * @return a copy of the pool key list.
218 * @since 2.12.0
219 */
220 default List<K> getKeys() {
221 return Collections.emptyList();
222 }
223
224 /**
225 * Gets the total number of instances currently borrowed from this pool but
226 * not yet returned. Returns a negative value if this information is not
227 * available.
228 * @return the total number of instances currently borrowed from this pool but
229 * not yet returned.
230 */
231 int getNumActive();
232
233 /**
234 * Gets the number of instances currently borrowed from but not yet
235 * returned to the pool corresponding to the given {@code key}.
236 * Returns a negative value if this information is not available.
237 *
238 * @param key the key to query
239 * @return the number of instances currently borrowed from but not yet
240 * returned to the pool corresponding to the given {@code key}.
241 */
242 int getNumActive(K key);
243
244 /**
245 * Gets the total number of instances currently idle in this pool.
246 * Returns a negative value if this information is not available.
247 * @return the total number of instances currently idle in this pool.
248 */
249 int getNumIdle();
250
251 /**
252 * Gets the number of instances corresponding to the given
253 * {@code key} currently idle in this pool. Returns a negative value if
254 * this information is not available.
255 *
256 * @param key the key to query
257 * @return the number of instances corresponding to the given
258 * {@code key} currently idle in this pool.
259 */
260 int getNumIdle(K key);
261
262 /**
263 * Invalidates an object from the pool.
264 * <p>
265 * By contract, {@code obj} <strong>must</strong> have been obtained
266 * using {@link #borrowObject borrowObject} or a related method as defined
267 * in an implementation or sub-interface using a {@code key} that is
268 * equivalent to the one used to borrow the {@code Object} in the first
269 * place.
270 * </p>
271 * <p>
272 * This method should be used when an object that has been borrowed is
273 * determined (due to an exception or other problem) to be invalid.
274 * </p>
275 *
276 * @param key the key used to obtain the object
277 * @param obj a {@link #borrowObject borrowed} instance to be returned.
278 * @throws Exception if the instance cannot be invalidated
279 */
280 void invalidateObject(K key, V obj) throws Exception;
281
282 /**
283 * Invalidates an object from the pool, using the provided
284 * {@link DestroyMode}.
285 * <p>
286 * By contract, {@code obj} <strong>must</strong> have been obtained
287 * using {@link #borrowObject borrowObject} or a related method as defined
288 * in an implementation or sub-interface using a {@code key} that is
289 * equivalent to the one used to borrow the {@code Object} in the first
290 * place.
291 * </p>
292 * <p>
293 * This method should be used when an object that has been borrowed is
294 * determined (due to an exception or other problem) to be invalid.
295 * </p>
296 *
297 * @param key the key used to obtain the object
298 * @param obj a {@link #borrowObject borrowed} instance to be returned.
299 * @param destroyMode destroy activation context provided to the factory
300 * @throws Exception if the instance cannot be invalidated
301 * @since 2.9.0
302 */
303 default void invalidateObject(final K key, final V obj, final DestroyMode destroyMode) throws Exception {
304 invalidateObject(key, obj);
305 }
306
307 /**
308 * Return an instance to the pool. By contract, {@code obj}
309 * <strong>must</strong> have been obtained using
310 * {@link #borrowObject borrowObject} or a related method as defined in an
311 * implementation or sub-interface using a {@code key} that is
312 * equivalent to the one used to borrow the instance in the first place.
313 *
314 * @param key the key used to obtain the object
315 * @param obj a {@link #borrowObject borrowed} instance to be returned.
316 * @throws IllegalStateException
317 * if an attempt is made to return an object to the pool that
318 * is in any state other than allocated (i.e. borrowed).
319 * Attempting to return an object more than once or attempting
320 * to return an object that was never borrowed from the pool
321 * will trigger this exception.
322 *
323 * @throws Exception if an instance cannot be returned to the pool
324 */
325 void returnObject(K key, V obj) throws Exception;
326 }