From d01a8a04e3d3d128093cd67358e5ecec2ea79483 Mon Sep 17 00:00:00 2001
From: lidongy <1879087903@qq.com>
Date: Fri, 24 Jun 2022 10:34:53 +0800
Subject: [PATCH 1/2] =?UTF-8?q?REPORT-73902=20update:=20jedis=E5=8D=87?=
=?UTF-8?q?=E7=BA=A7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
fine-jedis/README.md | 3 +
.../pool2/BaseKeyedPooledObjectFactory.java | 14 +-
.../apache/commons/pool2/BaseObjectPool.java | 10 +-
.../pool2/BasePooledObjectFactory.java | 2 +-
.../org/apache/commons/pool2/DestroyMode.java | 30 +
.../apache/commons/pool2/KeyedObjectPool.java | 273 +-
.../pool2/KeyedPooledObjectFactory.java | 43 +-
.../org/apache/commons/pool2/ObjectPool.java | 166 +-
.../org/apache/commons/pool2/PoolUtils.java | 188 +-
.../apache/commons/pool2/PooledObject.java | 61 +-
.../commons/pool2/PooledObjectFactory.java | 45 +-
.../commons/pool2/PooledObjectState.java | 1 +
.../commons/pool2/impl/AbandonedConfig.java | 16 +-
.../pool2/impl/BaseGenericObjectPool.java | 397 +-
.../pool2/impl/BaseObjectPoolConfig.java | 46 +-
.../commons/pool2/impl/CallStackUtils.java | 14 +-
.../pool2/impl/DefaultEvictionPolicy.java | 2 +
.../pool2/impl/DefaultPooledObject.java | 23 +-
.../pool2/impl/DefaultPooledObjectInfo.java | 6 +-
.../impl/DefaultPooledObjectInfoMBean.java | 10 +-
.../commons/pool2/impl/EvictionConfig.java | 1 +
.../commons/pool2/impl/EvictionPolicy.java | 7 +-
.../commons/pool2/impl/EvictionTimer.java | 175 +-
.../pool2/impl/GenericKeyedObjectPool.java | 277 +-
.../impl/GenericKeyedObjectPoolConfig.java | 9 +-
.../impl/GenericKeyedObjectPoolMXBean.java | 35 +
.../commons/pool2/impl/GenericObjectPool.java | 260 +-
.../pool2/impl/GenericObjectPoolConfig.java | 9 +-
.../pool2/impl/GenericObjectPoolMXBean.java | 40 +-
.../impl/InterruptibleReentrantLock.java | 1 +
.../pool2/impl/LinkedBlockingDeque.java | 63 +-
.../commons/pool2/impl/NoOpCallStack.java | 8 +-
.../commons/pool2/impl/PoolImplUtils.java | 122 +-
.../pool2/impl/SecurityManagerCallStack.java | 9 +-
.../pool2/impl/SoftReferenceObjectPool.java | 63 +-
.../apache/commons/pool2/impl/package.html | 1 -
.../commons/pool2/proxy/CglibProxySource.java | 2 +-
.../commons/pool2/proxy/JdkProxySource.java | 2 +-
.../pool2/proxy/ProxiedKeyedObjectPool.java | 6 +-
.../apache/commons/pool2/proxy/package.html | 2 +-
.../clients/jedis/AccessControlLogEntry.java | 100 +
.../clients/jedis/AccessControlUser.java | 53 +
.../redis/clients/jedis/BinaryClient.java | 1113 +++-
.../redis/clients/jedis/BinaryJedis.java | 1715 +++++-
.../clients/jedis/BinaryJedisCluster.java | 1337 ++++-
.../clients/jedis/BinaryJedisPubSub.java | 31 +-
.../clients/jedis/BinaryShardedJedis.java | 477 +-
.../redis/clients/jedis/BitPosParams.java | 2 +-
.../redis/clients/jedis/BuilderFactory.java | 794 ++-
.../fr/third/redis/clients/jedis/Client.java | 624 ++-
.../third/redis/clients/jedis/Connection.java | 174 +-
.../redis/clients/jedis/DebugParams.java | 4 +-
.../jedis/DefaultJedisClientConfig.java | 210 +
.../jedis/DefaultJedisSocketFactory.java | 228 +
.../redis/clients/jedis/GeoCoordinate.java | 3 +-
.../clients/jedis/GeoRadiusResponse.java | 9 +
.../redis/clients/jedis/HostAndPort.java | 57 +-
.../clients/jedis/HostAndPortMapper.java | 6 +
.../fr/third/redis/clients/jedis/Jedis.java | 1494 ++++-
.../clients/jedis/JedisClientConfig.java | 76 +
.../redis/clients/jedis/JedisCluster.java | 4935 ++++++++++-------
.../clients/jedis/JedisClusterCommand.java | 201 +-
.../jedis/JedisClusterConnectionHandler.java | 124 +-
.../jedis/JedisClusterHostAndPortMap.java | 15 +
.../clients/jedis/JedisClusterInfoCache.java | 194 +-
.../redis/clients/jedis/JedisFactory.java | 209 +-
.../third/redis/clients/jedis/JedisPool.java | 269 +-
.../clients/jedis/JedisPoolAbstract.java | 24 +-
.../redis/clients/jedis/JedisPoolConfig.java | 2 +-
.../redis/clients/jedis/JedisPubSub.java | 328 +-
.../clients/jedis/JedisSentinelPool.java | 270 +-
.../redis/clients/jedis/JedisShardInfo.java | 32 +-
.../JedisSlotBasedConnectionHandler.java | 87 +-
.../clients/jedis/JedisSocketFactory.java | 55 +
.../fr/third/redis/clients/jedis/Module.java | 10 +-
.../clients/jedis/MultiKeyPipelineBase.java | 369 +-
.../third/redis/clients/jedis/Pipeline.java | 8 +-
.../redis/clients/jedis/PipelineBase.java | 866 ++-
.../third/redis/clients/jedis/Protocol.java | 120 +-
.../fr/third/redis/clients/jedis/Queable.java | 4 +-
.../third/redis/clients/jedis/ScanParams.java | 14 +-
.../third/redis/clients/jedis/ScanResult.java | 1 -
.../redis/clients/jedis/ShardedJedis.java | 453 +-
.../clients/jedis/ShardedJedisPipeline.java | 17 +-
.../redis/clients/jedis/ShardedJedisPool.java | 51 +-
.../redis/clients/jedis/SortingParams.java | 20 +-
.../clients/jedis/StreamConsumersInfo.java | 52 +
.../redis/clients/jedis/StreamEntry.java | 41 +
.../redis/clients/jedis/StreamEntryID.java | 120 +
.../redis/clients/jedis/StreamGroupInfo.java | 60 +
.../third/redis/clients/jedis/StreamInfo.java | 82 +
.../clients/jedis/StreamPendingEntry.java | 59 +
.../clients/jedis/StreamPendingSummary.java | 38 +
.../redis/clients/jedis/Transaction.java | 32 +-
.../fr/third/redis/clients/jedis/Tuple.java | 14 +-
.../fr/third/redis/clients/jedis/ZParams.java | 15 +-
.../redis/clients/jedis/args/FlushMode.java | 30 +
.../clients/jedis/args/ListDirection.java | 21 +
.../redis/clients/jedis/args/Rawable.java | 6 +
.../redis/clients/jedis/args/UnblockType.java | 21 +
.../clients/jedis/args/package-info.java | 4 +
.../commands/AdvancedBinaryJedisCommands.java | 74 +-
.../jedis/commands/AdvancedJedisCommands.java | 70 +
.../clients/jedis/commands/BasicCommands.java | 117 +-
.../jedis/commands/BasicRedisPipeline.java | 7 +
.../commands/BinaryJedisClusterCommands.java | 159 +-
.../jedis/commands/BinaryJedisCommands.java | 200 +-
.../jedis/commands/BinaryRedisPipeline.java | 212 +-
.../commands/BinaryScriptingCommands.java | 4 +
.../clients/jedis/commands/Commands.java | 268 +-
.../JedisClusterBinaryScriptingCommands.java | 40 +-
.../jedis/commands/JedisClusterCommands.java | 365 +-
.../JedisClusterScriptingCommands.java | 35 +-
.../clients/jedis/commands/JedisCommands.java | 390 +-
.../jedis/commands/ModuleCommands.java | 3 +
.../commands/MultiKeyBinaryCommands.java | 65 +
.../MultiKeyBinaryJedisClusterCommands.java | 63 +
.../commands/MultiKeyBinaryRedisPipeline.java | 63 +
.../jedis/commands/MultiKeyCommands.java | 168 +-
.../commands/MultiKeyCommandsPipeline.java | 74 +
.../MultiKeyJedisClusterCommands.java | 83 +
.../jedis/commands/ProtocolCommand.java | 5 +-
.../clients/jedis/commands/RedisPipeline.java | 225 +-
.../JedisAccessControlException.java | 16 +
.../jedis/exceptions/JedisBusyException.java | 20 +-
.../JedisNoReachableClusterNodeException.java | 3 +
.../exceptions/JedisNoScriptException.java | 14 +-
.../exceptions/JedisRedirectionException.java | 4 +-
.../jedis/params/ClientKillParams.java | 76 +
.../clients/jedis/params/GeoAddParams.java | 69 +
.../clients/jedis/params/GeoRadiusParam.java | 21 +-
.../jedis/params/GeoRadiusStoreParam.java | 112 +
.../clients/jedis/params/GetExParams.java | 96 +
.../clients/jedis/params/LPosParams.java | 45 +
.../clients/jedis/params/MigrateParams.java | 64 +
.../redis/clients/jedis/params/Params.java | 40 +-
.../clients/jedis/params/RestoreParams.java | 72 +
.../redis/clients/jedis/params/SetParams.java | 80 +-
.../clients/jedis/params/XAddParams.java | 113 +
.../clients/jedis/params/XClaimParams.java | 56 +
.../clients/jedis/params/XPendingParams.java | 83 +
.../jedis/params/XReadGroupParams.java | 31 +
.../clients/jedis/params/XReadParams.java | 25 +
.../clients/jedis/params/XTrimParams.java | 90 +
.../clients/jedis/params/ZAddParams.java | 33 +-
.../clients/jedis/params/ZIncrByParams.java | 8 +-
.../clients/jedis/resps/KeyedListElement.java | 48 +
.../clients/jedis/resps/KeyedZSetElement.java | 46 +
.../clients/jedis/resps/package-info.java | 4 +
.../jedis/util/ByteArrayComparator.java | 10 +-
.../redis/clients/jedis/util/Hashing.java | 5 +-
.../clients/jedis/util/JedisByteHashMap.java | 21 +-
.../clients/jedis/util/JedisClusterCRC16.java | 67 +-
.../clients/jedis/util/JedisURIHelper.java | 16 +-
.../clients/jedis/util/KeyMergeUtil.java | 4 +-
.../third/redis/clients/jedis/util/Pool.java | 40 +-
.../clients/jedis/util/RedisInputStream.java | 5 +-
.../clients/jedis/util/RedisOutputStream.java | 26 +-
.../redis/clients/jedis/util/SafeEncoder.java | 31 +-
.../redis/clients/jedis/util/Sharded.java | 9 +-
.../redis/clients/jedis/util/Slowlog.java | 24 +-
161 files changed, 19214 insertions(+), 5225 deletions(-)
create mode 100644 fine-jedis/README.md
create mode 100644 fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/DestroyMode.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/AccessControlLogEntry.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/AccessControlUser.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/DefaultJedisClientConfig.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/DefaultJedisSocketFactory.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/HostAndPortMapper.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/JedisClientConfig.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/JedisClusterHostAndPortMap.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/JedisSocketFactory.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/StreamConsumersInfo.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/StreamEntry.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/StreamEntryID.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/StreamGroupInfo.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/StreamInfo.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/StreamPendingEntry.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/StreamPendingSummary.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/args/FlushMode.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/args/ListDirection.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/args/Rawable.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/args/UnblockType.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/args/package-info.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/exceptions/JedisAccessControlException.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/ClientKillParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/GeoAddParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/GeoRadiusStoreParam.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/GetExParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/LPosParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/MigrateParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/RestoreParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/XAddParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/XClaimParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/XPendingParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/XReadGroupParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/XReadParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/params/XTrimParams.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/resps/KeyedListElement.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/resps/KeyedZSetElement.java
create mode 100644 fine-jedis/src/main/java/com/fr/third/redis/clients/jedis/resps/package-info.java
diff --git a/fine-jedis/README.md b/fine-jedis/README.md
new file mode 100644
index 000000000..6d3107627
--- /dev/null
+++ b/fine-jedis/README.md
@@ -0,0 +1,3 @@
+# fine-jedis
+
+版本为3.6.0,内置的apache-commons-pool版本为2.9.0
\ No newline at end of file
diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BaseKeyedPooledObjectFactory.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BaseKeyedPooledObjectFactory.java
index bfb90e1ab..9a6982897 100644
--- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BaseKeyedPooledObjectFactory.java
+++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BaseKeyedPooledObjectFactory.java
@@ -17,11 +17,13 @@
package com.fr.third.org.apache.commons.pool2;
/**
- * A base implementation of KeyedPooledObjectFactory
.
+ * A base implementation of {@code KeyedPooledObjectFactory}.
*
* All operations defined here are essentially no-op's. *
+ ** This class is immutable, and therefore thread-safe. + *
* * @see KeyedPooledObjectFactory * @@ -30,8 +32,8 @@ package com.fr.third.org.apache.commons.pool2; * * @since 2.0 */ -public abstract class BaseKeyedPooledObjectFactory* The default implementation is a no-op. + *
* * @param key the key used when selecting the instance * @param p a {@code PooledObject} wrapping the instance to be destroyed @@ -78,10 +81,11 @@ public abstract class BaseKeyedPooledObjectFactory* The default implementation always returns {@code true}. + *
* * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be validated - * @return alwaystrue
in the default implementation
+ * @return always {@code true} in the default implementation
*/
@Override
public boolean validateObject(final K key, final PooledObject* The default implementation is a no-op. + *
* * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be activated @@ -106,6 +111,7 @@ public abstract class BaseKeyedPooledObjectFactory* The default implementation is a no-op. + *
* * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be passivated diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BaseObjectPool.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BaseObjectPool.java index 47b567f58..f3cfe6a77 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BaseObjectPool.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BaseObjectPool.java @@ -22,6 +22,7 @@ package com.fr.third.org.apache.commons.pool2; * indicating it is unsupported or throw {@link UnsupportedOperationException}. ** This class is intended to be thread-safe. + *
* * @param
- * This affects the behavior of isClosed
and
- * assertOpen
.
+ * This affects the behavior of {@code isClosed} and
+ * {@code assertOpen}.
+ *
true
when this pool has been closed.
+ * @return {@code true} when this pool has been closed.
*/
public final boolean isClosed() {
return closed;
}
/**
- * Throws an IllegalStateException
when this pool has been
+ * Throws an {@code IllegalStateException} when this pool has been
* closed.
*
* @throws IllegalStateException when this pool has been closed.
diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BasePooledObjectFactory.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BasePooledObjectFactory.java
index dad5bb0bb..2be3e35fd 100644
--- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BasePooledObjectFactory.java
+++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/BasePooledObjectFactory.java
@@ -17,7 +17,7 @@
package com.fr.third.org.apache.commons.pool2;
/**
- * A base implementation of PoolableObjectFactory
.
+ * A base implementation of {@code PoolableObjectFactory}.
* * All operations defined here are essentially no-op's. *
diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/DestroyMode.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/DestroyMode.java new file mode 100644 index 000000000..30c2a5303 --- /dev/null +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/DestroyMode.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.fr.third.org.apache.commons.pool2; + +/** + * Destroy context provided to object factories via destroyObject methods. Values provide information about why the pool + * is asking for a pooled object to be destroyed. + * + * @since 2.9.0 + */ +public enum DestroyMode { + /** Normal destroy */ + NORMAL, + /** Destroy abandoned object */ + ABANDONED +} diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/KeyedObjectPool.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/KeyedObjectPool.java index c21c1844a..ae2cc698f 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/KeyedObjectPool.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/KeyedObjectPool.java @@ -17,14 +17,18 @@ package com.fr.third.org.apache.commons.pool2; import java.io.Closeable; +import java.util.Collection; +import java.util.Iterator; import java.util.NoSuchElementException; /** * A "keyed" pooling interface. *
* A keyed pool maintains a pool of instances for each key value. + *
** Example of use: + *
*Object obj =null
; * Object key ="Key"
; @@ -48,22 +52,93 @@ import java.util.NoSuchElementException; * one instance per key value, or may choose to maintain a pool of instances * for each key (essentially creating a {@link java.util.Map Map} of * {@link ObjectPool pools}). + * *- * See {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool + * See {@link com.fr.third.org.apache.commons.pool2.impl.GenericKeyedObjectPool * GenericKeyedObjectPool} for an implementation. + *
* * @paramThe type of keys maintained by this pool. * @param Type of element pooled in this pool. * * @see KeyedPooledObjectFactory * @see ObjectPool - * @see org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool + * @see com.fr.third.org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool * * @since 2.0 */ -public interface KeyedObjectPool extends Closeable { +public interface KeyedObjectPool extends Closeable { + + /** + * Create an object using the {@link KeyedPooledObjectFactory factory} or + * other implementation dependent mechanism, passivate it, and then place it + * in the idle object pool. {@code addObject} is useful for + * "pre-loading" a pool with idle objects (Optional operation). + * + * @param key the key a new instance should be added to + * + * @throws Exception + * when {@link KeyedPooledObjectFactory#makeObject} fails. + * @throws IllegalStateException + * after {@link #close} has been called on this pool. + * @throws UnsupportedOperationException + * when this pool cannot add new idle objects. + */ + void addObject(K key) throws Exception, IllegalStateException, + UnsupportedOperationException; + + /** + * Calls {@link KeyedObjectPool#addObject(Object)} with each + * key in {@code keys} for {@code count} number of times. This has + * the same effect as calling {@link #addObjects(Object, int)} + * for each key in the {@code keys} collection. + * + * @param keys + * {@link Collection} of keys to add objects for. + * @param count + * the number of idle objects to add for each {@code key}. + * @throws Exception + * when {@link KeyedObjectPool#addObject(Object)} fails. + * @throws IllegalArgumentException + * when {@code keyedPool}, {@code keys}, or any value + * in {@code keys} is {@code null}. + * @see #addObjects(Object, int) + */ + default void addObjects(final Collection keys, final int count) throws Exception, IllegalArgumentException { + if (keys == null) { + throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEYS); + } + final Iterator iter = keys.iterator(); + while (iter.hasNext()) { + addObjects(iter.next(), count); + } + } + /** - * Obtains an instance from this pool for the specified key
. + * Calls {@link KeyedObjectPool#addObject(Object)} + * {@code key} {@code count} number of times. + * + * @param key + * the key to add objects for. + * @param count + * the number of idle objects to add for {@code key}. + * @throws Exception + * when {@link KeyedObjectPool#addObject(Object)} fails. + * @throws IllegalArgumentException + * when {@code key} is {@code null}. + * @since 2.8.0 + */ + default void addObjects(final K key, final int count) throws Exception, IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEY); + } + for (int i = 0; i < count; i++) { + addObject(key); + } + } + + /** + * Obtains an instance from this pool for the specified {@code key}. ** Instances returned from this method will have been either newly created * with {@link KeyedPooledObjectFactory#makeObject makeObject} or will be @@ -71,16 +146,19 @@ public interface KeyedObjectPool
*extends Closeable { * {@link KeyedPooledObjectFactory#activateObject activateObject} and then * (optionally) validated with * {@link KeyedPooledObjectFactory#validateObject validateObject}. + * * By contract, clients must return the borrowed object * using {@link #returnObject returnObject}, * {@link #invalidateObject invalidateObject}, or a related method as - * defined in an implementation or sub-interface, using a
*key
+ * defined in an implementation or sub-interface, using a {@code key} * that is {@link Object#equals equivalent} to the one used to borrow the * instance in the first place. + *- * The behaviour of this method when the pool has been exhausted is not + * The behavior of this method when the pool has been exhausted is not * strictly specified (although it may be specified by implementations). + *
* * @param key the key used to obtain the object * @@ -98,133 +176,146 @@ public interface KeyedObjectPoolextends Closeable { V borrowObject(K key) throws Exception, NoSuchElementException, IllegalStateException; /** - * Return an instance to the pool. By contract, obj
- * must have been obtained using - * {@link #borrowObject borrowObject} or a related method as defined in an - * implementation or sub-interface using akey
that is - * equivalent to the one used to borrow the instance in the first place. - * - * @param key the key used to obtain the object - * @param obj a {@link #borrowObject borrowed} instance to be returned. + * Clears the pool, removing all pooled instances (optional operation). * - * @throws IllegalStateException - * if an attempt is made to return an object to the pool that - * is in any state other than allocated (i.e. borrowed). - * Attempting to return an object more than once or attempting - * to return an object that was never borrowed from the pool - * will trigger this exception. + * @throws UnsupportedOperationException when this implementation doesn't + * support the operation * - * @throws Exception if an instance cannot be returned to the pool + * @throws Exception if the pool cannot be cleared */ - void returnObject(K key, V obj) throws Exception; + void clear() throws Exception, UnsupportedOperationException; /** - * Invalidates an object from the pool. - *- * By contract,
obj
must have been obtained - * using {@link #borrowObject borrowObject} or a related method as defined - * in an implementation or sub-interface using akey
that is - * equivalent to the one used to borrow theObject
in the first - * place. - *- * This method should be used when an object that has been borrowed is - * determined (due to an exception or other problem) to be invalid. + * Clears the specified pool, removing all pooled instances corresponding to + * the given {@code key} (optional operation). * - * @param key the key used to obtain the object - * @param obj a {@link #borrowObject borrowed} instance to be returned. + * @param key the key to clear * - * @throws Exception if the instance cannot be invalidated + * @throws UnsupportedOperationException when this implementation doesn't + * support the operation + * + * @throws Exception if the key cannot be cleared */ - void invalidateObject(K key, V obj) throws Exception; + void clear(K key) throws Exception, UnsupportedOperationException; /** - * Create an object using the {@link KeyedPooledObjectFactory factory} or - * other implementation dependent mechanism, passivate it, and then place it - * in the idle object pool.
addObject
is useful for - * "pre-loading" a pool with idle objects (Optional operation). - * - * @param key the key a new instance should be added to - * - * @throws Exception - * when {@link KeyedPooledObjectFactory#makeObject} fails. - * @throws IllegalStateException - * after {@link #close} has been called on this pool. - * @throws UnsupportedOperationException - * when this pool cannot add new idle objects. + * Close this pool, and free any resources associated with it. + *+ * Calling {@link #addObject addObject} or + * {@link #borrowObject borrowObject} after invoking this method on a pool + * will cause them to throw an {@link IllegalStateException}. + *
+ *+ * Implementations should silently fail if not all resources can be freed. + *
*/ - void addObject(K key) throws Exception, IllegalStateException, - UnsupportedOperationException; + @Override + void close(); /** - * Returns the number of instances corresponding to the given - *key
currently idle in this pool. Returns a negative value if - * this information is not available. - * - * @param key the key to query - * @return the number of instances corresponding to the given - *key
currently idle in this pool. + * Returns the total number of instances currently borrowed from this pool but + * not yet returned. Returns a negative value if this information is not + * available. + * @return the total number of instances currently borrowed from this pool but + * not yet returned. */ - int getNumIdle(K key); + int getNumActive(); /** * Returns the number of instances currently borrowed from but not yet - * returned to the pool corresponding to the givenkey
. + * returned to the pool corresponding to the given {@code key}. * Returns a negative value if this information is not available. * * @param key the key to query * @return the number of instances currently borrowed from but not yet - * returned to the pool corresponding to the givenkey
. -= */ + * returned to the pool corresponding to the given {@code key}. + */ int getNumActive(K key); /** * Returns the total number of instances currently idle in this pool. * Returns a negative value if this information is not available. * @return the total number of instances currently idle in this pool. - = */ + */ int getNumIdle(); /** - * Returns the total number of instances current borrowed from this pool but - * not yet returned. Returns a negative value if this information is not - * available. - * @return the total number of instances current borrowed from this pool but - * not yet returned. + * Returns the number of instances corresponding to the given + * {@code key} currently idle in this pool. Returns a negative value if + * this information is not available. + * + * @param key the key to query + * @return the number of instances corresponding to the given + * {@code key} currently idle in this pool. */ - int getNumActive(); + int getNumIdle(K key); /** - * Clears the pool, removing all pooled instances (optional operation). + * Invalidates an object from the pool. + *+ * By contract, {@code obj} must have been obtained + * using {@link #borrowObject borrowObject} or a related method as defined + * in an implementation or sub-interface using a {@code key} that is + * equivalent to the one used to borrow the {@code Object} in the first + * place. + *
+ *+ * This method should be used when an object that has been borrowed is + * determined (due to an exception or other problem) to be invalid. + *
* - * @throws UnsupportedOperationException when this implementation doesn't - * support the operation + * @param key the key used to obtain the object + * @param obj a {@link #borrowObject borrowed} instance to be returned. * - * @throws Exception if the pool cannot be cleared + * @throws Exception if the instance cannot be invalidated */ - void clear() throws Exception, UnsupportedOperationException; + void invalidateObject(K key, V obj) throws Exception; + /** - * Clears the specified pool, removing all pooled instances corresponding to - * the givenkey
(optional operation). - * - * @param key the key to clear + * Invalidates an object from the pool, using the provided + * {@link DestroyMode}. + *+ * By contract, {@code obj} must have been obtained + * using {@link #borrowObject borrowObject} or a related method as defined + * in an implementation or sub-interface using a {@code key} that is + * equivalent to the one used to borrow the {@code Object} in the first + * place. + *
+ *+ * This method should be used when an object that has been borrowed is + * determined (due to an exception or other problem) to be invalid. + *
* - * @throws UnsupportedOperationException when this implementation doesn't - * support the operation + * @param key the key used to obtain the object + * @param obj a {@link #borrowObject borrowed} instance to be returned. + * @param mode destroy activation context provided to the factory * - * @throws Exception if the key cannot be cleared + * @throws Exception if the instance cannot be invalidated + * @since 2.9.0 */ - void clear(K key) throws Exception, UnsupportedOperationException; + default void invalidateObject(final K key, final V obj, final DestroyMode mode) throws Exception { + invalidateObject(key, obj); + } /** - * Close this pool, and free any resources associated with it. - *- * Calling {@link #addObject addObject} or - * {@link #borrowObject borrowObject} after invoking this method on a pool - * will cause them to throw an {@link IllegalStateException}. - *
- * Implementations should silently fail if not all resources can be freed. + * Return an instance to the pool. By contract, {@code obj} + * must have been obtained using + * {@link #borrowObject borrowObject} or a related method as defined in an + * implementation or sub-interface using a {@code key} that is + * equivalent to the one used to borrow the instance in the first place. + * + * @param key the key used to obtain the object + * @param obj a {@link #borrowObject borrowed} instance to be returned. + * + * @throws IllegalStateException + * if an attempt is made to return an object to the pool that + * is in any state other than allocated (i.e. borrowed). + * Attempting to return an object more than once or attempting + * to return an object that was never borrowed from the pool + * will trigger this exception. + * + * @throws Exception if an instance cannot be returned to the pool */ - @Override - void close(); + void returnObject(K key, V obj) throws Exception; } diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/KeyedPooledObjectFactory.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/KeyedPooledObjectFactory.java index 12d85790f..0dd5645f7 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/KeyedPooledObjectFactory.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/KeyedPooledObjectFactory.java @@ -22,6 +22,7 @@ package com.fr.third.org.apache.commons.pool2; *
* By contract, when an {@link KeyedObjectPool} * delegates to a {@link KeyedPooledObjectFactory}, + *
**
- * {@link #makeObject} is called whenever a new instance is needed. @@ -35,7 +36,7 @@ package com.fr.third.org.apache.commons.pool2; * {@link #validateObject} may be invoked on {@link #activateObject activated} * instances to make sure they can be * {@link KeyedObjectPool#borrowObject borrowed} from the pool. - *
validateObject
may also be used to test an + * {@code validateObject} may also be used to test an * instance being {@link KeyedObjectPool#returnObject returned} to the pool * before it is {@link #passivateObject passivated}. It will only be invoked * on an activated instance. @@ -47,7 +48,7 @@ package com.fr.third.org.apache.commons.pool2; *- * {@link #destroyObject destroyObject} * is invoked on every instance when it is being "dropped" from the - * pool (whether due to the response from
validateObject
, + * pool (whether due to the response from {@code validateObject}, * or for reasons specific to the pool implementation.) There is no * guarantee that the instance being destroyed will * be considered active, passive or in a generally consistent state. @@ -56,13 +57,14 @@ package com.fr.third.org.apache.commons.pool2; * {@link KeyedPooledObjectFactory} must be thread-safe. The only promise * an {@link KeyedObjectPool} makes is that the same instance of an object will * not be passed to more than one method of a - *KeyedPoolableObjectFactory
at a time. + * {@code KeyedPoolableObjectFactory} at a time. ** While clients of a {@link KeyedObjectPool} borrow and return instances of * the underlying value type V, the factory methods act on instances of * {@link PooledObject PooledObject<V>}. These are the object wrappers that * pools use to track and maintain state informations about the objects that * they manage. + *
* * @see KeyedObjectPool * @see BaseKeyedPooledObjectFactory @@ -72,7 +74,8 @@ package com.fr.third.org.apache.commons.pool2; * * @since 2.0 */ -public interface KeyedPooledObjectFactory{ +public interface KeyedPooledObjectFactory { + /** * Create an instance that can be served by the pool and * wrap it in a {@link PooledObject} to be managed by the pool. @@ -91,11 +94,13 @@ public interface KeyedPooledObjectFactory { * Destroy an instance no longer needed by the pool. * * It is important for implementations of this method to be aware that there - * is no guarantee about what state
*obj
will be in and the + * is no guarantee about what state {@code obj} will be in and the * implementation should be prepared to handle unexpected errors. + ** Also, an implementation must take in to consideration that instances lost * to the garbage collector may never be destroyed. + *
* * @param key the key used when selecting the instance * @param p a {@code PooledObject} wrapping the instance to be destroyed @@ -108,14 +113,34 @@ public interface KeyedPooledObjectFactory{ */ void destroyObject(K key, PooledObject p) throws Exception; + /** + * Destroy an instance no longer needed by the pool, using the provided {@link DestroyMode}. + * + * @param key the key used when selecting the instance + * @param p a {@code PooledObject} wrapping the instance to be destroyed + * @param mode DestroyMode providing context to the factory + * + * @throws Exception should be avoided as it may be swallowed by + * the pool implementation. + * + * @see #validateObject + * @see KeyedObjectPool#invalidateObject + * @see #destroyObject(Object, PooledObject) + * @see DestroyMode + * @since 2.9.0 + */ + default void destroyObject(final K key, final PooledObject p, final DestroyMode mode) throws Exception { + destroyObject(key, p); + } + /** * Ensures that the instance is safe to be returned by the pool. * * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be validated * - * @return false
ifobj
is not valid and should - * be dropped from the pool,true
otherwise. + * @return {@code false} if {@code obj} is not valid and should + * be dropped from the pool, {@code true} otherwise. */ boolean validateObject(K key, PooledObjectp); @@ -125,7 +150,7 @@ public interface KeyedPooledObjectFactory { * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be activated * - * @throws Exception if there is a problem activating obj
, + * @throws Exception if there is a problem activating {@code obj}, * this exception may be swallowed by the pool. * * @see #destroyObject @@ -138,7 +163,7 @@ public interface KeyedPooledObjectFactory{ * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be passivated * - * @throws Exception if there is a problem passivating obj
, + * @throws Exception if there is a problem passivating {@code obj}, * this exception may be swallowed by the pool. * * @see #destroyObject diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/ObjectPool.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/ObjectPool.java index cc0735ef8..11c1f51a1 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/ObjectPool.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/ObjectPool.java @@ -23,6 +23,7 @@ import java.util.NoSuchElementException; * A pooling simple interface. ** Example of use: + *
*Object obj =*null
; * @@ -46,6 +47,7 @@ import java.util.NoSuchElementException; * }* See {@link BaseObjectPool} for a simple base implementation. + *
* * @paramType of element pooled in this pool. * @@ -56,6 +58,39 @@ import java.util.NoSuchElementException; * @since 2.0 */ public interface ObjectPool extends Closeable { + + /** + * Creates an object using the {@link PooledObjectFactory factory} or other + * implementation dependent mechanism, passivate it, and then place it in + * the idle object pool. {@code addObject} is useful for "pre-loading" + * a pool with idle objects. (Optional operation). + * + * @throws Exception + * when {@link PooledObjectFactory#makeObject} fails. + * @throws IllegalStateException + * after {@link #close} has been called on this pool. + * @throws UnsupportedOperationException + * when this pool cannot add new idle objects. + */ + void addObject() throws Exception, IllegalStateException, + UnsupportedOperationException; + + /** + * Calls {@link ObjectPool#addObject()} {@code count} + * number of times. + * + * @param count + * the number of idle objects to add. + * @throws Exception + * when {@link ObjectPool#addObject()} fails. + * @since 2.8.0 + */ + default void addObjects(final int count) throws Exception { + for (int i = 0; i < count; i++) { + addObject(); + } + } + /** * Obtains an instance from this pool. * @@ -64,14 +99,17 @@ public interface ObjectPool
*extends Closeable { * idle object and have been activated with * {@link PooledObjectFactory#activateObject} and then validated with * {@link PooledObjectFactory#validateObject}. + * * By contract, clients must return the borrowed instance * using {@link #returnObject}, {@link #invalidateObject}, or a related * method as defined in an implementation or sub-interface. + *
*- * The behaviour of this method when the pool has been exhausted + * The behavior of this method when the pool has been exhausted * is not strictly specified (although it may be specified by * implementations). + *
* * @return an instance from this pool. * @@ -88,57 +126,39 @@ public interface ObjectPoolextends Closeable { IllegalStateException; /** - * Return an instance to the pool. By contract, obj
- * must have been obtained using {@link #borrowObject()} or - * a related method as defined in an implementation or sub-interface. - * - * @param obj a {@link #borrowObject borrowed} instance to be returned. + * Clears any objects sitting idle in the pool, releasing any associated + * resources (optional operation). Idle objects cleared must be + * {@link PooledObjectFactory#destroyObject(PooledObject)}. * - * @throws IllegalStateException - * if an attempt is made to return an object to the pool that - * is in any state other than allocated (i.e. borrowed). - * Attempting to return an object more than once or attempting - * to return an object that was never borrowed from the pool - * will trigger this exception. + * @throws UnsupportedOperationException + * if this implementation does not support the operation * - * @throws Exception if an instance cannot be returned to the pool + * @throws Exception if the pool cannot be cleared */ - void returnObject(T obj) throws Exception; + void clear() throws Exception, UnsupportedOperationException; /** - * Invalidates an object from the pool. + * Closes this pool, and free any resources associated with it. *- * By contract,
*obj
must have been obtained - * using {@link #borrowObject} or a related method as defined in an - * implementation or sub-interface. + * Calling {@link #addObject} or {@link #borrowObject} after invoking this + * method on a pool will cause them to throw an {@link IllegalStateException}. + *- * This method should be used when an object that has been borrowed is - * determined (due to an exception or other problem) to be invalid. - * - * @param obj a {@link #borrowObject borrowed} instance to be disposed. - * - * @throws Exception if the instance cannot be invalidated + * Implementations should silently fail if not all resources can be freed. + *
*/ - void invalidateObject(T obj) throws Exception; + @Override + void close(); /** - * Create an object using the {@link PooledObjectFactory factory} or other - * implementation dependent mechanism, passivate it, and then place it in - * the idle object pool.addObject
is useful for "pre-loading" - * a pool with idle objects. (Optional operation). - * - * @throws Exception - * when {@link PooledObjectFactory#makeObject} fails. - * @throws IllegalStateException - * after {@link #close} has been called on this pool. - * @throws UnsupportedOperationException - * when this pool cannot add new idle objects. + * Returns the number of instances currently borrowed from this pool. Returns + * a negative value if this information is not available. + * @return the number of instances currently borrowed from this pool. */ - void addObject() throws Exception, IllegalStateException, - UnsupportedOperationException; + int getNumActive(); /** - * Return the number of instances currently idle in this pool. This may be + * Returns the number of instances currently idle in this pool. This may be * considered an approximation of the number of objects that can be * {@link #borrowObject borrowed} without creating any new instances. * Returns a negative value if this information is not available. @@ -147,32 +167,62 @@ public interface ObjectPoolextends Closeable { int getNumIdle(); /** - * Return the number of instances currently borrowed from this pool. Returns - * a negative value if this information is not available. - * @return the number of instances currently borrowed from this pool. + * Invalidates an object from the pool. + * + * By contract, {@code obj} must have been obtained + * using {@link #borrowObject} or a related method as defined in an + * implementation or sub-interface. + *
+ *+ * This method should be used when an object that has been borrowed is + * determined (due to an exception or other problem) to be invalid. + *
+ * + * @param obj a {@link #borrowObject borrowed} instance to be disposed. + * + * @throws Exception if the instance cannot be invalidated */ - int getNumActive(); + void invalidateObject(T obj) throws Exception; /** - * Clears any objects sitting idle in the pool, releasing any associated - * resources (optional operation). Idle objects cleared must be - * {@link PooledObjectFactory#destroyObject(PooledObject)}. + * Invalidates an object from the pool, using the provided + * {@link DestroyMode} + *+ * By contract, {@code obj} must have been obtained + * using {@link #borrowObject} or a related method as defined in an + * implementation or sub-interface. + *
+ *+ * This method should be used when an object that has been borrowed is + * determined (due to an exception or other problem) to be invalid. + *
* - * @throws UnsupportedOperationException - * if this implementation does not support the operation + * @param obj a {@link #borrowObject borrowed} instance to be disposed. + * @param mode destroy activation context provided to the factory * - * @throws Exception if the pool cannot be cleared + * @throws Exception if the instance cannot be invalidated + * @since 2.9.0 */ - void clear() throws Exception, UnsupportedOperationException; + default void invalidateObject(final T obj, final DestroyMode mode) throws Exception { + invalidateObject(obj); + } /** - * Close this pool, and free any resources associated with it. - *- * Calling {@link #addObject} or {@link #borrowObject} after invoking this - * method on a pool will cause them to throw an {@link IllegalStateException}. - *
- * Implementations should silently fail if not all resources can be freed. + * Returns an instance to the pool. By contract, {@code obj} + * must have been obtained using {@link #borrowObject()} or + * a related method as defined in an implementation or sub-interface. + * + * @param obj a {@link #borrowObject borrowed} instance to be returned. + * + * @throws IllegalStateException + * if an attempt is made to return an object to the pool that + * is in any state other than allocated (i.e. borrowed). + * Attempting to return an object more than once or attempting + * to return an object that was never borrowed from the pool + * will trigger this exception. + * + * @throws Exception if an instance cannot be returned to the pool */ - @Override - void close(); + void returnObject(T obj) throws Exception; + } diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PoolUtils.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PoolUtils.java index 8f6d515e5..f2a122af2 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PoolUtils.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PoolUtils.java @@ -36,6 +36,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; */ public final class PoolUtils { + private static final String MSG_FACTOR_NEGATIVE = "factor must be positive."; + private static final String MSG_MIN_IDLE = "minIdle must be non-negative."; + static final String MSG_NULL_KEY = "key must not be null."; + private static final String MSG_NULL_KEYED_POOL = "keyedPool must not be null."; + static final String MSG_NULL_KEYS = "keys must not be null."; + private static final String MSG_NULL_POOL = "pool must not be null."; + /** * Timer used to periodically check pools idle object count. Because a * {@link Timer} creates a {@link Thread}, an IODH is used. @@ -93,20 +100,20 @@ public final class PoolUtils { * @return the {@link TimerTask} that will periodically check the pools idle * object count. * @throws IllegalArgumentException - * when
pool
isnull
or when - *minIdle
is negative or whenperiod
- * isn't valid for {@link Timer#schedule(TimerTask, long, long)} + * when {@code pool} is {@code null} or when {@code minIdle} is + * negative or when {@code period} isn't valid for + * {@link Timer#schedule(TimerTask, long, long)} */ public staticTimerTask checkMinIdle(final ObjectPool pool, final int minIdle, final long period) throws IllegalArgumentException { if (pool == null) { - throw new IllegalArgumentException("keyedPool must not be null."); + throw new IllegalArgumentException(MSG_NULL_KEYED_POOL); } if (minIdle < 0) { - throw new IllegalArgumentException("minIdle must be non-negative."); + throw new IllegalArgumentException(MSG_MIN_IDLE); } - final TimerTask task = new ObjectPoolMinIdleTimerTask (pool, minIdle); + final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle); getMinIdleTimer().schedule(task, 0L, period); return task; } @@ -132,25 +139,24 @@ public final class PoolUtils { * @return the {@link TimerTask} that will periodically check the pools idle * object count. * @throws IllegalArgumentException - * when keyedPool
,key
is - *null
or whenminIdle
is negative or - * whenperiod
isn't valid for - * {@link Timer#schedule(TimerTask, long, long)}. + * when {@code keyedPool}, {@code key} is {@code null} or + * when {@code minIdle} is negative or when {@code period} isn't + * valid for {@link Timer#schedule(TimerTask, long, long)}. */ public staticTimerTask checkMinIdle( final KeyedObjectPool keyedPool, final K key, final int minIdle, final long period) throws IllegalArgumentException { if (keyedPool == null) { - throw new IllegalArgumentException("keyedPool must not be null."); + throw new IllegalArgumentException(MSG_NULL_KEYED_POOL); } if (key == null) { - throw new IllegalArgumentException("key must not be null."); + throw new IllegalArgumentException(MSG_NULL_KEY); } if (minIdle < 0) { - throw new IllegalArgumentException("minIdle must be non-negative."); + throw new IllegalArgumentException(MSG_MIN_IDLE); } - final TimerTask task = new KeyedObjectPoolMinIdleTimerTask ( + final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>( keyedPool, key, minIdle); getMinIdleTimer().schedule(task, 0L, period); return task; @@ -158,8 +164,8 @@ public final class PoolUtils { /** * Periodically check the idle object count for each key in the - * Collection
keys
in the keyedPool. At most one - * idle object will be added per period. + * {@code Collection keys} in the keyedPool. At most one idle object will be + * added per period. * * @param keyedPool * the keyedPool to check periodically. @@ -176,11 +182,10 @@ public final class PoolUtils { * @return a {@link Map} of key and {@link TimerTask} pairs that will * periodically check the pools idle object count. * @throws IllegalArgumentException - * whenkeyedPool
,keys
, or any of the - * values in the collection isnull
or when - *minIdle
is negative or whenperiod
- * isn't valid for {@link Timer#schedule(TimerTask, long, long)} - * . + * when {@code keyedPool}, {@code keys}, or any of the values in + * the collection is {@code null} or when {@code minIdle} is + * negative or when {@code period} isn't valid for + * {@link Timer#schedule(TimerTask, long, long)}. * @see #checkMinIdle(KeyedObjectPool, Object, int, long) */ public staticMap checkMinIdle( @@ -188,9 +193,9 @@ public final class PoolUtils { final int minIdle, final long period) throws IllegalArgumentException { if (keys == null) { - throw new IllegalArgumentException("keys must not be null."); + throw new IllegalArgumentException(MSG_NULL_KEYS); } - final Map tasks = new HashMap (keys.size()); + final Map tasks = new HashMap<>(keys.size()); final Iterator iter = keys.iterator(); while (iter.hasNext()) { final K key = iter.next(); @@ -201,8 +206,8 @@ public final class PoolUtils { } /** - * Call addObject()
onpool
count
- * number of times. + * Calls {@link ObjectPool#addObject()} on {@code pool} {@code count} number + * of times. * * @param pool * the pool to prefill. @@ -212,81 +217,76 @@ public final class PoolUtils { * @throws Exception * when {@link ObjectPool#addObject()} fails. * @throws IllegalArgumentException - * whenpool
isnull
. + * when {@code pool} is {@code null}. + * @deprecated Use {@link ObjectPool#addObjects(int)}. */ + @Deprecated public staticvoid prefill(final ObjectPool pool, final int count) throws Exception, IllegalArgumentException { if (pool == null) { - throw new IllegalArgumentException("pool must not be null."); - } - for (int i = 0; i < count; i++) { - pool.addObject(); + throw new IllegalArgumentException(MSG_NULL_POOL); } + pool.addObjects(count); } /** - * Call addObject(Object)
onkeyedPool
with - *key
count
number of times. + * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with + * {@code key} {@code count} number of times. * * @param keyedPool * the keyedPool to prefill. * @param key * the key to add objects for. * @param count - * the number of idle objects to add forkey
. + * the number of idle objects to add for {@code key}. * @paramthe type of the pool key * @param the type of pool entries * @throws Exception * when {@link KeyedObjectPool#addObject(Object)} fails. * @throws IllegalArgumentException - * when keyedPool
orkey
is - *null
. + * when {@code keyedPool} or {@code key} is {@code null}. + * @deprecated Use {@link KeyedObjectPool#addObjects(Object, int)}. */ + @Deprecated public staticvoid prefill(final KeyedObjectPool keyedPool, final K key, final int count) throws Exception, IllegalArgumentException { if (keyedPool == null) { - throw new IllegalArgumentException("keyedPool must not be null."); - } - if (key == null) { - throw new IllegalArgumentException("key must not be null."); - } - for (int i = 0; i < count; i++) { - keyedPool.addObject(key); + throw new IllegalArgumentException(MSG_NULL_KEYED_POOL); } + keyedPool.addObjects(key, count); } /** - * Call addObject(Object)
onkeyedPool
with each - * key inkeys
forcount
number of times. This has + * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with + * each key in {@code keys} for {@code count} number of times. This has * the same effect as calling {@link #prefill(KeyedObjectPool, Object, int)} - * for each key in thekeys
collection. + * for each key in the {@code keys} collection. * * @param keyedPool * the keyedPool to prefill. * @param keys * {@link Collection} of keys to add objects for. * @param count - * the number of idle objects to add for eachkey
. + * the number of idle objects to add for each {@code key}. * @paramthe type of the pool key * @param the type of pool entries * @throws Exception * when {@link KeyedObjectPool#addObject(Object)} fails. * @throws IllegalArgumentException - * when keyedPool
,keys
, or any value - * inkeys
isnull
. + * when {@code keyedPool}, {@code keys}, or any value in + * {@code keys} is {@code null}. * @see #prefill(KeyedObjectPool, Object, int) + * @deprecated Use {@link KeyedObjectPool#addObjects(Collection, int)}. */ + @Deprecated public staticvoid prefill(final KeyedObjectPool keyedPool, final Collection keys, final int count) throws Exception, IllegalArgumentException { if (keys == null) { - throw new IllegalArgumentException("keys must not be null."); - } - final Iterator iter = keys.iterator(); - while (iter.hasNext()) { - prefill(keyedPool, iter.next(), count); + throw new IllegalArgumentException(MSG_NULL_KEYS); } + keyedPool.addObjects(keys, count); } /** @@ -304,11 +304,13 @@ public final class PoolUtils { * @param pool * the ObjectPool to be "wrapped" in a synchronized ObjectPool. * @param the type of objects in the pool + * @throws IllegalArgumentException + * when {@code pool} is {@code null}. * @return a synchronized view of the specified ObjectPool. */ public static ObjectPool synchronizedPool(final ObjectPool pool) { if (pool == null) { - throw new IllegalArgumentException("pool must not be null."); + throw new IllegalArgumentException(MSG_NULL_POOL); } /* * assert !(pool instanceof GenericObjectPool) : @@ -321,7 +323,7 @@ public final class PoolUtils { * .equals(pool.getClass().getName()) : * "CompositeObjectPools are already thread-safe"; */ - return new SynchronizedObjectPool (pool); + return new SynchronizedObjectPool<>(pool); } /** @@ -354,7 +356,7 @@ public final class PoolUtils { * .equals(keyedPool.getClass().getName()) : * "CompositeKeyedObjectPools are already thread-safe"; */ - return new SynchronizedKeyedObjectPool (keyedPool); + return new SynchronizedKeyedObjectPool<>(keyedPool); } /** @@ -369,7 +371,7 @@ public final class PoolUtils { */ public static PooledObjectFactory synchronizedPooledFactory( final PooledObjectFactory factory) { - return new SynchronizedPooledObjectFactory (factory); + return new SynchronizedPooledObjectFactory<>(factory); } /** @@ -385,7 +387,7 @@ public final class PoolUtils { */ public static KeyedPooledObjectFactory synchronizedKeyedPooledFactory( final KeyedPooledObjectFactory keyedFactory) { - return new SynchronizedKeyedPooledObjectFactory (keyedFactory); + return new SynchronizedKeyedPooledObjectFactory<>(keyedFactory); } /** @@ -399,6 +401,8 @@ public final class PoolUtils { * the ObjectPool to be decorated so it shrinks its idle count * when possible. * @param the type of objects in the pool + * @throws IllegalArgumentException + * when {@code pool} is {@code null}. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(ObjectPool, float) @@ -429,6 +433,9 @@ public final class PoolUtils { * shrinks more aggressively. If 1 < factor then the pool * shrinks less aggressively. * @param the type of objects in the pool + * @throws IllegalArgumentException + * when {@code pool} is {@code null} or when {@code factor} is + * not positive. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(ObjectPool) @@ -436,12 +443,12 @@ public final class PoolUtils { public static ObjectPool erodingPool(final ObjectPool pool, final float factor) { if (pool == null) { - throw new IllegalArgumentException("pool must not be null."); + throw new IllegalArgumentException(MSG_NULL_POOL); } if (factor <= 0f) { - throw new IllegalArgumentException("factor must be positive."); + throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE); } - return new ErodingObjectPool (pool, factor); + return new ErodingObjectPool<>(pool, factor); } /** @@ -456,6 +463,8 @@ public final class PoolUtils { * count when possible. * @param the type of the pool key * @param the type of pool entries + * @throws IllegalArgumentException + * when {@code keyedPool} is {@code null}. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(KeyedObjectPool, float) @@ -489,6 +498,9 @@ public final class PoolUtils { * shrinks less aggressively. * @param the type of the pool key * @param the type of pool entries + * @throws IllegalArgumentException + * when {@code keyedPool} is {@code null} or when {@code factor} + * is not positive. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(KeyedObjectPool, float, boolean) @@ -529,6 +541,9 @@ public final class PoolUtils { * when true, each key is treated independently. * @param the type of the pool key * @param the type of pool entries + * @throws IllegalArgumentException + * when {@code keyedPool} is {@code null} or when {@code factor} + * is not positive. * @return a pool that adaptively decreases its size when idle objects are * no longer needed. * @see #erodingPool(KeyedObjectPool) @@ -538,19 +553,19 @@ public final class PoolUtils { final KeyedObjectPool keyedPool, final float factor, final boolean perKey) { if (keyedPool == null) { - throw new IllegalArgumentException("keyedPool must not be null."); + throw new IllegalArgumentException(MSG_NULL_KEYED_POOL); } if (factor <= 0f) { - throw new IllegalArgumentException("factor must be positive."); + throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE); } if (perKey) { - return new ErodingPerKeyKeyedObjectPool (keyedPool, factor); + return new ErodingPerKeyKeyedObjectPool<>(keyedPool, factor); } - return new ErodingKeyedObjectPool (keyedPool, factor); + return new ErodingKeyedObjectPool<>(keyedPool, factor); } /** - * Get the Timer
for checking keyedPool's idle count. + * Gets the {@code Timer} for checking keyedPool's idle count. * * @return the {@link Timer} for checking keyedPool's idle count. */ @@ -587,7 +602,7 @@ public final class PoolUtils { ObjectPoolMinIdleTimerTask(final ObjectPoolpool, final int minIdle) throws IllegalArgumentException { if (pool == null) { - throw new IllegalArgumentException("pool must not be null."); + throw new IllegalArgumentException(MSG_NULL_POOL); } this.pool = pool; this.minIdle = minIdle; @@ -639,6 +654,7 @@ public final class PoolUtils { */ private static final class KeyedObjectPoolMinIdleTimerTask extends TimerTask { + /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */ private final int minIdle; @@ -649,7 +665,7 @@ public final class PoolUtils { private final KeyedObjectPool keyedPool; /** - * Create a new KeyedObjecPoolMinIdleTimerTask. + * Creates a new KeyedObjecPoolMinIdleTimerTask. * * @param keyedPool * keyed object pool @@ -664,7 +680,7 @@ public final class PoolUtils { final K key, final int minIdle) throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException( - "keyedPool must not be null."); + MSG_NULL_KEYED_POOL); } this.keyedPool = keyedPool; this.key = key; @@ -735,7 +751,7 @@ public final class PoolUtils { private final ObjectPool pool; /** - * Create a new SynchronizedObjectPool wrapping the given pool. + * Creates a new SynchronizedObjectPool wrapping the given pool. * * @param pool * the ObjectPool to be "wrapped" in a synchronized @@ -746,7 +762,7 @@ public final class PoolUtils { SynchronizedObjectPool(final ObjectPool pool) throws IllegalArgumentException { if (pool == null) { - throw new IllegalArgumentException("pool must not be null."); + throw new IllegalArgumentException(MSG_NULL_POOL); } this.pool = pool; } @@ -912,7 +928,7 @@ public final class PoolUtils { private final KeyedObjectPool keyedPool; /** - * Create a new SynchronizedKeyedObjectPool wrapping the given pool + * Creates a new SynchronizedKeyedObjectPool wrapping the given pool * * @param keyedPool * KeyedObjectPool to wrap @@ -923,7 +939,7 @@ public final class PoolUtils { throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException( - "keyedPool must not be null."); + MSG_NULL_KEYED_POOL); } this.keyedPool = keyedPool; } @@ -1118,6 +1134,7 @@ public final class PoolUtils { */ private static final class SynchronizedPooledObjectFactory implements PooledObjectFactory { + /** Synchronization lock */ private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); @@ -1125,7 +1142,7 @@ public final class PoolUtils { private final PooledObjectFactory factory; /** - * Create a SynchronizedPoolableObjectFactory wrapping the given + * Creates a SynchronizedPoolableObjectFactory wrapping the given * factory. * * @param factory @@ -1234,6 +1251,7 @@ public final class PoolUtils { */ private static final class SynchronizedKeyedPooledObjectFactory implements KeyedPooledObjectFactory { + /** Synchronization lock */ private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); @@ -1241,7 +1259,7 @@ public final class PoolUtils { private final KeyedPooledObjectFactory keyedFactory; /** - * Create a SynchronizedKeyedPoolableObjectFactory wrapping the given + * Creates a SynchronizedKeyedPoolableObjectFactory wrapping the given * factory. * * @param keyedFactory @@ -1358,7 +1376,7 @@ public final class PoolUtils { private transient volatile int idleHighWaterMark; /** - * Create a new ErodingFactor with the given erosion factor. + * Creates a new ErodingFactor with the given erosion factor. * * @param factor * erosion factor @@ -1418,6 +1436,7 @@ public final class PoolUtils { * @param type of objects in the pool */ private static class ErodingObjectPool implements ObjectPool { + /** Underlying object pool */ private final ObjectPool pool; @@ -1425,7 +1444,7 @@ public final class PoolUtils { private final ErodingFactor factor; /** - * Create an ErodingObjectPool wrapping the given pool using the + * Creates an ErodingObjectPool wrapping the given pool using the * specified erosion factor. * * @param pool @@ -1563,6 +1582,7 @@ public final class PoolUtils { */ private static class ErodingKeyedObjectPool implements KeyedObjectPool { + /** Underlying pool */ private final KeyedObjectPool keyedPool; @@ -1570,7 +1590,7 @@ public final class PoolUtils { private final ErodingFactor erodingFactor; /** - * Create an ErodingObjectPool wrapping the given pool using the + * Creates an ErodingObjectPool wrapping the given pool using the * specified erosion factor. * * @param keyedPool @@ -1586,7 +1606,7 @@ public final class PoolUtils { } /** - * Create an ErodingObjectPool wrapping the given pool using the + * Creates an ErodingObjectPool wrapping the given pool using the * specified erosion factor. * * @param keyedPool @@ -1594,13 +1614,13 @@ public final class PoolUtils { * @param erodingFactor * erosion factor - determines the frequency of erosion * events - * @see #factor + * @see #erodingFactor */ protected ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final ErodingFactor erodingFactor) { if (keyedPool == null) { throw new IllegalArgumentException( - "keyedPool must not be null."); + MSG_NULL_KEYED_POOL); } this.keyedPool = keyedPool; this.erodingFactor = erodingFactor; @@ -1776,6 +1796,7 @@ public final class PoolUtils { */ private static final class ErodingPerKeyKeyedObjectPool extends ErodingKeyedObjectPool { + /** Erosion factor - same for all pools */ private final float factor; @@ -1783,7 +1804,7 @@ public final class PoolUtils { private final Map factors = Collections.synchronizedMap(new HashMap ()); /** - * Create a new ErordingPerKeyKeyedObjectPool decorating the given keyed + * Creates a new ErordingPerKeyKeyedObjectPool decorating the given keyed * pool with the specified erosion factor. * * @param keyedPool @@ -1815,10 +1836,11 @@ public final class PoolUtils { /** * {@inheritDoc} */ + @SuppressWarnings("resource") // getKeyedPool(): ivar access @Override public String toString() { return "ErodingPerKeyKeyedObjectPool{" + "factor=" + factor + ", keyedPool=" + getKeyedPool() + '}'; } } -} \ No newline at end of file +} diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObject.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObject.java index 9e1cd72cf..0c201f2b4 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObject.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObject.java @@ -24,6 +24,7 @@ import java.util.Deque; * state, for the pooled objects. * * Implementations of this class are required to be thread-safe. + *
* * @paramthe type of object in the pool * @@ -32,7 +33,7 @@ import java.util.Deque; public interface PooledObject extends Comparable > { /** - * Obtain the underlying object that is wrapped by this instance of + * Obtains the underlying object that is wrapped by this instance of * {@link PooledObject}. * * @return The wrapped object @@ -40,7 +41,7 @@ public interface PooledObject extends Comparable > { T getObject(); /** - * Obtain the time (using the same basis as + * Obtains the time (using the same basis as * {@link System#currentTimeMillis()}) that this object was created. * * @return The creation time for the wrapped object @@ -48,7 +49,7 @@ public interface PooledObject extends Comparable > { long getCreateTime(); /** - * Obtain the time in milliseconds that this object last spent in the + * Obtains the time in milliseconds that this object last spent in the * active state (it may still be active in which case subsequent calls will * return an increased value). * @@ -57,7 +58,17 @@ public interface PooledObject extends Comparable > { long getActiveTimeMillis(); /** - * Obtain the time in milliseconds that this object last spend in the + * Gets the number of times this object has been borrowed. + * + * @return -1 by default for old implementations prior to release 2.7.0. + * @since 2.7.0 + */ + default long getBorrowedCount() { + return -1; + } + + /** + * Obtains the time in milliseconds that this object last spend in the * idle state (it may still be idle in which case subsequent calls will * return an increased value). * @@ -66,21 +77,21 @@ public interface PooledObject extends Comparable > { long getIdleTimeMillis(); /** - * Obtain the time the wrapped object was last borrowed. + * Obtains the time the wrapped object was last borrowed. * * @return The time the object was last borrowed */ long getLastBorrowTime(); /** - * Obtain the time the wrapped object was last returned. + * Obtains the time the wrapped object was last returned. * * @return The time the object was last returned */ long getLastReturnTime(); /** - * Return an estimate of the last time this object was used. If the class + * Returns an estimate of the last time this object was used. If the class * of the pooled object implements {@link TrackedUse}, what is returned is * the maximum of {@link TrackedUse#getLastUsed()} and * {@link #getLastBorrowTime()}; otherwise this method gives the same @@ -96,8 +107,10 @@ public interface PooledObject extends Comparable > { * * Note: This class has a natural ordering that is inconsistent with * equals if distinct objects have the same identity hash code. + *
** {@inheritDoc} + *
*/ @Override int compareTo(PooledObjectother); @@ -118,12 +131,12 @@ public interface PooledObject extends Comparable > { String toString(); /** - * Attempt to place the pooled object in the + * Attempts to place the pooled object in the * {@link PooledObjectState#EVICTION} state. * - * @return true
if the object was placed in the + * @return {@code true} if the object was placed in the * {@link PooledObjectState#EVICTION} state otherwise - *false
+ * {@code false} */ boolean startEvictionTest(); @@ -167,17 +180,17 @@ public interface PooledObjectextends Comparable > { */ void setLogAbandoned(boolean logAbandoned); -// TODO: uncomment in 3.0 (API compatibility) -// /** -// * Configures the stack trace generation strategy based on whether or not fully -// * detailed stack traces are required. When set to false, abandoned logs may -// * only include caller class information rather than method names, line numbers, -// * and other normal metadata available in a full stack trace. -// * -// * @param requireFullStackTrace the new configuration setting for abandoned object -// * logging -// */ -// void setRequireFullStackTrace(boolean requireFullStackTrace); + /** + * Configures the stack trace generation strategy based on whether or not fully detailed stack traces are required. + * When set to false, abandoned logs may only include caller class information rather than method names, line + * numbers, and other normal metadata available in a full stack trace. + * + * @param requireFullStackTrace the new configuration setting for abandoned object logging + * @since 2.7.0 + */ + default void setRequireFullStackTrace(final boolean requireFullStackTrace) { + // noop + } /** * Record the current stack trace as the last time the object was used. @@ -209,10 +222,4 @@ public interface PooledObject extends Comparable > { */ void markReturning(); - // TODO: Uncomment this for version 3 (can't add it to 2.x as it will break - // API compatibility) - ///** - // * Get the number of times this object has been borrowed. - // */ - //long getBorrowedCount(); } diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObjectFactory.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObjectFactory.java index 7dc6e7df1..927e76e7e 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObjectFactory.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObjectFactory.java @@ -22,6 +22,7 @@ package com.fr.third.org.apache.commons.pool2; * * By contract, when an {@link ObjectPool} delegates to a * {@link PooledObjectFactory}, + *
**
* {@link PooledObjectFactory} must be thread-safe. The only promise * an {@link ObjectPool} makes is that the same instance of an object will not - * be passed to more than one method of a- * {@link #makeObject} is called whenever a new instance is needed. @@ -53,7 +54,7 @@ package com.fr.third.org.apache.commons.pool2; *
PoolableObjectFactory
+ * be passed to more than one method of a {@code PoolableObjectFactory} * at a time. ** While clients of a {@link KeyedObjectPool} borrow and return instances of @@ -61,6 +62,7 @@ package com.fr.third.org.apache.commons.pool2; * {@link PooledObject PooledObject<V>}. These are the object wrappers that * pools use to track and maintain state information about the objects that * they manage. + *
* * @paramType of element managed in this factory. * @@ -69,8 +71,9 @@ package com.fr.third.org.apache.commons.pool2; * @since 2.0 */ public interface PooledObjectFactory { + /** - * Create an instance that can be served by the pool and wrap it in a + * Creates an instance that can be served by the pool and wrap it in a * {@link PooledObject} to be managed by the pool. * * @return a {@code PooledObject} wrapping an instance that can be served by the pool @@ -81,11 +84,13 @@ public interface PooledObjectFactory { PooledObject makeObject() throws Exception; /** - * Destroys an instance no longer needed by the pool. + * Destroys an instance no longer needed by the pool, using the default (NORMAL) + * DestroyMode. * * It is important for implementations of this method to be aware that there - * is no guarantee about what state
*obj
will be in and the + * is no guarantee about what state {@code obj} will be in and the * implementation should be prepared to handle unexpected errors. + ** Also, an implementation must take in to consideration that instances lost * to the garbage collector may never be destroyed. @@ -101,22 +106,42 @@ public interface PooledObjectFactory
* * @return true if abandoned objects are to be removed by borrowObject */ @@ -202,7 +204,7 @@ public class AbandonedConfig { * @see #getRequireFullStackTrace() * @since 2.5 */ - public void setRequireFullStackTrace(boolean requireFullStackTrace) { + public void setRequireFullStackTrace(final boolean requireFullStackTrace) { this.requireFullStackTrace = requireFullStackTrace; } @@ -210,7 +212,7 @@ public class AbandonedConfig { * PrintWriter to use to log information on abandoned objects. * Use of default system encoding is deliberate. */ - private PrintWriter logWriter = new PrintWriter(System.out); + private PrintWriter logWriter = new PrintWriter(new OutputStreamWriter(System.out, Charset.defaultCharset())); /** * Returns the log writer being used by this configuration to log @@ -245,7 +247,7 @@ public class AbandonedConfig { * stack trace every time a method is called on a pooled object and retain * the most recent stack trace to aid debugging of abandoned objects? * - * @return{ */ void destroyObject(PooledObject p) throws Exception; + /** + * Destroys an instance no longer needed by the pool, using the provided + * DestroyMode. + * + * @param p a {@code PooledObject} wrapping the instance to be destroyed + * @param mode DestroyMode providing context to the factory + * + * @throws Exception should be avoided as it may be swallowed by + * the pool implementation. + * + * @see #validateObject + * @see ObjectPool#invalidateObject + * @see #destroyObject(PooledObject) + * @see DestroyMode + * @since 2.9.0 + */ + default void destroyObject(final PooledObject p, final DestroyMode mode) throws Exception { + destroyObject(p); + } + /** * Ensures that the instance is safe to be returned by the pool. * * @param p a {@code PooledObject} wrapping the instance to be validated * - * @return false
ifobj
is not valid and should - * be dropped from the pool,true
otherwise. + * @return {@code false} if {@code obj} is not valid and should + * be dropped from the pool, {@code true} otherwise. */ boolean validateObject(PooledObjectp); /** - * Reinitialize an instance to be returned by the pool. + * Reinitializes an instance to be returned by the pool. * * @param p a {@code PooledObject} wrapping the instance to be activated * - * @throws Exception if there is a problem activating obj
, + * @throws Exception if there is a problem activating {@code obj}, * this exception may be swallowed by the pool. * * @see #destroyObject @@ -124,11 +149,11 @@ public interface PooledObjectFactory{ void activateObject(PooledObject p) throws Exception; /** - * Uninitialize an instance to be returned to the idle object pool. + * Uninitializes an instance to be returned to the idle object pool. * * @param p a {@code PooledObject} wrapping the instance to be passivated * - * @throws Exception if there is a problem passivating obj
, + * @throws Exception if there is a problem passivating {@code obj}, * this exception may be swallowed by the pool. * * @see #destroyObject diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObjectState.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObjectState.java index 2469abf5a..22f1901ad 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObjectState.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/PooledObjectState.java @@ -22,6 +22,7 @@ package com.fr.third.org.apache.commons.pool2; * @since 2.0 */ public enum PooledObjectState { + /** * In the queue, not in use. */ diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/AbandonedConfig.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/AbandonedConfig.java index b19f3ef99..2f4a1f209 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/AbandonedConfig.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/AbandonedConfig.java @@ -17,11 +17,13 @@ package com.fr.third.org.apache.commons.pool2.impl; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.nio.charset.Charset; + import com.fr.third.org.apache.commons.pool2.TrackedUse; import com.fr.third.org.apache.commons.pool2.UsageTracking; -import java.io.PrintWriter; - /** * Configuration settings for abandoned object removal. * @@ -42,7 +44,7 @@ public class AbandonedConfig { * *If set to true, abandoned objects are removed by borrowObject if * there are fewer than 2 idle objects available in the pool and - *
+ * {@code getNumActive() > getMaxTotal() - 3}getNumActive() > getMaxTotal() - 3
true
if usage tracking is enabled + * @return {@code true} if usage tracking is enabled */ public boolean getUseUsageTracking() { return useUsageTracking; @@ -257,7 +259,7 @@ public class AbandonedConfig { * object and retain the most recent stack trace to aid debugging of * abandoned objects. * - * @param useUsageTracking A value oftrue
will enable + * @param useUsageTracking A value of {@code true} will enable * the recording of a stack trace on every use * of a pooled object */ diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/BaseGenericObjectPool.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/BaseGenericObjectPool.java index a8ded3f9a..d56818925 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/BaseGenericObjectPool.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/BaseGenericObjectPool.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.Deque; import java.util.Iterator; import java.util.TimerTask; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; @@ -39,6 +40,7 @@ import javax.management.ObjectName; import com.fr.third.org.apache.commons.pool2.BaseObject; import com.fr.third.org.apache.commons.pool2.PooledObject; +import com.fr.third.org.apache.commons.pool2.PooledObjectState; import com.fr.third.org.apache.commons.pool2.SwallowedExceptionListener; /** @@ -61,6 +63,8 @@ public abstract class BaseGenericObjectPoolextends BaseObject { */ public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100; + private static final String EVICTION_POLICY_TYPE_NAME = EvictionPolicy.class.getName(); + // Configuration attributes private volatile int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; @@ -107,7 +111,7 @@ public abstract class BaseGenericObjectPool extends BaseObject { // Monitoring (primarily JMX) attributes - private final ObjectName oname; + private final ObjectName objectName; private final String creationStackTrace; private final AtomicLong borrowedCount = new AtomicLong(0); private final AtomicLong returnedCount = new AtomicLong(0); @@ -131,12 +135,12 @@ public abstract class BaseGenericObjectPool extends BaseObject { * overridden by the config * @param jmxNamePrefix Prefix to be used for JMX name for the new pool */ - public BaseGenericObjectPool(final BaseObjectPoolConfig config, + public BaseGenericObjectPool(final BaseObjectPoolConfig config, final String jmxNameBase, final String jmxNamePrefix) { if (config.getJmxEnabled()) { - this.oname = jmxRegister(config, jmxNameBase, jmxNamePrefix); + this.objectName = jmxRegister(config, jmxNameBase, jmxNamePrefix); } else { - this.oname = null; + this.objectName = null; } // Populate the creation stack trace @@ -147,7 +151,7 @@ public abstract class BaseGenericObjectPool extends BaseObject { if (cl == null) { factoryClassLoader = null; } else { - factoryClassLoader = new WeakReference (cl); + factoryClassLoader = new WeakReference<>(cl); } fairness = config.getFairness(); @@ -185,11 +189,11 @@ public abstract class BaseGenericObjectPool extends BaseObject { } /** - * Returns whether to block when the borrowObject()
method is + * Returns whether to block when the {@code borrowObject()} method is * invoked when the pool is exhausted (the maximum number of "active" * objects has been reached). * - * @returntrue
ifborrowObject()
should block + * @return {@code true} if {@code borrowObject()} should block * when the pool is exhausted * * @see #setBlockWhenExhausted @@ -199,12 +203,12 @@ public abstract class BaseGenericObjectPoolextends BaseObject { } /** - * Sets whether to block when the borrowObject()
method is + * Sets whether to block when the {@code borrowObject()} method is * invoked when the pool is exhausted (the maximum number of "active" * objects has been reached). * - * @param blockWhenExhaustedtrue
if - *borrowObject()
should block + * @param blockWhenExhausted {@code true} if + * {@code borrowObject()} should block * when the pool is exhausted * * @see #getBlockWhenExhausted @@ -213,14 +217,42 @@ public abstract class BaseGenericObjectPoolextends BaseObject { this.blockWhenExhausted = blockWhenExhausted; } + /** + * Initializes the receiver with the given configuration. + * + * @param config Initialization source. + */ + protected void setConfig(final BaseObjectPoolConfig config) { + setLifo(config.getLifo()); + setMaxWaitMillis(config.getMaxWaitMillis()); + setBlockWhenExhausted(config.getBlockWhenExhausted()); + setTestOnCreate(config.getTestOnCreate()); + setTestOnBorrow(config.getTestOnBorrow()); + setTestOnReturn(config.getTestOnReturn()); + setTestWhileIdle(config.getTestWhileIdle()); + setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun()); + setMinEvictableIdleTimeMillis(config.getMinEvictableIdleTimeMillis()); + setTimeBetweenEvictionRunsMillis(config.getTimeBetweenEvictionRunsMillis()); + setSoftMinEvictableIdleTimeMillis(config.getSoftMinEvictableIdleTimeMillis()); + final EvictionPolicy policy = config.getEvictionPolicy(); + if (policy == null) { + // Use the class name (pre-2.6.0 compatible) + setEvictionPolicyClassName(config.getEvictionPolicyClassName()); + } else { + // Otherwise, use the class (2.6.0 feature) + setEvictionPolicy(policy); + } + setEvictorShutdownTimeoutMillis(config.getEvictorShutdownTimeoutMillis()); + } + /** * Returns the maximum amount of time (in milliseconds) the - * borrowObject()
method should block before throwing an + * {@code borrowObject()} method should block before throwing an * exception when the pool is exhausted and * {@link #getBlockWhenExhausted} is true. When less than 0, the - *borrowObject()
method may block indefinitely. + * {@code borrowObject()} method may block indefinitely. * - * @return the maximum number of millisecondsborrowObject()
+ * @return the maximum number of milliseconds {@code borrowObject()} * will block. * * @see #setMaxWaitMillis @@ -232,13 +264,13 @@ public abstract class BaseGenericObjectPoolextends BaseObject { /** * Sets the maximum amount of time (in milliseconds) the - * borrowObject()
method should block before throwing an + * {@code borrowObject()} method should block before throwing an * exception when the pool is exhausted and * {@link #getBlockWhenExhausted} is true. When less than 0, the - *borrowObject()
method may block indefinitely. + * {@code borrowObject()} method may block indefinitely. * * @param maxWaitMillis the maximum number of milliseconds - *borrowObject()
will block or negative + * {@code borrowObject()} will block or negative * for indefinitely. * * @see #getMaxWaitMillis @@ -249,14 +281,14 @@ public abstract class BaseGenericObjectPoolextends BaseObject { } /** - * Returns whether the pool has LIFO (last in, first out) behaviour with + * Returns whether the pool has LIFO (last in, first out) behavior with * respect to idle objects - always returning the most recently used object * from the pool, or as a FIFO (first in, first out) queue, where the pool * always returns the oldest object in the idle object pool. * - * @return true
if the pool is configured with LIFO behaviour - * orfalse
if the pool is configured with FIFO - * behaviour + * @return {@code true} if the pool is configured with LIFO behavior + * or {@code false} if the pool is configured with FIFO + * behavior * * @see #setLifo */ @@ -268,7 +300,7 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * Returns whether or not the pool serves threads waiting to borrow objects fairly. * True means that waiting threads are served as if waiting in a FIFO queue. * - * @return true
if waiting threads are to be served + * @return {@code true} if waiting threads are to be served * by the pool in arrival order */ public final boolean getFairness() { @@ -276,14 +308,14 @@ public abstract class BaseGenericObjectPoolextends BaseObject { } /** - * Sets whether the pool has LIFO (last in, first out) behaviour with + * Sets whether the pool has LIFO (last in, first out) behavior with * respect to idle objects - always returning the most recently used object * from the pool, or as a FIFO (first in, first out) queue, where the pool * always returns the oldest object in the idle object pool. * - * @param lifo true
if the pool is to be configured with LIFO - * behaviour orfalse
if the pool is to be - * configured with FIFO behaviour + * @param lifo {@code true} if the pool is to be configured with LIFO + * behavior or {@code false} if the pool is to be + * configured with FIFO behavior * * @see #getLifo() */ @@ -293,13 +325,13 @@ public abstract class BaseGenericObjectPoolextends BaseObject { /** * Returns whether objects created for the pool will be validated before - * being returned from the borrowObject()
method. Validation is - * performed by thevalidateObject()
method of the factory + * being returned from the {@code borrowObject()} method. Validation is + * performed by the {@code validateObject()} method of the factory * associated with the pool. If the object fails to validate, then - *borrowObject()
will fail. + * {@code borrowObject()} will fail. * - * @returntrue
if newly created objects are validated before - * being returned from theborrowObject()
method + * @return {@code true} if newly created objects are validated before + * being returned from the {@code borrowObject()} method * * @see #setTestOnCreate * @@ -311,14 +343,14 @@ public abstract class BaseGenericObjectPoolextends BaseObject { /** * Sets whether objects created for the pool will be validated before - * being returned from the borrowObject()
method. Validation is - * performed by thevalidateObject()
method of the factory + * being returned from the {@code borrowObject()} method. Validation is + * performed by the {@code validateObject()} method of the factory * associated with the pool. If the object fails to validate, then - *borrowObject()
will fail. + * {@code borrowObject()} will fail. * - * @param testOnCreatetrue
if newly created objects should be + * @param testOnCreate {@code true} if newly created objects should be * validated before being returned from the - *borrowObject()
method + * {@code borrowObject()} method * * @see #getTestOnCreate * @@ -330,14 +362,14 @@ public abstract class BaseGenericObjectPoolextends BaseObject { /** * Returns whether objects borrowed from the pool will be validated before - * being returned from the borrowObject()
method. Validation is - * performed by thevalidateObject()
method of the factory + * being returned from the {@code borrowObject()} method. Validation is + * performed by the {@code validateObject()} method of the factory * associated with the pool. If the object fails to validate, it will be * removed from the pool and destroyed, and a new attempt will be made to * borrow an object from the pool. * - * @returntrue
if objects are validated before being returned - * from theborrowObject()
method + * @return {@code true} if objects are validated before being returned + * from the {@code borrowObject()} method * * @see #setTestOnBorrow */ @@ -347,15 +379,15 @@ public abstract class BaseGenericObjectPoolextends BaseObject { /** * Sets whether objects borrowed from the pool will be validated before - * being returned from the borrowObject()
method. Validation is - * performed by thevalidateObject()
method of the factory + * being returned from the {@code borrowObject()} method. Validation is + * performed by the {@code validateObject()} method of the factory * associated with the pool. If the object fails to validate, it will be * removed from the pool and destroyed, and a new attempt will be made to * borrow an object from the pool. * - * @param testOnBorrowtrue
if objects should be validated + * @param testOnBorrow {@code true} if objects should be validated * before being returned from the - *borrowObject()
method + * {@code borrowObject()} method * * @see #getTestOnBorrow */ @@ -365,13 +397,13 @@ public abstract class BaseGenericObjectPoolextends BaseObject { /** * Returns whether objects borrowed from the pool will be validated when - * they are returned to the pool via the returnObject()
method. - * Validation is performed by thevalidateObject()
method of + * they are returned to the pool via the {@code returnObject()} method. + * Validation is performed by the {@code validateObject()} method of * the factory associated with the pool. Returning objects that fail validation * are destroyed rather then being returned the pool. * - * @returntrue
if objects are validated on return to - * the pool via thereturnObject()
method + * @return {@code true} if objects are validated on return to + * the pool via the {@code returnObject()} method * * @see #setTestOnReturn */ @@ -381,14 +413,14 @@ public abstract class BaseGenericObjectPoolextends BaseObject { /** * Sets whether objects borrowed from the pool will be validated when - * they are returned to the pool via the returnObject()
method. - * Validation is performed by thevalidateObject()
method of + * they are returned to the pool via the {@code returnObject()} method. + * Validation is performed by the {@code validateObject()} method of * the factory associated with the pool. Returning objects that fail validation * are destroyed rather then being returned the pool. * - * @param testOnReturntrue
if objects are validated on + * @param testOnReturn {@code true} if objects are validated on * return to the pool via the - *returnObject()
method + * {@code returnObject()} method * * @see #getTestOnReturn */ @@ -400,11 +432,11 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * Returns whether objects sitting idle in the pool will be validated by the * idle object evictor (if any - see * {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed - * by the validateObject()
method of the factory associated + * by the {@code validateObject()} method of the factory associated * with the pool. If the object fails to validate, it will be removed from * the pool and destroyed. * - * @returntrue
if objects will be validated by the evictor + * @return {@code true} if objects will be validated by the evictor * * @see #setTestWhileIdle * @see #setTimeBetweenEvictionRunsMillis @@ -417,14 +449,14 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * Returns whether objects sitting idle in the pool will be validated by the * idle object evictor (if any - see * {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed - * by the validateObject()
method of the factory associated + * by the {@code validateObject()} method of the factory associated * with the pool. If the object fails to validate, it will be removed from * the pool and destroyed. Note that setting this property has no effect * unless the idle object evictor is enabled by setting - *timeBetweenEvictionRunsMillis
to a positive value. + * {@code timeBetweenEvictionRunsMillis} to a positive value. * * @param testWhileIdle - *true
so objects will be validated by the evictor + * {@code true} so objects will be validated by the evictor * * @see #getTestWhileIdle * @see #setTimeBetweenEvictionRunsMillis @@ -447,9 +479,11 @@ public abstract class BaseGenericObjectPoolextends BaseObject { } /** - * Sets the number of milliseconds to sleep between runs of the idle - * object evictor thread. When non-positive, no idle object evictor thread - * will be run. + * Sets the number of milliseconds to sleep between runs of the idle object evictor thread. + * + *
* * @param timeBetweenEvictionRunsMillis * number of milliseconds to sleep between evictor runs @@ -469,7 +503,7 @@ public abstract class BaseGenericObjectPool- When positive, the idle object evictor thread starts.
+ *- When non-positive, no idle object evictor thread runs.
+ *extends BaseObject { * number of idle instances in the pool. When negative, the number of tests * performed will be ceil({@link #getNumIdle}/ * abs({@link #getNumTestsPerEvictionRun}))
which means that when the - * value is-n
roughly one nth of the idle objects will be + * value is {@code -n} roughly one nth of the idle objects will be * tested per run. * * @return max number of objects to examine during each evictor run @@ -488,7 +522,7 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * number of idle instances in the pool. When negative, the number of tests * performed will be ceil({@link #getNumIdle}/ * abs({@link #getNumTestsPerEvictionRun}))
which means that when the - * value is-n
roughly one nth of the idle objects will be + * value is {@code -n} roughly one nth of the idle objects will be * tested per run. * * @param numTestsPerEvictionRun @@ -539,7 +573,7 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * Returns the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor (if any - * see {@link #setTimeBetweenEvictionRunsMillis(long)}), - * with the extra condition that at least minIdle
object + * with the extra condition that at least {@code minIdle} object * instances remain in the pool. This setting is overridden by * {@link #getMinEvictableIdleTimeMillis} (that is, if * {@link #getMinEvictableIdleTimeMillis} is positive, then @@ -558,7 +592,7 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * Sets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor (if any - * see {@link #setTimeBetweenEvictionRunsMillis(long)}), - * with the extra condition that at least minIdle
object + * with the extra condition that at least {@code minIdle} object * instances remain in the pool. This setting is overridden by * {@link #getMinEvictableIdleTimeMillis} (that is, if * {@link #getMinEvictableIdleTimeMillis} is positive, then @@ -589,59 +623,81 @@ public abstract class BaseGenericObjectPoolextends BaseObject { } /** - * Sets the name of the {@link EvictionPolicy} implementation that is - * used by this pool. The Pool will attempt to load the class using the - * thread context class loader. If that fails, the Pool will attempt to load - * the class using the class loader that loaded this class. + * Sets the eviction policy for this pool. * - * @param evictionPolicyClassName the fully qualified class name of the - * new eviction policy + * @param evictionPolicy + * the eviction policy for this pool. + * @since 2.6.0 + */ + public void setEvictionPolicy(final EvictionPolicy evictionPolicy) { + this.evictionPolicy = evictionPolicy; + } + + /** + * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to + * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy} + * interface. + * + * @param evictionPolicyClassName + * the fully qualified class name of the new eviction policy + * @param classLoader + * the class loader to load the given {@code evictionPolicyClassName}. * * @see #getEvictionPolicyClassName() + * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the + * {@link EvictionPolicy} interface. */ - public final void setEvictionPolicyClassName( - final String evictionPolicyClassName) { + public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) { + // Getting epClass here and now best matches the caller's environment + final Class> epClass = EvictionPolicy.class; + final ClassLoader epClassLoader = epClass.getClassLoader(); try { - Class> clazz; try { - clazz = Class.forName(evictionPolicyClassName, true, - Thread.currentThread().getContextClassLoader()); - } catch (final ClassNotFoundException e) { - clazz = Class.forName(evictionPolicyClassName); - } - final Object policy = clazz.getConstructor().newInstance(); - if (policy instanceof EvictionPolicy>) { - @SuppressWarnings("unchecked") // safe, because we just checked the class - final - EvictionPolicy evicPolicy = (EvictionPolicy ) policy; - this.evictionPolicy = evicPolicy; - } else { - throw new IllegalArgumentException("[" + evictionPolicyClassName + - "] does not implement EvictionPolicy"); + setEvictionPolicy(evictionPolicyClassName, classLoader); + } catch (final ClassCastException | ClassNotFoundException e) { + setEvictionPolicy(evictionPolicyClassName, epClassLoader); } - } catch (final ClassNotFoundException e) { - throw new IllegalArgumentException( - "Unable to create EvictionPolicy instance of type " + - evictionPolicyClassName, e); - } catch (final InstantiationException e) { - throw new IllegalArgumentException( - "Unable to create EvictionPolicy instance of type " + - evictionPolicyClassName, e); - } catch (final IllegalAccessException e) { - throw new IllegalArgumentException( - "Unable to create EvictionPolicy instance of type " + - evictionPolicyClassName, e); - } catch (final InvocationTargetException e) { - throw new IllegalArgumentException( - "Unable to create EvictionPolicy instance of type " + - evictionPolicyClassName, e); - } catch (final NoSuchMethodException e) { - throw new IllegalArgumentException( - "Unable to create EvictionPolicy instance of type " + - evictionPolicyClassName, e); + } catch (final ClassCastException e) { + throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" + + classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME); + } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException | + InvocationTargetException | NoSuchMethodException e) { + final String exMessage = "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " + + evictionPolicyClassName; + throw new IllegalArgumentException(exMessage, e); } } + /** + * Sets the eviction policy. + * + * @param className Eviction policy class name. + * @param classLoader Load the class from this class loader. + */ + @SuppressWarnings("unchecked") + private void setEvictionPolicy(final String className, final ClassLoader classLoader) + throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + final Class> clazz = Class.forName(className, true, classLoader); + final Object policy = clazz.getConstructor().newInstance(); + this.evictionPolicy = (EvictionPolicy ) policy; + } + + /** + * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to + * load the class using the thread context class loader. If that fails, the use the class loader for the + * {@link EvictionPolicy} interface. + * + * @param evictionPolicyClassName + * the fully qualified class name of the new eviction policy + * + * @see #getEvictionPolicyClassName() + * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the + * {@link EvictionPolicy} interface. + */ + public final void setEvictionPolicyClassName(final String evictionPolicyClassName) { + setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader()); + } + /** * Gets the timeout that will be used when waiting for the Evictor to * shutdown if this pool is closed and it is the only pool still using the @@ -676,18 +732,18 @@ public abstract class BaseGenericObjectPool extends BaseObject { /** * Has this pool instance been closed. - * @return true
when this pool has been closed. + * @return {@code true} when this pool has been closed. */ public final boolean isClosed() { return closed; } /** - *Perform
numTests
idle object eviction tests, evicting + *Perform {@code numTests} idle object eviction tests, evicting * examined objects that meet the criteria for eviction. If - *
* * @throws Exception when there is a problem evicting idle objects. @@ -699,8 +755,9 @@ public abstract class BaseGenericObjectPooltestWhileIdle
is true, examined objects are validated + * {@code testWhileIdle} is true, examined objects are validated * when visited (and removed if invalid); otherwise only objects that - * have been idle for more thanminEvicableIdleTimeMillis
+ * have been idle for more than {@code minEvicableIdleTimeMillis} * are removed.extends BaseObject { * * @return the eviction policy * @since 2.4 + * @since 2.6.0 Changed access from protected to public. */ - protected EvictionPolicy getEvictionPolicy() { + public EvictionPolicy getEvictionPolicy() { return evictionPolicy; } @@ -726,18 +783,33 @@ public abstract class BaseGenericObjectPool extends BaseObject { */ final void startEvictor(final long delay) { synchronized (evictionLock) { - if (null != evictor) { - EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS); - evictor = null; - evictionIterator = null; - } - if (delay > 0) { - evictor = new Evictor(); - EvictionTimer.schedule(evictor, delay, delay); + if (evictor == null) { // Starting evictor for the first time or after a cancel + if (delay > 0) { // Starting new evictor + evictor = new Evictor(); + EvictionTimer.schedule(evictor, delay, delay); + } + } else { // Stop or restart of existing evictor + if (delay > 0) { // Restart + synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls + EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS, true); + evictor = null; + evictionIterator = null; + evictor = new Evictor(); + EvictionTimer.schedule(evictor, delay, delay); + } + } else { // Stopping evictor + EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS, false); + } } } } + /** + * Stops the evictor. + */ + void stopEvictor() { + startEvictor(-1L); + } /** * Tries to ensure that the configured minimum number of idle instances are * available in the pool. @@ -750,12 +822,12 @@ public abstract class BaseGenericObjectPool extends BaseObject { /** * Provides the name under which the pool has been registered with the - * platform MBean server or null
if the pool has not been + * platform MBean server or {@code null} if the pool has not been * registered. * @return the JMX name */ public final ObjectName getJmxName() { - return oname; + return objectName; } /** @@ -818,7 +890,7 @@ public abstract class BaseGenericObjectPoolextends BaseObject { /** * The total number of objects destroyed by this pool as a result of failing - * validation during borrowObject()
over the lifetime of the + * validation during {@code borrowObject()} over the lifetime of the * pool. * @return validation destroyed object count */ @@ -874,7 +946,7 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * The listener used (if any) to receive notifications of exceptions * unavoidably swallowed by the pool. * - * @return The listener or null
for no listener + * @return The listener or {@code null} for no listener */ public final SwallowedExceptionListener getSwallowedExceptionListener() { return swallowedExceptionListener; @@ -884,7 +956,7 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * The listener used (if any) to receive notifications of exceptions * unavoidably swallowed by the pool. * - * @param swallowedExceptionListener The listener or null
+ * @param swallowedExceptionListener The listener or {@code null} * for no listener */ public final void setSwallowedExceptionListener( @@ -896,9 +968,9 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * Swallows an exception and notifies the configured listener for swallowed * exceptions queue. * - * @param e exception to be swallowed + * @param swallowException exception to be swallowed */ - final void swallowException(final Exception e) { + final void swallowException(final Exception swallowException) { final SwallowedExceptionListener listener = getSwallowedExceptionListener(); if (listener == null) { @@ -906,11 +978,9 @@ public abstract class BaseGenericObjectPool extends BaseObject { } try { - listener.onSwallowException(e); - } catch (final OutOfMemoryError oome) { - throw oome; - } catch (final VirtualMachineError vme) { - throw vme; + listener.onSwallowException(swallowException); + } catch (final VirtualMachineError e) { + throw e; } catch (final Throwable t) { // Ignore. Enjoy the irony. } @@ -946,17 +1016,30 @@ public abstract class BaseGenericObjectPool extends BaseObject { activeTimes.add(activeTime); } + /** + * Marks the object as returning to the pool. + * @param pooledObject instance to return to the keyed pool + */ + protected void markReturningState(final PooledObject pooledObject) { + synchronized(pooledObject) { + final PooledObjectState state = pooledObject.getState(); + if (state != PooledObjectState.ALLOCATED) { + throw new IllegalStateException( + "Object has already been returned to this pool or is invalid"); + } + pooledObject.markReturning(); // Keep from being marked abandoned + } + } + /** * Unregisters this pool's MBean. */ final void jmxUnregister() { - if (oname != null) { + if (objectName != null) { try { ManagementFactory.getPlatformMBeanServer().unregisterMBean( - oname); - } catch (final MBeanRegistrationException e) { - swallowException(e); - } catch (final InstanceNotFoundException e) { + objectName); + } catch (final MBeanRegistrationException | InstanceNotFoundException e) { swallowException(e); } } @@ -965,7 +1048,7 @@ public abstract class BaseGenericObjectPool extends BaseObject { /** * Registers the pool with the platform MBean server. * The registered name will be - * jmxNameBase + jmxNamePrefix + i
where i is the least + * {@code jmxNameBase + jmxNamePrefix + i} where i is the least * integer greater than or equal to 1 such that the name is not already * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException * returning null. @@ -975,9 +1058,9 @@ public abstract class BaseGenericObjectPoolextends BaseObject { * @param jmxNamePrefix name prefix * @return registered ObjectName, null if registration fails */ - private ObjectName jmxRegister(final BaseObjectPoolConfig config, + private ObjectName jmxRegister(final BaseObjectPoolConfig config, final String jmxNameBase, String jmxNamePrefix) { - ObjectName objectName = null; + ObjectName newObjectName = null; final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); int i = 1; boolean registered = false; @@ -996,7 +1079,7 @@ public abstract class BaseGenericObjectPool extends BaseObject { objName = new ObjectName(base + jmxNamePrefix + i); } mbs.registerMBean(this, objName); - objectName = objName; + newObjectName = objName; registered = true; } catch (final MalformedObjectNameException e) { if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals( @@ -1012,15 +1095,12 @@ public abstract class BaseGenericObjectPool extends BaseObject { } catch (final InstanceAlreadyExistsException e) { // Increment the index and try again i++; - } catch (final MBeanRegistrationException e) { - // Shouldn't happen. Skip registration if it does. - registered = true; - } catch (final NotCompliantMBeanException e) { + } catch (final MBeanRegistrationException | NotCompliantMBeanException e) { // Shouldn't happen. Skip registration if it does. registered = true; } } - return objectName; + return newObjectName; } /** @@ -1045,7 +1125,10 @@ public abstract class BaseGenericObjectPool extends BaseObject { * * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis */ - class Evictor extends TimerTask { + class Evictor implements Runnable { + + private ScheduledFuture> scheduledFuture; + /** * Run pool maintenance. Evict objects qualifying for eviction and then * ensure that the minimum number of idle instances are available. @@ -1093,6 +1176,25 @@ public abstract class BaseGenericObjectPool extends BaseObject { Thread.currentThread().setContextClassLoader(savedClassLoader); } } + + + /** + * Sets the scheduled future. + * + * @param scheduledFuture the scheduled future. + */ + void setScheduledFuture(final ScheduledFuture> scheduledFuture) { + this.scheduledFuture = scheduledFuture; + } + + + /** + * Cancels the scheduled future. + */ + void cancel() { + scheduledFuture.cancel(false); + } + } /** @@ -1309,7 +1411,7 @@ public abstract class BaseGenericObjectPool extends BaseObject { builder.append(", factoryClassLoader="); builder.append(factoryClassLoader); builder.append(", oname="); - builder.append(oname); + builder.append(objectName); builder.append(", creationStackTrace="); builder.append(creationStackTrace); builder.append(", borrowedCount="); @@ -1336,4 +1438,5 @@ public abstract class BaseGenericObjectPool extends BaseObject { builder.append(swallowedExceptionListener); } + } diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/BaseObjectPoolConfig.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/BaseObjectPoolConfig.java index f54c51456..0f6a7418d 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/BaseObjectPoolConfig.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/BaseObjectPoolConfig.java @@ -24,10 +24,12 @@ import com.fr.third.org.apache.commons.pool2.BaseObject; * defined by the public constants. * * This class is not thread-safe. + *
* + * @paramType of element pooled. * @since 2.0 */ -public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneable { +public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneable { /** * The default value for the {@code lifo} configuration attribute. @@ -146,7 +148,7 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneab /** * The default value for the base name to use to name JMX enabled pools - * created with a configuration instance. The default is null
+ * created with a configuration instance. The default is {@code null} * which means the pool will provide the base name to use. * @see GenericObjectPool#getJmxName() * @see GenericKeyedObjectPool#getJmxName() @@ -159,9 +161,7 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneab * @see GenericObjectPool#getEvictionPolicyClassName() * @see GenericKeyedObjectPool#getEvictionPolicyClassName() */ - public static final String DEFAULT_EVICTION_POLICY_CLASS_NAME = - "com.fr.third.org.apache.commons.pool2.impl.DefaultEvictionPolicy"; - + public static final String DEFAULT_EVICTION_POLICY_CLASS_NAME = DefaultEvictionPolicy.class.getName(); private boolean lifo = DEFAULT_LIFO; @@ -181,6 +181,8 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneab private int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN; + private EvictionPolicyevictionPolicy = null; // Only 2.6.0 applications set this + private String evictionPolicyClassName = DEFAULT_EVICTION_POLICY_CLASS_NAME; private boolean testOnCreate = DEFAULT_TEST_ON_CREATE; @@ -552,6 +554,21 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneab this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } + /** + * Get the value for the {@code evictionPolicyClass} configuration + * attribute for pools created with this configuration instance. + * + * @return The current setting of {@code evictionPolicyClass} for this + * configuration instance + * + * @see GenericObjectPool#getEvictionPolicy() + * @see GenericKeyedObjectPool#getEvictionPolicy() + * @since 2.6.0 + */ + public EvictionPolicy getEvictionPolicy() { + return evictionPolicy; + } + /** * Get the value for the {@code evictionPolicyClassName} configuration * attribute for pools created with this configuration instance. @@ -566,6 +583,21 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneab return evictionPolicyClassName; } + /** + * Set the value for the {@code evictionPolicyClass} configuration + * attribute for pools created with this configuration instance. + * + * @param evictionPolicy The new setting of + * {@code evictionPolicyClass} for this configuration instance + * + * @see GenericObjectPool#getEvictionPolicy() + * @see GenericKeyedObjectPool#getEvictionPolicy() + * @since 2.6.0 + */ + public void setEvictionPolicy(final EvictionPolicy evictionPolicy) { + this.evictionPolicy = evictionPolicy; + } + /** * Set the value for the {@code evictionPolicyClassName} configuration * attribute for pools created with this configuration instance. @@ -633,7 +665,7 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneab /** * Gets the value of the JMX name base that will be used as part of the * name assigned to JMX enabled pools created with this configuration - * instance. A value of null
means that the pool will define + * instance. A value of {@code null} means that the pool will define * the JMX name base. * * @return The current setting of {@code jmxNameBase} for this @@ -646,7 +678,7 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneab /** * Sets the value of the JMX name base that will be used as part of the * name assigned to JMX enabled pools created with this configuration - * instance. A value ofnull
means that the pool will define + * instance. A value of {@code null} means that the pool will define * the JMX name base. * * @param jmxNameBase The new setting of {@code jmxNameBase} diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/CallStackUtils.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/CallStackUtils.java index e223fb745..686dad881 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/CallStackUtils.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/CallStackUtils.java @@ -25,13 +25,9 @@ import java.security.AccessControlException; */ public final class CallStackUtils { - private static final boolean CAN_CREATE_SECURITY_MANAGER; - - static { - CAN_CREATE_SECURITY_MANAGER = canCreateSecurityManager(); - } - /** + * Returns whether the caller can create a security manager in the current environment. + * * @return {@code true} if it is able to create a security manager in the current environment, {@code false} * otherwise. */ @@ -76,9 +72,9 @@ public final class CallStackUtils { public static CallStack newCallStack(final String messageFormat, final boolean useTimestamp, final boolean requireFullStackTrace) { - return CAN_CREATE_SECURITY_MANAGER && !requireFullStackTrace - ? new SecurityManagerCallStack(messageFormat, useTimestamp) - : new ThrowableCallStack(messageFormat, useTimestamp); + return canCreateSecurityManager() && !requireFullStackTrace ? + new SecurityManagerCallStack(messageFormat, useTimestamp) : + new ThrowableCallStack(messageFormat, useTimestamp); } /** diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultEvictionPolicy.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultEvictionPolicy.java index ad5afc601..5be188f8c 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultEvictionPolicy.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultEvictionPolicy.java @@ -31,7 +31,9 @@ import com.fr.third.org.apache.commons.pool2.PooledObject; * {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} / * {@link GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()} * + ** This class is immutable and thread-safe. + *
* * @paramthe type of objects in the pool * diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObject.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObject.java index c7dd093ec..740bff894 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObject.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObject.java @@ -28,6 +28,7 @@ import java.util.Deque; * the pooled objects. * * This class is intended to be thread-safe. + *
* * @paramthe type of object in the pool * @@ -47,7 +48,7 @@ public class DefaultPooledObject implements PooledObject { private volatile long borrowedCount = 0; /** - * Create a new instance that wraps the provided object so that the pool can + * Creates a new instance that wraps the provided object so that the pool can * track the state of the pooled object. * * @param object The object to wrap @@ -81,10 +82,10 @@ public class DefaultPooledObject implements PooledObject { @Override public long getIdleTimeMillis() { final long elapsed = System.currentTimeMillis() - lastReturnTime; - // elapsed may be negative if: - // - another thread updates lastReturnTime during the calculation window - // - System.currentTimeMillis() is not monotonic (e.g. system time is set back) - return elapsed >= 0 ? elapsed : 0; + // elapsed may be negative if: + // - another thread updates lastReturnTime during the calculation window + // - System.currentTimeMillis() is not monotonic (e.g. system time is set back) + return elapsed >= 0 ? elapsed : 0; } @Override @@ -98,16 +99,17 @@ public class DefaultPooledObject implements PooledObject { } /** - * Get the number of times this object has been borrowed. + * Gets the number of times this object has been borrowed. * @return The number of times this object has been borrowed. * @since 2.1 */ + @Override public long getBorrowedCount() { return borrowedCount; } /** - * Return an estimate of the last time this object was used. If the class + * Returns an estimate of the last time this object was used. If the class * of the pooled object implements {@link TrackedUse}, what is returned is * the maximum of {@link TrackedUse#getLastUsed()} and * {@link #getLastBorrowTime()}; otherwise this method gives the same @@ -204,9 +206,11 @@ public class DefaultPooledObject implements PooledObject { /** * Deallocates the object and sets it {@link PooledObjectState#IDLE IDLE} - * if it is currently {@link PooledObjectState#ALLOCATED ALLOCATED}. + * if it is currently {@link PooledObjectState#ALLOCATED ALLOCATED} + * or {@link PooledObjectState#RETURNING RETURNING}. * * @return {@code true} if the state was {@link PooledObjectState#ALLOCATED ALLOCATED} + * or {@link PooledObjectState#RETURNING RETURNING}. */ @Override public synchronized boolean deallocate() { @@ -284,8 +288,7 @@ public class DefaultPooledObject implements PooledObject { * logging * @since 2.5 */ - // TODO: uncomment below in 3.0 - // @Override + @Override public void setRequireFullStackTrace(final boolean requireFullStackTrace) { borrowedBy = CallStackUtils.newCallStack("'Pooled object created' " + "yyyy-MM-dd HH:mm:ss Z 'by the following code has not been returned to the pool:'", diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObjectInfo.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObjectInfo.java index 3dd860fce..da38f7eb8 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObjectInfo.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObjectInfo.java @@ -93,11 +93,7 @@ public class DefaultPooledObjectInfo implements DefaultPooledObjectInfoMBean { @Override public long getBorrowedCount() { - // TODO Simplify this once getBorrowedCount has been added to PooledObject - if (pooledObject instanceof DefaultPooledObject) { - return ((DefaultPooledObject>) pooledObject).getBorrowedCount(); - } - return -1; + return pooledObject.getBorrowedCount(); } /** diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObjectInfoMBean.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObjectInfoMBean.java index 13d17236a..2259072a3 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObjectInfoMBean.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/DefaultPooledObjectInfoMBean.java @@ -42,7 +42,7 @@ public interface DefaultPooledObjectInfoMBean { * Obtain the time that pooled object was created. * * @return The creation time for the pooled object formatted as - * yyyy-MM-dd HH:mm:ss Z
+ * {@code yyyy-MM-dd HH:mm:ss Z} */ String getCreateTimeFormatted(); @@ -57,8 +57,8 @@ public interface DefaultPooledObjectInfoMBean { /** * Obtain the time that pooled object was last borrowed. * - * @return The last borrowed time for the pooled object formated as - *yyyy-MM-dd HH:mm:ss Z
+ * @return The last borrowed time for the pooled object formatted as + * {@code yyyy-MM-dd HH:mm:ss Z} */ String getLastBorrowTimeFormatted(); @@ -82,8 +82,8 @@ public interface DefaultPooledObjectInfoMBean { /** * Obtain the time that pooled object was last returned. * - * @return The last returned time for the pooled object formated as - *yyyy-MM-dd HH:mm:ss Z
+ * @return The last returned time for the pooled object formatted as + * {@code yyyy-MM-dd HH:mm:ss Z} */ String getLastReturnTimeFormatted(); diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionConfig.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionConfig.java index a4cac4df8..c40619584 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionConfig.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionConfig.java @@ -22,6 +22,7 @@ package com.fr.third.org.apache.commons.pool2.impl; * its own specific configuration attributes. ** This class is immutable and thread-safe. + *
* * @since 2.0 */ diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionPolicy.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionPolicy.java index c2ea2132d..0be30e47b 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionPolicy.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionPolicy.java @@ -37,9 +37,8 @@ public interface EvictionPolicy{ * @param underTest The pooled object being tested for eviction * @param idleCount The current number of idle objects in the pool including * the object under test - * @return true
if the object should be evicted, otherwise - *false
+ * @return {@code true} if the object should be evicted, otherwise + * {@code false} */ - boolean evict(EvictionConfig config, PooledObjectunderTest, - int idleCount); + boolean evict(EvictionConfig config, PooledObject underTest, int idleCount); } diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionTimer.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionTimer.java index 5a241c5d6..444d588ef 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionTimer.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/EvictionTimer.java @@ -16,26 +16,32 @@ */ package com.fr.third.org.apache.commons.pool2.impl; +import java.lang.ref.WeakReference; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.TimerTask; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; + /** - * Provides a shared idle object eviction timer for all pools. This class is - * currently implemented using {@link ScheduledThreadPoolExecutor}. This - * implementation may change in any future release. This class keeps track of - * how many pools are using it. If no pools are using the timer, it is cancelled. - * This prevents a thread being left running which, in application server - * environments, can lead to memory leads and/or prevent applications from - * shutting down or reloading cleanly. + * Provides a shared idle object eviction timer for all pools. + * + * This class is currently implemented using {@link ScheduledThreadPoolExecutor}. This implementation may change in any + * future release. This class keeps track of how many pools are using it. If no pools are using the timer, it is + * cancelled. This prevents a thread being left running which, in application server environments, can lead to memory + * leads and/or prevent applications from shutting down or reloading cleanly. + *
*- * This class has package scope to prevent its inclusion in the pool public API. - * The class declaration below should *not* be changed to public. + * This class has package scope to prevent its inclusion in the pool public API. The class declaration below should + * *not* be changed to public. + *
** This class is intended to be thread-safe. + *
* * @since 2.0 */ @@ -44,10 +50,10 @@ class EvictionTimer { /** Executor instance */ private static ScheduledThreadPoolExecutor executor; //@GuardedBy("EvictionTimer.class") - /** Static usage count tracker */ - private static int usageCount; //@GuardedBy("EvictionTimer.class") + /** Keys are weak references to tasks, values are runners managed by executor. */ + private static final HashMap, WeakRunner> taskMap = new HashMap<>(); // @GuardedBy("EvictionTimer.class") - /** Prevent instantiation */ + /** Prevents instantiation */ private EvictionTimer() { // Hide the default constructor } @@ -63,37 +69,50 @@ class EvictionTimer { return builder.toString(); } - /** - * Add the specified eviction task to the timer. Tasks that are added with a - * call to this method *must* call {@link #cancel(TimerTask)} to cancel the - * task to prevent memory and/or thread leaks in application server - * environments. - * @param task Task to be scheduled - * @param delay Delay in milliseconds before task is executed - * @param period Time in milliseconds between executions + * Adds the specified eviction task to the timer. Tasks that are added with + * a call to this method *must* call {@link + * #cancel(org.apache.commons.pool2.impl.BaseGenericObjectPool.Evictor, long, TimeUnit)} + * to cancel the task to prevent memory and/or thread leaks in application + * server environments. + * + * @param task Task to be scheduled. + * @param delay Delay in milliseconds before task is executed. + * @param period Time in milliseconds between executions. */ - static synchronized void schedule(final Runnable task, final long delay, final long period) { + static synchronized void schedule( + final BaseGenericObjectPool>.Evictor task, final long delay, final long period) { if (null == executor) { executor = new ScheduledThreadPoolExecutor(1, new EvictorThreadFactory()); + executor.setRemoveOnCancelPolicy(true); + executor.scheduleAtFixedRate(new Reaper(), delay, period, TimeUnit.MILLISECONDS); } - usageCount++; - executor.scheduleWithFixedDelay(task, delay, period, TimeUnit.MILLISECONDS); + final WeakReference ref = new WeakReference<>(task); + final WeakRunner runner = new WeakRunner(ref); + final ScheduledFuture> scheduledFuture = + executor.scheduleWithFixedDelay(runner, delay, period, TimeUnit.MILLISECONDS); + task.setScheduledFuture(scheduledFuture); + taskMap.put(ref, runner); } /** - * Remove the specified eviction task from the timer. + * Removes the specified eviction task from the timer. * - * @param task Task to be cancelled + * @param evictor Task to be cancelled. * @param timeout If the associated executor is no longer required, how * long should this thread wait for the executor to * terminate? - * @param unit The units for the specified timeout + * @param unit The units for the specified timeout. + * @param restarting The state of the evictor. */ - static synchronized void cancel(final TimerTask task, final long timeout, final TimeUnit unit) { - task.cancel(); - usageCount--; - if (usageCount == 0) { + static synchronized void cancel( + final BaseGenericObjectPool>.Evictor evictor, final long timeout, final TimeUnit unit, + final boolean restarting) { + if (evictor != null) { + evictor.cancel(); + remove(evictor); + } + if (!restarting && executor != null && taskMap.isEmpty()) { executor.shutdown(); try { executor.awaitTermination(timeout, unit); @@ -107,23 +126,95 @@ class EvictionTimer { } /** - * Thread factory that creates a thread, with the context classloader from this class. + * Removes evictor from the task set and executor. + * Only called when holding the class lock. + * + * @param evictor Eviction task to remove + */ + private static void remove(final BaseGenericObjectPool>.Evictor evictor) { + for (Entry , WeakRunner> entry : taskMap.entrySet()) { + if (entry.getKey().get() == evictor) { + executor.remove(entry.getValue()); + taskMap.remove(entry.getKey()); + break; + } + } + } + + /** + * @return the number of eviction tasks under management. + */ + static synchronized int getNumTasks() { + return taskMap.size(); + } + + /** + * Thread factory that creates a daemon thread, with the context class loader from this class. */ private static class EvictorThreadFactory implements ThreadFactory { @Override - public Thread newThread(final Runnable r) { - final Thread t = new Thread(null, r, "commons-pool-evictor-thread"); - - AccessController.doPrivileged(new PrivilegedAction () { - @Override - public Void run() { - t.setContextClassLoader(EvictorThreadFactory.class.getClassLoader()); - return null; - } + public Thread newThread(final Runnable runnable) { + final Thread thread = new Thread(null, runnable, "commons-pool-evictor-thread"); + thread.setDaemon(true); // POOL-363 - Required for applications using Runtime.addShutdownHook(). + AccessController.doPrivileged((PrivilegedAction ) () -> { + thread.setContextClassLoader(EvictorThreadFactory.class.getClassLoader()); + return null; }); - return t; + return thread; + } + } + + /** + * Task that removes references to abandoned tasks and shuts + * down the executor if there are no live tasks left. + */ + private static class Reaper implements Runnable { + @Override + public void run() { + synchronized (EvictionTimer.class) { + for (Entry , WeakRunner> entry : taskMap.entrySet()) { + if (entry.getKey().get() == null) { + executor.remove(entry.getValue()); + taskMap.remove(entry.getKey()); + } + } + if (taskMap.isEmpty() && executor != null) { + executor.shutdown(); + executor.setCorePoolSize(0); + executor = null; + } + } + } + } + + /** + * Runnable that runs the referent of a weak reference. When the referent is no + * no longer reachable, run is no-op. + */ + private static class WeakRunner implements Runnable { + + private final WeakReference ref; + + /** + * Constructs a new instance to track the given reference. + * + * @param ref the reference to track. + */ + private WeakRunner(final WeakReference ref) { + this.ref = ref; + } + + @Override + public void run() { + final Runnable task = ref.get(); + if (task != null) { + task.run(); + } else { + executor.remove(this); + taskMap.remove(ref); + } } } } diff --git a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java index 06f0f3a00..7d33be1e3 100644 --- a/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java +++ b/fine-jedis/src/main/java/com/fr/third/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java @@ -33,6 +33,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import com.fr.third.org.apache.commons.pool2.DestroyMode; import com.fr.third.org.apache.commons.pool2.KeyedObjectPool; import com.fr.third.org.apache.commons.pool2.KeyedPooledObjectFactory; import com.fr.third.org.apache.commons.pool2.PoolUtils; @@ -41,20 +42,22 @@ import com.fr.third.org.apache.commons.pool2.PooledObjectState; import com.fr.third.org.apache.commons.pool2.SwallowedExceptionListener; /** - * A configurable KeyedObjectPool
implementation. + * A configurable {@code KeyedObjectPool} implementation. ** When coupled with the appropriate {@link KeyedPooledObjectFactory}, - *
*GenericKeyedObjectPool
provides robust pooling functionality for - * keyed objects. AGenericKeyedObjectPool
can be viewed as a map + * {@code GenericKeyedObjectPool} provides robust pooling functionality for + * keyed objects. A {@code GenericKeyedObjectPool} can be viewed as a map * of sub-pools, keyed on the (unique) key values provided to the * {@link #preparePool preparePool}, {@link #addObject addObject} or * {@link #borrowObject borrowObject} methods. Each time a new key value is * provided to one of these methods, a sub-new pool is created under the given - * key to be managed by the containingGenericKeyedObjectPool.
+ * key to be managed by the containing {@code GenericKeyedObjectPool.} + ** Note that the current implementation uses a ConcurrentHashMap which uses * equals() to compare keys. * This means that distinct instance keys must be distinguishable using equals. + *
** Optionally, one may configure the pool to examine and possibly evict objects * as they sit idle in the pool and to ensure that a minimum number of idle @@ -63,12 +66,15 @@ import com.fr.third.org.apache.commons.pool2.SwallowedExceptionListener; * configuring this optional feature. Eviction runs contend with client threads * for access to objects in the pool, so if they run too frequently performance * issues may result. + *
** Implementation note: To prevent possible deadlocks, care has been taken to * ensure that no call to a factory method will occur within a synchronization * block. See POOL-125 and DBCP-44 for more information. + *
** This class is intended to be thread-safe. + *
* * @see GenericObjectPool * @@ -77,20 +83,20 @@ import com.fr.third.org.apache.commons.pool2.SwallowedExceptionListener; * * @since 2.0 */ -public class GenericKeyedObjectPoolextends BaseGenericObjectPool - implements KeyedObjectPool , GenericKeyedObjectPoolMXBean { +public class GenericKeyedObjectPool extends BaseGenericObjectPool + implements KeyedObjectPool , GenericKeyedObjectPoolMXBean { /** - * Create a new GenericKeyedObjectPool
using defaults from + * Create a new {@code GenericKeyedObjectPool} using defaults from * {@link GenericKeyedObjectPoolConfig}. * @param factory the factory to be used to create entries */ - public GenericKeyedObjectPool(final KeyedPooledObjectFactoryfactory) { - this(factory, new GenericKeyedObjectPoolConfig()); + public GenericKeyedObjectPool(final KeyedPooledObjectFactory factory) { + this(factory, new GenericKeyedObjectPoolConfig ()); } /** - * Create a new GenericKeyedObjectPool
using a specific + * Create a new {@code GenericKeyedObjectPool} using a specific * configuration. * * @param factory the factory to be used to create entries @@ -99,8 +105,8 @@ public class GenericKeyedObjectPoolextends BaseGenericObjectPool * the configuration object will not be reflected in the * pool. */ - public GenericKeyedObjectPool(final KeyedPooledObjectFactory factory, - final GenericKeyedObjectPoolConfig config) { + public GenericKeyedObjectPool(final KeyedPooledObjectFactory factory, + final GenericKeyedObjectPoolConfig config) { super(config, ONAME_BASE, config.getJmxNamePrefix()); @@ -112,8 +118,6 @@ public class GenericKeyedObjectPool extends BaseGenericObjectPool this.fairness = config.getFairness(); setConfig(config); - - startEvictor(getTimeBetweenEvictionRunsMillis()); } /** @@ -238,26 +242,12 @@ public class GenericKeyedObjectPool extends BaseGenericObjectPool * * @see GenericKeyedObjectPoolConfig */ - public void setConfig(final GenericKeyedObjectPoolConfig conf) { - setLifo(conf.getLifo()); + public void setConfig(final GenericKeyedObjectPoolConfig conf) { + super.setConfig(conf); setMaxIdlePerKey(conf.getMaxIdlePerKey()); setMaxTotalPerKey(conf.getMaxTotalPerKey()); setMaxTotal(conf.getMaxTotal()); setMinIdlePerKey(conf.getMinIdlePerKey()); - setMaxWaitMillis(conf.getMaxWaitMillis()); - setBlockWhenExhausted(conf.getBlockWhenExhausted()); - setTestOnCreate(conf.getTestOnCreate()); - setTestOnBorrow(conf.getTestOnBorrow()); - setTestOnReturn(conf.getTestOnReturn()); - setTestWhileIdle(conf.getTestWhileIdle()); - setNumTestsPerEvictionRun(conf.getNumTestsPerEvictionRun()); - setMinEvictableIdleTimeMillis(conf.getMinEvictableIdleTimeMillis()); - setSoftMinEvictableIdleTimeMillis( - conf.getSoftMinEvictableIdleTimeMillis()); - setTimeBetweenEvictionRunsMillis( - conf.getTimeBetweenEvictionRunsMillis()); - setEvictionPolicyClassName(conf.getEvictionPolicyClassName()); - setEvictorShutdownTimeoutMillis(conf.getEvictorShutdownTimeoutMillis()); } /** @@ -290,7 +280,7 @@ public class GenericKeyedObjectPool extends BaseGenericObjectPool * associated with the given key, then an idle instance will be selected * based on the value of {@link #getLifo()}, activated and returned. If * activation fails, or {@link #getTestOnBorrow() testOnBorrow} is set to - * true
and validation fails, the instance is destroyed and the + * {@code true} and validation fails, the instance is destroyed and the * next available instance is examined. This continues until either a valid * instance is returned or there are no more idle instances available. *@@ -298,24 +288,24 @@ public class GenericKeyedObjectPool
extends BaseGenericObjectPool * the given key, behavior depends on the {@link #getMaxTotalPerKey() * maxTotalPerKey}, {@link #getMaxTotal() maxTotal}, and (if applicable) * {@link #getBlockWhenExhausted()} and the value passed in to the - * borrowMaxWaitMillis
parameter. If the number of instances checked + * {@code borrowMaxWaitMillis} parameter. If the number of instances checked * out from the sub-pool under the given key is less than - *maxTotalPerKey
and the total number of instances in - * circulation (under all keys) is less thanmaxTotal
, a new + * {@code maxTotalPerKey} and the total number of instances in + * circulation (under all keys) is less than {@code maxTotal}, a new * instance is created, activated and (if applicable) validated and returned - * to the caller. If validation fails, aNoSuchElementException
+ * to the caller. If validation fails, a {@code NoSuchElementException} * will be thrown. ** If the associated sub-pool is exhausted (no available idle instances and * no capacity to create new ones), this method will either block * ({@link #getBlockWhenExhausted()} is true) or throw a - *
NoSuchElementException
+ * {@code NoSuchElementException} * ({@link #getBlockWhenExhausted()} is false). * The length of time that this method will block when * {@link #getBlockWhenExhausted()} is true is determined by the value - * passed in to theborrowMaxWait
parameter. + * passed in to the {@code borrowMaxWait} parameter. *- * When
maxTotal
is set to a positive value and this method is + * When {@code maxTotal} is set to a positive value and this method is * invoked when at the limit with no idle instances available under the requested * key, an attempt is made to create room by clearing the oldest 15% of the * elements from the keyed sub-pools. @@ -387,7 +377,7 @@ public class GenericKeyedObjectPoolextends BaseGenericObjectPool factory.activateObject(key, p); } catch (final Exception e) { try { - destroy(key, p, true); + destroy(key, p, true, DestroyMode.NORMAL); } catch (final Exception e1) { // Ignore - activation failure is more important } @@ -399,7 +389,7 @@ public class GenericKeyedObjectPool extends BaseGenericObjectPool throw nsee; } } - if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) { + if (p != null && getTestOnBorrow()) { boolean validate = false; Throwable validationThrowable = null; try { @@ -410,7 +400,7 @@ public class GenericKeyedObjectPool extends BaseGenericObjectPool } if (!validate) { try { - destroy(key, p, true); + destroy(key, p, true, DestroyMode.NORMAL); destroyedByBorrowValidationCount.incrementAndGet(); } catch (final Exception e) { // Ignore - validation failure is more important @@ -463,41 +453,31 @@ public class GenericKeyedObjectPool extends BaseGenericObjectPool final ObjectDeque