You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rd...@apache.org on 2006/03/21 22:41:57 UTC
svn commit: r387630 [3/4] - in
/jakarta/commons/proper/pool/contrib/composite-pool: ./ java/ java/org/
java/org/mcarthur/ java/org/mcarthur/sandy/
java/org/mcarthur/sandy/commons/ java/org/mcarthur/sandy/commons/pool/
java/org/mcarthur/sandy/commons/po...
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/KeyedPoolableObjectFactoryAdapter.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/KeyedPoolableObjectFactoryAdapter.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/KeyedPoolableObjectFactoryAdapter.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/KeyedPoolableObjectFactoryAdapter.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import org.apache.commons.pool.KeyedPoolableObjectFactory;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.PoolableObjectFactory;
+
+import java.io.Serializable;
+
+/**
+ * Adapter to let an {@link ObjectPool} use a {@link KeyedPoolableObjectFactory}. Before first use
+ * {@link #setCompositeKeyedObjectPool(CompositeKeyedObjectPool)} must be called so that a reference to the
+ * {@link ThreadLocal} used to pass the key through the {@link ObjectPool} can be aquired.
+ *
+ * @author Sandy McArthur
+ * @since #.#
+ * @version $Revision$ $Date$
+ */
+final class KeyedPoolableObjectFactoryAdapter implements PoolableObjectFactory, Serializable {
+
+ private static final long serialVersionUID = 8664321206626066192L;
+
+ /**
+ * The keyed object factory we're adapting.
+ */
+ // XXX: Add better handling of when this instance is not Serializable
+ private final KeyedPoolableObjectFactory delegate;
+
+ /**
+ * Where we get the current key before delegating to the keyed object factory.
+ * On deserialization this will be set by {@link CompositeKeyedObjectPool}'s constructor.
+ */
+ private transient ThreadLocal keys;
+
+ KeyedPoolableObjectFactoryAdapter(final KeyedPoolableObjectFactory delegate) {
+ this.delegate = delegate;
+ }
+
+ /**
+ * The keyed object pool that uses this adapter.
+ *
+ * @param pool the keyed object pool that uses this adapter.
+ */
+ public void setCompositeKeyedObjectPool(final CompositeKeyedObjectPool pool) {
+ if (pool == null) {
+ throw new IllegalArgumentException("pool must not be null.");
+ }
+ if (pool.getKeys() == null) {
+ throw new IllegalArgumentException("pool's keys must not be null.");
+ }
+ keys = pool.getKeys();
+ }
+
+ /**
+ * Creates an instance that can be returned by the pool.
+ *
+ * @return an instance that can be returned by the pool.
+ * @throws Exception when the delegate does.
+ */
+ public Object makeObject() throws Exception {
+ return delegate.makeObject(keys.get());
+ }
+
+ /**
+ * Destroys an instance no longer needed by the pool.
+ *
+ * @param obj the instance to be destroyed
+ * @throws Exception when the delegate does.
+ */
+ public void destroyObject(final Object obj) throws Exception {
+ delegate.destroyObject(keys.get(), obj);
+ }
+
+ /**
+ * Ensures that the instance is safe to be returned by the pool.
+ * Returns <tt>false</tt> if this object should be destroyed.
+ * @param obj the instance to be validated
+ * @return <tt>false</tt> if this <i>obj</i> is not valid and should
+ * be dropped from the pool, <tt>true</tt> otherwise.
+ */
+ public boolean validateObject(final Object obj) {
+ return delegate.validateObject(keys.get(), obj);
+ }
+
+ /**
+ * Reinitialize an instance to be returned by the pool.
+ *
+ * @param obj the instance to be activated
+ * @throws Exception when the delegate does.
+ */
+ public void activateObject(final Object obj) throws Exception {
+ delegate.activateObject(keys.get(), obj);
+ }
+
+ /**
+ * Uninitialize an instance to be returned to the pool.
+ *
+ * @param obj the instance to be passivated
+ * @throws Exception when the delegate does.
+ */
+ public void passivateObject(final Object obj) throws Exception {
+ delegate.passivateObject(keys.get(), obj);
+ }
+
+ /**
+ * This adapter's delegate keyed object factory. Needed by {@link CompositeKeyedObjectPoolFactory#getKeyedFactory()}.
+ *
+ * @return this adapter's delegate keyed object factory.
+ */
+ KeyedPoolableObjectFactory getDelegate() {
+ return delegate;
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Lender.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Lender.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Lender.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Lender.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import java.util.ListIterator;
+
+/**
+ * Handles how idle objects are added and removed from the idle object pool.
+ * Implementations are expected to be called from a synchronized context on the idle object pool.
+ *
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ * @since #.#
+ */
+interface Lender {
+
+ /**
+ * Called once to associate this manager with an object pool by the {@link CompositeObjectPool} constructor.
+ *
+ * @param objectPool the pool to associate with.
+ * @throws IllegalArgumentException if <code>objectPool</code> is <code>null</code>.
+ * @throws IllegalStateException if this method is called more than once.
+ */
+ public void setCompositeObjectPool(CompositeObjectPool objectPool) throws IllegalArgumentException, IllegalStateException;
+
+ /**
+ * Take an object from the idle object pool.
+ *
+ * @return a previously idle object.
+ */
+ public Object borrow();
+
+ /**
+ * Return an object to the idle object pool. Implementations must call {@link Object#notifyAll()} on the idle object
+ * pool so the {@link WaitLimitManager} can work.
+ *
+ * @param obj the object to return to the idle object pool.
+ */
+ public void repay(Object obj);
+
+ /**
+ * Returns a list iterator of the elements in this pool. The list iterator should be implemented such that the first
+ * element retuend by {@link ListIterator#next()} is most likely to be the least desirable idle object.
+ * Implementations of the {@link Lender} interface that wrap/unwrap idle objects should do the same here.
+ * Clients should be aware that it is likely that {@link ListIterator#next()} or {@link ListIterator#previous()}
+ * will return null. Client that receive a null should call {@link ListIterator#remove()} but {@link Lender}s that
+ * receive an unexpected null must never automatically {@link ListIterator#remove()} an element as that would break
+ * the {@link ListIterator#hasNext()} and {@link ListIterator#hasPrevious()} contracts for the client.
+ * Use of this list iternator <b>must be</b> synchronized on the {@link CompositeObjectPool#getPool() pool}. Clients
+ * that synchronize on the {@link CompositeObjectPool#getPool() pool} should make special effort to be quick or not
+ * hold on to that lock for too long of a period as no other threads will be able to access the pool at the same
+ * time.
+ *
+ * @return a list iterator of the elements in this pool.
+ */
+ public ListIterator listIterator();
+
+ /**
+ * Return the size of the idle object pool.
+ *
+ * @return the size of the idle object pool the lender is accessing.
+ */
+ public int size();
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/LifoLender.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/LifoLender.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/LifoLender.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/LifoLender.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A Last In First Out (LIFO) {@link Lender}.
+ *
+ * @see BorrowType#LIFO
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ * @since #.#
+ */
+final class LifoLender extends AbstractLender implements Serializable {
+
+ private static final long serialVersionUID = 5836740439617614901L;
+
+ public Object borrow() {
+ final List pool = getObjectPool().getPool();
+ assert Thread.holdsLock(pool);
+ if (pool instanceof LinkedList) {
+ return ((LinkedList)pool).removeLast();
+ } else {
+ return pool.remove(pool.size() - 1);
+ }
+ }
+
+ public String toString() {
+ return "LIFO";
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/LimitBehavior.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/LimitBehavior.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/LimitBehavior.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/LimitBehavior.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.NoSuchElementException;
+
+/**
+ * Specifies the behavior of when the max number of active objects has been reached.
+ *
+ * @see CompositeObjectPoolFactory#setLimitBehavior(LimitBehavior)
+ * @see CompositeKeyedObjectPoolFactory#setLimitBehavior(LimitBehavior)
+ * @author Sandy McArthur
+ * @since #.#
+ * @version $Revision$ $Date$
+ */
+public final class LimitBehavior implements Serializable {
+
+ private static final long serialVersionUID = -4325661345028907604L;
+
+ /**
+ * When the number of active objects has been reached fail with a {@link NoSuchElementException} instead of
+ * returning a new object.
+ */
+ public static final LimitBehavior FAIL = new LimitBehavior("FAIL");
+
+ /**
+ * When the number of active objects has been reached wait for the specified amount of time before failing with
+ * a {@link NoSuchElementException}.
+ */
+ public static final LimitBehavior WAIT = new LimitBehavior("WAIT");
+
+ /**
+ * enum name.
+ */
+ private final String name;
+
+ private LimitBehavior(final String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ // Autogenerated with Java 1.5 enums
+ public static LimitBehavior[] values() {
+ return new LimitBehavior[] {FAIL, WAIT};
+ }
+
+ // necessary for serialization
+ private static int nextOrdinal = 0;
+ private final int ordinal = nextOrdinal++;
+ private Object readResolve() throws ObjectStreamException {
+ return values()[ordinal];
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Manager.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Manager.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Manager.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Manager.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import org.apache.commons.pool.PoolableObjectFactory;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Controls the behavior of how the pool grown or errors.
+ * Managers are expected to transition an object from an active or idle state and vice versa.
+ * Implementations are expected to be called from a synchronized context on the idle object pool.
+ *
+ * @see ExhaustionBehavior
+ * @see LimitBehavior
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ * @since #.#
+ */
+interface Manager {
+
+ /**
+ * Called once to associate this manager with an object pool by the {@link CompositeObjectPool} constructor.
+ *
+ * @param objectPool the pool to associate with.
+ * @throws IllegalArgumentException if <code>objectPool</code> is <code>null</code>.
+ * @throws IllegalStateException if this method is called more than once.
+ */
+ public void setCompositeObjectPool(CompositeObjectPool objectPool) throws IllegalArgumentException, IllegalStateException;
+
+ /**
+ * Retreives the next object from the pool. Objects from the pool will be
+ * {@link PoolableObjectFactory#activateObject(Object) activated} and
+ * {@link PoolableObjectFactory#validateObject(Object) validated}.
+ * Newly {@link PoolableObjectFactory#makeObject() created} objects will not be activated or validated.
+ *
+ * @return a new or activated object.
+ * @throws NoSuchElementException if the pool is empty and no new object can be created.
+ * @throws Exception usually from {@link PoolableObjectFactory} methods.
+ */
+ public Object nextFromPool() throws NoSuchElementException, Exception;
+
+ /**
+ * Return an object to the pool. Object will be {@link PoolableObjectFactory#passivateObject(Object) passivated}.
+ *
+ * @param obj the object to return to the pool.
+ * @throws Exception as thrown by {@link PoolableObjectFactory#passivateObject(Object)}.
+ */
+ public void returnToPool(Object obj) throws Exception;
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/NullLender.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/NullLender.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/NullLender.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/NullLender.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.ListIterator;
+
+/**
+ * Neither borrow nor return objects.
+ *
+ * @see BorrowType#NULL
+ * @author Sandy McArthur
+ * @since #.#
+ * @version $Revision$ $Date$
+ */
+final class NullLender implements Lender, Serializable {
+
+ private static final long serialVersionUID = -135471856936204860L;
+
+ /**
+ * Called once to associate this manager with an object pool by the {@link CompositeObjectPool} constructor.
+ *
+ * @param objectPool the pool to associate with.
+ * @throws IllegalArgumentException if <code>objectPool</code> is <code>null</code>.
+ * @throws IllegalStateException if this method is called more than once.
+ */
+ public void setCompositeObjectPool(final CompositeObjectPool objectPool) throws IllegalArgumentException, IllegalStateException {
+ // nothing
+ }
+
+ /**
+ * Return <code>null</code>.
+ *
+ * @return <code>null</code>.
+ */
+ public Object borrow() {
+ return null;
+ }
+
+ /**
+ * Discards the object.
+ *
+ * @param obj the object to be discarded.
+ */
+ public void repay(final Object obj) {
+ // nothing
+ }
+
+ /**
+ * Returns a list iterator from an empty list.
+ *
+ * @return a list iterator from an empty list.
+ */
+ public ListIterator listIterator() {
+ return Collections.EMPTY_LIST.listIterator();
+ }
+
+ /**
+ * Return <code>0</code>.
+ *
+ * @return <code>0</code>.
+ */
+ public int size() {
+ return 0;
+ }
+
+ public String toString() {
+ return "NULL";
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/NullTracker.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/NullTracker.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/NullTracker.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/NullTracker.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import java.io.Serializable;
+
+/**
+ * Doesn't actually track active objects. Not compatiable with any {@link ActiveLimitManager} implementation.
+ *
+ * @see TrackingType#NULL
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ * @since #.#
+ */
+final class NullTracker implements Tracker, Serializable {
+
+ private static final long serialVersionUID = -5846405955762769678L;
+
+ /**
+ * Don't do anything.
+ *
+ * @param obj was borrowed from the pool.
+ */
+ public void borrowed(final Object obj) {
+ }
+
+ /**
+ * Don't do anything.
+ *
+ * @param obj being returned to the pool.
+ */
+ public void returned(final Object obj) {
+ }
+
+ /**
+ * Throws {@link UnsupportedOperationException}.
+ *
+ * @return doesn't, always throws an {@link UnsupportedOperationException}.
+ * @throws UnsupportedOperationException
+ */
+ public int getBorrowed() {
+ throw new UnsupportedOperationException("tracking disabled");
+ }
+
+ public String toString() {
+ return "NullTracker{}";
+ }
+}
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/ReferenceTracker.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/ReferenceTracker.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/ReferenceTracker.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/ReferenceTracker.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Keeps track of active objects with {@link Reference}s and detectes when they are not returned to the pool.
+ *
+ * @see TrackingType#REFERENCE
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ * @since #.#
+ */
+class ReferenceTracker implements Tracker, Serializable {
+
+ private static final long serialVersionUID = 3271870427019790961L;
+
+ /**
+ * ReferenceQueue of borrowed objects so we can detect when they have been garbage collected instead of being
+ * returned to the pool.
+ */
+ protected final transient ReferenceQueue rq = new ReferenceQueue();
+
+ /**
+ * Map used to track active objects.
+ */
+ protected final transient Map map = Collections.synchronizedMap(new HashMap());
+
+ /**
+ * The number of borrowed objects that were lost to the garbage collector.
+ */
+ private transient int lost = 0;
+
+ public void borrowed(final Object obj) {
+ workQueue();
+ final IdentityReference ref;
+ synchronized (rq) {
+ ref = wrapBorrowed(obj);
+ }
+ map.put(ref.getKey(), ref);
+ }
+
+ /**
+ * Wrap the object in a reference.
+ *
+ * @param obj the object to be wrapped.
+ * @return a type of reference around obj.
+ */
+ protected IdentityReference wrapBorrowed(final Object obj) {
+ return new IdentityWeakReference(obj, rq);
+ }
+
+ /**
+ * Stop tracking an active object. Remove it from the active object {@link #map} and remove it from the reference
+ * queue.
+ *
+ * @param obj a returning active object.
+ * @throws IllegalStateException when an object that wasn't brorrowed from this pool is returned.
+ */
+ public void returned(final Object obj) throws IllegalStateException {
+ workQueue();
+ final IdentityKey key = new IdentityKey(obj);
+ final IdentityReference ref = (IdentityReference)map.remove(key);
+ if (ref != null) {
+ ref.clear();
+ } else {
+ throw new IllegalStateException("Cannot return an object that wasn't borrowed from this pool or has already been returned to this pool. " + obj);
+ }
+ }
+
+ public int getBorrowed() {
+ workQueue();
+ return map.size();
+ }
+
+ /**
+ * Work the {@link #rq reference queue} to detected any lost objects. This calls
+ * {@link #referenceToBeRemoved(ReferenceTracker.IdentityReference)} just before removal from the {@link #map}.
+ */
+ private void workQueue() {
+ synchronized (rq) {
+ for (Reference ref = rq.poll(); ref != null; ref = rq.poll()) {
+ final IdentityReference identRef = (IdentityReference)ref;
+ referenceToBeRemoved(identRef);
+ map.remove(identRef.getKey());
+ lost++;
+ }
+ }
+ }
+
+ /**
+ * Give sub-classes a chance to take action just before a reference is removed. The parameter <code>ref</code> will
+ * be a {@link Reference} aquired from the {@link #wrapBorrowed(Object)} method.
+ *
+ * @param ref the reference that is being removed from the reference queue.
+ */
+ protected void referenceToBeRemoved(final IdentityReference ref) {
+ // nothing to do here
+ }
+
+ /**
+ * Get the number of borrowed objects that were lost. An object is lost when it is borrowed from a pool
+ * and garbage collected instead of being returned.
+ *
+ * @return the number of borrowed objects that were lost.
+ */
+ protected int getLost() {
+ return lost;
+ }
+
+ public String toString() {
+ return "ReferenceTracker{" +
+ "active=" + map.size() +
+ ", lost=" + getLost() +
+ '}';
+ }
+
+ /**
+ * A wrapper for an object has an {@link #equals(Object)} and {@link #hashCode()} based on the
+ * {@link System#identityHashCode(Object) identityHashCode} of an object. This is needed else
+ * {@link ReferenceTracker#map} could not find and track more than one object that are
+ * {@link Object#equals(Object) equal}. If the JDK ever adds a WeakIdentityHashMap we should use that instead.
+ */
+ protected static final class IdentityKey {
+
+ /**
+ * The {@link System#identityHashCode(Object)} of the object.
+ */
+ private final int ident; // XXX: Going need something more than this on 64 bit systems.
+
+ IdentityKey(final Object obj) {
+ this(System.identityHashCode(obj));
+ }
+
+ IdentityKey(final int ident) {
+ this.ident = ident;
+ }
+
+ public int hashCode() {
+ return ident;
+ }
+
+ public boolean equals(final Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+
+ final IdentityKey that = (IdentityKey)obj;
+
+ return ident == that.ident;
+ }
+ }
+
+ /**
+ * Implementator of this interface should usually also extend a {@link Reference} class.
+ */
+ protected interface IdentityReference {
+
+ /**
+ * A key that can be used by a map to store/find this reference but does not make this reference strongly
+ * reachable.
+ *
+ * @return key to store/find this reference.
+ */
+ public IdentityKey getKey();
+
+ /**
+ * Clears this reference.
+ *
+ * @see Reference#clear()
+ */
+ public void clear();
+ }
+
+ /**
+ * A {@link WeakReference} that keeps track of enough information to create an {@link ReferenceTracker.IdentityKey}.
+ */
+ private static final class IdentityWeakReference extends WeakReference implements IdentityReference {
+
+ /**
+ * The {@link System#identityHashCode(Object)} of the object.
+ */
+ private final int ident; // XXX: Going need something more than this on 64 bit systems.
+
+ IdentityWeakReference(final Object referent, final ReferenceQueue q) {
+ super(referent, q);
+ ident = System.identityHashCode(referent);
+ }
+
+ public IdentityKey getKey() {
+ return new IdentityKey(ident);
+ }
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/SimpleTracker.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/SimpleTracker.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/SimpleTracker.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/SimpleTracker.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import java.io.Serializable;
+
+/**
+ * Pretends to track active objects by using a counter. This implementation just increments and decrements a counter and
+ * trusts the user will properly return an object. If the counter goes negative it throws an
+ * {@link IllegalStateException}.
+ *
+ * @see TrackingType#SIMPLE
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ * @since #.#
+ */
+final class SimpleTracker implements Tracker, Serializable {
+
+ private static final long serialVersionUID = -7300626285071421255L;
+
+ /**
+ * The number of "borrowed" or active objects from the pool.
+ */
+ private transient volatile int active = 0;
+
+ /**
+ * Increment {@link #active} by one.
+ *
+ * @param obj was borrowed from the pool.
+ */
+ public void borrowed(final Object obj) {
+ active++;
+ }
+
+ /**
+ * Decrement {@link #active} by one.
+ *
+ * @param obj being returned to the pool.
+ * @throws IllegalStateException when more objects have been returned than borrowed.
+ */
+ public void returned(final Object obj) throws IllegalStateException {
+ if (--active < 0) {
+ active++; // undo, object won't be returned
+ throw new IllegalStateException("More objects returned than were borrowed. Most recent object: " + obj);
+ }
+ }
+
+ /**
+ * The number of "borrowed" or active objects from the pool.
+ *
+ * @return the number of "borrowed" active objects.
+ */
+ public int getBorrowed() {
+ return active;
+ }
+
+ public String toString() {
+ return "SimpleTracker{" +
+ "active=" + active +
+ '}';
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/SoftLender.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/SoftLender.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/SoftLender.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/SoftLender.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import org.apache.commons.pool.ObjectPool;
+
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * Wraps object in a {@link SoftReference} before letting a delegate {@link Lender} add them to the idle object pool.
+ * Idle objects that are garbage collected will not be {@link ObjectPool#invalidateObject(Object) invalidated}.
+ *
+ * @see BorrowType#SOFT_FIFO
+ * @see BorrowType#SOFT_LIFO
+ * @author Sandy McArthur
+ * @since #.#
+ * @version $Revision$ $Date$
+ */
+final class SoftLender extends DelegateLender implements Serializable {
+
+ private static final long serialVersionUID = 8589090657730065177L;
+
+ /**
+ * Create a lnder that allows the garbage collector to remove objects from the idle object pool.
+ *
+ * @param delegate delegate the lender to delegate to, must not be <code>null</code>.
+ * @throws IllegalArgumentException when <code>delegate</code> is <code>null</code>.
+ */
+ SoftLender(final Lender delegate) throws IllegalArgumentException {
+ super(delegate);
+ }
+
+ /**
+ * Unwrap the {@link Reference} from the borrowed object.
+ *
+ * @return a previously idle object.
+ */
+ public Object borrow() {
+ return ((Reference)super.borrow()).get();
+ }
+
+ /**
+ * Wrap the object in a {@link SoftReference} before letting the delegate {@link Lender} return an object to the
+ * idle object pool.
+ *
+ * @param obj the object to return to the idle object pool.
+ */
+ public void repay(final Object obj) {
+ super.repay(new SoftReference(obj));
+ }
+
+ /**
+ * Returns a list iterator of the elements in this pool. The list iterator should be implemented such that the first
+ * element retuend by {@link ListIterator#next()} is most likely to be the least desirable idle object.
+ * Implementations of the {@link Lender} interface that wrap/unwrap idle objects should do the same here.
+ *
+ * @return a list iterator of the elements in this pool.
+ */
+ public ListIterator listIterator() {
+ return new SoftListIterator(super.listIterator());
+ }
+
+ /**
+ * Return the size of the idle object pool. Also removes any broken {@link Reference}s so the size is more accurate.
+ *
+ * @return the size of the idle object pool the lender is accessing.
+ */
+ public int size() {
+ final Object lock = getObjectPool().getPool();
+ synchronized (lock) {
+ final Iterator iter = super.listIterator();
+ while (iter.hasNext()) {
+ final Reference ref = (Reference)iter.next();
+ if (ref.get() == null) {
+ iter.remove();
+ }
+ }
+ }
+ return super.size();
+ }
+
+ public String toString() {
+ return "Soft{" + super.toString() + "}";
+ }
+
+ /**
+ * A {@link ListIterator} that unwrapps {@link Reference}s.
+ */
+ private static class SoftListIterator implements ListIterator {
+ private final ListIterator iter;
+
+ private SoftListIterator(final ListIterator iter) {
+ this.iter = iter;
+ }
+
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ /**
+ * Unwrap an {@link Reference} and return the next object if it hasn't been garbage collected.
+ *
+ * @return an unwrapped object or <code>null</code> if an object has been garbage collected.
+ * @see ListIterator#next()
+ */
+ public Object next() {
+ final Reference ref = (Reference)iter.next();
+ return ref != null ? ref.get() : null;
+ }
+
+ public boolean hasPrevious() {
+ return iter.hasPrevious();
+ }
+
+ /**
+ * Unwrap an {@link Reference} and return the previous object if it hasn't been garbage collected.
+ *
+ * @return an unwrapped object or <code>null</code> if an object has been garbage collected.
+ * @see ListIterator#previous()
+ */
+ public Object previous() {
+ final Reference ref = (Reference)iter.previous();
+ return ref != null ? ref.get() : null;
+ }
+
+ public int nextIndex() {
+ return iter.nextIndex();
+ }
+
+ public int previousIndex() {
+ return iter.previousIndex();
+ }
+
+ public void remove() {
+ iter.remove();
+ }
+
+ public void set(final Object o) {
+ iter.set(o);
+ }
+
+ public void add(final Object o) {
+ iter.add(o);
+ }
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Tracker.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Tracker.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Tracker.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/Tracker.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.PoolableObjectFactory;
+
+/**
+ * Tracks active objects. Implementations are expected to be called from a synchronized context so
+ * {@link #getBorrowed()} is accurate.</p>
+ *
+ * <p>{@link #borrowed(Object)} for an object will always be called before {@link #returned(Object)} is called.</p>
+ *
+ * <p>Implementations must not make any assumptions about nor modify the state of the objects it sees. This is simply
+ * a tool for active object accounting.</p>
+ *
+ * @see TrackingType
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ * @since #.#
+ */
+interface Tracker {
+
+ /**
+ * An object has been borrowed from the pool. The object will have been
+ * {@link PoolableObjectFactory#activateObject(Object) activated} and
+ * {@link PoolableObjectFactory#validateObject(Object) validated} and is about to be returned to the client.
+ *
+ * <p>Objects created via {@link ObjectPool#addObject()} are also "borrowed" so that when
+ * {@link ObjectPool#returnObject(Object)} {@link #returned(Object) returns} that object it isn't unexpected.
+ *
+ * @param obj was borrowed from the pool.
+ */
+ public void borrowed(Object obj);
+
+ /**
+ * An object is being {@link ObjectPool#returnObject(Object) returned} to the pool.
+ * {@link ObjectPool#invalidateObject(Object) Invalid} objects are also "returned" via this method.
+ *
+ * @param obj being returned to the pool.
+ */
+ public void returned(Object obj);
+
+ /**
+ * The number of "borrowed" or active objects from the pool.
+ *
+ * @return the number of "borrowed" active objects.
+ */
+ public int getBorrowed();
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/TrackingType.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/TrackingType.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/TrackingType.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/TrackingType.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.ref.WeakReference;
+
+/**
+ * Specifies how active objects are tracked while they are out of the pool.
+ *
+ * @see CompositeObjectPoolFactory#setTrackerType(TrackingType)
+ * @see CompositeKeyedObjectPoolFactory#setTrackerType(TrackingType)
+ * @author Sandy McArthur
+ * @since #.#
+ * @version $Revision$ $Date$
+ */
+public final class TrackingType implements Serializable {
+
+ private static final long serialVersionUID = 181851949909846032L;
+
+ /**
+ * Do not track how objects are borrowed from the pool. While this is the fastest tracking type it is
+ * incompatable with pools that limit the number of objects in the pool.
+ */
+ public static final TrackingType NULL = new TrackingType("NULL");
+
+ /**
+ * Borrowed object tracker that trusts you'll return the objects you borrow. This is the most common method of
+ * tracking active objects. If you return more objects than you borrow then this will throw an
+ * {@link IllegalStateException}.
+ */
+ public static final TrackingType SIMPLE = new TrackingType("SIMPLE");
+
+ /**
+ * Borrowed object tracker that detects when borrowed objects are lost. This implementation keeps track of
+ * borrowed objects with {@link WeakReference weak references} and decrements the active count when lost objects
+ * are garbage collected. The point in time at which an object is detected as being lost is dependant on the
+ * first object borrowed or returned to the pool after garbage collector has collected the lost object. If you
+ * return an object that wasn't borrowed from the pool an {@link IllegalStateException} will be thrown.
+ */
+ public static final TrackingType REFERENCE = new TrackingType("REFERENCE");
+
+ /**
+ * Like {@link #REFERENCE} but prints a stack trace for lost objects from when the object was borrowed from the
+ * pool. The point in time at which the stack trace is printed is dependent on the garbage collector's behavior.
+ */
+ public static final TrackingType DEBUG = new TrackingType("DEBUG");
+
+ /**
+ * enum name.
+ */
+ private final String name;
+
+ private TrackingType(final String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ // Autogenerated with Java 1.5 enums
+ public static TrackingType[] values() {
+ return new TrackingType[] {NULL, SIMPLE, REFERENCE, DEBUG};
+ }
+
+ // necessary for serialization
+ private static int nextOrdinal = 0;
+ private final int ordinal = nextOrdinal++;
+ private Object readResolve() throws ObjectStreamException {
+ return values()[ordinal];
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/WaitLimitManager.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/WaitLimitManager.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/WaitLimitManager.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/WaitLimitManager.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import org.apache.commons.pool.PoolableObjectFactory;
+
+import java.io.Serializable;
+import java.util.NoSuchElementException;
+
+/**
+ * Waits for an object to become available if the pool is exhausted. A {@link NoSuchElementException} is thrown if an
+ * object doesn't become available in the specified amount of time. For this to work all {@link Lender}s must call
+ * {@link Object#notifyAll()} on the idle object pool once they've returned an object.
+ *
+ * @see LimitBehavior#WAIT
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ * @since #.#
+ */
+final class WaitLimitManager extends ActiveLimitManager implements Serializable {
+
+ private static final long serialVersionUID = 2536750269978303711L;
+
+ private long maxWaitMillis = 0; // forever
+
+ WaitLimitManager(final Manager delegate) throws IllegalArgumentException {
+ super(delegate);
+ }
+
+ /**
+ * Checks to see how many objects are in play and will not allow more than that.
+ * Delegates object management to another {@link Manager}.
+ *
+ * @return a new or activated object.
+ * @throws NoSuchElementException if the pool is empty and no new object can be created.
+ * @throws Exception usually from {@link PoolableObjectFactory} methods.
+ * @throws InterruptedException when the {@link Thread} is interrupted.
+ */
+ public Object nextFromPool() throws NoSuchElementException, Exception, InterruptedException {
+ final Object poolLock = objectPool.getPool();
+ assert Thread.holdsLock(poolLock);
+ final long endTime = maxWaitMillis > 0 ? System.currentTimeMillis() + maxWaitMillis : Long.MAX_VALUE;
+ while (maxWaitMillis <= 0 || endTime > System.currentTimeMillis()) {
+ if (Thread.currentThread().isInterrupted()) {
+ throw new InterruptedException();
+ }
+ if (objectPool.getNumActive() < getMaxActive()) {
+ return super.nextFromPool();
+ }
+ // Don't wait if the pool was closed between the start of the while and here.
+ if (objectPool.isOpen()) {
+ final long waitTime = Math.max(1, endTime - System.currentTimeMillis());
+ poolLock.wait(maxWaitMillis > 0 ? waitTime : 0);
+ } else {
+ throw new IllegalStateException("Trying to aquire an object from a closed pool.");
+ }
+ }
+ if (objectPool.isOpen()) {
+ throw new NoSuchElementException("Unable to aquire new object in allowed time of: " + maxWaitMillis);
+ } else {
+ throw new IllegalStateException("Trying to aquire an object from a closed pool.");
+ }
+ }
+
+ /**
+ * The max wait time in milli-seconds for a pooled object to become available.
+ *
+ * @return max wait time in milli-seconds for a pooled object to become available.
+ */
+ public long getMaxWaitMillis() {
+ return maxWaitMillis;
+ }
+
+ /**
+ * Set the max wait time in milli-seconds for a pooled object to become available.
+ * A non-positve value means wait forever.
+ *
+ * @param maxWaitMillis max wait for an object to become available or <= 0 for no limit.
+ */
+ public void setMaxWaitMillis(final long maxWaitMillis) {
+ this.maxWaitMillis = maxWaitMillis;
+ }
+
+ public String toString() {
+ return "WaitLimitManager{" +
+ "maxActive=" + getMaxActive() +
+ ", maxWaitMillis=" + maxWaitMillis +
+ ", delegate=" + super.toString() +
+ '}';
+ }
+}
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/package.html
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/package.html?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/package.html (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/java/org/mcarthur/sandy/commons/pool/composite/package.html Tue Mar 21 13:41:53 2006
@@ -0,0 +1,166 @@
+<!--
+ ~ Copyright 2006 The Apache Software Foundation.
+ ~
+ ~ Licensed 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.
+ -->
+
+<!-- $Id: $ -->
+<html>
+<body>
+<p>
+ Composite [Keyed] Object Pool implementation.
+</p>
+
+<h3>About</h3>
+<p>
+ The classes in this package are used to implement the {@link org.apache.commons.pool.ObjectPool} and
+ the {@link org.apache.commons.pool.KeyedObjectPool} interfaces building the desired feature set via
+ object composition. Almost every interesting class or method in this package is package-private or
+ privately scoped. This is intentional as clients of this code should not care about implementations
+ as much as the desired feature set. This should make future transitions to more correct or better
+ performant code painless or at least much less painful.
+</p>
+
+<h3>Public Code Tour</h3>
+
+<h4>Factories</h4>
+<p>
+ There are two object pool factories in this package:
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPoolFactory} and
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeKeyedObjectPoolFactory}.
+</p>
+<p>
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeKeyedObjectPoolFactory}
+ actually delegates almost all of it's work to the regular
+ composite object pool factory. The only interesting part about it is in the
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeKeyedObjectPoolFactory#setKeyedFactory} method
+ where it wraps the {@link org.apache.commons.pool.KeyedPoolableObjectFactory} in an adapter that uses a
+ ThreadLocal to pass the key through the {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPool}
+ backing the {@link org.mcarthur.sandy.commons.pool.composite.CompositeKeyedObjectPool} for that particular key.
+ More on that later.
+</p>
+<p>
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPoolFactory} does all of it's heavy lifting in
+ three methods:
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPoolFactory#getLender},
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPoolFactory#getManager}, and
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPoolFactory#getTracker}.
+ All other methods are little more than java bean pattern getters and setters.
+ Those three methods check that the factory has not been configured in an invalid way and compose the
+ each of the three components that make up a {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPool}.
+ Also, if possible any optimizations are made here.
+</p>
+
+<h4>Type safe enums</h4>
+<p>
+ Any public class not mentioned in the above facades or factories sections is a type safe enum used by the factories
+ to specify the desired configuration. Type safe enums are used for two reasons. First, they represent the desired
+ feature set as opposed to a specific implementation. Second, by using them it is nearly impossible to configure
+ a factory in an invalid configuration.
+</p>
+
+<hr width="50%"/>
+
+<h3>Private Code Tour</h3>
+<p>
+ The following is intended to help those who wish to better understand the design of the composite object pool
+ implementation.
+</p>
+
+<h3>Object Pools</h3>
+<p>
+ Behind the scenes there are two package-private object pool implementations:
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPool} and
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeKeyedObjectPool}.
+</p>
+
+<h4>CompositeKeyedObjectPool</h4>
+<p>
+ The {@link org.mcarthur.sandy.commons.pool.composite.CompositeKeyedObjectPool} is implemented as a map of keys to
+ object pools. When a new key is used it uses a {@link org.apache.commons.pool.ObjectPoolFactory} to create an
+ object pool for that key. I do not believe there is anything in
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeKeyedObjectPool} that requires the use of
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPool} to back each key. Also there is nothing to
+ prevent the use of {@link org.apache.commons.pool.ObjectPool}s that are configured differently for each key
+ but this feature seemed to have minimal utility. Such functionality could be obtained via careful use of the
+ {@link org.mcarthur.sandy.commons.pool.composite.CompositeKeyedObjectPoolFactory#createPool(org.apache.commons.pool.ObjectPoolFactory)}
+ method.
+</p>
+
+<h4>CompositeObjectPool</h4>
+<p>
+ The {@link org.mcarthur.sandy.commons.pool.composite.CompositeObjectPool} is the heart and soul of this object pool
+ implementation. Again, delegation is what makes this sucker tick. There are three component types the composite
+ object pool delegates it's work to and from where it acquires it's feature set.
+</p>
+
+<h5>Lender</h5>
+<p>
+ A {@link org.mcarthur.sandy.commons.pool.composite.Lender} maintains idle objects and the order in which objects are
+ borrowed. It is common for lenders to be stacked to get the desired functionality. There are three terminating
+ lenders: {@link org.mcarthur.sandy.commons.pool.composite.FifoLender},
+ {@link org.mcarthur.sandy.commons.pool.composite.LifoLender}, and
+ {@link org.mcarthur.sandy.commons.pool.composite.NullLender}.
+ Next there is a {@link org.mcarthur.sandy.commons.pool.composite.SoftLender} which can be used to allow garbage
+ collection of idle objects. It would be possible to create a WeakLender but I'm not sure I see any utility in that.
+ Finally there is a class of {@link org.mcarthur.sandy.commons.pool.composite.EvictorLender}s that are used to
+ preform idle object eviction.
+</p>
+
+<h6>EvictorLenders</h6>
+<p>
+ There are two {@link org.mcarthur.sandy.commons.pool.composite.EvictorLender}s that can be chained together:
+ {@link org.mcarthur.sandy.commons.pool.composite.IdleEvictorLender} and
+ {@link org.mcarthur.sandy.commons.pool.composite.InvalidEvictorLender}.
+ Both evictor types use a {@link java.util.Timer} to schedule their work. The Timer class claims to be very scalable
+ which is good because there will be a lot of {@link java.util.TimerTask}s in a large object pool.
+ Each of the evictor types create a TimerTask that will run at a future time to possibly evict one idle object.
+ This design makes idle object eviction quite deterministic and limits contention for the object pool to the bare
+ minimum.
+</p>
+
+<h5>Manager</h5>
+<p>
+ {@link org.mcarthur.sandy.commons.pool.composite.Manager}: a manager does most of the heavy lifting between a
+ {@link org.mcarthur.sandy.commons.pool.composite.Lender} and a
+ {@link org.mcarthur.sandy.commons.pool.composite.Tracker}. A manager is responsible for activating and validating
+ idle objects and passivating and possibly validating active objects. It is also responsible for controlling the
+ growth and size of the pool. Managers can also be stacked together to get the desired feature set. There are two
+ terminating mangers: {@link org.mcarthur.sandy.commons.pool.composite.FailManager} and
+ {@link org.mcarthur.sandy.commons.pool.composite.GrowManager}. These two manager interact with the poolable object
+ factory and the lenders to activate idle object or create new ones.
+ {@link org.mcarthur.sandy.commons.pool.composite.IdleLimitManager} is a unique in that it is really the only manager
+ that does any interesting work in the {@link org.mcarthur.sandy.commons.pool.composite.IdleLimitManager#returnToPool}
+ method. Finally there are two {@link org.mcarthur.sandy.commons.pool.composite.ActiveLimitManager}s that implement
+ the behaviors for when a pool has reached it's limit of active objects:
+ {@link org.mcarthur.sandy.commons.pool.composite.FailLimitManager} and
+ {@link org.mcarthur.sandy.commons.pool.composite.WaitLimitManager}.
+</p>
+
+<h5>Tracker</h5>
+<p>
+ {@link org.mcarthur.sandy.commons.pool.composite.Tracker}: a tracker's sole responsibility is keeping track of
+ active objects borrowed from the pool. A tracker will never touch an object that is considered to be idle. The
+ {@link org.mcarthur.sandy.commons.pool.composite.NullTracker} and
+ {@link org.mcarthur.sandy.commons.pool.composite.SimpleTracker} classes are very simple. The
+ {@link org.mcarthur.sandy.commons.pool.composite.ReferenceTracker} is much more interesting. It can detect when a
+ borrowed object is not returned to the pool (assuming the garbage collector does it's thing in a timely manner).
+ Most of it's complexity comes from the need to carefully track borrowed objects without creating a strong reference
+ to them. The trickery needed to make this work is rather neat, especially when the
+ {@link org.mcarthur.sandy.commons.pool.composite.DebugTracker} is used.
+</p>
+
+@author Sandy McArthur
+
+</body>
+</html>
\ No newline at end of file
Added: jakarta/commons/proper/pool/contrib/composite-pool/test/org/mcarthur/sandy/commons/pool/composite/PerformanceTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/contrib/composite-pool/test/org/mcarthur/sandy/commons/pool/composite/PerformanceTest.java?rev=387630&view=auto
==============================================================================
--- jakarta/commons/proper/pool/contrib/composite-pool/test/org/mcarthur/sandy/commons/pool/composite/PerformanceTest.java (added)
+++ jakarta/commons/proper/pool/contrib/composite-pool/test/org/mcarthur/sandy/commons/pool/composite/PerformanceTest.java Tue Mar 21 13:41:53 2006
@@ -0,0 +1,624 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.mcarthur.sandy.commons.pool.composite;
+
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.BasePoolableObjectFactory;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Date;
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+/**
+ * A collection of benchmarks to confirm and establish performance properties.
+ *
+ * @author Sandy McArthur
+ * @since #.#
+ * @version $Revision$ $Date$
+ */
+public class PerformanceTest {
+ public static final Object LOCK = new Object();
+ private static final List borrowTypes = Arrays.asList(BorrowType.values());
+ private static final List exhaustionBehaviors = Arrays.asList(ExhaustionBehavior.values());
+ private static final List maxIdles = Arrays.asList(new Integer[] {new Integer(-1), new Integer(10)});
+ private static final List maxActives = Arrays.asList(new Integer[] {new Integer(-1), new Integer(10)});
+ private static final List limitBehaviors = Arrays.asList(LimitBehavior.values());
+ private static final List maxWaits = Arrays.asList(new Integer[] {new Integer(-1), new Integer(50)}); // not sure how to use this
+ private static final List trackingTypes = new ArrayList(Arrays.asList(TrackingType.values()));
+ private static final List validateOnReturns = Arrays.asList(new Boolean[] {Boolean.FALSE, Boolean.TRUE});
+ // evictIdleMillis
+ // evictInvalidFrequencyMillis
+ static {
+ trackingTypes.remove(TrackingType.DEBUG); // based off of TrackingType.REFERENCE and slower (about 1/5 as fast)
+ }
+
+ private Iterator borrowIter = borrowTypes.iterator();
+ private Iterator exhaustionIter = exhaustionBehaviors.iterator();
+ private Iterator maxIdleIter = maxIdles.iterator();
+ private Iterator maxActiveIter = maxActives.iterator();
+ private Iterator limitIter = limitBehaviors.iterator();
+ private Iterator trackingIter = trackingTypes.iterator();
+ private Iterator validateIter = validateOnReturns.iterator();
+
+ private PoolableObjectFactory objectFactory = new IntegerFactory();
+
+ private final CompositeObjectPoolFactory poolFactory = new CompositeObjectPoolFactory(objectFactory);
+
+ private Set ranCombinations = new HashSet();
+
+ private boolean nextCompositeSettings() {
+ boolean newCombination = true;
+ if (!validateIter.hasNext()) {
+ validateIter = validateOnReturns.iterator();
+
+ if (!trackingIter.hasNext()) {
+ trackingIter = trackingTypes.iterator();
+
+ if (!limitIter.hasNext()) {
+ limitIter = limitBehaviors.iterator();
+
+ if (!maxActiveIter.hasNext()) {
+ maxActiveIter = maxActives.iterator();
+
+ if (!maxIdleIter.hasNext()) {
+ maxIdleIter = maxIdles.iterator();
+
+ if (!exhaustionIter.hasNext()) {
+ exhaustionIter = exhaustionBehaviors.iterator();
+
+ if (!borrowIter.hasNext()) {
+ borrowIter = borrowTypes.iterator();
+ newCombination = false;
+ }
+ poolFactory.setBorrowType((BorrowType)borrowIter.next());
+ }
+ poolFactory.setExhaustionBehavior((ExhaustionBehavior)exhaustionIter.next());
+ }
+ poolFactory.setMaxIdle(((Integer)maxIdleIter.next()).intValue());
+ }
+ poolFactory.setMaxActive(((Integer)maxActiveIter.next()).intValue());
+ }
+ poolFactory.setLimitBehavior((LimitBehavior)limitIter.next());
+ }
+ poolFactory.setTrackerType((TrackingType)trackingIter.next());
+ }
+ poolFactory.setValidateOnReturn(((Boolean)validateIter.next()).booleanValue());
+
+ return newCombination;
+ }
+
+ private void runEveryComposite(final int seconds) {
+ do {
+ try {
+ final String combination = poolFactory.toString();
+ if (ranCombinations.add(combination)) { // skip dups
+ ((IntegerFactory)objectFactory).reset();
+ final ObjectPool pool = poolFactory.createPool();
+ System.out.print(combination);
+ System.out.print("\t");
+
+ testForNumSeconds(seconds, pool);
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ gc();
+ } while (nextCompositeSettings());
+ ranCombinations.clear();
+ }
+
+ private static void gc() {
+ System.gc();
+ System.gc();
+ System.gc();
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ // ignored
+ }
+ }
+
+ private static double testForNumSeconds(final int seconds, final ObjectPool pool) throws Exception {
+ // Prime for FAIL exhaust
+ try {
+ if (pool.getNumIdle() == 0) {
+ pool.addObject();
+ }
+ } catch (UnsupportedOperationException uoe) {
+ // ignore
+ }
+
+ long startTime = System.currentTimeMillis();
+ while (startTime == System.currentTimeMillis()) ;
+ startTime = System.currentTimeMillis();
+ final long endTime = startTime + (seconds * 1000);
+ long actualEndTime;
+ int loops = 0;
+ while (endTime >= (actualEndTime = System.currentTimeMillis())) {
+ Object obj = null;
+ try {
+ obj = pool.borrowObject();
+ pool.returnObject(obj);
+ } catch (Exception e) {
+ if (obj != null) {
+ pool.invalidateObject(obj);
+ }
+ }
+ loops++;
+ }
+ final double borrowsPerSecond = ((double)loops / ((double)(actualEndTime - startTime) / 1000D));
+ System.out.println(borrowsPerSecond + " borrows per second");
+ return borrowsPerSecond;
+ }
+
+
+ private void runEveryGeneric(final int seconds) {
+ ((IntegerFactory)objectFactory).reset();
+ ObjectPool pool = new GenericObjectPool(objectFactory, -1, GenericObjectPool.WHEN_EXHAUSTED_GROW, -1, -1, 0, true, false, -1, -1, -1, false);
+ try {
+ System.out.print("GenericObjectPool{maxActive=-1, maxIdle=-1}");
+ System.out.print("\t");
+ testForNumSeconds(seconds, pool);
+ gc();
+
+ pool = new GenericObjectPool(objectFactory, 10, GenericObjectPool.WHEN_EXHAUSTED_GROW, -1, -1, 0, true, false, -1, -1, -1, false);
+ System.out.print("GenericObjectPool{maxActive=10, maxIdle=-1}");
+ System.out.print("\t");
+ testForNumSeconds(seconds, pool);
+ gc();
+
+ pool = new GenericObjectPool(objectFactory, -1, GenericObjectPool.WHEN_EXHAUSTED_GROW, -1, 10, 0, true, false, -1, -1, -1, false);
+ System.out.print("GenericObjectPool{maxActive=-1, maxIdle=10}");
+ System.out.print("\t");
+ testForNumSeconds(seconds, pool);
+ gc();
+
+ pool = new GenericObjectPool(objectFactory, 10, GenericObjectPool.WHEN_EXHAUSTED_GROW, -1, 10, 0, true, false, -1, -1, -1, false);
+ System.out.print("GenericObjectPool{maxActive=10, maxIdle=10}");
+ System.out.print("\t");
+ testForNumSeconds(seconds, pool);
+ gc();
+ } catch (Exception e) {
+
+ }
+ }
+
+
+ private void compareCompositeGerneic(final int seconds) {
+ final CompareCompositeGeneric ccg = new CompareCompositeGeneric();
+ do {
+ gc();
+
+ ObjectPool objectPool;
+ gc();
+
+ try {
+ System.out.print("GOP:noTestOnBorrow\t" + ccg + "\t");
+ objectPool = ccg.getGeneric();
+ ((GenericObjectPool)objectPool).setTestOnBorrow(false);
+ testForNumSeconds(seconds, objectPool);
+ } catch (Exception e) {
+ System.out.println("exception thrown! " + e.getMessage());
+ }
+
+ double gopBPS = -1;
+ try {
+ System.out.print("GenericObjectPool\t" + ccg + "\t");
+ objectPool = ccg.getGeneric();
+ ((GenericObjectPool)objectPool).setTestOnBorrow(true);
+ gopBPS = testForNumSeconds(seconds, objectPool);
+ } catch (Exception e) {
+ System.out.println("exception thrown! " + e.getMessage());
+ }
+
+ gc();
+
+ double copBPS = -1;
+ try {
+ System.out.print("CompositeObjectPool\t" + ccg + "\t");
+ objectPool = ccg.getComposite();
+ copBPS = testForNumSeconds(seconds, objectPool);
+ } catch (Exception e) {
+ System.out.println("exception thrown! " + e.getMessage());
+ }
+
+ System.out.println("CompositeObjectPool/GenericObjectPool = " + (copBPS / gopBPS));
+
+ gc();
+ } while (ccg.nextSettings());
+ }
+
+ private double runThreadedTest(final ObjectPool pool, final int numThreads, final int seconds) {
+ final ThreadGroup threadGroup = new ThreadGroup("Testers");
+ final Thread[] threads = new Thread[numThreads];
+ final Borrower[] borrowers = new Borrower[threads.length];
+
+ long startTime = System.currentTimeMillis();
+ long actualEndTime;
+ synchronized (LOCK) {
+ for (int i=0; i < threads.length; i++) {
+ borrowers[i] = new Borrower(pool);
+ threads[i] = new Thread(threadGroup, borrowers[i]);
+ threads[i].start();
+ }
+ while (startTime == System.currentTimeMillis()) ;
+ startTime = System.currentTimeMillis();
+ }
+
+ try {
+ Thread.sleep(seconds * 1000);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ try {
+ pool.close();
+ } catch (Exception e) {
+ // ignored
+ }
+ actualEndTime = System.currentTimeMillis();
+
+ Thread.yield();
+ int loops = 0;
+ for (int i=0; i < threads.length; i++) {
+ if (threads[i].isAlive()) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ loops += borrowers[i].getLoops();
+ }
+ final double borrowsPerSecond = ((double)loops / ((double)(actualEndTime - startTime) / 1000D));
+ System.out.println(borrowsPerSecond + " borrows per second");
+ return borrowsPerSecond;
+ }
+
+ private void compareThreadedCompositeGerneic(final int numThreads, final int seconds) {
+ final CompareCompositeGeneric ccg = new CompareCompositeGeneric();
+ do {
+ gc();
+
+ ObjectPool objectPool;
+ gc();
+
+ try {
+ System.out.print("GOP:noTestOnBorrow\t" + ccg + "\t");
+ objectPool = ccg.getGeneric();
+ ((GenericObjectPool)objectPool).setTestOnBorrow(false);
+ runThreadedTest(objectPool, numThreads, seconds);
+ } catch (Exception e) {
+ System.out.println("exception thrown! " + e.getMessage());
+ }
+
+ double gopBPS = -1;
+ try {
+ System.out.print("GenericObjectPool\t" + ccg + "\t");
+ objectPool = ccg.getGeneric();
+ ((GenericObjectPool)objectPool).setTestOnBorrow(true);
+ gopBPS = runThreadedTest(objectPool, numThreads, seconds);
+ } catch (Exception e) {
+ System.out.println("exception thrown! " + e.getMessage());
+ }
+
+ gc();
+
+ double copBPS = -1;
+ try {
+ System.out.print("CompositeObjectPool\t" + ccg + "\t");
+ objectPool = ccg.getComposite();
+ copBPS = runThreadedTest(objectPool, numThreads, seconds);
+ } catch (Exception e) {
+ System.out.println("exception thrown! " + e.getMessage());
+ }
+
+ System.out.println("CompositeObjectPool/GenericObjectPool = " + (copBPS / gopBPS));
+
+ gc();
+ } while (ccg.nextSettings());
+ }
+
+
+
+ public static void main(final String[] args) throws Exception {
+ System.out.println("Testing Class: " + PerformanceTest.class.getName());
+ PerformanceTest test = new PerformanceTest();
+
+ if (true) {
+ System.out.println("Single Threaded Test");
+ System.out.println("Warm up run (15): " + new Date());
+ test.compareCompositeGerneic(15);
+ //test.runEveryGeneric(20);
+ //test.runEveryComposite(20);
+ System.out.println("Go go go (60): " + new Date());
+ test.compareCompositeGerneic(60);
+ //test.runEveryGeneric(60);
+ //test.runEveryComposite(60);
+ System.out.println("Done: " + new Date());
+ }
+
+ if (false) {
+ int numThreads = 5;
+ System.out.println("Threaded Test: " + numThreads);
+ System.out.println("Warm up run (15): " + new Date());
+ test.compareThreadedCompositeGerneic(numThreads, 15);
+ System.out.println("Go go go (60): " + new Date());
+ test.compareThreadedCompositeGerneic(numThreads, 60);
+ System.out.println("Done: " + new Date());
+ }
+
+ if (false) {
+ System.out.println("List performances");
+ CompositeObjectPool cop;
+ System.out.print("ArrayList:w:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new ArrayList(1), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 1; i++) cop.addObject();
+ testForNumSeconds(25, cop);
+ gc();
+
+ System.out.print("LinkedList:w:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new LinkedList(), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 1; i++) cop.addObject();
+ testForNumSeconds(25, cop);
+ gc();
+
+ System.out.print("ArrayList:1:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new ArrayList(1), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 1; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("LinkedList:1:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new LinkedList(), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 1; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("ArrayList:2:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new ArrayList(2), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 2; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("LinkedList:2:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new LinkedList(), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 2; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("ArrayList:3:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new ArrayList(3), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 3; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("LinkedList:3:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new LinkedList(), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 3; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("ArrayList:5:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new ArrayList(5), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 5; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("LinkedList:5:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new LinkedList(), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 5; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("ArrayList:10:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new ArrayList(10), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 10; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("LinkedList:10:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new LinkedList(), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 10; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("ArrayList:25:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new ArrayList(25), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 25; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("LinkedList:25:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new LinkedList(), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 25; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("ArrayList:50:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new ArrayList(50), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 50; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ System.out.print("LinkedList:50:\t");
+ cop = new CompositeObjectPool(new IntegerFactory(), new LinkedList(), new GrowManager(), new FifoLender(), new SimpleTracker(), false, null);
+ for (int i=0; i < 50; i++) cop.addObject();
+ testForNumSeconds(60, cop);
+ gc();
+
+ }
+
+ }
+
+ private static class CompareCompositeGeneric {
+ private static final List maxIdles = Arrays.asList(new Integer[] {new Integer(-1), new Integer(10)});
+ private static final List maxActives = Arrays.asList(new Integer[] {new Integer(-1), new Integer(10)});
+ private static final List validateOnReturns = Arrays.asList(new Boolean[] {Boolean.FALSE, Boolean.TRUE});
+
+ private Iterator maxIdleIter = maxIdles.iterator();
+ private Iterator maxActiveIter = maxActives.iterator();
+ private Iterator validateIter = validateOnReturns.iterator();
+
+ private IntegerFactory objectFactory = new IntegerFactory();
+ private CompositeObjectPoolFactory compositeFactory = new CompositeObjectPoolFactory(objectFactory);
+ private GenericObjectPool.Config genericConfig = new GenericObjectPool.Config();
+
+ private Integer maxIdle;
+ private Integer maxActive;
+ private Boolean validateOnReturn;
+
+ public CompareCompositeGeneric() {
+ maxIdle = (Integer)maxIdleIter.next();
+ maxActive = (Integer)maxActiveIter.next();
+ validateOnReturn = (Boolean)validateIter.next();
+
+ compositeFactory.setBorrowType(BorrowType.FIFO);
+ compositeFactory.setExhaustionBehavior(ExhaustionBehavior.GROW);
+ compositeFactory.setLimitBehavior(LimitBehavior.FAIL);
+ compositeFactory.setTrackerType(TrackingType.SIMPLE);
+
+ genericConfig.minIdle = 0;
+ genericConfig.testOnBorrow = true;
+ genericConfig.testOnReturn = false;
+ genericConfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+ }
+
+ public boolean nextSettings() {
+ boolean newCombination = true;
+ if (!validateIter.hasNext()) {
+ validateIter = validateOnReturns.iterator();
+
+ if (!maxActiveIter.hasNext()) {
+ maxActiveIter = maxActives.iterator();
+
+ if (!maxIdleIter.hasNext()) {
+ maxIdleIter = maxIdles.iterator();
+ newCombination = false;
+ }
+ maxIdle = (Integer)maxIdleIter.next();
+ }
+ maxActive = (Integer)maxActiveIter.next();
+ }
+ validateOnReturn = (Boolean)validateIter.next();
+
+ return newCombination;
+ }
+
+ public CompositeObjectPool getComposite() {
+ objectFactory.reset();
+ compositeFactory.setMaxActive(maxActive.intValue());
+ compositeFactory.setMaxIdle(maxIdle.intValue());
+ compositeFactory.setValidateOnReturn(validateOnReturn.booleanValue());
+ return (CompositeObjectPool)compositeFactory.createPool();
+ }
+
+ public GenericObjectPool getGeneric() {
+ objectFactory.reset();
+ genericConfig.maxActive = maxActive.intValue();
+ genericConfig.maxIdle = maxIdle.intValue();
+ genericConfig.testOnReturn = validateOnReturn.booleanValue();
+ return new GenericObjectPool(objectFactory, genericConfig);
+ }
+
+
+ public String toString() {
+ return '{' +
+ "maxIdle=" + maxIdle +
+ ", maxActive=" + maxActive +
+ ", validateOnReturn=" + validateOnReturn +
+ '}';
+ }
+ }
+ private static class IntegerFactory extends BasePoolableObjectFactory {
+ private int count = 0;
+ private boolean oddValid = true;
+ private boolean evenValid = true;
+
+ public Object makeObject() throws Exception {
+ return new Integer(count++);
+ }
+
+ public boolean validateObject(final Object obj) {
+ final Integer num = (Integer)obj;
+ if (num.intValue() % 2 == 0) {
+ return evenValid;
+ } else {
+ return oddValid;
+ }
+ }
+
+ public void setValid(final boolean valid) {
+ setEvenValid(valid);
+ setOddValid(valid);
+ }
+
+ public void setOddValid(final boolean oddValid) {
+ this.oddValid = oddValid;
+ }
+
+ public void setEvenValid(final boolean evenValid) {
+ this.evenValid = evenValid;
+ }
+
+ public void reset() {
+ count = 0;
+ oddValid = true;
+ evenValid = true;
+ }
+
+ public String toString() {
+ return "IntegerFactory{}";
+ }
+ }
+
+ private static class Borrower implements Runnable {
+ private final ObjectPool pool;
+ private int loops = 0;
+
+ public Borrower(final ObjectPool pool) {
+ this.pool = pool;
+ }
+
+ public void run() {
+ synchronized(LOCK) {
+ loops = 0;
+ }
+ while (true) {
+ try {
+ final Object obj = pool.borrowObject();
+ loops++;
+ pool.returnObject(obj);
+ } catch (IllegalStateException ise) {
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public int getLoops() {
+ return loops;
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org