This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* A base implementation of <code>KeyedPooledObjectFactory</code>.
* <p>
* All operations defined here are essentially no-op's.
* </p>
* <p>
* This class is immutable, and therefore thread-safe.
* </p>
*
* @see KeyedPooledObjectFactory
*
* @param <K> The type of keys managed by this factory.
* @param <V> Type of element managed by this factory.
*
* @since 2.0
*/
public abstract class BaseKeyedPooledObjectFactory<K, V> extends BaseObject
implements KeyedPooledObjectFactory<K, V> {
/**
* Create an instance that can be served by the pool.
*
* @param key the key used when constructing the object
* @return an instance that can be served by the pool
*
* @throws Exception if there is a problem creating a new instance,
* this will be propagated to the code requesting an object.
*/
public abstract V create(K key)
throws Exception;
/**
* Wrap the provided instance with an implementation of
* {@link PooledObject}.
*
* @param value the instance to wrap
*
* @return The provided instance, wrapped by a {@link PooledObject}
*/
public abstract PooledObject<V> wrap(V value);
@Override
public PooledObject<V> makeObject(final K key) throws Exception {
return wrap(create(key));
}
/**
* Destroy an instance no longer needed by the pool.
* <p>
* The default implementation is a no-op.
* </p>
*
* @param key the key used when selecting the instance
* @param p a {@code PooledObject} wrapping the instance to be destroyed
*/
@Override
public void destroyObject(final K key, final PooledObject<V> p)
throws Exception {
// The default implementation is a no-op.
}
/**
* Ensures that the instance is safe to be returned by the pool.
* <p>
* The default implementation always returns {@code true}.
* </p>
*
* @param key the key used when selecting the object
* @param p a {@code PooledObject} wrapping the instance to be validated
* @return always <code>true</code> in the default implementation
*/
@Override
public boolean validateObject(final K key, final PooledObject<V> p) {
return true;
}
/**
* Reinitialize an instance to be returned by the pool.
* <p>
* The default implementation is a no-op.
* </p>
*
* @param key the key used when selecting the object
* @param p a {@code PooledObject} wrapping the instance to be activated
*/
@Override
public void activateObject(final K key, final PooledObject<V> p)
throws Exception {
// The default implementation is a no-op.
}
/**
* Uninitialize an instance to be returned to the idle object pool.
* <p>
* The default implementation is a no-op.
* </p>
*
* @param key the key used when selecting the object
* @param p a {@code PooledObject} wrapping the instance to be passivated
*/
@Override
public void passivateObject(final K key, final PooledObject<V> p)
throws Exception {
// The default implementation is a no-op.
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* A base class for common functionality.
*
* @since 2.4.3
*/
public abstract class BaseObject {
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(getClass().getSimpleName());
builder.append(" [");
toStringAppendFields(builder);
builder.append("]");
return builder.toString();
}
/**
* Used by sub-classes to include the fields defined by the sub-class in the
* {@link #toString()} output.
*
* @param builder Field names and values are appended to this object
*/
protected void toStringAppendFields(final StringBuilder builder) {
// do nothing by default, needed for b/w compatibility.
}
}

View File

@@ -0,0 +1,144 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* A simple base implementation of {@link ObjectPool}.
* Optional operations are implemented to either do nothing, return a value
* indicating it is unsupported or throw {@link UnsupportedOperationException}.
* <p>
* This class is intended to be thread-safe.
* </p>
*
* @param <T> Type of element pooled in this pool.
*
* @since 2.0
*/
public abstract class BaseObjectPool<T> extends BaseObject implements ObjectPool<T> {
@Override
public abstract T borrowObject() throws Exception;
@Override
public abstract void returnObject(T obj) throws Exception;
@Override
public abstract void invalidateObject(T obj) throws Exception;
/**
* Not supported in this base implementation.
*
* @return a negative value.
*/
@Override
public int getNumIdle() {
return -1;
}
/**
* Not supported in this base implementation.
*
* @return a negative value.
*/
@Override
public int getNumActive() {
return -1;
}
/**
* Not supported in this base implementation.
*
* @throws UnsupportedOperationException if the pool does not implement this
* method
*/
@Override
public void clear() throws Exception, UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Not supported in this base implementation. Subclasses should override
* this behavior.
*
* @throws UnsupportedOperationException if the pool does not implement this
* method
*/
@Override
public void addObject() throws Exception, UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Calls {@link ObjectPool#addObject()} <code>count</code>
* number of times.
*
* @param count
* the number of idle objects to add.
* @throws Exception
* when {@link ObjectPool#addObject()} fails.
* @since 2.8.0
*/
@Override
public void addObjects(final int count) throws Exception {
for (int i = 0; i < count; i++) {
addObject();
}
}
/**
* {@inheritDoc}
* <p>
* This affects the behavior of <code>isClosed</code> and
* <code>assertOpen</code>.
* </p>
*/
@Override
public void close() {
closed = true;
}
/**
* Has this pool instance been closed.
*
* @return <code>true</code> when this pool has been closed.
*/
public final boolean isClosed() {
return closed;
}
/**
* Throws an <code>IllegalStateException</code> when this pool has been
* closed.
*
* @throws IllegalStateException when this pool has been closed.
*
* @see #isClosed()
*/
protected final void assertOpen() throws IllegalStateException {
if (isClosed()) {
throw new IllegalStateException("Pool not open");
}
}
private volatile boolean closed = false;
@Override
protected void toStringAppendFields(final StringBuilder builder) {
builder.append("closed=");
builder.append(closed);
}
}

View File

@@ -0,0 +1,104 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* A base implementation of <code>PoolableObjectFactory</code>.
* <p>
* All operations defined here are essentially no-op's.
* <p>
* This class is immutable, and therefore thread-safe
*
* @param <T> Type of element managed in this factory.
*
* @see PooledObjectFactory
* @see BaseKeyedPooledObjectFactory
*
* @since 2.0
*/
public abstract class BasePooledObjectFactory<T> extends BaseObject implements PooledObjectFactory<T> {
/**
* Creates an object instance, to be wrapped in a {@link PooledObject}.
* <p>This method <strong>must</strong> support concurrent, multi-threaded
* activation.</p>
*
* @return an instance to be served by the pool
*
* @throws Exception if there is a problem creating a new instance,
* this will be propagated to the code requesting an object.
*/
public abstract T create() throws Exception;
/**
* Wrap the provided instance with an implementation of
* {@link PooledObject}.
*
* @param obj the instance to wrap
*
* @return The provided instance, wrapped by a {@link PooledObject}
*/
public abstract PooledObject<T> wrap(T obj);
@Override
public PooledObject<T> makeObject() throws Exception {
return wrap(create());
}
/**
* No-op.
*
* @param p ignored
*/
@Override
public void destroyObject(final PooledObject<T> p)
throws Exception {
// The default implementation is a no-op.
}
/**
* This implementation always returns {@code true}.
*
* @param p ignored
*
* @return {@code true}
*/
@Override
public boolean validateObject(final PooledObject<T> p) {
return true;
}
/**
* No-op.
*
* @param p ignored
*/
@Override
public void activateObject(final PooledObject<T> p) throws Exception {
// The default implementation is a no-op.
}
/**
* No-op.
*
* @param p ignored
*/
@Override
public void passivateObject(final PooledObject<T> p)
throws Exception {
// The default implementation is a no-op.
}
}

View File

@@ -0,0 +1,278 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
import java.io.Closeable;
import java.util.Collection;
import java.util.NoSuchElementException;
/**
* A "keyed" pooling interface.
* <p>
* A keyed pool maintains a pool of instances for each key value.
* </p>
* <p>
* Example of use:
* </p>
* <pre style="border:solid thin; padding: 1ex;"
* > Object obj = <code style="color:#00C">null</code>;
* Object key = <code style="color:#C00">"Key"</code>;
*
* <code style="color:#00C">try</code> {
* obj = pool.borrowObject(key);
* <code style="color:#0C0">//...use the object...</code>
* } <code style="color:#00C">catch</code>(Exception e) {
* <code style="color:#0C0">// invalidate the object</code>
* pool.invalidateObject(key, obj);
* <code style="color:#0C0">// do not return the object to the pool twice</code>
* obj = <code style="color:#00C">null</code>;
* } <code style="color:#00C">finally</code> {
* <code style="color:#0C0">// make sure the object is returned to the pool</code>
* <code style="color:#00C">if</code>(<code style="color:#00C">null</code> != obj) {
* pool.returnObject(key, obj);
* }
* }</pre>
* <p>
* {@link KeyedObjectPool} implementations <i>may</i> choose to store at most
* 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}).
* </p>
* <p>
* See {@link org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPool
* GenericKeyedObjectPool} for an implementation.
* </p>
*
* @param <K> The type of keys maintained by this pool.
* @param <V> Type of element pooled in this pool.
*
* @see KeyedPooledObjectFactory
* @see ObjectPool
* @see org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool
*
* @since 2.0
*/
public interface KeyedObjectPool<K, V> 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</code> 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</code> for <code>count</code> number of times. This has
* the same effect as calling {@link #addObjects(Object, int)}
* for each key in the <code>keys</code> collection.
*
* @param keys
* {@link Collection} of keys to add objects for.
* @param count
* the number of idle objects to add for each <code>key</code>.
* @throws Exception
* when {@link KeyedObjectPool#addObject(Object)} fails.
* @throws IllegalArgumentException
* when <code>keyedPool</code>, <code>keys</code>, or any value
* in <code>keys</code> is <code>null</code>.
* @see #addObjects(Object, int)
*/
void addObjects(final Collection<K> keys, final int count) throws Exception, IllegalArgumentException;
/**
* Calls {@link KeyedObjectPool#addObject(Object)}
* <code>key</code> <code>count</code> number of times.
*
* @param key
* the key to add objects for.
* @param count
* the number of idle objects to add for <code>key</code>.
* @throws Exception
* when {@link KeyedObjectPool#addObject(Object)} fails.
* @throws IllegalArgumentException
* when <code>key</code> is <code>null</code>.
* @since 2.8.0
*/
void addObjects(final K key, final int count) throws Exception, IllegalArgumentException;
/**
* Obtains an instance from this pool for the specified <code>key</code>.
* <p>
* Instances returned from this method will have been either newly created
* with {@link KeyedPooledObjectFactory#makeObject makeObject} or will be
* a previously idle object and have been activated with
* {@link KeyedPooledObjectFactory#activateObject activateObject} and then
* (optionally) validated with
* {@link KeyedPooledObjectFactory#validateObject validateObject}.
* </p>
* <p>
* By contract, clients <strong>must</strong> 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 <code>key</code>
* that is {@link Object#equals equivalent} to the one used to borrow the
* instance in the first place.
* </p>
* <p>
* The behaviour of this method when the pool has been exhausted is not
* strictly specified (although it may be specified by implementations).
* </p>
*
* @param key the key used to obtain the object
*
* @return an instance from this pool.
*
* @throws IllegalStateException
* after {@link #close close} has been called on this pool
* @throws Exception
* when {@link KeyedPooledObjectFactory#makeObject
* makeObject} throws an exception
* @throws NoSuchElementException
* when the pool is exhausted and cannot or will not return
* another instance
*/
V borrowObject(K key) throws Exception, NoSuchElementException, IllegalStateException;
/**
* Clears the pool, removing all pooled instances (optional operation).
*
* @throws UnsupportedOperationException when this implementation doesn't
* support the operation
*
* @throws Exception if the pool cannot be cleared
*/
void clear() throws Exception, UnsupportedOperationException;
/**
* Clears the specified pool, removing all pooled instances corresponding to
* the given <code>key</code> (optional operation).
*
* @param key the key to clear
*
* @throws UnsupportedOperationException when this implementation doesn't
* support the operation
*
* @throws Exception if the key cannot be cleared
*/
void clear(K key) throws Exception, UnsupportedOperationException;
/**
* Close this pool, and free any resources associated with it.
* <p>
* Calling {@link #addObject addObject} or
* {@link #borrowObject borrowObject} after invoking this method on a pool
* will cause them to throw an {@link IllegalStateException}.
* </p>
* <p>
* Implementations should silently fail if not all resources can be freed.
* </p>
*/
@Override
void close();
/**
* 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 getNumActive();
/**
* Returns the number of instances currently borrowed from but not yet
* returned to the pool corresponding to the given <code>key</code>.
* 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 given <code>key</code>.
*/
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 number of instances corresponding to the given
* <code>key</code> 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</code> currently idle in this pool.
*/
int getNumIdle(K key);
/**
* Invalidates an object from the pool.
* <p>
* By contract, <code>obj</code> <strong>must</strong> have been obtained
* using {@link #borrowObject borrowObject} or a related method as defined
* in an implementation or sub-interface using a <code>key</code> that is
* equivalent to the one used to borrow the <code>Object</code> in the first
* place.
* </p>
* <p>
* This method should be used when an object that has been borrowed is
* determined (due to an exception or other problem) to be invalid.
* </p>
*
* @param key the key used to obtain the object
* @param obj a {@link #borrowObject borrowed} instance to be returned.
*
* @throws Exception if the instance cannot be invalidated
*/
void invalidateObject(K key, V obj) throws Exception;
/**
* Return an instance to the pool. By contract, <code>obj</code>
* <strong>must</strong> have been obtained using
* {@link #borrowObject borrowObject} or a related method as defined in an
* implementation or sub-interface using a <code>key</code> 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
*/
void returnObject(K key, V obj) throws Exception;
}

View File

@@ -0,0 +1,153 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* An interface defining life-cycle methods for
* instances to be served by a {@link KeyedObjectPool}.
* <p>
* By contract, when an {@link KeyedObjectPool}
* delegates to a {@link KeyedPooledObjectFactory},
* </p>
* <ol>
* <li>
* {@link #makeObject} is called whenever a new instance is needed.
* </li>
* <li>
* {@link #activateObject} is invoked on every instance that has been
* {@link #passivateObject passivated} before it is
* {@link KeyedObjectPool#borrowObject borrowed} from the pool.
* </li>
* <li>
* {@link #validateObject} may be invoked on {@link #activateObject activated}
* instances to make sure they can be
* {@link KeyedObjectPool#borrowObject borrowed} from the pool.
* <code>validateObject</code> 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.
* </li>
* <li>
* {@link #passivateObject passivateObject}
* is invoked on every instance when it is returned to the pool.
* </li>
* <li>
* {@link #destroyObject destroyObject}
* is invoked on every instance when it is being "dropped" from the
* pool (whether due to the response from <code>validateObject</code>,
* 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.
* </li>
* </ol>
* {@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
* <code>KeyedPoolableObjectFactory</code> at a time.
* <p>
* 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&lt;V&gt;}. These are the object wrappers that
* pools use to track and maintain state informations about the objects that
* they manage.
* </p>
*
* @see KeyedObjectPool
* @see BaseKeyedPooledObjectFactory
*
* @param <K> The type of keys managed by this factory.
* @param <V> Type of element managed by this factory.
*
* @since 2.0
*/
public interface KeyedPooledObjectFactory<K, V> {
/**
* Create an instance that can be served by the pool and
* wrap it in a {@link PooledObject} to be managed by the pool.
*
* @param key the key used when constructing the object
*
* @return a {@code PooledObject} wrapping an instance that can
* be served by the pool.
*
* @throws Exception if there is a problem creating a new instance,
* this will be propagated to the code requesting an object.
*/
PooledObject<V> makeObject(K key) throws Exception;
/**
* Destroy an instance no longer needed by the pool.
* <p>
* It is important for implementations of this method to be aware that there
* is no guarantee about what state <code>obj</code> will be in and the
* implementation should be prepared to handle unexpected errors.
* </p>
* <p>
* Also, an implementation must take in to consideration that instances lost
* to the garbage collector may never be destroyed.
* </p>
*
* @param key the key used when selecting the instance
* @param p a {@code PooledObject} wrapping the instance to be destroyed
*
* @throws Exception should be avoided as it may be swallowed by
* the pool implementation.
*
* @see #validateObject
* @see KeyedObjectPool#invalidateObject
*/
void destroyObject(K key, PooledObject<V> p) throws Exception;
/**
* 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 <code>false</code> if <code>obj</code> is not valid and should
* be dropped from the pool, <code>true</code> otherwise.
*/
boolean validateObject(K key, PooledObject<V> p);
/**
* Reinitialize an instance 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 activated
*
* @throws Exception if there is a problem activating <code>obj</code>,
* this exception may be swallowed by the pool.
*
* @see #destroyObject
*/
void activateObject(K key, PooledObject<V> p) throws Exception;
/**
* Uninitialize an instance to be returned to the idle object pool.
*
* @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 <code>obj</code>,
* this exception may be swallowed by the pool.
*
* @see #destroyObject
*/
void passivateObject(K key, PooledObject<V> p) throws Exception;
}

View File

@@ -0,0 +1,200 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
import java.io.Closeable;
import java.util.NoSuchElementException;
/**
* A pooling simple interface.
* <p>
* Example of use:
* </p>
* <pre style="border:solid thin; padding: 1ex;"
* > Object obj = <code style="color:#00C">null</code>;
*
* <code style="color:#00C">try</code> {
* obj = pool.borrowObject();
* <code style="color:#00C">try</code> {
* <code style="color:#0C0">//...use the object...</code>
* } <code style="color:#00C">catch</code>(Exception e) {
* <code style="color:#0C0">// invalidate the object</code>
* pool.invalidateObject(obj);
* <code style="color:#0C0">// do not return the object to the pool twice</code>
* obj = <code style="color:#00C">null</code>;
* } <code style="color:#00C">finally</code> {
* <code style="color:#0C0">// make sure the object is returned to the pool</code>
* <code style="color:#00C">if</code>(<code style="color:#00C">null</code> != obj) {
* pool.returnObject(obj);
* }
* }
* } <code style="color:#00C">catch</code>(Exception e) {
* <code style="color:#0C0">// failed to borrow an object</code>
* }</pre>
* <p>
* See {@link BaseObjectPool} for a simple base implementation.
* </p>
*
* @param <T> Type of element pooled in this pool.
*
* @see PooledObjectFactory
* @see KeyedObjectPool
* @see BaseObjectPool
*
* @since 2.0
*/
public interface ObjectPool<T> 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</code> 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</code>
* number of times.
*
* @param count
* the number of idle objects to add.
* @throws Exception
* when {@link ObjectPool#addObject()} fails.
* @since 2.8.0
*/
void addObjects(final int count) throws Exception;
/**
* Obtains an instance from this pool.
* <p>
* Instances returned from this method will have been either newly created
* with {@link PooledObjectFactory#makeObject} or will be a previously
* idle object and have been activated with
* {@link PooledObjectFactory#activateObject} and then validated with
* {@link PooledObjectFactory#validateObject}.
* </p>
* <p>
* By contract, clients <strong>must</strong> return the borrowed instance
* using {@link #returnObject}, {@link #invalidateObject}, or a related
* method as defined in an implementation or sub-interface.
* </p>
* <p>
* The behaviour of this method when the pool has been exhausted
* is not strictly specified (although it may be specified by
* implementations).
* </p>
*
* @return an instance from this pool.
*
* @throws IllegalStateException
* after {@link #close close} has been called on this pool.
* @throws Exception
* when {@link PooledObjectFactory#makeObject} throws an
* exception.
* @throws NoSuchElementException
* when the pool is exhausted and cannot or will not return
* another instance.
*/
T borrowObject() throws Exception, NoSuchElementException,
IllegalStateException;
/**
* Clears any objects sitting idle in the pool, releasing any associated
* resources (optional operation). Idle objects cleared must be
* {@link PooledObjectFactory#destroyObject(PooledObject)}.
*
* @throws UnsupportedOperationException
* if this implementation does not support the operation
*
* @throws Exception if the pool cannot be cleared
*/
void clear() throws Exception, UnsupportedOperationException;
/**
* Closes this pool, and free any resources associated with it.
* <p>
* Calling {@link #addObject} or {@link #borrowObject} after invoking this
* method on a pool will cause them to throw an {@link IllegalStateException}.
* </p>
* <p>
* Implementations should silently fail if not all resources can be freed.
* </p>
*/
@Override
void close();
/**
* 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.
*/
int getNumActive();
/**
* 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.
* @return the number of instances currently idle in this pool.
*/
int getNumIdle();
/**
* Invalidates an object from the pool.
* <p>
* By contract, <code>obj</code> <strong>must</strong> have been obtained
* using {@link #borrowObject} or a related method as defined in an
* implementation or sub-interface.
* </p>
* <p>
* This method should be used when an object that has been borrowed is
* determined (due to an exception or other problem) to be invalid.
* </p>
*
* @param obj a {@link #borrowObject borrowed} instance to be disposed.
*
* @throws Exception if the instance cannot be invalidated
*/
void invalidateObject(T obj) throws Exception;
/**
* Returns an instance to the pool. By contract, <code>obj</code>
* <strong>must</strong> 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
*/
void returnObject(T obj) throws Exception;
}

View File

@@ -0,0 +1,717 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
/**
* This class consists exclusively of static methods that operate on or return
* ObjectPool or KeyedObjectPool related interfaces.
*
* @since 2.0
*/
public final class PoolUtils {
private static final String MSG_MIN_IDLE = "minIdle must be non-negative.";
public static final String MSG_NULL_KEY = "key must not be null.";
private static final String MSG_NULL_KEYED_POOL = "keyedPool must not be null.";
public 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.
*/
static class TimerHolder {
static final Timer MIN_IDLE_TIMER = new Timer(true);
}
/**
* PoolUtils instances should NOT be constructed in standard programming.
* Instead, the class should be used procedurally: PoolUtils.adapt(aPool);.
* This constructor is public to permit tools that require a JavaBean
* instance to operate.
*/
public PoolUtils() {
}
/**
* Should the supplied Throwable be re-thrown (eg if it is an instance of
* one of the Throwables that should never be swallowed). Used by the pool
* error handling for operations that throw exceptions that normally need to
* be ignored.
*
* @param t
* The Throwable to check
* @throws ThreadDeath
* if that is passed in
* @throws VirtualMachineError
* if that is passed in
*/
public static void checkRethrow(final Throwable t) {
if (t instanceof ThreadDeath) {
throw (ThreadDeath) t;
}
if (t instanceof VirtualMachineError) {
throw (VirtualMachineError) t;
}
// All other instances of Throwable will be silently swallowed
}
/**
* Periodically check the idle object count for the pool. At most one idle
* object will be added per period. If there is an exception when calling
* {@link ObjectPool#addObject()} then no more checks will be performed.
*
* @param pool
* the pool to check periodically.
* @param minIdle
* if the {@link ObjectPool#getNumIdle()} is less than this then
* add an idle object.
* @param period
* the frequency to check the number of idle objects in a pool,
* see {@link Timer#schedule(TimerTask, long, long)}.
* @param <T> the type of objects in the pool
* @return the {@link TimerTask} that will periodically check the pools idle
* object count.
* @throws IllegalArgumentException
* when <code>pool</code> is <code>null</code> or when
* <code>minIdle</code> is negative or when <code>period</code>
* isn't valid for {@link Timer#schedule(TimerTask, long, long)}
*/
public static <T> TimerTask checkMinIdle(final ObjectPool<T> pool,
final int minIdle, final long period)
throws IllegalArgumentException {
if (pool == null) {
throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (minIdle < 0) {
throw new IllegalArgumentException(MSG_MIN_IDLE);
}
final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle);
getMinIdleTimer().schedule(task, 0L, period);
return task;
}
/**
* Periodically check the idle object count for the key in the keyedPool. At
* most one idle object will be added per period. If there is an exception
* when calling {@link KeyedObjectPool#addObject(Object)} then no more
* checks for that key will be performed.
*
* @param keyedPool
* the keyedPool to check periodically.
* @param key
* the key to check the idle count of.
* @param minIdle
* if the {@link KeyedObjectPool#getNumIdle(Object)} is less than
* this then add an idle object.
* @param period
* the frequency to check the number of idle objects in a
* keyedPool, see {@link Timer#schedule(TimerTask, long, long)}.
* @param <K> the type of the pool key
* @param <V> the type of pool entries
* @return the {@link TimerTask} that will periodically check the pools idle
* object count.
* @throws IllegalArgumentException
* when <code>keyedPool</code>, <code>key</code> is
* <code>null</code> or when <code>minIdle</code> is negative or
* when <code>period</code> isn't valid for
* {@link Timer#schedule(TimerTask, long, long)}.
*/
public static <K, V> TimerTask checkMinIdle(
final KeyedObjectPool<K, V> keyedPool, final K key,
final int minIdle, final long period)
throws IllegalArgumentException {
if (keyedPool == null) {
throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (key == null) {
throw new IllegalArgumentException(MSG_NULL_KEY);
}
if (minIdle < 0) {
throw new IllegalArgumentException(MSG_MIN_IDLE);
}
final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>(
keyedPool, key, minIdle);
getMinIdleTimer().schedule(task, 0L, period);
return task;
}
/**
* Periodically check the idle object count for each key in the
* <code>Collection</code> <code>keys</code> in the keyedPool. At most one
* idle object will be added per period.
*
* @param keyedPool
* the keyedPool to check periodically.
* @param keys
* a collection of keys to check the idle object count.
* @param minIdle
* if the {@link KeyedObjectPool#getNumIdle(Object)} is less than
* this then add an idle object.
* @param period
* the frequency to check the number of idle objects in a
* keyedPool, see {@link Timer#schedule(TimerTask, long, long)}.
* @param <K> the type of the pool key
* @param <V> the type of pool entries
* @return a {@link Map} of key and {@link TimerTask} pairs that will
* periodically check the pools idle object count.
* @throws IllegalArgumentException
* when <code>keyedPool</code>, <code>keys</code>, or any of the
* values in the collection is <code>null</code> or when
* <code>minIdle</code> is negative or when <code>period</code>
* isn't valid for {@link Timer#schedule(TimerTask, long, long)}
* .
* @see #checkMinIdle(KeyedObjectPool, Object, int, long)
*/
public static <K, V> Map<K, TimerTask> checkMinIdle(
final KeyedObjectPool<K, V> keyedPool, final Collection<K> keys,
final int minIdle, final long period)
throws IllegalArgumentException {
if (keys == null) {
throw new IllegalArgumentException(MSG_NULL_KEYS);
}
final Map<K, TimerTask> tasks = new HashMap<>(keys.size());
final Iterator<K> iter = keys.iterator();
while (iter.hasNext()) {
final K key = iter.next();
final TimerTask task = checkMinIdle(keyedPool, key, minIdle, period);
tasks.put(key, task);
}
return tasks;
}
/**
* Calls {@link ObjectPool#addObject()} on <code>pool</code> <code>count</code>
* number of times.
*
* @param pool
* the pool to prefill.
* @param count
* the number of idle objects to add.
* @param <T> the type of objects in the pool
* @throws Exception
* when {@link ObjectPool#addObject()} fails.
* @throws IllegalArgumentException
* when <code>pool</code> is <code>null</code>.
* @deprecated Use {@link ObjectPool#addObjects(int)}.
*/
@Deprecated
public static <T> void prefill(final ObjectPool<T> pool, final int count)
throws Exception, IllegalArgumentException {
if (pool == null) {
throw new IllegalArgumentException(MSG_NULL_POOL);
}
pool.addObjects(count);
}
/**
* Calls {@link KeyedObjectPool#addObject(Object)} on <code>keyedPool</code> with
* <code>key</code> <code>count</code> 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 for <code>key</code>.
* @param <K> the type of the pool key
* @param <V> the type of pool entries
* @throws Exception
* when {@link KeyedObjectPool#addObject(Object)} fails.
* @throws IllegalArgumentException
* when <code>keyedPool</code> or <code>key</code> is
* <code>null</code>.
* @deprecated Use {@link KeyedObjectPool#addObjects(Object, int)}.
*/
@Deprecated
public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
final K key, final int count) throws Exception,
IllegalArgumentException {
if (keyedPool == null) {
throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
keyedPool.addObjects(key, count);
}
/**
* Calls {@link KeyedObjectPool#addObject(Object)} on <code>keyedPool</code> with each
* key in <code>keys</code> for <code>count</code> number of times. This has
* the same effect as calling {@link #prefill(KeyedObjectPool, Object, int)}
* for each key in the <code>keys</code> 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 each <code>key</code>.
* @param <K> the type of the pool key
* @param <V> the type of pool entries
* @throws Exception
* when {@link KeyedObjectPool#addObject(Object)} fails.
* @throws IllegalArgumentException
* when <code>keyedPool</code>, <code>keys</code>, or any value
* in <code>keys</code> is <code>null</code>.
* @see #prefill(KeyedObjectPool, Object, int)
* @deprecated Use {@link KeyedObjectPool#addObjects(Collection, int)}.
*/
@Deprecated
public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
final Collection<K> keys, final int count) throws Exception,
IllegalArgumentException {
if (keys == null) {
throw new IllegalArgumentException(MSG_NULL_KEYS);
}
keyedPool.addObjects(keys, count);
}
/**
* Returns a synchronized (thread-safe) PooledObjectFactory backed by the
* specified PooledObjectFactory.
*
* @param factory
* the PooledObjectFactory to be "wrapped" in a synchronized
* PooledObjectFactory.
* @param <T> the type of objects in the pool
* @return a synchronized view of the specified PooledObjectFactory.
*/
public static <T> PooledObjectFactory<T> synchronizedPooledFactory(
final PooledObjectFactory<T> factory) {
return new SynchronizedPooledObjectFactory<>(factory);
}
/**
* Returns a synchronized (thread-safe) KeyedPooledObjectFactory backed by
* the specified KeyedPoolableObjectFactory.
*
* @param keyedFactory
* the KeyedPooledObjectFactory to be "wrapped" in a
* synchronized KeyedPooledObjectFactory.
* @param <K> the type of the pool key
* @param <V> the type of pool entries
* @return a synchronized view of the specified KeyedPooledObjectFactory.
*/
public static <K, V> KeyedPooledObjectFactory<K, V> synchronizedKeyedPooledFactory(
final KeyedPooledObjectFactory<K, V> keyedFactory) {
return new SynchronizedKeyedPooledObjectFactory<>(keyedFactory);
}
/**
* Gets the <code>Timer</code> for checking keyedPool's idle count.
*
* @return the {@link Timer} for checking keyedPool's idle count.
*/
private static Timer getMinIdleTimer() {
return TimerHolder.MIN_IDLE_TIMER;
}
/**
* Timer task that adds objects to the pool until the number of idle
* instances reaches the configured minIdle. Note that this is not the same
* as the pool's minIdle setting.
*
* @param <T> type of objects in the pool
*/
private static final class ObjectPoolMinIdleTimerTask<T> extends TimerTask {
/** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
private final int minIdle;
/** Object pool */
private final ObjectPool<T> pool;
/**
* Create a new ObjectPoolMinIdleTimerTask for the given pool with the
* given minIdle setting.
*
* @param pool
* object pool
* @param minIdle
* number of idle instances to maintain
* @throws IllegalArgumentException
* if the pool is null
*/
ObjectPoolMinIdleTimerTask(final ObjectPool<T> pool, final int minIdle)
throws IllegalArgumentException {
if (pool == null) {
throw new IllegalArgumentException(MSG_NULL_POOL);
}
this.pool = pool;
this.minIdle = minIdle;
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
boolean success = false;
try {
if (pool.getNumIdle() < minIdle) {
pool.addObject();
}
success = true;
} catch (final Exception e) {
cancel();
} finally {
// detect other types of Throwable and cancel this Timer
if (!success) {
cancel();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("ObjectPoolMinIdleTimerTask");
sb.append("{minIdle=").append(minIdle);
sb.append(", pool=").append(pool);
sb.append('}');
return sb.toString();
}
}
/**
* Timer task that adds objects to the pool until the number of idle
* instances for the given key reaches the configured minIdle. Note that
* this is not the same as the pool's minIdle setting.
*
* @param <K> object pool key type
* @param <V> object pool value type
*/
private static final class KeyedObjectPoolMinIdleTimerTask<K, V> extends
TimerTask {
/** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
private final int minIdle;
/** Key to ensure minIdle for */
private final K key;
/** Keyed object pool */
private final KeyedObjectPool<K, V> keyedPool;
/**
* Creates a new KeyedObjecPoolMinIdleTimerTask.
*
* @param keyedPool
* keyed object pool
* @param key
* key to ensure minimum number of idle instances
* @param minIdle
* minimum number of idle instances
* @throws IllegalArgumentException
* if the key is null
*/
KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool<K, V> keyedPool,
final K key, final int minIdle) throws IllegalArgumentException {
if (keyedPool == null) {
throw new IllegalArgumentException(
MSG_NULL_KEYED_POOL);
}
this.keyedPool = keyedPool;
this.key = key;
this.minIdle = minIdle;
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
boolean success = false;
try {
if (keyedPool.getNumIdle(key) < minIdle) {
keyedPool.addObject(key);
}
success = true;
} catch (final Exception e) {
cancel();
} finally {
// detect other types of Throwable and cancel this Timer
if (!success) {
cancel();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("KeyedObjectPoolMinIdleTimerTask");
sb.append("{minIdle=").append(minIdle);
sb.append(", key=").append(key);
sb.append(", keyedPool=").append(keyedPool);
sb.append('}');
return sb.toString();
}
}
/**
* A fully synchronized PooledObjectFactory that wraps a
* PooledObjectFactory and synchronizes access to the wrapped factory
* methods.
* <p>
* <b>Note:</b> This should not be used on pool implementations that already
* provide proper synchronization such as the pools provided in the Commons
* Pool library.
* </p>
*
* @param <T> pooled object factory type
*/
private static final class SynchronizedPooledObjectFactory<T> implements
PooledObjectFactory<T> {
/** Synchronization lock */
private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
/** Wrapped factory */
private final PooledObjectFactory<T> factory;
/**
* Creates a SynchronizedPoolableObjectFactory wrapping the given
* factory.
*
* @param factory
* underlying factory to wrap
* @throws IllegalArgumentException
* if the factory is null
*/
SynchronizedPooledObjectFactory(final PooledObjectFactory<T> factory)
throws IllegalArgumentException {
if (factory == null) {
throw new IllegalArgumentException("factory must not be null.");
}
this.factory = factory;
}
/**
* {@inheritDoc}
*/
@Override
public PooledObject<T> makeObject() throws Exception {
writeLock.lock();
try {
return factory.makeObject();
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public void destroyObject(final PooledObject<T> p) throws Exception {
writeLock.lock();
try {
factory.destroyObject(p);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean validateObject(final PooledObject<T> p) {
writeLock.lock();
try {
return factory.validateObject(p);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public void activateObject(final PooledObject<T> p) throws Exception {
writeLock.lock();
try {
factory.activateObject(p);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public void passivateObject(final PooledObject<T> p) throws Exception {
writeLock.lock();
try {
factory.passivateObject(p);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SynchronizedPoolableObjectFactory");
sb.append("{factory=").append(factory);
sb.append('}');
return sb.toString();
}
}
/**
* A fully synchronized KeyedPooledObjectFactory that wraps a
* KeyedPooledObjectFactory and synchronizes access to the wrapped factory
* methods.
* <p>
* <b>Note:</b> This should not be used on pool implementations that already
* provide proper synchronization such as the pools provided in the Commons
* Pool library.
* </p>
*
* @param <K> pooled object factory key type
* @param <V> pooled object factory key value
*/
private static final class SynchronizedKeyedPooledObjectFactory<K, V>
implements KeyedPooledObjectFactory<K, V> {
/** Synchronization lock */
private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
/** Wrapped factory */
private final KeyedPooledObjectFactory<K, V> keyedFactory;
/**
* Creates a SynchronizedKeyedPoolableObjectFactory wrapping the given
* factory.
*
* @param keyedFactory
* underlying factory to wrap
* @throws IllegalArgumentException
* if the factory is null
*/
SynchronizedKeyedPooledObjectFactory(
final KeyedPooledObjectFactory<K, V> keyedFactory)
throws IllegalArgumentException {
if (keyedFactory == null) {
throw new IllegalArgumentException(
"keyedFactory must not be null.");
}
this.keyedFactory = keyedFactory;
}
/**
* {@inheritDoc}
*/
@Override
public PooledObject<V> makeObject(final K key) throws Exception {
writeLock.lock();
try {
return keyedFactory.makeObject(key);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public void destroyObject(final K key, final PooledObject<V> p) throws Exception {
writeLock.lock();
try {
keyedFactory.destroyObject(key, p);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean validateObject(final K key, final PooledObject<V> p) {
writeLock.lock();
try {
return keyedFactory.validateObject(key, p);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public void activateObject(final K key, final PooledObject<V> p) throws Exception {
writeLock.lock();
try {
keyedFactory.activateObject(key, p);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public void passivateObject(final K key, final PooledObject<V> p) throws Exception {
writeLock.lock();
try {
keyedFactory.passivateObject(key, p);
} finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SynchronizedKeyedPoolableObjectFactory");
sb.append("{keyedFactory=").append(keyedFactory);
sb.append('}');
return sb.toString();
}
}
}

View File

@@ -0,0 +1,220 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
import java.io.PrintWriter;
import java.util.Deque;
/**
* Defines the wrapper that is used to track the additional information, such as
* state, for the pooled objects.
* <p>
* Implementations of this class are required to be thread-safe.
* </p>
*
* @param <T> the type of object in the pool
*
* @since 2.0
*/
public interface PooledObject<T> extends Comparable<PooledObject<T>> {
/**
* Obtains the underlying object that is wrapped by this instance of
* {@link PooledObject}.
*
* @return The wrapped object
*/
T getObject();
/**
* Obtains the time (using the same basis as
* {@link System#currentTimeMillis()}) that this object was created.
*
* @return The creation time for the wrapped object
*/
long getCreateTime();
/**
* 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).
*
* @return The time in milliseconds last spent in the active state
*/
long getActiveTimeMillis();
/**
* Gets the number of times this object has been borrowed.
*
* @return The number of times this object has been borrowed.
* @since 2.7.0
*/
long getBorrowedCount();
/**
* 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).
*
* @return The time in milliseconds last spent in the idle state
*/
long getIdleTimeMillis();
/**
* Obtains the time the wrapped object was last borrowed.
*
* @return The time the object was last borrowed
*/
long getLastBorrowTime();
/**
* Obtains the time the wrapped object was last returned.
*
* @return The time the object was last returned
*/
long getLastReturnTime();
/**
* 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
* value as {@link #getLastBorrowTime()}.
*
* @return the last time this object was used
*/
long getLastUsedTime();
/**
* Orders instances based on idle time - i.e. the length of time since the
* instance was returned to the pool. Used by the GKOP idle object evictor.
*<p>
* Note: This class has a natural ordering that is inconsistent with
* equals if distinct objects have the same identity hash code.
* </p>
* <p>
* {@inheritDoc}
* </p>
*/
@Override
int compareTo(PooledObject<T> other);
@Override
boolean equals(Object obj);
@Override
int hashCode();
/**
* Provides a String form of the wrapper for debug purposes. The format is
* not fixed and may change at any time.
* <p>
* {@inheritDoc}
*/
@Override
String toString();
/**
* Attempts to place the pooled object in the
* {@link PooledObjectState#EVICTION} state.
*
* @return <code>true</code> if the object was placed in the
* {@link PooledObjectState#EVICTION} state otherwise
* <code>false</code>
*/
boolean startEvictionTest();
/**
* Called to inform the object that the eviction test has ended.
*
* @param idleQueue The queue of idle objects to which the object should be
* returned
*
* @return Currently not used
*/
boolean endEvictionTest(Deque<PooledObject<T>> idleQueue);
/**
* Allocates the object.
*
* @return {@code true} if the original state was {@link PooledObjectState#IDLE IDLE}
*/
boolean allocate();
/**
* Deallocates the object and sets it {@link PooledObjectState#IDLE IDLE}
* if it is currently {@link PooledObjectState#ALLOCATED ALLOCATED}.
*
* @return {@code true} if the state was {@link PooledObjectState#ALLOCATED ALLOCATED}
*/
boolean deallocate();
/**
* Sets the state to {@link PooledObjectState#INVALID INVALID}
*/
void invalidate();
/**
* Is abandoned object tracking being used? If this is true the
* implementation will need to record the stack trace of the last caller to
* borrow this object.
*
* @param logAbandoned The new configuration setting for abandoned
* object tracking
*/
void setLogAbandoned(boolean logAbandoned);
/**
* 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
*/
void setRequireFullStackTrace(final boolean requireFullStackTrace);
/**
* Record the current stack trace as the last time the object was used.
*/
void use();
/**
* Prints the stack trace of the code that borrowed this pooled object and
* the stack trace of the last code to use this object (if available) to
* the supplied writer.
*
* @param writer The destination for the debug output
*/
void printStackTrace(PrintWriter writer);
/**
* Returns the state of this object.
* @return state
*/
PooledObjectState getState();
/**
* Marks the pooled object as abandoned.
*/
void markAbandoned();
/**
* Marks the object as returning to the pool.
*/
void markReturning();
}

View File

@@ -0,0 +1,141 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* An interface defining life-cycle methods for instances to be served by an
* {@link ObjectPool}.
* <p>
* By contract, when an {@link ObjectPool} delegates to a
* {@link PooledObjectFactory},
* </p>
* <ol>
* <li>
* {@link #makeObject} is called whenever a new instance is needed.
* </li>
* <li>
* {@link #activateObject} is invoked on every instance that has been
* {@link #passivateObject passivated} before it is
* {@link ObjectPool#borrowObject borrowed} from the pool.
* </li>
* <li>
* {@link #validateObject} may be invoked on {@link #activateObject activated}
* instances to make sure they can be {@link ObjectPool#borrowObject borrowed}
* from the pool. {@link #validateObject} may also be used to
* test an instance being {@link ObjectPool#returnObject returned} to the pool
* before it is {@link #passivateObject passivated}. It will only be invoked
* on an activated instance.
* </li>
* <li>
* {@link #passivateObject} is invoked on every instance when it is returned
* to the pool.
* </li>
* <li>
* {@link #destroyObject} is invoked on every instance when it is being
* "dropped" from the pool (whether due to the response from
* {@link #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.
* </li>
* </ol>
* {@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 <code>PoolableObjectFactory</code>
* at a time.
* <p>
* While clients of a {@link KeyedObjectPool} borrow and return instances of
* the underlying value type {@code V}, the factory methods act on instances of
* {@link PooledObject PooledObject&lt;V&gt;}. These are the object wrappers that
* pools use to track and maintain state information about the objects that
* they manage.
* </p>
*
* @param <T> Type of element managed in this factory.
*
* @see ObjectPool
*
* @since 2.0
*/
public interface PooledObjectFactory<T> {
/**
* 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
*
* @throws Exception if there is a problem creating a new instance,
* this will be propagated to the code requesting an object.
*/
PooledObject<T> makeObject() throws Exception;
/**
* Destroys an instance no longer needed by the pool.
* <p>
* It is important for implementations of this method to be aware that there
* is no guarantee about what state <code>obj</code> will be in and the
* implementation should be prepared to handle unexpected errors.
* </p>
* <p>
* Also, an implementation must take in to consideration that instances lost
* to the garbage collector may never be destroyed.
* </p>
*
* @param p a {@code PooledObject} wrapping the instance to be destroyed
*
* @throws Exception should be avoided as it may be swallowed by
* the pool implementation.
*
* @see #validateObject
* @see ObjectPool#invalidateObject
*/
void destroyObject(PooledObject<T> p) throws Exception;
/**
* Ensures that the instance is safe to be returned by the pool.
*
* @param p a {@code PooledObject} wrapping the instance to be validated
*
* @return <code>false</code> if <code>obj</code> is not valid and should
* be dropped from the pool, <code>true</code> otherwise.
*/
boolean validateObject(PooledObject<T> p);
/**
* 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 <code>obj</code>,
* this exception may be swallowed by the pool.
*
* @see #destroyObject
*/
void activateObject(PooledObject<T> p) throws Exception;
/**
* 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 <code>obj</code>,
* this exception may be swallowed by the pool.
*
* @see #destroyObject
*/
void passivateObject(PooledObject<T> p) throws Exception;
}

View File

@@ -0,0 +1,87 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* Provides the possible states that a {@link PooledObject} may be in.
*
* @since 2.0
*/
public enum PooledObjectState {
/**
* In the queue, not in use.
*/
IDLE,
/**
* In use.
*/
ALLOCATED,
/**
* In the queue, currently being tested for possible eviction.
*/
EVICTION,
/**
* Not in the queue, currently being tested for possible eviction. An
* attempt to borrow the object was made while being tested which removed it
* from the queue. It should be returned to the head of the queue once
* eviction testing completes.
* TODO: Consider allocating object and ignoring the result of the eviction
* test.
*/
EVICTION_RETURN_TO_HEAD,
/**
* In the queue, currently being validated.
*/
VALIDATION,
/**
* Not in queue, currently being validated. The object was borrowed while
* being validated and since testOnBorrow was configured, it was removed
* from the queue and pre-allocated. It should be allocated once validation
* completes.
*/
VALIDATION_PREALLOCATED,
/**
* Not in queue, currently being validated. An attempt to borrow the object
* was made while previously being tested for eviction which removed it from
* the queue. It should be returned to the head of the queue once validation
* completes.
*/
VALIDATION_RETURN_TO_HEAD,
/**
* Failed maintenance (e.g. eviction test or validation) and will be / has
* been destroyed
*/
INVALID,
/**
* Deemed abandoned, to be invalidated.
*/
ABANDONED,
/**
* Returning to the pool.
*/
RETURNING
}

View File

@@ -0,0 +1,36 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* Pools that unavoidably swallow exceptions may be configured with an instance
* of this listener so the user may receive notification of when this happens.
* The listener should not throw an exception when called but pools calling
* listeners should protect themselves against exceptions anyway.
*
* @since 2.0
*/
public interface SwallowedExceptionListener {
/**
* This method is called every time the implementation unavoidably swallows
* an exception.
*
* @param e The exception that was swallowed
*/
void onSwallowException(Exception e);
}

View File

@@ -0,0 +1,36 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* This interface allows pooled objects to make information available about when
* and how they were used available to the object pool. The object pool may, but
* is not required, to use this information to make more informed decisions when
* determining the state of a pooled object - for instance whether or not the
* object has been abandoned.
*
* @since 2.0
*/
public interface TrackedUse {
/**
* Get the last time this object was used in ms.
*
* @return long time in ms
*/
long getLastUsed();
}

View File

@@ -0,0 +1,39 @@
/*
* 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 org.apache.tomcat.dbcp.pool2;
/**
* This interface may be implemented by an object pool to enable clients
* (primarily those clients that wrap pools to provide pools with extended
* features) to provide additional information to the pool relating to object
* using allowing more informed decisions and reporting to be made regarding
* abandoned objects.
*
* @param <T> The type of object provided by the pool.
*
* @since 2.0
*/
public interface UsageTracking<T> {
/**
* This method is called every time a pooled object is used to enable the pool to
* better track borrowed objects.
*
* @param pooledObject The object that is being used
*/
void use(T pooledObject);
}

View File

@@ -0,0 +1,292 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.io.PrintWriter;
/**
* Configuration settings for abandoned object removal.
*
* @since 2.0
*/
public class AbandonedConfig {
/**
* Whether or not borrowObject performs abandoned object removal.
*/
private boolean removeAbandonedOnBorrow = false;
/**
* <p>Flag to remove abandoned objects if they exceed the
* removeAbandonedTimeout when borrowObject is invoked.</p>
*
* <p>The default value is false.</p>
*
* <p>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() &gt; getMaxTotal() - 3</code></p>
*
* @return true if abandoned objects are to be removed by borrowObject
*/
public boolean getRemoveAbandonedOnBorrow() {
return this.removeAbandonedOnBorrow;
}
/**
* <p>Flag to remove abandoned objects if they exceed the
* removeAbandonedTimeout when borrowObject is invoked.</p>
*
* @param removeAbandonedOnBorrow true means abandoned objects will be
* removed by borrowObject
* @see #getRemoveAbandonedOnBorrow()
*/
public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) {
this.removeAbandonedOnBorrow = removeAbandonedOnBorrow;
}
/**
* Whether or not pool maintenance (evictor) performs abandoned object
* removal.
*/
private boolean removeAbandonedOnMaintenance = false;
/**
* <p>Flag to remove abandoned objects if they exceed the
* removeAbandonedTimeout when pool maintenance (the "evictor")
* runs.</p>
*
* <p>The default value is false.</p>
*
* <p>If set to true, abandoned objects are removed by the pool
* maintenance thread when it runs. This setting has no effect
* unless maintenance is enabled by setting
*{@link GenericObjectPool#getTimeBetweenEvictionRunsMillis() timeBetweenEvictionRunsMillis}
* to a positive number.</p>
*
* @return true if abandoned objects are to be removed by the evictor
*/
public boolean getRemoveAbandonedOnMaintenance() {
return this.removeAbandonedOnMaintenance;
}
/**
* <p>Flag to remove abandoned objects if they exceed the
* removeAbandonedTimeout when pool maintenance runs.</p>
*
* @param removeAbandonedOnMaintenance true means abandoned objects will be
* removed by pool maintenance
* @see #getRemoveAbandonedOnMaintenance
*/
public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) {
this.removeAbandonedOnMaintenance = removeAbandonedOnMaintenance;
}
/**
* Timeout in seconds before an abandoned object can be removed.
*/
private int removeAbandonedTimeout = 300;
/**
* <p>Timeout in seconds before an abandoned object can be removed.</p>
*
* <p>The time of most recent use of an object is the maximum (latest) of
* {@link org.apache.tomcat.dbcp.pool2.TrackedUse#getLastUsed()}
* (if this class of the object implements
* TrackedUse) and the time when the object was borrowed from the pool.</p>
*
* <p>The default value is 300 seconds.</p>
*
* @return the abandoned object timeout in seconds
*/
public int getRemoveAbandonedTimeout() {
return this.removeAbandonedTimeout;
}
/**
* <p>Sets the timeout in seconds before an abandoned object can be
* removed</p>
*
* <p>Setting this property has no effect if
* {@link #getRemoveAbandonedOnBorrow() removeAbandonedOnBorrow} and
* {@link #getRemoveAbandonedOnMaintenance() removeAbandonedOnMaintenance}
* are both false.</p>
*
* @param removeAbandonedTimeout new abandoned timeout in seconds
* @see #getRemoveAbandonedTimeout()
*/
public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) {
this.removeAbandonedTimeout = removeAbandonedTimeout;
}
/**
* Determines whether or not to log stack traces for application code
* which abandoned an object.
*/
private boolean logAbandoned = false;
/**
* Flag to log stack traces for application code which abandoned
* an object.
*
* Defaults to false.
* Logging of abandoned objects adds overhead for every object created
* because a stack trace has to be generated.
*
* @return boolean true if stack trace logging is turned on for abandoned
* objects
*
*/
public boolean getLogAbandoned() {
return this.logAbandoned;
}
/**
* Sets the flag to log stack traces for application code which abandoned
* an object.
*
* @param logAbandoned true turns on abandoned stack trace logging
* @see #getLogAbandoned()
*
*/
public void setLogAbandoned(final boolean logAbandoned) {
this.logAbandoned = logAbandoned;
}
/**
* Determines whether or not to log full stack traces when logAbandoned is true.
* If disabled, then a faster method for logging stack traces with only class data
* may be used if possible.
*
* @since 2.5
*/
private boolean requireFullStackTrace = true;
/**
* Indicates if full stack traces are required when {@link #getLogAbandoned() logAbandoned}
* is true. Defaults to true. Logging of abandoned objects requiring a full stack trace will
* generate an entire stack trace to generate for every object created. If this is disabled,
* a faster but less informative stack walking mechanism may be used if available.
*
* @return true if full stack traces are required for logging abandoned connections, or false
* if abbreviated stack traces are acceptable
* @see CallStack
* @since 2.5
*/
public boolean getRequireFullStackTrace() {
return requireFullStackTrace;
}
/**
* Sets the flag to require full stack traces for logging abandoned connections when enabled.
*
* @param requireFullStackTrace indicates whether or not full stack traces are required in
* abandoned connection logs
* @see CallStack
* @see #getRequireFullStackTrace()
* @since 2.5
*/
public void setRequireFullStackTrace(final boolean requireFullStackTrace) {
this.requireFullStackTrace = requireFullStackTrace;
}
/**
* PrintWriter to use to log information on abandoned objects.
* Use of default system encoding is deliberate.
*/
private PrintWriter logWriter = new PrintWriter(System.out);
/**
* Returns the log writer being used by this configuration to log
* information on abandoned objects. If not set, a PrintWriter based on
* System.out with the system default encoding is used.
*
* @return log writer in use
*/
public PrintWriter getLogWriter() {
return logWriter;
}
/**
* Sets the log writer to be used by this configuration to log
* information on abandoned objects.
*
* @param logWriter The new log writer
*/
public void setLogWriter(final PrintWriter logWriter) {
this.logWriter = logWriter;
}
/**
* If the pool implements
* {@link org.apache.tomcat.dbcp.pool2.UsageTracking}, should the pool
* record a 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?
*/
private boolean useUsageTracking = false;
/**
* If the pool implements
* {@link org.apache.tomcat.dbcp.pool2.UsageTracking}, should the pool
* record a
* 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 <code>true</code> if usage tracking is enabled
*/
public boolean getUseUsageTracking() {
return useUsageTracking;
}
/**
* If the pool implements
* {@link org.apache.tomcat.dbcp.pool2.UsageTracking}, configure whether the
* pool
* should record a 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.
*
* @param useUsageTracking A value of <code>true</code> will enable
* the recording of a stack trace on every use
* of a pooled object
*/
public void setUseUsageTracking(final boolean useUsageTracking) {
this.useUsageTracking = useUsageTracking;
}
/**
* @since 2.4.3
*/
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("AbandonedConfig [removeAbandonedOnBorrow=");
builder.append(removeAbandonedOnBorrow);
builder.append(", removeAbandonedOnMaintenance=");
builder.append(removeAbandonedOnMaintenance);
builder.append(", removeAbandonedTimeout=");
builder.append(removeAbandonedTimeout);
builder.append(", logAbandoned=");
builder.append(logAbandoned);
builder.append(", logWriter=");
builder.append(logWriter);
builder.append(", useUsageTracking=");
builder.append(useUsageTracking);
builder.append("]");
return builder.toString();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,750 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import org.apache.tomcat.dbcp.pool2.BaseObject;
/**
* Provides the implementation for the common attributes shared by the
* sub-classes. New instances of this class will be created using the defaults
* defined by the public constants.
* <p>
* This class is not thread-safe.
* </p>
*
* @param <T> Type of element pooled.
* @since 2.0
*/
public abstract class BaseObjectPoolConfig<T> extends BaseObject implements Cloneable {
/**
* The default value for the {@code lifo} configuration attribute.
* @see GenericObjectPool#getLifo()
* @see GenericKeyedObjectPool#getLifo()
*/
public static final boolean DEFAULT_LIFO = true;
/**
* The default value for the {@code fairness} configuration attribute.
* @see GenericObjectPool#getFairness()
* @see GenericKeyedObjectPool#getFairness()
*/
public static final boolean DEFAULT_FAIRNESS = false;
/**
* The default value for the {@code maxWait} configuration attribute.
* @see GenericObjectPool#getMaxWaitMillis()
* @see GenericKeyedObjectPool#getMaxWaitMillis()
*/
public static final long DEFAULT_MAX_WAIT_MILLIS = -1L;
/**
* The default value for the {@code minEvictableIdleTimeMillis}
* configuration attribute.
* @see GenericObjectPool#getMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()
*/
public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS =
1000L * 60L * 30L;
/**
* The default value for the {@code softMinEvictableIdleTimeMillis}
* configuration attribute.
* @see GenericObjectPool#getSoftMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()
*/
public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1;
/**
* The default value for {@code evictorShutdownTimeoutMillis} configuration
* attribute.
* @see GenericObjectPool#getEvictorShutdownTimeoutMillis()
* @see GenericKeyedObjectPool#getEvictorShutdownTimeoutMillis()
*/
public static final long DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS =
10L * 1000L;
/**
* The default value for the {@code numTestsPerEvictionRun} configuration
* attribute.
* @see GenericObjectPool#getNumTestsPerEvictionRun()
* @see GenericKeyedObjectPool#getNumTestsPerEvictionRun()
*/
public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
/**
* The default value for the {@code testOnCreate} configuration attribute.
* @see GenericObjectPool#getTestOnCreate()
* @see GenericKeyedObjectPool#getTestOnCreate()
*
* @since 2.2
*/
public static final boolean DEFAULT_TEST_ON_CREATE = false;
/**
* The default value for the {@code testOnBorrow} configuration attribute.
* @see GenericObjectPool#getTestOnBorrow()
* @see GenericKeyedObjectPool#getTestOnBorrow()
*/
public static final boolean DEFAULT_TEST_ON_BORROW = false;
/**
* The default value for the {@code testOnReturn} configuration attribute.
* @see GenericObjectPool#getTestOnReturn()
* @see GenericKeyedObjectPool#getTestOnReturn()
*/
public static final boolean DEFAULT_TEST_ON_RETURN = false;
/**
* The default value for the {@code testWhileIdle} configuration attribute.
* @see GenericObjectPool#getTestWhileIdle()
* @see GenericKeyedObjectPool#getTestWhileIdle()
*/
public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
/**
* The default value for the {@code timeBetweenEvictionRunsMillis}
* configuration attribute.
* @see GenericObjectPool#getTimeBetweenEvictionRunsMillis()
* @see GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis()
*/
public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
/**
* The default value for the {@code blockWhenExhausted} configuration
* attribute.
* @see GenericObjectPool#getBlockWhenExhausted()
* @see GenericKeyedObjectPool#getBlockWhenExhausted()
*/
public static final boolean DEFAULT_BLOCK_WHEN_EXHAUSTED = true;
/**
* The default value for enabling JMX for pools created with a configuration
* instance.
*/
public static final boolean DEFAULT_JMX_ENABLE = true;
/**
* The default value for the prefix used to name JMX enabled pools created
* with a configuration instance.
* @see GenericObjectPool#getJmxName()
* @see GenericKeyedObjectPool#getJmxName()
*/
public static final String DEFAULT_JMX_NAME_PREFIX = "pool";
/**
* The default value for the base name to use to name JMX enabled pools
* created with a configuration instance. The default is <code>null</code>
* which means the pool will provide the base name to use.
* @see GenericObjectPool#getJmxName()
* @see GenericKeyedObjectPool#getJmxName()
*/
public static final String DEFAULT_JMX_NAME_BASE = null;
/**
* The default value for the {@code evictionPolicyClassName} configuration
* attribute.
* @see GenericObjectPool#getEvictionPolicyClassName()
* @see GenericKeyedObjectPool#getEvictionPolicyClassName()
*/
public static final String DEFAULT_EVICTION_POLICY_CLASS_NAME = DefaultEvictionPolicy.class.getName();
private boolean lifo = DEFAULT_LIFO;
private boolean fairness = DEFAULT_FAIRNESS;
private long maxWaitMillis = DEFAULT_MAX_WAIT_MILLIS;
private long minEvictableIdleTimeMillis =
DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private long evictorShutdownTimeoutMillis =
DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS;
private long softMinEvictableIdleTimeMillis =
DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private int numTestsPerEvictionRun =
DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
private EvictionPolicy<T> evictionPolicy = null; // Only 2.6.0 applications set this
private String evictionPolicyClassName = DEFAULT_EVICTION_POLICY_CLASS_NAME;
private boolean testOnCreate = DEFAULT_TEST_ON_CREATE;
private boolean testOnBorrow = DEFAULT_TEST_ON_BORROW;
private boolean testOnReturn = DEFAULT_TEST_ON_RETURN;
private boolean testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
private long timeBetweenEvictionRunsMillis =
DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
private boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED;
private boolean jmxEnabled = DEFAULT_JMX_ENABLE;
// TODO Consider changing this to a single property for 3.x
private String jmxNamePrefix = DEFAULT_JMX_NAME_PREFIX;
private String jmxNameBase = DEFAULT_JMX_NAME_BASE;
/**
* Get the value for the {@code lifo} configuration attribute for pools
* created with this configuration instance.
*
* @return The current setting of {@code lifo} for this configuration
* instance
*
* @see GenericObjectPool#getLifo()
* @see GenericKeyedObjectPool#getLifo()
*/
public boolean getLifo() {
return lifo;
}
/**
* Get the value for the {@code fairness} configuration attribute for pools
* created with this configuration instance.
*
* @return The current setting of {@code fairness} for this configuration
* instance
*
* @see GenericObjectPool#getFairness()
* @see GenericKeyedObjectPool#getFairness()
*/
public boolean getFairness() {
return fairness;
}
/**
* Set the value for the {@code lifo} configuration attribute for pools
* created with this configuration instance.
*
* @param lifo The new setting of {@code lifo}
* for this configuration instance
*
* @see GenericObjectPool#getLifo()
* @see GenericKeyedObjectPool#getLifo()
*/
public void setLifo(final boolean lifo) {
this.lifo = lifo;
}
/**
* Set the value for the {@code fairness} configuration attribute for pools
* created with this configuration instance.
*
* @param fairness The new setting of {@code fairness}
* for this configuration instance
*
* @see GenericObjectPool#getFairness()
* @see GenericKeyedObjectPool#getFairness()
*/
public void setFairness(final boolean fairness) {
this.fairness = fairness;
}
/**
* Get the value for the {@code maxWait} configuration attribute for pools
* created with this configuration instance.
*
* @return The current setting of {@code maxWait} for this
* configuration instance
*
* @see GenericObjectPool#getMaxWaitMillis()
* @see GenericKeyedObjectPool#getMaxWaitMillis()
*/
public long getMaxWaitMillis() {
return maxWaitMillis;
}
/**
* Set the value for the {@code maxWait} configuration attribute for pools
* created with this configuration instance.
*
* @param maxWaitMillis The new setting of {@code maxWaitMillis}
* for this configuration instance
*
* @see GenericObjectPool#getMaxWaitMillis()
* @see GenericKeyedObjectPool#getMaxWaitMillis()
*/
public void setMaxWaitMillis(final long maxWaitMillis) {
this.maxWaitMillis = maxWaitMillis;
}
/**
* Get the value for the {@code minEvictableIdleTimeMillis} configuration
* attribute for pools created with this configuration instance.
*
* @return The current setting of {@code minEvictableIdleTimeMillis} for
* this configuration instance
*
* @see GenericObjectPool#getMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()
*/
public long getMinEvictableIdleTimeMillis() {
return minEvictableIdleTimeMillis;
}
/**
* Set the value for the {@code minEvictableIdleTimeMillis} configuration
* attribute for pools created with this configuration instance.
*
* @param minEvictableIdleTimeMillis The new setting of
* {@code minEvictableIdleTimeMillis} for this configuration instance
*
* @see GenericObjectPool#getMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()
*/
public void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
/**
* Get the value for the {@code softMinEvictableIdleTimeMillis}
* configuration attribute for pools created with this configuration
* instance.
*
* @return The current setting of {@code softMinEvictableIdleTimeMillis}
* for this configuration instance
*
* @see GenericObjectPool#getSoftMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()
*/
public long getSoftMinEvictableIdleTimeMillis() {
return softMinEvictableIdleTimeMillis;
}
/**
* Set the value for the {@code softMinEvictableIdleTimeMillis}
* configuration attribute for pools created with this configuration
* instance.
*
* @param softMinEvictableIdleTimeMillis The new setting of
* {@code softMinEvictableIdleTimeMillis} for this configuration
* instance
*
* @see GenericObjectPool#getSoftMinEvictableIdleTimeMillis()
* @see GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()
*/
public void setSoftMinEvictableIdleTimeMillis(
final long softMinEvictableIdleTimeMillis) {
this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
}
/**
* Get the value for the {@code numTestsPerEvictionRun} configuration
* attribute for pools created with this configuration instance.
*
* @return The current setting of {@code numTestsPerEvictionRun} for this
* configuration instance
*
* @see GenericObjectPool#getNumTestsPerEvictionRun()
* @see GenericKeyedObjectPool#getNumTestsPerEvictionRun()
*/
public int getNumTestsPerEvictionRun() {
return numTestsPerEvictionRun;
}
/**
* Set the value for the {@code numTestsPerEvictionRun} configuration
* attribute for pools created with this configuration instance.
*
* @param numTestsPerEvictionRun The new setting of
* {@code numTestsPerEvictionRun} for this configuration instance
*
* @see GenericObjectPool#getNumTestsPerEvictionRun()
* @see GenericKeyedObjectPool#getNumTestsPerEvictionRun()
*/
public void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
this.numTestsPerEvictionRun = numTestsPerEvictionRun;
}
/**
* Get the value for the {@code evictorShutdownTimeoutMillis} configuration
* attribute for pools created with this configuration instance.
*
* @return The current setting of {@code evictorShutdownTimeoutMillis} for
* this configuration instance
*
* @see GenericObjectPool#getEvictorShutdownTimeoutMillis()
* @see GenericKeyedObjectPool#getEvictorShutdownTimeoutMillis()
*/
public long getEvictorShutdownTimeoutMillis() {
return evictorShutdownTimeoutMillis;
}
/**
* Set the value for the {@code evictorShutdownTimeoutMillis} configuration
* attribute for pools created with this configuration instance.
*
* @param evictorShutdownTimeoutMillis The new setting of
* {@code evictorShutdownTimeoutMillis} for this configuration
* instance
*
* @see GenericObjectPool#getEvictorShutdownTimeoutMillis()
* @see GenericKeyedObjectPool#getEvictorShutdownTimeoutMillis()
*/
public void setEvictorShutdownTimeoutMillis(
final long evictorShutdownTimeoutMillis) {
this.evictorShutdownTimeoutMillis = evictorShutdownTimeoutMillis;
}
/**
* Get the value for the {@code testOnCreate} configuration attribute for
* pools created with this configuration instance.
*
* @return The current setting of {@code testOnCreate} for this
* configuration instance
*
* @see GenericObjectPool#getTestOnCreate()
* @see GenericKeyedObjectPool#getTestOnCreate()
*
* @since 2.2
*/
public boolean getTestOnCreate() {
return testOnCreate;
}
/**
* Set the value for the {@code testOnCreate} configuration attribute for
* pools created with this configuration instance.
*
* @param testOnCreate The new setting of {@code testOnCreate}
* for this configuration instance
*
* @see GenericObjectPool#getTestOnCreate()
* @see GenericKeyedObjectPool#getTestOnCreate()
*
* @since 2.2
*/
public void setTestOnCreate(final boolean testOnCreate) {
this.testOnCreate = testOnCreate;
}
/**
* Get the value for the {@code testOnBorrow} configuration attribute for
* pools created with this configuration instance.
*
* @return The current setting of {@code testOnBorrow} for this
* configuration instance
*
* @see GenericObjectPool#getTestOnBorrow()
* @see GenericKeyedObjectPool#getTestOnBorrow()
*/
public boolean getTestOnBorrow() {
return testOnBorrow;
}
/**
* Set the value for the {@code testOnBorrow} configuration attribute for
* pools created with this configuration instance.
*
* @param testOnBorrow The new setting of {@code testOnBorrow}
* for this configuration instance
*
* @see GenericObjectPool#getTestOnBorrow()
* @see GenericKeyedObjectPool#getTestOnBorrow()
*/
public void setTestOnBorrow(final boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
/**
* Get the value for the {@code testOnReturn} configuration attribute for
* pools created with this configuration instance.
*
* @return The current setting of {@code testOnReturn} for this
* configuration instance
*
* @see GenericObjectPool#getTestOnReturn()
* @see GenericKeyedObjectPool#getTestOnReturn()
*/
public boolean getTestOnReturn() {
return testOnReturn;
}
/**
* Set the value for the {@code testOnReturn} configuration attribute for
* pools created with this configuration instance.
*
* @param testOnReturn The new setting of {@code testOnReturn}
* for this configuration instance
*
* @see GenericObjectPool#getTestOnReturn()
* @see GenericKeyedObjectPool#getTestOnReturn()
*/
public void setTestOnReturn(final boolean testOnReturn) {
this.testOnReturn = testOnReturn;
}
/**
* Get the value for the {@code testWhileIdle} configuration attribute for
* pools created with this configuration instance.
*
* @return The current setting of {@code testWhileIdle} for this
* configuration instance
*
* @see GenericObjectPool#getTestWhileIdle()
* @see GenericKeyedObjectPool#getTestWhileIdle()
*/
public boolean getTestWhileIdle() {
return testWhileIdle;
}
/**
* Set the value for the {@code testWhileIdle} configuration attribute for
* pools created with this configuration instance.
*
* @param testWhileIdle The new setting of {@code testWhileIdle}
* for this configuration instance
*
* @see GenericObjectPool#getTestWhileIdle()
* @see GenericKeyedObjectPool#getTestWhileIdle()
*/
public void setTestWhileIdle(final boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
/**
* Get the value for the {@code timeBetweenEvictionRunsMillis} configuration
* attribute for pools created with this configuration instance.
*
* @return The current setting of {@code timeBetweenEvictionRunsMillis} for
* this configuration instance
*
* @see GenericObjectPool#getTimeBetweenEvictionRunsMillis()
* @see GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis()
*/
public long getTimeBetweenEvictionRunsMillis() {
return timeBetweenEvictionRunsMillis;
}
/**
* Set the value for the {@code timeBetweenEvictionRunsMillis} configuration
* attribute for pools created with this configuration instance.
*
* @param timeBetweenEvictionRunsMillis The new setting of
* {@code timeBetweenEvictionRunsMillis} for this configuration
* instance
*
* @see GenericObjectPool#getTimeBetweenEvictionRunsMillis()
* @see GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis()
*/
public void setTimeBetweenEvictionRunsMillis(
final long timeBetweenEvictionRunsMillis) {
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<T> getEvictionPolicy() {
return evictionPolicy;
}
/**
* Get the value for the {@code evictionPolicyClassName} configuration
* attribute for pools created with this configuration instance.
*
* @return The current setting of {@code evictionPolicyClassName} for this
* configuration instance
*
* @see GenericObjectPool#getEvictionPolicyClassName()
* @see GenericKeyedObjectPool#getEvictionPolicyClassName()
*/
public String getEvictionPolicyClassName() {
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<T> evictionPolicy) {
this.evictionPolicy = evictionPolicy;
}
/**
* Set the value for the {@code evictionPolicyClassName} configuration
* attribute for pools created with this configuration instance.
*
* @param evictionPolicyClassName The new setting of
* {@code evictionPolicyClassName} for this configuration instance
*
* @see GenericObjectPool#getEvictionPolicyClassName()
* @see GenericKeyedObjectPool#getEvictionPolicyClassName()
*/
public void setEvictionPolicyClassName(final String evictionPolicyClassName) {
this.evictionPolicyClassName = evictionPolicyClassName;
}
/**
* Get the value for the {@code blockWhenExhausted} configuration attribute
* for pools created with this configuration instance.
*
* @return The current setting of {@code blockWhenExhausted} for this
* configuration instance
*
* @see GenericObjectPool#getBlockWhenExhausted()
* @see GenericKeyedObjectPool#getBlockWhenExhausted()
*/
public boolean getBlockWhenExhausted() {
return blockWhenExhausted;
}
/**
* Set the value for the {@code blockWhenExhausted} configuration attribute
* for pools created with this configuration instance.
*
* @param blockWhenExhausted The new setting of {@code blockWhenExhausted}
* for this configuration instance
*
* @see GenericObjectPool#getBlockWhenExhausted()
* @see GenericKeyedObjectPool#getBlockWhenExhausted()
*/
public void setBlockWhenExhausted(final boolean blockWhenExhausted) {
this.blockWhenExhausted = blockWhenExhausted;
}
/**
* Gets the value of the flag that determines if JMX will be enabled for
* pools created with this configuration instance.
*
* @return The current setting of {@code jmxEnabled} for this configuration
* instance
*/
public boolean getJmxEnabled() {
return jmxEnabled;
}
/**
* Sets the value of the flag that determines if JMX will be enabled for
* pools created with this configuration instance.
*
* @param jmxEnabled The new setting of {@code jmxEnabled}
* for this configuration instance
*/
public void setJmxEnabled(final boolean jmxEnabled) {
this.jmxEnabled = jmxEnabled;
}
/**
* 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 <code>null</code> means that the pool will define
* the JMX name base.
*
* @return The current setting of {@code jmxNameBase} for this
* configuration instance
*/
public String getJmxNameBase() {
return jmxNameBase;
}
/**
* 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 of <code>null</code> means that the pool will define
* the JMX name base.
*
* @param jmxNameBase The new setting of {@code jmxNameBase}
* for this configuration instance
*/
public void setJmxNameBase(final String jmxNameBase) {
this.jmxNameBase = jmxNameBase;
}
/**
* Gets the value of the JMX name prefix that will be used as part of the
* name assigned to JMX enabled pools created with this configuration
* instance.
*
* @return The current setting of {@code jmxNamePrefix} for this
* configuration instance
*/
public String getJmxNamePrefix() {
return jmxNamePrefix;
}
/**
* Sets the value of the JMX name prefix that will be used as part of the
* name assigned to JMX enabled pools created with this configuration
* instance.
*
* @param jmxNamePrefix The new setting of {@code jmxNamePrefix}
* for this configuration instance
*/
public void setJmxNamePrefix(final String jmxNamePrefix) {
this.jmxNamePrefix = jmxNamePrefix;
}
@Override
protected void toStringAppendFields(final StringBuilder builder) {
builder.append("lifo=");
builder.append(lifo);
builder.append(", fairness=");
builder.append(fairness);
builder.append(", maxWaitMillis=");
builder.append(maxWaitMillis);
builder.append(", minEvictableIdleTimeMillis=");
builder.append(minEvictableIdleTimeMillis);
builder.append(", softMinEvictableIdleTimeMillis=");
builder.append(softMinEvictableIdleTimeMillis);
builder.append(", numTestsPerEvictionRun=");
builder.append(numTestsPerEvictionRun);
builder.append(", evictionPolicyClassName=");
builder.append(evictionPolicyClassName);
builder.append(", testOnCreate=");
builder.append(testOnCreate);
builder.append(", testOnBorrow=");
builder.append(testOnBorrow);
builder.append(", testOnReturn=");
builder.append(testOnReturn);
builder.append(", testWhileIdle=");
builder.append(testWhileIdle);
builder.append(", timeBetweenEvictionRunsMillis=");
builder.append(timeBetweenEvictionRunsMillis);
builder.append(", blockWhenExhausted=");
builder.append(blockWhenExhausted);
builder.append(", jmxEnabled=");
builder.append(jmxEnabled);
builder.append(", jmxNamePrefix=");
builder.append(jmxNamePrefix);
builder.append(", jmxNameBase=");
builder.append(jmxNameBase);
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.io.PrintWriter;
/**
* Strategy for obtaining and printing the current call stack. This is primarily useful for
* {@link org.apache.tomcat.dbcp.pool2.UsageTracking usage tracking} so
* that different JVMs and configurations can use more efficient strategies
* for obtaining the current call stack depending on metadata needs.
*
* @see CallStackUtils
* @since 2.4.3
*/
public interface CallStack {
/**
* Prints the current stack trace if available to a PrintWriter. The format is undefined and is primarily useful
* for debugging issues with {@link org.apache.tomcat.dbcp.pool2.PooledObject} usage in user code.
*
* @param writer a PrintWriter to write the current stack trace to if available
* @return true if a stack trace was available to print or false if nothing was printed
*/
boolean printStackTrace(final PrintWriter writer);
/**
* Takes a snapshot of the current call stack. Subsequent calls to {@link #printStackTrace(PrintWriter)} will print
* out that stack trace until it is {@linkplain #clear() cleared}.
*/
void fillInStackTrace();
/**
* Clears the current stack trace snapshot. Subsequent calls to {@link #printStackTrace(PrintWriter)} will be
* no-ops until another call to {@link #fillInStackTrace()}.
*/
void clear();
}

View File

@@ -0,0 +1,85 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.security.AccessControlException;
/**
* Utility methods for {@link CallStack}.
*
* @since 2.4.3
*/
public final class CallStackUtils {
/**
* 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.
*/
private static boolean canCreateSecurityManager() {
final SecurityManager manager = System.getSecurityManager();
if (manager == null) {
return true;
}
try {
manager.checkPermission(new RuntimePermission("createSecurityManager"));
return true;
} catch (final AccessControlException ignored) {
return false;
}
}
/**
* Constructs a new {@link CallStack} using the fastest allowed strategy.
*
* @param messageFormat message (or format) to print first in stack traces
* @param useTimestamp if true, interpret message as a SimpleDateFormat and print the created timestamp; otherwise,
* print message format literally
* @return a new CallStack
* @deprecated use {@link #newCallStack(String, boolean, boolean)}
*/
@Deprecated
public static CallStack newCallStack(final String messageFormat, final boolean useTimestamp) {
return newCallStack(messageFormat, useTimestamp, false);
}
/**
* Constructs a new {@link CallStack} using the fasted allowed strategy.
*
* @param messageFormat message (or format) to print first in stack traces
* @param useTimestamp if true, interpret message as a SimpleDateFormat and print the created timestamp;
* otherwise, print message format literally
* @param requireFullStackTrace if true, forces the use of a stack walking mechanism that includes full stack trace
* information; otherwise, uses a faster implementation if possible
* @return a new CallStack
* @since 2.5
*/
public static CallStack newCallStack(final String messageFormat,
final boolean useTimestamp,
final boolean requireFullStackTrace) {
return canCreateSecurityManager() && !requireFullStackTrace
? new SecurityManagerCallStack(messageFormat, useTimestamp)
: new ThrowableCallStack(messageFormat, useTimestamp);
}
/**
* Hidden constructor.
*/
private CallStackUtils() {
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import org.apache.tomcat.dbcp.pool2.PooledObject;
/**
* Provides the default implementation of {@link EvictionPolicy} used by the
* pools. Objects will be evicted if the following conditions are met:
* <ul>
* <li>the object has been idle longer than
* {@link GenericObjectPool#getMinEvictableIdleTimeMillis()} /
* {@link GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()}</li>
* <li>there are more than {@link GenericObjectPool#getMinIdle()} /
* {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} idle objects in
* the pool and the object has been idle for longer than
* {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} /
* {@link GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()}
* </ul>
* <p>
* This class is immutable and thread-safe.
* </p>
*
* @param <T> the type of objects in the pool
*
* @since 2.0
*/
public class DefaultEvictionPolicy<T> implements EvictionPolicy<T> {
@Override
public boolean evict(final EvictionConfig config, final PooledObject<T> underTest,
final int idleCount) {
if ((config.getIdleSoftEvictTime() < underTest.getIdleTimeMillis() &&
config.getMinIdle() < idleCount) ||
config.getIdleEvictTime() < underTest.getIdleTimeMillis()) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,298 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.io.PrintWriter;
import java.util.Deque;
import org.apache.tomcat.dbcp.pool2.PooledObject;
import org.apache.tomcat.dbcp.pool2.PooledObjectState;
import org.apache.tomcat.dbcp.pool2.TrackedUse;
/**
* This wrapper is used to track the additional information, such as state, for
* the pooled objects.
* <p>
* This class is intended to be thread-safe.
* </p>
*
* @param <T> the type of object in the pool
*
* @since 2.0
*/
public class DefaultPooledObject<T> implements PooledObject<T> {
private final T object;
private PooledObjectState state = PooledObjectState.IDLE; // @GuardedBy("this") to ensure transitions are valid
private final long createTime = System.currentTimeMillis();
private volatile long lastBorrowTime = createTime;
private volatile long lastUseTime = createTime;
private volatile long lastReturnTime = createTime;
private volatile boolean logAbandoned = false;
private volatile CallStack borrowedBy = NoOpCallStack.INSTANCE;
private volatile CallStack usedBy = NoOpCallStack.INSTANCE;
private volatile long borrowedCount = 0;
/**
* 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
*/
public DefaultPooledObject(final T object) {
this.object = object;
}
@Override
public T getObject() {
return object;
}
@Override
public long getCreateTime() {
return createTime;
}
@Override
public long getActiveTimeMillis() {
// Take copies to avoid threading issues
final long rTime = lastReturnTime;
final long bTime = lastBorrowTime;
if (rTime > bTime) {
return rTime - bTime;
}
return System.currentTimeMillis() - bTime;
}
@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;
}
@Override
public long getLastBorrowTime() {
return lastBorrowTime;
}
@Override
public long getLastReturnTime() {
return lastReturnTime;
}
/**
* 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;
}
/**
* 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
* value as {@link #getLastBorrowTime()}.
*
* @return the last time this object was used
*/
@Override
public long getLastUsedTime() {
if (object instanceof TrackedUse) {
return Math.max(((TrackedUse) object).getLastUsed(), lastUseTime);
}
return lastUseTime;
}
@Override
public int compareTo(final PooledObject<T> other) {
final long lastActiveDiff = this.getLastReturnTime() - other.getLastReturnTime();
if (lastActiveDiff == 0) {
// Make sure the natural ordering is broadly consistent with equals
// although this will break down if distinct objects have the same
// identity hash code.
// see java.lang.Comparable Javadocs
return System.identityHashCode(this) - System.identityHashCode(other);
}
// handle int overflow
return (int)Math.min(Math.max(lastActiveDiff, Integer.MIN_VALUE), Integer.MAX_VALUE);
}
@Override
public String toString() {
final StringBuilder result = new StringBuilder();
result.append("Object: ");
result.append(object.toString());
result.append(", State: ");
synchronized (this) {
result.append(state.toString());
}
return result.toString();
// TODO add other attributes
}
@Override
public synchronized boolean startEvictionTest() {
if (state == PooledObjectState.IDLE) {
state = PooledObjectState.EVICTION;
return true;
}
return false;
}
@Override
public synchronized boolean endEvictionTest(
final Deque<PooledObject<T>> idleQueue) {
if (state == PooledObjectState.EVICTION) {
state = PooledObjectState.IDLE;
return true;
} else if (state == PooledObjectState.EVICTION_RETURN_TO_HEAD) {
state = PooledObjectState.IDLE;
if (!idleQueue.offerFirst(this)) {
// TODO - Should never happen
}
}
return false;
}
/**
* Allocates the object.
*
* @return {@code true} if the original state was {@link PooledObjectState#IDLE IDLE}
*/
@Override
public synchronized boolean allocate() {
if (state == PooledObjectState.IDLE) {
state = PooledObjectState.ALLOCATED;
lastBorrowTime = System.currentTimeMillis();
lastUseTime = lastBorrowTime;
borrowedCount++;
if (logAbandoned) {
borrowedBy.fillInStackTrace();
}
return true;
} else if (state == PooledObjectState.EVICTION) {
// TODO Allocate anyway and ignore eviction test
state = PooledObjectState.EVICTION_RETURN_TO_HEAD;
return false;
}
// TODO if validating and testOnBorrow == true then pre-allocate for
// performance
return false;
}
/**
* Deallocates the object and sets it {@link PooledObjectState#IDLE IDLE}
* if it is currently {@link PooledObjectState#ALLOCATED ALLOCATED}.
*
* @return {@code true} if the state was {@link PooledObjectState#ALLOCATED ALLOCATED}
*/
@Override
public synchronized boolean deallocate() {
if (state == PooledObjectState.ALLOCATED ||
state == PooledObjectState.RETURNING) {
state = PooledObjectState.IDLE;
lastReturnTime = System.currentTimeMillis();
borrowedBy.clear();
return true;
}
return false;
}
/**
* Sets the state to {@link PooledObjectState#INVALID INVALID}
*/
@Override
public synchronized void invalidate() {
state = PooledObjectState.INVALID;
}
@Override
public void use() {
lastUseTime = System.currentTimeMillis();
usedBy.fillInStackTrace();
}
@Override
public void printStackTrace(final PrintWriter writer) {
boolean written = borrowedBy.printStackTrace(writer);
written |= usedBy.printStackTrace(writer);
if (written) {
writer.flush();
}
}
/**
* Returns the state of this object.
* @return state
*/
@Override
public synchronized PooledObjectState getState() {
return state;
}
/**
* Marks the pooled object as abandoned.
*/
@Override
public synchronized void markAbandoned() {
state = PooledObjectState.ABANDONED;
}
/**
* Marks the object as returning to the pool.
*/
@Override
public synchronized void markReturning() {
state = PooledObjectState.RETURNING;
}
@Override
public void setLogAbandoned(final boolean logAbandoned) {
this.logAbandoned = logAbandoned;
}
/**
* 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.5
*/
@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:'",
true, requireFullStackTrace);
usedBy = CallStackUtils.newCallStack("The last code to use this object was:",
false, requireFullStackTrace);
}
}

View File

@@ -0,0 +1,110 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import org.apache.tomcat.dbcp.pool2.PooledObject;
/**
* Implementation of object that is used to provide information on pooled
* objects via JMX.
*
* @since 2.0
*/
public class DefaultPooledObjectInfo implements DefaultPooledObjectInfoMBean {
private final PooledObject<?> pooledObject;
/**
* Create a new instance for the given pooled object.
*
* @param pooledObject The pooled object that this instance will represent
*/
public DefaultPooledObjectInfo(final PooledObject<?> pooledObject) {
this.pooledObject = pooledObject;
}
@Override
public long getCreateTime() {
return pooledObject.getCreateTime();
}
@Override
public String getCreateTimeFormatted() {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
return sdf.format(Long.valueOf(pooledObject.getCreateTime()));
}
@Override
public long getLastBorrowTime() {
return pooledObject.getLastBorrowTime();
}
@Override
public String getLastBorrowTimeFormatted() {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
return sdf.format(Long.valueOf(pooledObject.getLastBorrowTime()));
}
@Override
public String getLastBorrowTrace() {
final StringWriter sw = new StringWriter();
pooledObject.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
@Override
public long getLastReturnTime() {
return pooledObject.getLastReturnTime();
}
@Override
public String getLastReturnTimeFormatted() {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
return sdf.format(Long.valueOf(pooledObject.getLastReturnTime()));
}
@Override
public String getPooledObjectType() {
return pooledObject.getObject().getClass().getName();
}
@Override
public String getPooledObjectToString() {
return pooledObject.getObject().toString();
}
@Override
public long getBorrowedCount() {
return pooledObject.getBorrowedCount();
}
/**
* @since 2.4.3
*/
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("DefaultPooledObjectInfo [pooledObject=");
builder.append(pooledObject);
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,115 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
/**
* The interface that defines the information about pooled objects that will be
* exposed via JMX.
*
* NOTE: This interface exists only to define those attributes and methods that
* will be made available via JMX. It must not be implemented by clients
* as it is subject to change between major, minor and patch version
* releases of commons pool. Clients that implement this interface may
* not, therefore, be able to upgrade to a new minor or patch release
* without requiring code changes.
*
* @since 2.0
*/
public interface DefaultPooledObjectInfoMBean {
/**
* Obtain the time (using the same basis as
* {@link System#currentTimeMillis()}) that pooled object was created.
*
* @return The creation time for the pooled object
*/
long getCreateTime();
/**
* Obtain the time that pooled object was created.
*
* @return The creation time for the pooled object formatted as
* <code>yyyy-MM-dd HH:mm:ss Z</code>
*/
String getCreateTimeFormatted();
/**
* Obtain the time (using the same basis as
* {@link System#currentTimeMillis()}) the polled object was last borrowed.
*
* @return The time the pooled object was last borrowed
*/
long getLastBorrowTime();
/**
* Obtain the time that pooled object was last borrowed.
*
* @return The last borrowed time for the pooled object formated as
* <code>yyyy-MM-dd HH:mm:ss Z</code>
*/
String getLastBorrowTimeFormatted();
/**
* Obtain the stack trace recorded when the pooled object was last borrowed.
*
* @return The stack trace showing which code last borrowed the pooled
* object
*/
String getLastBorrowTrace();
/**
* Obtain the time (using the same basis as
* {@link System#currentTimeMillis()})the wrapped object was last returned.
*
* @return The time the object was last returned
*/
long getLastReturnTime();
/**
* Obtain the time that pooled object was last returned.
*
* @return The last returned time for the pooled object formated as
* <code>yyyy-MM-dd HH:mm:ss Z</code>
*/
String getLastReturnTimeFormatted();
/**
* Obtain the name of the class of the pooled object.
*
* @return The pooled object's class name
*
* @see Class#getName()
*/
String getPooledObjectType();
/**
* Provides a String form of the wrapper for debug purposes. The format is
* not fixed and may change at any time.
*
* @return A string representation of the pooled object
*
* @see Object#toString()
*/
String getPooledObjectToString();
/**
* Get the number of times this object has been borrowed.
* @return The number of times this object has been borrowed.
* @since 2.1
*/
long getBorrowedCount();
}

View File

@@ -0,0 +1,115 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
/**
* This class is used by pool implementations to pass configuration information
* to {@link EvictionPolicy} instances. The {@link EvictionPolicy} may also have
* its own specific configuration attributes.
* <p>
* This class is immutable and thread-safe.
* </p>
*
* @since 2.0
*/
public class EvictionConfig {
private final long idleEvictTime;
private final long idleSoftEvictTime;
private final int minIdle;
/**
* Create a new eviction configuration with the specified parameters.
* Instances are immutable.
*
* @param poolIdleEvictTime Expected to be provided by
* {@link BaseGenericObjectPool#getMinEvictableIdleTimeMillis()}
* @param poolIdleSoftEvictTime Expected to be provided by
* {@link BaseGenericObjectPool#getSoftMinEvictableIdleTimeMillis()}
* @param minIdle Expected to be provided by
* {@link GenericObjectPool#getMinIdle()} or
* {@link GenericKeyedObjectPool#getMinIdlePerKey()}
*/
public EvictionConfig(final long poolIdleEvictTime, final long poolIdleSoftEvictTime,
final int minIdle) {
if (poolIdleEvictTime > 0) {
idleEvictTime = poolIdleEvictTime;
} else {
idleEvictTime = Long.MAX_VALUE;
}
if (poolIdleSoftEvictTime > 0) {
idleSoftEvictTime = poolIdleSoftEvictTime;
} else {
idleSoftEvictTime = Long.MAX_VALUE;
}
this.minIdle = minIdle;
}
/**
* Obtain the {@code idleEvictTime} for this eviction configuration
* instance.
* <p>
* How the evictor behaves based on this value will be determined by the
* configured {@link EvictionPolicy}.
*
* @return The {@code idleEvictTime} in milliseconds
*/
public long getIdleEvictTime() {
return idleEvictTime;
}
/**
* Obtain the {@code idleSoftEvictTime} for this eviction configuration
* instance.
* <p>
* How the evictor behaves based on this value will be determined by the
* configured {@link EvictionPolicy}.
*
* @return The (@code idleSoftEvictTime} in milliseconds
*/
public long getIdleSoftEvictTime() {
return idleSoftEvictTime;
}
/**
* Obtain the {@code minIdle} for this eviction configuration instance.
* <p>
* How the evictor behaves based on this value will be determined by the
* configured {@link EvictionPolicy}.
*
* @return The {@code minIdle}
*/
public int getMinIdle() {
return minIdle;
}
/**
* @since 2.4
*/
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("EvictionConfig [idleEvictTime=");
builder.append(idleEvictTime);
builder.append(", idleSoftEvictTime=");
builder.append(idleSoftEvictTime);
builder.append(", minIdle=");
builder.append(minIdle);
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,44 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import org.apache.tomcat.dbcp.pool2.PooledObject;
/**
* To provide a custom eviction policy (i.e. something other than {@link
* DefaultEvictionPolicy} for a pool, users must provide an implementation of
* this interface that provides the required eviction policy.
*
* @param <T> the type of objects in the pool
*
* @since 2.0
*/
public interface EvictionPolicy<T> {
/**
* This method is called to test if an idle object in the pool should be
* evicted or not.
*
* @param config The pool configuration settings related to eviction
* @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 <code>true</code> if the object should be evicted, otherwise
* <code>false</code>
*/
boolean evict(EvictionConfig config, PooledObject<T> underTest, int idleCount);
}

View File

@@ -0,0 +1,134 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.security.AccessController;
import java.security.PrivilegedAction;
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.
* <p>
* 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.
* </p>
* <p>
* This class has package scope to prevent its inclusion in the pool public API. The class declaration below should
* *not* be changed to public.
* </p>
* <p>
* This class is intended to be thread-safe.
* </p>
*
* @since 2.0
*/
class EvictionTimer {
/** Executor instance */
private static ScheduledThreadPoolExecutor executor; //@GuardedBy("EvictionTimer.class")
/** Prevents instantiation */
private EvictionTimer() {
// Hide the default constructor
}
/**
* @since 2.4.3
*/
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("EvictionTimer []");
return builder.toString();
}
/**
* Adds the specified eviction task to the timer. Tasks that are added with a
* call to this method *must* call {@link #cancel(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 BaseGenericObjectPool<?>.Evictor task, final long delay, final long period) {
if (null == executor) {
executor = new ScheduledThreadPoolExecutor(1, new EvictorThreadFactory());
executor.setRemoveOnCancelPolicy(true);
}
final ScheduledFuture<?> scheduledFuture =
executor.scheduleWithFixedDelay(task, delay, period, TimeUnit.MILLISECONDS);
task.setScheduledFuture(scheduledFuture);
}
/**
* Removes the specified eviction task from the timer.
*
* @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.
*/
static synchronized void cancel(
final BaseGenericObjectPool<?>.Evictor evictor, final long timeout, final TimeUnit unit) {
if (evictor != null) {
evictor.cancel();
}
if (executor != null && executor.getQueue().isEmpty()) {
executor.shutdown();
try {
executor.awaitTermination(timeout, unit);
} catch (final InterruptedException e) {
// Swallow
// Significant API changes would be required to propagate this
}
executor.setCorePoolSize(0);
executor = null;
}
}
/**
* 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 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(new PrivilegedAction<Void>() {
@Override
public Void run() {
thread.setContextClassLoader(EvictorThreadFactory.class.getClassLoader());
return null;
}
});
return thread;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
/**
* A simple "struct" encapsulating the configuration for a
* {@link GenericKeyedObjectPool}.
*
* <p>
* This class is not thread-safe; it is only intended to be used to provide
* attributes used when creating a pool.
* </p>
*
* @param <T> Type of element pooled.
* @since 2.0
*/
public class GenericKeyedObjectPoolConfig<T> extends BaseObjectPoolConfig<T> {
/**
* The default value for the {@code maxTotalPerKey} configuration attribute.
* @see GenericKeyedObjectPool#getMaxTotalPerKey()
*/
public static final int DEFAULT_MAX_TOTAL_PER_KEY = 8;
/**
* The default value for the {@code maxTotal} configuration attribute.
* @see GenericKeyedObjectPool#getMaxTotal()
*/
public static final int DEFAULT_MAX_TOTAL = -1;
/**
* The default value for the {@code minIdlePerKey} configuration attribute.
* @see GenericKeyedObjectPool#getMinIdlePerKey()
*/
public static final int DEFAULT_MIN_IDLE_PER_KEY = 0;
/**
* The default value for the {@code maxIdlePerKey} configuration attribute.
* @see GenericKeyedObjectPool#getMaxIdlePerKey()
*/
public static final int DEFAULT_MAX_IDLE_PER_KEY = 8;
private int minIdlePerKey = DEFAULT_MIN_IDLE_PER_KEY;
private int maxIdlePerKey = DEFAULT_MAX_IDLE_PER_KEY;
private int maxTotalPerKey = DEFAULT_MAX_TOTAL_PER_KEY;
private int maxTotal = DEFAULT_MAX_TOTAL;
/**
* Create a new configuration with default settings.
*/
public GenericKeyedObjectPoolConfig() {
}
/**
* Get the value for the {@code maxTotal} configuration attribute
* for pools created with this configuration instance.
*
* @return The current setting of {@code maxTotal} for this
* configuration instance
*
* @see GenericKeyedObjectPool#getMaxTotal()
*/
public int getMaxTotal() {
return maxTotal;
}
/**
* Set the value for the {@code maxTotal} configuration attribute for
* pools created with this configuration instance.
*
* @param maxTotal The new setting of {@code maxTotal}
* for this configuration instance
*
* @see GenericKeyedObjectPool#setMaxTotal(int)
*/
public void setMaxTotal(final int maxTotal) {
this.maxTotal = maxTotal;
}
/**
* Get the value for the {@code maxTotalPerKey} configuration attribute
* for pools created with this configuration instance.
*
* @return The current setting of {@code maxTotalPerKey} for this
* configuration instance
*
* @see GenericKeyedObjectPool#getMaxTotalPerKey()
*/
public int getMaxTotalPerKey() {
return maxTotalPerKey;
}
/**
* Set the value for the {@code maxTotalPerKey} configuration attribute for
* pools created with this configuration instance.
*
* @param maxTotalPerKey The new setting of {@code maxTotalPerKey}
* for this configuration instance
*
* @see GenericKeyedObjectPool#setMaxTotalPerKey(int)
*/
public void setMaxTotalPerKey(final int maxTotalPerKey) {
this.maxTotalPerKey = maxTotalPerKey;
}
/**
* Get the value for the {@code minIdlePerKey} configuration attribute
* for pools created with this configuration instance.
*
* @return The current setting of {@code minIdlePerKey} for this
* configuration instance
*
* @see GenericKeyedObjectPool#getMinIdlePerKey()
*/
public int getMinIdlePerKey() {
return minIdlePerKey;
}
/**
* Set the value for the {@code minIdlePerKey} configuration attribute for
* pools created with this configuration instance.
*
* @param minIdlePerKey The new setting of {@code minIdlePerKey}
* for this configuration instance
*
* @see GenericKeyedObjectPool#setMinIdlePerKey(int)
*/
public void setMinIdlePerKey(final int minIdlePerKey) {
this.minIdlePerKey = minIdlePerKey;
}
/**
* Get the value for the {@code maxIdlePerKey} configuration attribute
* for pools created with this configuration instance.
*
* @return The current setting of {@code maxIdlePerKey} for this
* configuration instance
*
* @see GenericKeyedObjectPool#getMaxIdlePerKey()
*/
public int getMaxIdlePerKey() {
return maxIdlePerKey;
}
/**
* Set the value for the {@code maxIdlePerKey} configuration attribute for
* pools created with this configuration instance.
*
* @param maxIdlePerKey The new setting of {@code maxIdlePerKey}
* for this configuration instance
*
* @see GenericKeyedObjectPool#setMaxIdlePerKey(int)
*/
public void setMaxIdlePerKey(final int maxIdlePerKey) {
this.maxIdlePerKey = maxIdlePerKey;
}
@SuppressWarnings("unchecked")
@Override
public GenericKeyedObjectPoolConfig<T> clone() {
try {
return (GenericKeyedObjectPoolConfig<T>) super.clone();
} catch (final CloneNotSupportedException e) {
throw new AssertionError(); // Can't happen
}
}
@Override
protected void toStringAppendFields(final StringBuilder builder) {
super.toStringAppendFields(builder);
builder.append(", minIdlePerKey=");
builder.append(minIdlePerKey);
builder.append(", maxIdlePerKey=");
builder.append(maxIdlePerKey);
builder.append(", maxTotalPerKey=");
builder.append(maxTotalPerKey);
builder.append(", maxTotal=");
builder.append(maxTotal);
}
}

View File

@@ -0,0 +1,240 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.util.List;
import java.util.Map;
/**
* Defines the methods that will be made available via JMX.
*
* NOTE: This interface exists only to define those attributes and methods that
* will be made available via JMX. It must not be implemented by clients
* as it is subject to change between major, minor and patch version
* releases of commons pool. Clients that implement this interface may
* not, therefore, be able to upgrade to a new minor or patch release
* without requiring code changes.
*
* @param <K> The type of keys maintained by the pool.
*
* @since 2.0
*/
public interface GenericKeyedObjectPoolMXBean<K> {
// Expose getters for configuration settings
/**
* See {@link GenericKeyedObjectPool#getBlockWhenExhausted()}
* @return See {@link GenericKeyedObjectPool#getBlockWhenExhausted()}
*/
boolean getBlockWhenExhausted();
/**
* See {@link GenericKeyedObjectPool#getFairness()}
* @return See {@link GenericKeyedObjectPool#getFairness()}
*/
boolean getFairness();
/**
* See {@link GenericKeyedObjectPool#getLifo()}
* @return See {@link GenericKeyedObjectPool#getLifo()}
*/
boolean getLifo();
/**
* See {@link GenericKeyedObjectPool#getMaxIdlePerKey()}
* @return See {@link GenericKeyedObjectPool#getMaxIdlePerKey()}
*/
int getMaxIdlePerKey();
/**
* See {@link GenericKeyedObjectPool#getMaxTotal()}
* @return See {@link GenericKeyedObjectPool#getMaxTotal()}
*/
int getMaxTotal();
/**
* See {@link GenericKeyedObjectPool#getMaxTotalPerKey()}
* @return See {@link GenericKeyedObjectPool#getMaxTotalPerKey()}
*/
int getMaxTotalPerKey();
/**
* See {@link GenericKeyedObjectPool#getMaxWaitMillis()}
* @return See {@link GenericKeyedObjectPool#getMaxWaitMillis()}
*/
long getMaxWaitMillis();
/**
* See {@link GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()}
* @return See {@link GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()}
*/
long getMinEvictableIdleTimeMillis();
/**
* See {@link GenericKeyedObjectPool#getMinIdlePerKey()}
* @return See {@link GenericKeyedObjectPool#getMinIdlePerKey()}
*/
int getMinIdlePerKey();
/**
* See {@link GenericKeyedObjectPool#getNumActive()}
* @return See {@link GenericKeyedObjectPool#getNumActive()}
*/
int getNumActive();
/**
* See {@link GenericKeyedObjectPool#getNumIdle()}
* @return See {@link GenericKeyedObjectPool#getNumIdle()}
*/
int getNumIdle();
/**
* See {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun()}
* @return See {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun()}
*/
int getNumTestsPerEvictionRun();
/**
* See {@link GenericKeyedObjectPool#getTestOnCreate()}
* @return See {@link GenericKeyedObjectPool#getTestOnCreate()}
* @since 2.2
*/
boolean getTestOnCreate();
/**
* See {@link GenericKeyedObjectPool#getTestOnBorrow()}
* @return See {@link GenericKeyedObjectPool#getTestOnBorrow()}
*/
boolean getTestOnBorrow();
/**
* See {@link GenericKeyedObjectPool#getTestOnReturn()}
* @return See {@link GenericKeyedObjectPool#getTestOnReturn()}
*/
boolean getTestOnReturn();
/**
* See {@link GenericKeyedObjectPool#getTestWhileIdle()}
* @return See {@link GenericKeyedObjectPool#getTestWhileIdle()}
*/
boolean getTestWhileIdle();
/**
* See {@link GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis()}
* @return See {@link GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis()}
*/
long getTimeBetweenEvictionRunsMillis();
/**
* See {@link GenericKeyedObjectPool#isClosed()}
* @return See {@link GenericKeyedObjectPool#isClosed()}
*/
boolean isClosed();
// Expose getters for monitoring attributes
/**
* See {@link GenericKeyedObjectPool#getNumActivePerKey()}
* @return See {@link GenericKeyedObjectPool#getNumActivePerKey()}
*/
Map<String,Integer> getNumActivePerKey();
/**
* See {@link GenericKeyedObjectPool#getBorrowedCount()}
* @return See {@link GenericKeyedObjectPool#getBorrowedCount()}
*/
long getBorrowedCount();
/**
* See {@link GenericKeyedObjectPool#getReturnedCount()}
* @return See {@link GenericKeyedObjectPool#getReturnedCount()}
*/
long getReturnedCount();
/**
* See {@link GenericKeyedObjectPool#getCreatedCount()}
* @return See {@link GenericKeyedObjectPool#getCreatedCount()}
*/
long getCreatedCount();
/**
* See {@link GenericKeyedObjectPool#getDestroyedCount()}
* @return See {@link GenericKeyedObjectPool#getDestroyedCount()}
*/
long getDestroyedCount();
/**
* See {@link GenericKeyedObjectPool#getDestroyedByEvictorCount()}
* @return See {@link GenericKeyedObjectPool#getDestroyedByEvictorCount()}
*/
long getDestroyedByEvictorCount();
/**
* See {@link GenericKeyedObjectPool#getDestroyedByBorrowValidationCount()}
* @return See {@link GenericKeyedObjectPool#getDestroyedByBorrowValidationCount()}
*/
long getDestroyedByBorrowValidationCount();
/**
* See {@link GenericKeyedObjectPool#getMeanActiveTimeMillis()}
* @return See {@link GenericKeyedObjectPool#getMeanActiveTimeMillis()}
*/
long getMeanActiveTimeMillis();
/**
* See {@link GenericKeyedObjectPool#getMeanIdleTimeMillis()}
* @return See {@link GenericKeyedObjectPool#getMeanIdleTimeMillis()}
*/
long getMeanIdleTimeMillis();
/**
* See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()}
* @return See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()}
*/
long getMeanBorrowWaitTimeMillis();
/**
* See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()}
* @return See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()}
*/
long getMaxBorrowWaitTimeMillis();
/**
* See {@link GenericKeyedObjectPool#getCreationStackTrace()}
* @return See {@link GenericKeyedObjectPool#getCreationStackTrace()}
*/
String getCreationStackTrace();
/**
* See {@link GenericKeyedObjectPool#getNumWaiters()}
* @return See {@link GenericKeyedObjectPool#getNumWaiters()}
*/
int getNumWaiters();
/**
* See {@link GenericKeyedObjectPool#getNumWaitersByKey()}
* @return See {@link GenericKeyedObjectPool#getNumWaitersByKey()}
*/
Map<String,Integer> getNumWaitersByKey();
/**
* See {@link GenericKeyedObjectPool#listAllObjects()}
* @return See {@link GenericKeyedObjectPool#listAllObjects()}
*/
Map<String,List<DefaultPooledObjectInfo>> listAllObjects();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
/**
* A simple "struct" encapsulating the configuration for a
* {@link GenericObjectPool}.
*
* <p>
* This class is not thread-safe; it is only intended to be used to provide
* attributes used when creating a pool.
* </p>
*
* @param <T> Type of element pooled.
* @since 2.0
*/
public class GenericObjectPoolConfig<T> extends BaseObjectPoolConfig<T> {
/**
* The default value for the {@code maxTotal} configuration attribute.
* @see GenericObjectPool#getMaxTotal()
*/
public static final int DEFAULT_MAX_TOTAL = 8;
/**
* The default value for the {@code maxIdle} configuration attribute.
* @see GenericObjectPool#getMaxIdle()
*/
public static final int DEFAULT_MAX_IDLE = 8;
/**
* The default value for the {@code minIdle} configuration attribute.
* @see GenericObjectPool#getMinIdle()
*/
public static final int DEFAULT_MIN_IDLE = 0;
private int maxTotal = DEFAULT_MAX_TOTAL;
private int maxIdle = DEFAULT_MAX_IDLE;
private int minIdle = DEFAULT_MIN_IDLE;
/**
* Get the value for the {@code maxTotal} configuration attribute
* for pools created with this configuration instance.
*
* @return The current setting of {@code maxTotal} for this
* configuration instance
*
* @see GenericObjectPool#getMaxTotal()
*/
public int getMaxTotal() {
return maxTotal;
}
/**
* Set the value for the {@code maxTotal} configuration attribute for
* pools created with this configuration instance.
*
* @param maxTotal The new setting of {@code maxTotal}
* for this configuration instance
*
* @see GenericObjectPool#setMaxTotal(int)
*/
public void setMaxTotal(final int maxTotal) {
this.maxTotal = maxTotal;
}
/**
* Get the value for the {@code maxIdle} configuration attribute
* for pools created with this configuration instance.
*
* @return The current setting of {@code maxIdle} for this
* configuration instance
*
* @see GenericObjectPool#getMaxIdle()
*/
public int getMaxIdle() {
return maxIdle;
}
/**
* Set the value for the {@code maxIdle} configuration attribute for
* pools created with this configuration instance.
*
* @param maxIdle The new setting of {@code maxIdle}
* for this configuration instance
*
* @see GenericObjectPool#setMaxIdle(int)
*/
public void setMaxIdle(final int maxIdle) {
this.maxIdle = maxIdle;
}
/**
* Get the value for the {@code minIdle} configuration attribute
* for pools created with this configuration instance.
*
* @return The current setting of {@code minIdle} for this
* configuration instance
*
* @see GenericObjectPool#getMinIdle()
*/
public int getMinIdle() {
return minIdle;
}
/**
* Set the value for the {@code minIdle} configuration attribute for
* pools created with this configuration instance.
*
* @param minIdle The new setting of {@code minIdle}
* for this configuration instance
*
* @see GenericObjectPool#setMinIdle(int)
*/
public void setMinIdle(final int minIdle) {
this.minIdle = minIdle;
}
@SuppressWarnings("unchecked")
@Override
public GenericObjectPoolConfig<T> clone() {
try {
return (GenericObjectPoolConfig<T>) super.clone();
} catch (final CloneNotSupportedException e) {
throw new AssertionError(); // Can't happen
}
}
@Override
protected void toStringAppendFields(final StringBuilder builder) {
super.toStringAppendFields(builder);
builder.append(", maxTotal=");
builder.append(maxTotal);
builder.append(", maxIdle=");
builder.append(maxIdle);
builder.append(", minIdle=");
builder.append(minIdle);
}
}

View File

@@ -0,0 +1,257 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.util.Set;
/**
* Defines the methods that will be made available via JMX.
*
* NOTE: This interface exists only to define those attributes and methods that
* will be made available via JMX. It must not be implemented by clients
* as it is subject to change between major, minor and patch version
* releases of commons pool. Clients that implement this interface may
* not, therefore, be able to upgrade to a new minor or patch release
* without requiring code changes.
*
* @since 2.0
*/
public interface GenericObjectPoolMXBean {
// Getters for basic configuration settings
/**
* See {@link GenericObjectPool#getBlockWhenExhausted()}
* @return See {@link GenericObjectPool#getBlockWhenExhausted()}
*/
boolean getBlockWhenExhausted();
/**
* See {@link GenericObjectPool#getLifo()}
* @return See {@link GenericObjectPool#getLifo()}
*/
boolean getFairness();
/**
* See {@link GenericObjectPool#getFairness()}
* @return See {@link GenericObjectPool#getFairness()}
*/
boolean getLifo();
/**
* See {@link GenericObjectPool#getMaxIdle()}
* @return See {@link GenericObjectPool#getMaxIdle()}
*/
int getMaxIdle();
/**
* See {@link GenericObjectPool#getMaxTotal()}
* @return See {@link GenericObjectPool#getMaxTotal()}
*/
int getMaxTotal();
/**
* See {@link GenericObjectPool#getMaxWaitMillis()}
* @return See {@link GenericObjectPool#getMaxWaitMillis()}
*/
long getMaxWaitMillis();
/**
* See {@link GenericObjectPool#getMinEvictableIdleTimeMillis()}
* @return See {@link GenericObjectPool#getMinEvictableIdleTimeMillis()}
*/
long getMinEvictableIdleTimeMillis();
/**
* See {@link GenericObjectPool#getMinIdle()}
* @return See {@link GenericObjectPool#getMinIdle()}
*/
int getMinIdle();
/**
* See {@link GenericObjectPool#getNumActive()}
* @return See {@link GenericObjectPool#getNumActive()}
*/
int getNumActive();
/**
* See {@link GenericObjectPool#getNumIdle()}
* @return See {@link GenericObjectPool#getNumIdle()}
*/
int getNumIdle();
/**
* See {@link GenericObjectPool#getNumTestsPerEvictionRun()}
* @return See {@link GenericObjectPool#getNumTestsPerEvictionRun()}
*/
int getNumTestsPerEvictionRun();
/**
* See {@link GenericObjectPool#getTestOnCreate()}
* @return See {@link GenericObjectPool#getTestOnCreate()}
* @since 2.2
*/
boolean getTestOnCreate();
/**
* See {@link GenericObjectPool#getTestOnBorrow()}
* @return See {@link GenericObjectPool#getTestOnBorrow()}
*/
boolean getTestOnBorrow();
/**
* See {@link GenericObjectPool#getTestOnReturn()}
* @return See {@link GenericObjectPool#getTestOnReturn()}
*/
boolean getTestOnReturn();
/**
* See {@link GenericObjectPool#getTestWhileIdle()}
* @return See {@link GenericObjectPool#getTestWhileIdle()}
*/
boolean getTestWhileIdle();
/**
* See {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis()}
* @return See {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis()}
*/
long getTimeBetweenEvictionRunsMillis();
/**
* See {@link GenericObjectPool#isClosed()}
* @return See {@link GenericObjectPool#isClosed()}
*/
boolean isClosed();
// Getters for monitoring attributes
/**
* See {@link GenericObjectPool#getBorrowedCount()}
* @return See {@link GenericObjectPool#getBorrowedCount()}
*/
long getBorrowedCount();
/**
* See {@link GenericObjectPool#getReturnedCount()}
* @return See {@link GenericObjectPool#getReturnedCount()}
*/
long getReturnedCount();
/**
* See {@link GenericObjectPool#getCreatedCount()}
* @return See {@link GenericObjectPool#getCreatedCount()}
*/
long getCreatedCount();
/**
* See {@link GenericObjectPool#getDestroyedCount()}
* @return See {@link GenericObjectPool#getDestroyedCount()}
*/
long getDestroyedCount();
/**
* See {@link GenericObjectPool#getDestroyedByEvictorCount()}
* @return See {@link GenericObjectPool#getDestroyedByEvictorCount()}
*/
long getDestroyedByEvictorCount();
/**
* See {@link GenericObjectPool#getDestroyedByBorrowValidationCount()}
* @return See {@link GenericObjectPool#getDestroyedByBorrowValidationCount()}
*/
long getDestroyedByBorrowValidationCount();
/**
* See {@link GenericObjectPool#getMeanActiveTimeMillis()}
* @return See {@link GenericObjectPool#getMeanActiveTimeMillis()}
*/
long getMeanActiveTimeMillis();
/**
* See {@link GenericObjectPool#getMeanIdleTimeMillis()}
* @return See {@link GenericObjectPool#getMeanIdleTimeMillis()}
*/
long getMeanIdleTimeMillis();
/**
* See {@link GenericObjectPool#getMeanBorrowWaitTimeMillis()}
* @return See {@link GenericObjectPool#getMeanBorrowWaitTimeMillis()}
*/
long getMeanBorrowWaitTimeMillis();
/**
* See {@link GenericObjectPool#getMaxBorrowWaitTimeMillis()}
* @return See {@link GenericObjectPool#getMaxBorrowWaitTimeMillis()}
*/
long getMaxBorrowWaitTimeMillis();
/**
* See {@link GenericObjectPool#getCreationStackTrace()}
* @return See {@link GenericObjectPool#getCreationStackTrace()}
*/
String getCreationStackTrace();
/**
* See {@link GenericObjectPool#getNumWaiters()}
* @return See {@link GenericObjectPool#getNumWaiters()}
*/
int getNumWaiters();
// Getters for abandoned object removal configuration
/**
* See {@link GenericObjectPool#isAbandonedConfig()}
* @return See {@link GenericObjectPool#isAbandonedConfig()}
*/
boolean isAbandonedConfig();
/**
* See {@link GenericObjectPool#getLogAbandoned()}
* @return See {@link GenericObjectPool#getLogAbandoned()}
*/
boolean getLogAbandoned();
/**
* See {@link GenericObjectPool#getRemoveAbandonedOnBorrow()}
* @return See {@link GenericObjectPool#getRemoveAbandonedOnBorrow()}
*/
boolean getRemoveAbandonedOnBorrow();
/**
* See {@link GenericObjectPool#getRemoveAbandonedOnMaintenance()}
* @return See {@link GenericObjectPool#getRemoveAbandonedOnMaintenance()}
*/
boolean getRemoveAbandonedOnMaintenance();
/**
* See {@link GenericObjectPool#getRemoveAbandonedTimeout()}
* @return See {@link GenericObjectPool#getRemoveAbandonedTimeout()}
*/
int getRemoveAbandonedTimeout();
/**
* See {@link GenericObjectPool#getFactoryType()}
* @return See {@link GenericObjectPool#getFactoryType()}
*/
String getFactoryType();
/**
* See {@link GenericObjectPool#listAllObjects()}
* @return See {@link GenericObjectPool#listAllObjects()}
*/
Set<DefaultPooledObjectInfo> listAllObjects();
}

View File

@@ -0,0 +1,58 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.util.Collection;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* This sub-class was created to expose the waiting threads so that they can be
* interrupted when the pool using the queue that uses this lock is closed. The
* class is intended for internal use only.
* <p>
* This class is intended to be thread-safe.
* </p>
*
* @since 2.0
*/
class InterruptibleReentrantLock extends ReentrantLock {
private static final long serialVersionUID = 1L;
/**
* Create a new InterruptibleReentrantLock with the given fairness policy.
*
* @param fairness true means threads should acquire contended locks as if
* waiting in a FIFO queue
*/
public InterruptibleReentrantLock(final boolean fairness) {
super(fairness);
}
/**
* Interrupt the threads that are waiting on a specific condition
*
* @param condition the condition on which the threads are waiting.
*/
public void interruptWaiters(final Condition condition) {
final Collection<Thread> threads = getWaitingThreads(condition);
for (final Thread thread : threads) {
thread.interrupt();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.io.PrintWriter;
/**
* CallStack strategy using no-op implementations of all functionality. Can be used by default when abandoned object
* logging is disabled.
*
* @since 2.5
*/
public class NoOpCallStack implements CallStack {
/**
* Singleton instance.
*/
public static final CallStack INSTANCE = new NoOpCallStack();
/**
* Constructs the singleton instance.
*/
private NoOpCallStack() {
}
@Override
public boolean printStackTrace(final PrintWriter writer) {
return false;
}
@Override
public void fillInStackTrace() {
// no-op
}
@Override
public void clear() {
// no-op
}
}

View File

@@ -0,0 +1,156 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import org.apache.tomcat.dbcp.pool2.PooledObjectFactory;
/**
* Implementation specific utilities.
*
* @since 2.0
*/
class PoolImplUtils {
/**
* Identifies the concrete type of object that an object factory creates.
*
* @param factoryClass
* The factory to examine
*
* @return the type of object the factory creates
*/
@SuppressWarnings("rawtypes")
static Class<?> getFactoryType(final Class<? extends PooledObjectFactory> factoryClass) {
final Class<PooledObjectFactory> type = PooledObjectFactory.class;
final Object genericType = getGenericType(type, factoryClass);
if (genericType instanceof Integer) {
// POOL-324 org.apache.commons.pool2.impl.GenericObjectPool.getFactoryType() throws
// java.lang.ClassCastException
//
// A bit hackish, but we must handle cases when getGenericType() does not return a concrete types.
final ParameterizedType pi = getParameterizedType(type, factoryClass);
if (pi != null) {
final Type[] bounds = ((TypeVariable) pi.getActualTypeArguments()[((Integer) genericType).intValue()]).getBounds();
if (bounds != null && bounds.length > 0) {
final Type bound0 = bounds[0];
if (bound0 instanceof Class) {
return (Class<?>) bound0;
}
}
}
// last resort: Always return a Class
return Object.class;
}
return (Class<?>) genericType;
}
/**
* Obtains the concrete type used by an implementation of an interface that uses a generic type.
*
* @param type
* The interface that defines a generic type
* @param clazz
* The class that implements the interface with a concrete type
* @param <T>
* The interface type
*
* @return concrete type used by the implementation
*/
private static <T> Object getGenericType(final Class<T> type, final Class<? extends T> clazz) {
if (type == null || clazz == null) {
// Error will be logged further up the call stack
return null;
}
// Look to see if this class implements the generic interface
final ParameterizedType pi = getParameterizedType(type, clazz);
if (pi != null) {
return getTypeParameter(clazz, pi.getActualTypeArguments()[0]);
}
// Interface not found on this class. Look at the superclass.
@SuppressWarnings("unchecked")
final Class<? extends T> superClass = (Class<? extends T>) clazz.getSuperclass();
final Object result = getGenericType(type, superClass);
if (result instanceof Class<?>) {
// Superclass implements interface and defines explicit type for generic
return result;
} else if (result instanceof Integer) {
// Superclass implements interface and defines unknown type for generic
// Map that unknown type to the generic types defined in this class
final ParameterizedType superClassType = (ParameterizedType) clazz.getGenericSuperclass();
return getTypeParameter(clazz, superClassType.getActualTypeArguments()[((Integer) result).intValue()]);
} else {
// Error will be logged further up the call stack
return null;
}
}
/**
* Gets the matching parameterized type or null.
* @param type
* The interface that defines a generic type.
* @param clazz
* The class that implements the interface with a concrete type.
* @param <T>
* The interface type.
* @return the matching parameterized type or null.
*/
private static <T> ParameterizedType getParameterizedType(final Class<T> type, final Class<? extends T> clazz) {
for (final Type iface : clazz.getGenericInterfaces()) {
// Only need to check interfaces that use generics
if (iface instanceof ParameterizedType) {
final ParameterizedType pi = (ParameterizedType) iface;
// Look for the generic interface
if (pi.getRawType() instanceof Class && type.isAssignableFrom((Class<?>) pi.getRawType())) {
return pi;
}
}
}
return null;
}
/**
* For a generic parameter, return either the Class used or if the type is unknown, the index for the type in
* definition of the class
*
* @param clazz
* defining class
* @param argType
* the type argument of interest
*
* @return An instance of {@link Class} representing the type used by the type parameter or an instance of
* {@link Integer} representing the index for the type in the definition of the defining class
*/
private static Object getTypeParameter(final Class<?> clazz, final Type argType) {
if (argType instanceof Class<?>) {
return argType;
}
final TypeVariable<?>[] tvs = clazz.getTypeParameters();
for (int i = 0; i < tvs.length; i++) {
if (tvs[i].equals(argType)) {
return Integer.valueOf(i);
}
}
return null;
}
}

View File

@@ -0,0 +1,98 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.lang.ref.SoftReference;
/**
* Extension of {@link DefaultPooledObject} to wrap pooled soft references.
*
* <p>This class is intended to be thread-safe.</p>
*
* @param <T> the type of the underlying object that the wrapped SoftReference
* refers to.
*
* @since 2.0
*/
public class PooledSoftReference<T> extends DefaultPooledObject<T> {
/** SoftReference wrapped by this object */
private volatile SoftReference<T> reference;
/**
* Creates a new PooledSoftReference wrapping the provided reference.
*
* @param reference SoftReference to be managed by the pool
*/
public PooledSoftReference(final SoftReference<T> reference) {
super(null); // Null the hard reference in the parent
this.reference = reference;
}
/**
* Returns the object that the wrapped SoftReference refers to.
* <p>
* Note that if the reference has been cleared, this method will return
* null.
*
* @return Object referred to by the SoftReference
*/
@Override
public T getObject() {
return reference.get();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder result = new StringBuilder();
result.append("Referenced Object: ");
result.append(getObject().toString());
result.append(", State: ");
synchronized (this) {
result.append(getState().toString());
}
return result.toString();
// TODO add other attributes
// TODO encapsulate state and other attribute display in parent
}
/**
* Returns the SoftReference wrapped by this object.
*
* @return underlying SoftReference
*/
public synchronized SoftReference<T> getReference() {
return reference;
}
/**
* Sets the wrapped reference.
*
* <p>This method exists to allow a new, non-registered reference to be
* held by the pool to track objects that have been checked out of the pool.
* The actual parameter <strong>should</strong> be a reference to the same
* object that {@link #getObject()} returns before calling this method.</p>
*
* @param reference new reference
*/
public synchronized void setReference(final SoftReference<T> reference) {
this.reference = reference;
}
}

View File

@@ -0,0 +1,129 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
/**
* CallStack strategy using a {@link SecurityManager}. Obtaining the current call stack is much faster via a
* SecurityManger, but access to the underlying method may be restricted by the current SecurityManager. In environments
* where a SecurityManager cannot be created, {@link ThrowableCallStack} should be used instead.
*
* @see RuntimePermission
* @see SecurityManager#getClassContext()
* @since 2.4.3
*/
public class SecurityManagerCallStack implements CallStack {
private final String messageFormat;
//@GuardedBy("dateFormat")
private final DateFormat dateFormat;
private final PrivateSecurityManager securityManager;
private volatile Snapshot snapshot;
/**
* Create a new instance.
*
* @param messageFormat message format
* @param useTimestamp whether to format the dates in the output message or not
*/
public SecurityManagerCallStack(final String messageFormat, final boolean useTimestamp) {
this.messageFormat = messageFormat;
this.dateFormat = useTimestamp ? new SimpleDateFormat(messageFormat) : null;
this.securityManager = AccessController.doPrivileged(new PrivilegedAction<PrivateSecurityManager>() {
@Override
public PrivateSecurityManager run() {
return new PrivateSecurityManager();
}
});
}
@Override
public boolean printStackTrace(final PrintWriter writer) {
final Snapshot snapshotRef = this.snapshot;
if (snapshotRef == null) {
return false;
}
final String message;
if (dateFormat == null) {
message = messageFormat;
} else {
synchronized (dateFormat) {
message = dateFormat.format(Long.valueOf(snapshotRef.timestamp));
}
}
writer.println(message);
for (final WeakReference<Class<?>> reference : snapshotRef.stack) {
writer.println(reference.get());
}
return true;
}
@Override
public void fillInStackTrace() {
snapshot = new Snapshot(securityManager.getCallStack());
}
@Override
public void clear() {
snapshot = null;
}
/**
* A custom security manager.
*/
private static class PrivateSecurityManager extends SecurityManager {
/**
* Get the class stack.
*
* @return class stack
*/
private List<WeakReference<Class<?>>> getCallStack() {
final Class<?>[] classes = getClassContext();
final List<WeakReference<Class<?>>> stack = new ArrayList<>(classes.length);
for (final Class<?> klass : classes) {
stack.add(new WeakReference<Class<?>>(klass));
}
return stack;
}
}
/**
* A snapshot of a class stack.
*/
private static class Snapshot {
private final long timestamp = System.currentTimeMillis();
private final List<WeakReference<Class<?>>> stack;
/**
* Create a new snapshot with a class stack.
*
* @param stack class stack
*/
private Snapshot(final List<WeakReference<Class<?>>> stack) {
this.stack = stack;
}
}
}

View File

@@ -0,0 +1,456 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.apache.tomcat.dbcp.pool2.BaseObjectPool;
import org.apache.tomcat.dbcp.pool2.PoolUtils;
import org.apache.tomcat.dbcp.pool2.PooledObjectFactory;
/**
* A {@link java.lang.ref.SoftReference SoftReference} based
* {@link org.apache.tomcat.dbcp.pool2.ObjectPool}.
* <p>
* This class is intended to be thread-safe.
* </p>
*
* @param <T>
* Type of element pooled in this pool.
*
* @since 2.0
*/
public class SoftReferenceObjectPool<T> extends BaseObjectPool<T> {
/** Factory to source pooled objects */
private final PooledObjectFactory<T> factory;
/**
* Queue of broken references that might be able to be removed from
* <code>_pool</code>. This is used to help {@link #getNumIdle()} be more
* accurate with minimal performance overhead.
*/
private final ReferenceQueue<T> refQueue = new ReferenceQueue<>();
/** Count of instances that have been checkout out to pool clients */
private int numActive = 0; // @GuardedBy("this")
/** Total number of instances that have been destroyed */
private long destroyCount = 0; // @GuardedBy("this")
/** Total number of instances that have been created */
private long createCount = 0; // @GuardedBy("this")
/** Idle references - waiting to be borrowed */
private final LinkedBlockingDeque<PooledSoftReference<T>> idleReferences =
new LinkedBlockingDeque<>();
/** All references - checked out or waiting to be borrowed. */
private final ArrayList<PooledSoftReference<T>> allReferences =
new ArrayList<>();
/**
* Create a <code>SoftReferenceObjectPool</code> with the specified factory.
*
* @param factory object factory to use.
*/
public SoftReferenceObjectPool(final PooledObjectFactory<T> factory) {
this.factory = factory;
}
/**
* Borrows an object from the pool. If there are no idle instances available
* in the pool, the configured factory's
* {@link PooledObjectFactory#makeObject()} method is invoked to create a
* new instance.
* <p>
* All instances are {@link PooledObjectFactory#activateObject(
* org.apache.tomcat.dbcp.pool2.PooledObject) activated}
* and {@link PooledObjectFactory#validateObject(
* org.apache.tomcat.dbcp.pool2.PooledObject)
* validated} before being returned by this method. If validation fails or
* an exception occurs activating or validating an idle instance, the
* failing instance is {@link PooledObjectFactory#destroyObject(
* org.apache.tomcat.dbcp.pool2.PooledObject)
* destroyed} and another instance is retrieved from the pool, validated and
* activated. This process continues until either the pool is empty or an
* instance passes validation. If the pool is empty on activation or it does
* not contain any valid instances, the factory's <code>makeObject</code>
* method is used to create a new instance. If the created instance either
* raises an exception on activation or fails validation,
* <code>NoSuchElementException</code> is thrown. Exceptions thrown by
* <code>MakeObject</code> are propagated to the caller; but other than
* <code>ThreadDeath</code> or <code>VirtualMachineError</code>, exceptions
* generated by activation, validation or destroy methods are swallowed
* silently.
*
* @throws NoSuchElementException
* if a valid object cannot be provided
* @throws IllegalStateException
* if invoked on a {@link #close() closed} pool
* @throws Exception
* if an exception occurs creating a new instance
* @return a valid, activated object instance
*/
@SuppressWarnings("null") // ref cannot be null
@Override
public synchronized T borrowObject() throws Exception {
assertOpen();
T obj = null;
boolean newlyCreated = false;
PooledSoftReference<T> ref = null;
while (null == obj) {
if (idleReferences.isEmpty()) {
if (null == factory) {
throw new NoSuchElementException();
}
newlyCreated = true;
obj = factory.makeObject().getObject();
createCount++;
// Do not register with the queue
ref = new PooledSoftReference<>(new SoftReference<>(obj));
allReferences.add(ref);
} else {
ref = idleReferences.pollFirst();
obj = ref.getObject();
// Clear the reference so it will not be queued, but replace with a
// a new, non-registered reference so we can still track this object
// in allReferences
ref.getReference().clear();
ref.setReference(new SoftReference<>(obj));
}
if (null != factory && null != obj) {
try {
factory.activateObject(ref);
if (!factory.validateObject(ref)) {
throw new Exception("ValidateObject failed");
}
} catch (final Throwable t) {
PoolUtils.checkRethrow(t);
try {
destroy(ref);
} catch (final Throwable t2) {
PoolUtils.checkRethrow(t2);
// Swallowed
} finally {
obj = null;
}
if (newlyCreated) {
throw new NoSuchElementException(
"Could not create a validated object, cause: " +
t.getMessage());
}
}
}
}
numActive++;
ref.allocate();
return obj;
}
/**
* Returns an instance to the pool after successful validation and
* passivation. The returning instance is destroyed if any of the following
* are true:
* <ul>
* <li>the pool is closed</li>
* <li>{@link PooledObjectFactory#validateObject(
* org.apache.tomcat.dbcp.pool2.PooledObject) validation} fails
* </li>
* <li>{@link PooledObjectFactory#passivateObject(
* org.apache.tomcat.dbcp.pool2.PooledObject) passivation}
* throws an exception</li>
* </ul>
* Exceptions passivating or destroying instances are silently swallowed.
* Exceptions validating instances are propagated to the client.
*
* @param obj
* instance to return to the pool
* @throws IllegalArgumentException
* if obj is not currently part of this pool
*/
@Override
public synchronized void returnObject(final T obj) throws Exception {
boolean success = !isClosed();
final PooledSoftReference<T> ref = findReference(obj);
if (ref == null) {
throw new IllegalStateException(
"Returned object not currently part of this pool");
}
if (factory != null) {
if (!factory.validateObject(ref)) {
success = false;
} else {
try {
factory.passivateObject(ref);
} catch (final Exception e) {
success = false;
}
}
}
final boolean shouldDestroy = !success;
numActive--;
if (success) {
// Deallocate and add to the idle instance pool
ref.deallocate();
idleReferences.add(ref);
}
notifyAll(); // numActive has changed
if (shouldDestroy && factory != null) {
try {
destroy(ref);
} catch (final Exception e) {
// ignored
}
}
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void invalidateObject(final T obj) throws Exception {
final PooledSoftReference<T> ref = findReference(obj);
if (ref == null) {
throw new IllegalStateException(
"Object to invalidate is not currently part of this pool");
}
if (factory != null) {
destroy(ref);
}
numActive--;
notifyAll(); // numActive has changed
}
/**
* Creates an object, and places it into the pool. addObject() is useful for
* "pre-loading" a pool with idle objects.
* <p>
* Before being added to the pool, the newly created instance is
* {@link PooledObjectFactory#validateObject(
* org.apache.tomcat.dbcp.pool2.PooledObject) validated} and
* {@link PooledObjectFactory#passivateObject(
* org.apache.tomcat.dbcp.pool2.PooledObject) passivated}. If
* validation fails, the new instance is
* {@link PooledObjectFactory#destroyObject(
* org.apache.tomcat.dbcp.pool2.PooledObject) destroyed}. Exceptions
* generated by the factory <code>makeObject</code> or
* <code>passivate</code> are propagated to the caller. Exceptions
* destroying instances are silently swallowed.
*
* @throws IllegalStateException
* if invoked on a {@link #close() closed} pool
* @throws Exception
* when the {@link #getFactory() factory} has a problem creating
* or passivating an object.
*/
@Override
public synchronized void addObject() throws Exception {
assertOpen();
if (factory == null) {
throw new IllegalStateException(
"Cannot add objects without a factory.");
}
final T obj = factory.makeObject().getObject();
createCount++;
// Create and register with the queue
final PooledSoftReference<T> ref = new PooledSoftReference<>(
new SoftReference<>(obj, refQueue));
allReferences.add(ref);
boolean success = true;
if (!factory.validateObject(ref)) {
success = false;
} else {
factory.passivateObject(ref);
}
final boolean shouldDestroy = !success;
if (success) {
idleReferences.add(ref);
notifyAll(); // numActive has changed
}
if (shouldDestroy) {
try {
destroy(ref);
} catch (final Exception e) {
// ignored
}
}
}
/**
* Returns an approximation not less than the of the number of idle
* instances in the pool.
*
* @return estimated number of idle instances in the pool
*/
@Override
public synchronized int getNumIdle() {
pruneClearedReferences();
return idleReferences.size();
}
/**
* Returns the number of instances currently borrowed from this pool.
*
* @return the number of instances currently borrowed from this pool
*/
@Override
public synchronized int getNumActive() {
return numActive;
}
/**
* Clears any objects sitting idle in the pool.
*/
@Override
public synchronized void clear() {
if (null != factory) {
final Iterator<PooledSoftReference<T>> iter = idleReferences.iterator();
while (iter.hasNext()) {
try {
final PooledSoftReference<T> ref = iter.next();
if (null != ref.getObject()) {
factory.destroyObject(ref);
}
} catch (final Exception e) {
// ignore error, keep destroying the rest
}
}
}
idleReferences.clear();
pruneClearedReferences();
}
/**
* Closes this pool, and frees any resources associated with it. Invokes
* {@link #clear()} to destroy and remove instances in the pool.
* <p>
* Calling {@link #addObject} or {@link #borrowObject} after invoking this
* method on a pool will cause them to throw an
* {@link IllegalStateException}.
*/
@Override
public void close() {
super.close();
clear();
}
/**
* Returns the {@link PooledObjectFactory} used by this pool to create and
* manage object instances.
*
* @return the factory
*/
public synchronized PooledObjectFactory<T> getFactory() {
return factory;
}
/**
* If any idle objects were garbage collected, remove their
* {@link Reference} wrappers from the idle object pool.
*/
private void pruneClearedReferences() {
// Remove wrappers for enqueued references from idle and allReferences lists
removeClearedReferences(idleReferences.iterator());
removeClearedReferences(allReferences.iterator());
while (refQueue.poll() != null) {
// empty
}
}
/**
* Finds the PooledSoftReference in allReferences that points to obj.
*
* @param obj returning object
* @return PooledSoftReference wrapping a soft reference to obj
*/
private PooledSoftReference<T> findReference(final T obj) {
final Iterator<PooledSoftReference<T>> iterator = allReferences.iterator();
while (iterator.hasNext()) {
final PooledSoftReference<T> reference = iterator.next();
if (reference.getObject() != null && reference.getObject().equals(obj)) {
return reference;
}
}
return null;
}
/**
* Destroys a {@code PooledSoftReference} and removes it from the idle and all
* references pools.
*
* @param toDestroy PooledSoftReference to destroy
*
* @throws Exception If an error occurs while trying to destroy the object
*/
private void destroy(final PooledSoftReference<T> toDestroy) throws Exception {
toDestroy.invalidate();
idleReferences.remove(toDestroy);
allReferences.remove(toDestroy);
try {
factory.destroyObject(toDestroy);
} finally {
destroyCount++;
toDestroy.getReference().clear();
}
}
/**
* Clears cleared references from iterator's collection
* @param iterator iterator over idle/allReferences
*/
private void removeClearedReferences(final Iterator<PooledSoftReference<T>> iterator) {
PooledSoftReference<T> ref;
while (iterator.hasNext()) {
ref = iterator.next();
if (ref.getReference() == null || ref.getReference().isEnqueued()) {
iterator.remove();
}
}
}
@Override
protected void toStringAppendFields(final StringBuilder builder) {
super.toStringAppendFields(builder);
builder.append(", factory=");
builder.append(factory);
builder.append(", refQueue=");
builder.append(refQueue);
builder.append(", numActive=");
builder.append(numActive);
builder.append(", destroyCount=");
builder.append(destroyCount);
builder.append(", createCount=");
builder.append(createCount);
builder.append(", idleReferences=");
builder.append(idleReferences);
builder.append(", allReferences=");
builder.append(allReferences);
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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 org.apache.tomcat.dbcp.pool2.impl;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* CallStack strategy that uses the stack trace from a {@link Throwable}. This strategy, while slower than the
* SecurityManager implementation, provides call stack method names and other metadata in addition to the call stack
* of classes.
*
* @see Throwable#fillInStackTrace()
* @since 2.4.3
*/
public class ThrowableCallStack implements CallStack {
private final String messageFormat;
//@GuardedBy("dateFormat")
private final DateFormat dateFormat;
private volatile Snapshot snapshot;
/**
* Create a new instance.
*
* @param messageFormat message format
* @param useTimestamp whether to format the dates in the output message or not
*/
public ThrowableCallStack(final String messageFormat, final boolean useTimestamp) {
this.messageFormat = messageFormat;
this.dateFormat = useTimestamp ? new SimpleDateFormat(messageFormat) : null;
}
@Override
public synchronized boolean printStackTrace(final PrintWriter writer) {
final Snapshot snapshotRef = this.snapshot;
if (snapshotRef == null) {
return false;
}
final String message;
if (dateFormat == null) {
message = messageFormat;
} else {
synchronized (dateFormat) {
message = dateFormat.format(Long.valueOf(snapshotRef.timestamp));
}
}
writer.println(message);
snapshotRef.printStackTrace(writer);
return true;
}
@Override
public void fillInStackTrace() {
snapshot = new Snapshot();
}
@Override
public void clear() {
snapshot = null;
}
/**
* A snapshot of a throwable.
*/
private static class Snapshot extends Throwable {
private static final long serialVersionUID = 1L;
private final long timestamp = System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,41 @@
<!--
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.
-->
<html>
<head>
<title>Package Documentation for org.apache.tomcat.dbcp.pool2.impl</title>
</head>
<body>
<p>
Object pooling API implementations.
</p>
<p>
{@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool GenericObjectPool}
({@link org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool})
provides a more robust (but also more complicated)
implementation of {@link org.apache.tomcat.dbcp.pool2.ObjectPool ObjectPool}
({@link org.apache.tomcat.dbcp.pool2.KeyedObjectPool KeyedObjectPool}).
</p>
<p>
{@link org.apache.tomcat.dbcp.pool2.impl.SoftReferenceObjectPool SoftReferenceObjectPool}
provides a {@link java.lang.ref.SoftReference SoftReference} based
{@link org.apache.tomcat.dbcp.pool2.ObjectPool ObjectPool}.
</p>
<p>
See also the {@link org.apache.tomcat.dbcp.pool2} package.
</p>
</body>
</html>

View File

@@ -0,0 +1,62 @@
<!--
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.
-->
<html>
<head>
<title>Package Documentation for org.apache.tomcat.dbcp.pool2</title>
</head>
<body>
<p>
Object pooling API.
</p>
<p>
The <code>org.apache.tomcat.dbcp.pool2</code> package defines a simple
interface for a pool of object instances, and a handful of base
classes that may be useful when creating pool implementations.
</p>
<p>
The <code>pool</code> package itself doesn't define a specific object
pooling implementation, but rather a contract that implementations may
support in order to be fully interchangeable.
</p>
<p>
The <code>pool</code> package separates the way in which instances are
pooled from the way in which they are created, resulting in a pair of
interfaces:
</p>
<dl>
<dt>{@link org.apache.tomcat.dbcp.pool2.ObjectPool ObjectPool}</dt>
<dd>
defines a simple object pooling interface, with methods for
borrowing instances from and returning them to the pool.
</dd>
<dt>{@link org.apache.tomcat.dbcp.pool2.PooledObjectFactory PooledObjectFactory}</dt>
<dd>
defines lifecycle methods for object instances contained within a pool.
By associating a factory with a pool, the pool can create new object
instances as needed.
</dd>
</dl>
<p>
The <code>pool</code> package also provides a keyed pool interface,
which pools instances of multiple types, accessed according to an
arbitrary key. See
{@link org.apache.tomcat.dbcp.pool2.KeyedObjectPool KeyedObjectPool} and
{@link org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory
KeyedPooledObjectFactory}.
</p>
</body>
</html>