Author: djencks Date: Mon Nov 1 09:34:13 2004 New Revision: 56257 Added: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/AbstractSinglePoolConnectionInterceptor.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/PoolIdleReleaserTimer.java Modified: geronimo/trunk/modules/assembly/src/plan/j2ee-deployer-plan.xml geronimo/trunk/modules/assembly/src/plan/j2ee-server-plan.xml geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/deployment/ConnectorModuleBuilder.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/AbstractConnectionManager.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/GenericConnectionManager.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/MultiPoolConnectionInterceptor.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/PoolingAttributes.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/SinglePoolConnectionInterceptor.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/SinglePoolMatchAllConnectionInterceptor.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/NoPool.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/PartitionedPool.java geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/SinglePool.java geronimo/trunk/modules/connector/src/schema/geronimo-connector_1_5.xsd geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/deployment/RAR_1_0ConfigBuilderTest.java geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/deployment/RAR_1_5ConfigBuilderTest.java geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/ConnectionManagerTestUtils.java geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/PoolDequeTest.java Log: GERONIMO-412. Implement minSize and idleTimeout for connection pools, and make maxSize, minSize, blockingTimeoutMilliseconds, and idleTimeoutMinutes read-write at runtime. Set default values from module builder configuration and make plan values optional. No significant testing yet.
Modified: geronimo/trunk/modules/assembly/src/plan/j2ee-deployer-plan.xml ============================================================================== --- geronimo/trunk/modules/assembly/src/plan/j2ee-deployer-plan.xml (original) +++ geronimo/trunk/modules/assembly/src/plan/j2ee-deployer-plan.xml Mon Nov 1 09:34:13 2004 @@ -109,7 +109,12 @@ <gbean name="geronimo.deployer:role=ClientEJBReferenceBuilder,config=org/apache/geronimo/J2EEDeployer" class="org.openejb.deployment.RemoteEJBReferenceBuilder"/> - <gbean name="geronimo.deployer:role=ModuleBuilder,type=Connector,config=org/apache/geronimo/J2EEDeployer" class="org.apache.geronimo.connector.deployment.ConnectorModuleBuilder"/> + <gbean name="geronimo.deployer:role=ModuleBuilder,type=Connector,config=org/apache/geronimo/J2EEDeployer" class="org.apache.geronimo.connector.deployment.ConnectorModuleBuilder"> + <attribute name="defaultMaxSize" type="int">10</attribute> + <attribute name="defaultMinSize" type="int">0</attribute> + <attribute name="defaultBlockingTimeoutMilliseconds" type="int">5000</attribute> + <attribute name="defaultIdleTimeoutMinutes" type="int">15</attribute> + </gbean> <gbean name="geronimo.deployer:role=ModuleBuilder,type=AppClient,config=org/apache/geronimo/J2EEDeployer" class="org.apache.geronimo.client.builder.AppClientModuleBuilder"> <attribute name="transactionContextManagerObjectName" type="javax.management.ObjectName">geronimo.client:type=TransactionContextManager</attribute> Modified: geronimo/trunk/modules/assembly/src/plan/j2ee-server-plan.xml ============================================================================== --- geronimo/trunk/modules/assembly/src/plan/j2ee-server-plan.xml (original) +++ geronimo/trunk/modules/assembly/src/plan/j2ee-server-plan.xml Mon Nov 1 09:34:13 2004 @@ -268,7 +268,12 @@ <gbean name="geronimo.deployer:role=ClientEJBReferenceBuilder,config=org/apache/geronimo/Server" class="org.openejb.deployment.RemoteEJBReferenceBuilder"/> - <gbean name="geronimo.deployer:role=ModuleBuilder,type=Connector,config=org/apache/geronimo/Server" class="org.apache.geronimo.connector.deployment.ConnectorModuleBuilder"/> + <gbean name="geronimo.deployer:role=ModuleBuilder,type=Connector,config=org/apache/geronimo/Server" class="org.apache.geronimo.connector.deployment.ConnectorModuleBuilder"> + <attribute name="defaultMaxSize" type="int">10</attribute> + <attribute name="defaultMinSize" type="int">0</attribute> + <attribute name="defaultBlockingTimeoutMilliseconds" type="int">5000</attribute> + <attribute name="defaultIdleTimeoutMinutes" type="int">15</attribute> + </gbean> <gbean name="geronimo.deployer:role=ModuleBuilder,type=AppClient,config=org/apache/geronimo/Server" class="org.apache.geronimo.client.builder.AppClientModuleBuilder"> <attribute name="transactionContextManagerObjectName" type="javax.management.ObjectName">geronimo.client:type=TransactionContextManager</attribute> Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/deployment/ConnectorModuleBuilder.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/deployment/ConnectorModuleBuilder.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/deployment/ConnectorModuleBuilder.java Mon Nov 1 09:34:13 2004 @@ -80,6 +80,8 @@ import org.apache.geronimo.xbeans.geronimo.GerDependencyType; import org.apache.geronimo.xbeans.geronimo.GerGbeanType; import org.apache.geronimo.xbeans.geronimo.GerResourceadapterType; +import org.apache.geronimo.xbeans.geronimo.GerSinglepoolType; +import org.apache.geronimo.xbeans.geronimo.GerPartitionedpoolType; import org.apache.geronimo.xbeans.j2ee.ActivationspecType; import org.apache.geronimo.xbeans.j2ee.AdminobjectType; import org.apache.geronimo.xbeans.j2ee.ConfigPropertyType; @@ -104,9 +106,17 @@ private static final String BASE_REALM_BRIDGE_NAME = "geronimo.security:service=RealmBridge,name="; private static final String BASE_PASSWORD_CREDENTIAL_LOGIN_MODULE_NAME = "geronimo.security:service=Realm,type=PasswordCredential,name="; + private final int defaultMaxSize; + private final int defaultMinSize; + private final int defaultBlockingTimeoutMilliseconds; + private final int defaultIdleTimeoutMinutes; private final Kernel kernel; - public ConnectorModuleBuilder(Kernel kernel) { + public ConnectorModuleBuilder(int defaultMaxSize, int defaultMinSize, int defaultBlockingTimeoutMilliseconds, int defaultIdleTimeoutMinutes, Kernel kernel) { + this.defaultMaxSize = defaultMaxSize; + this.defaultMinSize = defaultMinSize; + this.defaultBlockingTimeoutMilliseconds = defaultBlockingTimeoutMilliseconds; + this.defaultIdleTimeoutMinutes = defaultIdleTimeoutMinutes; this.kernel = kernel; } @@ -438,7 +448,7 @@ } - } + } // // admin objects (think message queuse and topics) // @@ -451,35 +461,35 @@ } // add configured admin objects for (int i = 0; i < geronimoConnector.getAdminobjectArray().length; i++) { - GerAdminobjectType gerAdminObject = geronimoConnector.getAdminobjectArray()[i]; + GerAdminobjectType gerAdminObject = geronimoConnector.getAdminobjectArray()[i]; + + String adminObjectInterface = gerAdminObject.getAdminobjectInterface().getStringValue(); + AdminobjectType adminObject = (AdminobjectType) adminObjectInterfaceMap.get(adminObjectInterface); + if (adminObject == null) { + throw new DeploymentException("No admin object declared for interface: " + adminObjectInterface); + } + + for (int j = 0; j < gerAdminObject.getAdminobjectInstanceArray().length; j++) { + GerAdminobjectInstanceType gerAdminObjectInstance = gerAdminObject.getAdminobjectInstanceArray()[j]; + + // create the adminObjectGBean + GBeanInfoBuilder adminObjectInfoFactory = new GBeanInfoBuilder("org.apache.geronimo.connector.AdminObjectWrapper", cl); + ConfigProperty[] configProperties = getConfigProperties(adminObject.getConfigPropertyArray(), gerAdminObjectInstance.getConfigPropertySettingArray()); + GBeanMBean adminObjectGBean = setUpDynamicGBean(adminObjectInfoFactory, configProperties, cl); - String adminObjectInterface = gerAdminObject.getAdminobjectInterface().getStringValue(); - AdminobjectType adminObject = (AdminobjectType) adminObjectInterfaceMap.get(adminObjectInterface); - if (adminObject == null) { - throw new DeploymentException("No admin object declared for interface: " + adminObjectInterface); - } - - for (int j = 0; j < gerAdminObject.getAdminobjectInstanceArray().length; j++) { - GerAdminobjectInstanceType gerAdminObjectInstance = gerAdminObject.getAdminobjectInstanceArray()[j]; - - // create the adminObjectGBean - GBeanInfoBuilder adminObjectInfoFactory = new GBeanInfoBuilder("org.apache.geronimo.connector.AdminObjectWrapper", cl); - ConfigProperty[] configProperties = getConfigProperties(adminObject.getConfigPropertyArray(), gerAdminObjectInstance.getConfigPropertySettingArray()); - GBeanMBean adminObjectGBean = setUpDynamicGBean(adminObjectInfoFactory, configProperties, cl); - - // set the standard properties - try { - adminObjectGBean.setAttribute("adminObjectInterface", cl.loadClass(adminObjectInterface)); - adminObjectGBean.setAttribute("adminObjectClass", cl.loadClass(adminObject.getAdminobjectClass().getStringValue())); - } catch (Exception e) { - throw new DeploymentException("Could not initialize AdminObject", e); - } - - // add it - ObjectName adminObjectObjectName = NameFactory.getResourceComponentName(null, null, null, null, gerAdminObjectInstance.getMessageDestinationName(), NameFactory.JCA_ADMIN_OBJECT, moduleJ2eeContext); - earContext.addGBean(adminObjectObjectName, adminObjectGBean); - } - } + // set the standard properties + try { + adminObjectGBean.setAttribute("adminObjectInterface", cl.loadClass(adminObjectInterface)); + adminObjectGBean.setAttribute("adminObjectClass", cl.loadClass(adminObject.getAdminobjectClass().getStringValue())); + } catch (Exception e) { + throw new DeploymentException("Could not initialize AdminObject", e); + } + + // add it + ObjectName adminObjectObjectName = NameFactory.getResourceComponentName(null, null, null, null, gerAdminObjectInstance.getMessageDestinationName(), NameFactory.JCA_ADMIN_OBJECT, moduleJ2eeContext); + earContext.addGBean(adminObjectObjectName, adminObjectGBean); + } + } } private Map getActivationSpecInfoMap(MessagelistenerType[] messagelistenerArray, ClassLoader cl) throws DeploymentException { @@ -512,9 +522,9 @@ } GBeanInfo gbeanInfo = infoFactory.getBeanInfo(); - Class activationSpecClass = null; try { - activationSpecClass = cl.loadClass(activationSpecClassName); + //make sure the class is available, but we don't use it. + cl.loadClass(activationSpecClassName); } catch (ClassNotFoundException e) { throw new DeploymentException("Could not load ActivationSpec class", e); } @@ -659,24 +669,29 @@ throw new DeploymentException("Unexpected transaction support element"); } PoolingSupport pooling = null; - //TODO configure this -// int idleTimeoutMinutes = 15; if (connectionManager.getSinglePool() != null) { - pooling = new SinglePool(connectionManager.getSinglePool().getMaxSize(), - connectionManager.getSinglePool().getBlockingTimeoutMilliseconds(), -// idleTimeoutMinutes, - connectionManager.getSinglePool().getMatchOne() != null, - connectionManager.getSinglePool().getMatchAll() != null, - connectionManager.getSinglePool().getSelectOneAssumeMatch() != null); + GerSinglepoolType pool = connectionManager.getSinglePool(); + + pooling = new SinglePool( + pool.isSetMaxSize() ? pool.getMaxSize() : defaultMaxSize, + pool.isSetMinSize() ? pool.getMinSize() : defaultMinSize, + pool.isSetBlockingTimeoutMilliseconds() ? pool.getBlockingTimeoutMilliseconds() : defaultBlockingTimeoutMilliseconds, + pool.isSetIdleTimeoutMinutes() ? pool.getIdleTimeoutMinutes() : defaultIdleTimeoutMinutes, + pool.getMatchOne() != null, + pool.getMatchAll() != null, + pool.getSelectOneAssumeMatch() != null); } else if (connectionManager.getPartitionedPool() != null) { - pooling = new PartitionedPool(connectionManager.getPartitionedPool().getPartitionByConnectionrequestinfo() != null, - connectionManager.getPartitionedPool().getPartitionBySubject() != null, - connectionManager.getPartitionedPool().getMaxSize(), - connectionManager.getPartitionedPool().getBlockingTimeoutMilliseconds(), -// idleTimeoutMinutes, - connectionManager.getPartitionedPool().getMatchOne() != null, - connectionManager.getPartitionedPool().getMatchAll() != null, - connectionManager.getPartitionedPool().getSelectOneAssumeMatch() != null); + GerPartitionedpoolType pool = connectionManager.getPartitionedPool(); + pooling = new PartitionedPool( + pool.isSetMaxSize() ? pool.getMaxSize() : defaultMaxSize, + pool.isSetMinSize() ? pool.getMinSize() : defaultMinSize, + pool.isSetBlockingTimeoutMilliseconds() ? pool.getBlockingTimeoutMilliseconds() : defaultBlockingTimeoutMilliseconds, + pool.isSetIdleTimeoutMinutes() ? pool.getIdleTimeoutMinutes() : defaultIdleTimeoutMinutes, + pool.getMatchOne() != null, + pool.getMatchAll() != null, + pool.getSelectOneAssumeMatch() != null, + pool.isSetPartitionByConnectionrequestinfo(), + pool.isSetPartitionBySubject()); } else if (connectionManager.getNoPool() != null) { pooling = new NoPool(); } else { @@ -836,12 +851,19 @@ public static final GBeanInfo GBEAN_INFO; static { - GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(ConnectorModuleBuilder.class); - infoFactory.addAttribute("kernel", Kernel.class, false); - infoFactory.addInterface(ModuleBuilder.class); - infoFactory.addInterface(ResourceReferenceBuilder.class); - infoFactory.setConstructor(new String[] {"kernel"}); - GBEAN_INFO = infoFactory.getBeanInfo(); + GBeanInfoBuilder infoBuilder = new GBeanInfoBuilder(ConnectorModuleBuilder.class); + infoBuilder.addAttribute("defaultMaxSize", int.class, true); + infoBuilder.addAttribute("defaultMinSize", int.class, true); + infoBuilder.addAttribute("defaultBlockingTimeoutMilliseconds", int.class, true); + infoBuilder.addAttribute("defaultIdleTimeoutMinutes", int.class, true); + + infoBuilder.addAttribute("kernel", Kernel.class, false); + + infoBuilder.addInterface(ModuleBuilder.class); + infoBuilder.addInterface(ResourceReferenceBuilder.class); + + infoBuilder.setConstructor(new String[]{"defaultMaxSize", "defaultMinSize", "defaultBlockingTimeoutMilliseconds", "defaultIdleTimeoutMinutes", "kernel"}); + GBEAN_INFO = infoBuilder.getBeanInfo(); } public static GBeanInfo getGBeanInfo() { Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/AbstractConnectionManager.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/AbstractConnectionManager.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/AbstractConnectionManager.java Mon Nov 1 09:34:13 2004 @@ -26,6 +26,7 @@ import org.apache.geronimo.gbean.GBeanInfo; import org.apache.geronimo.gbean.GBeanInfoBuilder; import org.apache.geronimo.transaction.manager.NamedXAResource; +import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PoolingSupport; /** * @version $Rev$ $Date$ @@ -98,6 +99,18 @@ return getPooling().getPartitionMaxSize(); } + public void setPartitionMaxSize(int maxSize) throws InterruptedException { + getPooling().setPartitionMaxSize(maxSize); + } + + public int getPartitionMinSize() { + return getPooling().getPartitionMinSize(); + } + + public void setPartitionMinSize(int minSize) { + getPooling().setPartitionMinSize(minSize); + } + public int getIdleConnectionCount() { return getPooling().getIdleConnectionCount(); } @@ -106,6 +119,21 @@ return getPooling().getConnectionCount(); } + public int getBlockingTimeoutMilliseconds() { + return getPooling().getBlockingTimeoutMilliseconds(); + } + + public void setBlockingTimeoutMilliseconds(int timeoutMilliseconds) { + getPooling().setBlockingTimeoutMilliseconds(timeoutMilliseconds); + } + + public int getIdleTimeoutMinutes() { + return getPooling().getIdleTimeoutMinutes(); + } + + public void setIdleTimeoutMinutes(int idleTimeoutMinutes) { + getPooling().setIdleTimeoutMinutes(idleTimeoutMinutes); + } private ConnectionInterceptor getStack() { return interceptors.getStack(); @@ -115,26 +143,30 @@ return interceptors.getRecoveryStack(); } - private PoolingAttributes getPooling() { + //public for persistence of pooling attributes (max, min size, blocking/idle timeouts) + public PoolingSupport getPooling() { return interceptors.getPoolingAttributes(); } public interface Interceptors { ConnectionInterceptor getStack(); + ConnectionInterceptor getRecoveryStack(); - PoolingAttributes getPoolingAttributes(); + + PoolingSupport getPoolingAttributes(); } protected static final GBeanInfo GBEAN_INFO; static { - GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(AbstractConnectionManager.class); + GBeanInfoBuilder infoBuilder = new GBeanInfoBuilder(AbstractConnectionManager.class); - infoFactory.addInterface(ConnectionManagerFactory.class); - infoFactory.addInterface(PoolingAttributes.class); + infoBuilder.addInterface(ConnectionManagerFactory.class); + //these attributes are persisted via the pooling state. + infoBuilder.addInterface(PoolingAttributes.class); - GBEAN_INFO = infoFactory.getBeanInfo(); + GBEAN_INFO = infoBuilder.getBeanInfo(); } } Added: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/AbstractSinglePoolConnectionInterceptor.java ============================================================================== --- (empty file) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/AbstractSinglePoolConnectionInterceptor.java Mon Nov 1 09:34:13 2004 @@ -0,0 +1,281 @@ +/** + * + * Copyright 2003-2004 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.apache.geronimo.connector.outbound; + +import java.util.TimerTask; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Timer; +import javax.resource.spi.ManagedConnectionFactory; +import javax.resource.spi.ConnectionRequestInfo; +import javax.resource.ResourceException; +import javax.security.auth.Subject; + +import EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore; +import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock; +import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @version $Rev: $ $Date: $ + */ +public abstract class AbstractSinglePoolConnectionInterceptor implements ConnectionInterceptor, PoolingAttributes { + protected static Log log = LogFactory.getLog(SinglePoolConnectionInterceptor.class.getName()); + protected final ConnectionInterceptor next; + private final ReadWriteLock resizeLock = new WriterPreferenceReadWriteLock(); + protected FIFOSemaphore permits; + protected int blockingTimeoutMilliseconds; + protected int connectionCount = 0; + private long idleTimeoutMilliseconds; + private IdleReleaser idleReleaser; + protected Timer timer = PoolIdleReleaserTimer.getTimer(); + protected int minSize = 0; + protected int shrinkLater = 0; + + public AbstractSinglePoolConnectionInterceptor(final ConnectionInterceptor next, + int maxSize, + int minSize, + int blockingTimeoutMilliseconds, + int idleTimeoutMinutes) { + this.next = next; + this.minSize = minSize; + this.blockingTimeoutMilliseconds = blockingTimeoutMilliseconds; + setIdleTimeoutMinutes(idleTimeoutMinutes); + permits = new FIFOSemaphore(maxSize); + } + + public void getConnection(ConnectionInfo connectionInfo) throws ResourceException { + if (connectionInfo.getManagedConnectionInfo().getManagedConnection() != null) { + return; + } + try { + resizeLock.readLock().acquire(); + try { + if (permits.attempt(blockingTimeoutMilliseconds)) { + internalGetConnection(connectionInfo); + } else { + throw new ResourceException("No ManagedConnections available " + + "within configured blocking timeout ( " + + blockingTimeoutMilliseconds + + " [ms] )"); + + } + } finally { + resizeLock.readLock().release(); + } + + } catch (InterruptedException ie) { + throw new ResourceException("Interrupted while requesting permit!"); + } // end of try-catch + } + + protected abstract void internalGetConnection(ConnectionInfo connectionInfo) throws ResourceException; + + public void returnConnection(ConnectionInfo connectionInfo, + ConnectionReturnAction connectionReturnAction) { + if (log.isTraceEnabled()) { + log.trace("returning connection" + connectionInfo.getConnectionHandle()); + } + try { + resizeLock.readLock().acquire(); + } catch (InterruptedException e) { + //TODO figure out something better to do here!!! + throw new RuntimeException("Interrupted before returning connection! Pool is now in an invalid state!"); + } + try { + ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); + if (connectionReturnAction == ConnectionReturnAction.RETURN_HANDLE && mci.hasConnectionHandles()) { + return; + } + + boolean wasInPool = internalReturn(connectionInfo, connectionReturnAction); + + if (!wasInPool) { + permits.release(); + } + } finally { + resizeLock.readLock().release(); + } + } + + protected abstract boolean internalReturn(ConnectionInfo connectionInfo, ConnectionReturnAction connectionReturnAction); + + public int getPartitionCount() { + return 1; + } + + public abstract int getPartitionMaxSize(); + + public void setPartitionMaxSize(int maxSize) throws InterruptedException { + if (maxSize <= 0) { + throw new IllegalArgumentException("Max size must be positive, not " + maxSize); + } + if (maxSize != getPartitionMaxSize()) { + resizeLock.writeLock().acquire(); + try { + //example: old maxsize 40, permits 20, connection count 20 + //new maxSize 10 + //shrinkLater is 10 + //shrinkNow is 20 + //2nd example: old maxsize 30, permits 10, connection count 10 + //new maxSize 40 + //shrinkLater and shrinkNow are 0. + int checkedOut = (int) permits.permits(); + shrinkLater = checkedOut - maxSize; + if (shrinkLater < 0) { + shrinkLater = 0; + } + int shrinkNow = checkedOut + connectionCount - maxSize - shrinkLater; + if (shrinkNow < 0) { + shrinkNow = 0; + } + + permits = new FIFOSemaphore(maxSize); + //1st example: acquire 10 (all) + //2nd example: acquire 10 (same as in old semaphore) + for (int i = 0; i < checkedOut - shrinkLater; i++) { + permits.acquire(); + } + //1st example: copy 0 (none) + //2nd example: copy 10 (all) + transferConnections(maxSize, shrinkNow); + } finally { + resizeLock.writeLock().release(); + } + } + } + + protected abstract void transferConnections(int maxSize, int shrinkNow); + + public abstract int getIdleConnectionCount(); + + public int getConnectionCount() { + return connectionCount; + } + + public int getPartitionMinSize() { + return minSize; + } + + public void setPartitionMinSize(int minSize) { + this.minSize = minSize; + } + + public int getBlockingTimeoutMilliseconds() { + return blockingTimeoutMilliseconds; + } + + public void setBlockingTimeoutMilliseconds(int blockingTimeoutMilliseconds) { + if (blockingTimeoutMilliseconds < 0) { + throw new IllegalArgumentException("blockingTimeoutMilliseconds must be positive or 0, not " + blockingTimeoutMilliseconds); + } + if (blockingTimeoutMilliseconds == 0) { + this.blockingTimeoutMilliseconds = Integer.MAX_VALUE; + } else { + this.blockingTimeoutMilliseconds = blockingTimeoutMilliseconds; + } + } + + public int getIdleTimeoutMinutes() { + return (int) idleTimeoutMilliseconds / (1000 * 60); + } + + public void setIdleTimeoutMinutes(int idleTimeoutMinutes) { + if (idleTimeoutMinutes < 0) { + throw new IllegalArgumentException("idleTimeoutMinutes must be positive or 0, not " + idleTimeoutMinutes); + } + if (idleReleaser != null) { + idleReleaser.cancel(); + } + if (idleTimeoutMinutes > 0) { + this.idleTimeoutMilliseconds = idleTimeoutMinutes * 60 * 1000; + idleReleaser = new IdleReleaser(); + timer.schedule(idleReleaser, this.idleTimeoutMilliseconds, this.idleTimeoutMilliseconds); + } + } + + protected abstract void getExpiredManagedConnectionInfos(long threshold, ArrayList killList); + + protected abstract boolean addToPool(ManagedConnectionInfo mci); + + private class IdleReleaser extends TimerTask { + + public void run() { + try { + resizeLock.readLock().acquire(); + } catch (InterruptedException e) { + return; + } + try { + long threshold = System.currentTimeMillis() - idleTimeoutMilliseconds; + ArrayList killList = new ArrayList(getPartitionMaxSize()); + getExpiredManagedConnectionInfos(threshold, killList); + for (Iterator i = killList.iterator(); i.hasNext();) { + ManagedConnectionInfo managedConnectionInfo = (ManagedConnectionInfo) i.next(); + ConnectionInfo killInfo = new ConnectionInfo(managedConnectionInfo); + internalReturn(killInfo, ConnectionReturnAction.DESTROY); + } + permits.release(killList.size()); + } finally { + resizeLock.readLock().release(); + } + } + + } + + protected class FillTask extends TimerTask { + private final ManagedConnectionFactory managedConnectionFactory; + private final Subject subject; + private final ConnectionRequestInfo cri; + + public FillTask(ConnectionInfo connectionInfo) { + managedConnectionFactory = connectionInfo.getManagedConnectionInfo().getManagedConnectionFactory(); + subject = connectionInfo.getManagedConnectionInfo().getSubject(); + cri = connectionInfo.getManagedConnectionInfo().getConnectionRequestInfo(); + } + + public void run() { + try { + resizeLock.readLock().acquire(); + } catch (InterruptedException e) { + return; + } + try { + while (connectionCount < minSize) { + ManagedConnectionInfo mci = new ManagedConnectionInfo(managedConnectionFactory, cri); + mci.setSubject(subject); + ConnectionInfo ci = new ConnectionInfo(mci); + try { + next.getConnection(ci); + } catch (ResourceException e) { + return; + } + boolean added = false; + added = addToPool(mci); + if (!added) { + internalReturn(ci, ConnectionReturnAction.DESTROY); + return; + } + } + } finally { + resizeLock.readLock().release(); + } + } + + } +} Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/GenericConnectionManager.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/GenericConnectionManager.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/GenericConnectionManager.java Mon Nov 1 09:34:13 2004 @@ -52,7 +52,7 @@ private final ConnectionInterceptor stack; private final ConnectionInterceptor recoveryStack; - private final PoolingAttributes poolingSupport; + private final PoolingSupport poolingSupport; /** * Order of constructed interceptors: @@ -110,7 +110,7 @@ return recoveryStack; } - public PoolingAttributes getPoolingAttributes() { + public PoolingSupport getPoolingAttributes() { return poolingSupport; } } @@ -119,19 +119,19 @@ public static final GBeanInfo GBEAN_INFO; static { - GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(GenericConnectionManager.class, AbstractConnectionManager.GBEAN_INFO); + GBeanInfoBuilder infoBuilder = new GBeanInfoBuilder(GenericConnectionManager.class, AbstractConnectionManager.GBEAN_INFO); - infoFactory.addAttribute("name", String.class, true); - infoFactory.addAttribute("transactionSupport", TransactionSupport.class, true); - infoFactory.addAttribute("pooling", PoolingSupport.class, true); + infoBuilder.addAttribute("name", String.class, true); + infoBuilder.addAttribute("transactionSupport", TransactionSupport.class, true); + infoBuilder.addAttribute("pooling", PoolingSupport.class, true); - infoFactory.addAttribute("objectName", String.class, false); + infoBuilder.addAttribute("objectName", String.class, false); - infoFactory.addReference("ConnectionTracker", ConnectionTracker.class); - infoFactory.addReference("RealmBridge", RealmBridge.class); - infoFactory.addReference("TransactionContextManager", TransactionContextManager.class); + infoBuilder.addReference("ConnectionTracker", ConnectionTracker.class); + infoBuilder.addReference("RealmBridge", RealmBridge.class); + infoBuilder.addReference("TransactionContextManager", TransactionContextManager.class); - infoFactory.setConstructor(new String[]{ + infoBuilder.setConstructor(new String[]{ "transactionSupport", "pooling", "objectName", @@ -139,7 +139,7 @@ "ConnectionTracker", "TransactionContextManager"}); - GBEAN_INFO = infoFactory.getBeanInfo(); + GBEAN_INFO = infoBuilder.getBeanInfo(); } public static GBeanInfo getGBeanInfo() { Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/MultiPoolConnectionInterceptor.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/MultiPoolConnectionInterceptor.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/MultiPoolConnectionInterceptor.java Mon Nov 1 09:34:13 2004 @@ -94,6 +94,26 @@ return singlePoolFactory.getPartitionMaxSize(); } + public void setPartitionMaxSize(int maxSize) throws InterruptedException { + singlePoolFactory.setPartitionMaxSize(maxSize); + for (Iterator iterator = pools.entrySet().iterator(); iterator.hasNext();) { + PoolingAttributes poolingAttributes = (PoolingAttributes) ((Map.Entry) iterator.next()).getValue(); + poolingAttributes.setPartitionMaxSize(maxSize); + } + } + + public int getPartitionMinSize() { + return singlePoolFactory.getPartitionMinSize(); + } + + public void setPartitionMinSize(int minSize) { + singlePoolFactory.setPartitionMinSize(minSize); + for (Iterator iterator = pools.entrySet().iterator(); iterator.hasNext();) { + PoolingAttributes poolingAttributes = (PoolingAttributes) ((Map.Entry) iterator.next()).getValue(); + poolingAttributes.setPartitionMinSize(minSize); + } + } + public int getIdleConnectionCount() { int count = 0; for (Iterator iterator = pools.entrySet().iterator(); iterator.hasNext();) { @@ -110,6 +130,30 @@ count += poolingAttributes.getConnectionCount(); } return count; + } + + public int getBlockingTimeoutMilliseconds() { + return singlePoolFactory.getBlockingTimeoutMilliseconds(); + } + + public void setBlockingTimeoutMilliseconds(int timeoutMilliseconds) { + singlePoolFactory.setBlockingTimeoutMilliseconds(timeoutMilliseconds); + for (Iterator iterator = pools.entrySet().iterator(); iterator.hasNext();) { + PoolingAttributes poolingAttributes = (PoolingAttributes) ((Map.Entry) iterator.next()).getValue(); + poolingAttributes.setBlockingTimeoutMilliseconds(timeoutMilliseconds); + } + } + + public int getIdleTimeoutMinutes() { + return singlePoolFactory.getIdleTimeoutMinutes(); + } + + public void setIdleTimeoutMinutes(int idleTimeoutMinutes) { + singlePoolFactory.setIdleTimeoutMinutes(idleTimeoutMinutes); + for (Iterator iterator = pools.entrySet().iterator(); iterator.hasNext();) { + PoolingAttributes poolingAttributes = (PoolingAttributes) ((Map.Entry) iterator.next()).getValue(); + poolingAttributes.setIdleTimeoutMinutes(idleTimeoutMinutes); + } } static class SubjectCRIKey { Added: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/PoolIdleReleaserTimer.java ============================================================================== --- (empty file) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/PoolIdleReleaserTimer.java Mon Nov 1 09:34:13 2004 @@ -0,0 +1,31 @@ +/** + * + * Copyright 2003-2004 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.apache.geronimo.connector.outbound; + +import java.util.Timer; + +/** + * @version $Rev: $ $Date: $ + */ +public class PoolIdleReleaserTimer { + + private static final Timer timer = new Timer(true); + + public static Timer getTimer() { + return timer; + } +} Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/PoolingAttributes.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/PoolingAttributes.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/PoolingAttributes.java Mon Nov 1 09:34:13 2004 @@ -23,9 +23,23 @@ public interface PoolingAttributes { int getPartitionCount(); - int getPartitionMaxSize(); + int getConnectionCount(); int getIdleConnectionCount(); - int getConnectionCount(); + int getPartitionMaxSize(); + + void setPartitionMaxSize(int maxSize) throws InterruptedException; + + int getPartitionMinSize(); + + void setPartitionMinSize(int minSize); + + int getBlockingTimeoutMilliseconds(); + + void setBlockingTimeoutMilliseconds(int timeoutMilliseconds); + + int getIdleTimeoutMinutes(); + + void setIdleTimeoutMinutes(int idleTimeoutMinutes); } Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/SinglePoolConnectionInterceptor.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/SinglePoolConnectionInterceptor.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/SinglePoolConnectionInterceptor.java Mon Nov 1 09:34:13 2004 @@ -17,15 +17,11 @@ package org.apache.geronimo.connector.outbound; +import java.util.ArrayList; import java.util.Collections; - import javax.resource.ResourceException; import javax.resource.spi.ManagedConnection; -import EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** * SinglePoolConnectionInterceptor chooses a single connection from the pool. If selectOneAssumeMatch * is true, it simply returns the selected connection. @@ -36,184 +32,175 @@ * selected connection does match before returning it: if not it throws an exception. * * @version $Rev$ $Date$ - * */ -public class SinglePoolConnectionInterceptor implements ConnectionInterceptor, PoolingAttributes { - - private static Log log = LogFactory.getLog(SinglePoolConnectionInterceptor.class.getName()); +public class SinglePoolConnectionInterceptor extends AbstractSinglePoolConnectionInterceptor { - private final ConnectionInterceptor next; - - private FIFOSemaphore permits; + private boolean selectOneAssumeMatch; private PoolDeque pool; - private int blockingTimeout; - private boolean selectOneAssumeMatch; - private int connectionCount = 0; - - public SinglePoolConnectionInterceptor( - final ConnectionInterceptor next, - int maxSize, - int blockingTimeout, - boolean selectOneAssumeMatch) { - this.next = next; - this.blockingTimeout = blockingTimeout; - permits = new FIFOSemaphore(maxSize); + public SinglePoolConnectionInterceptor(final ConnectionInterceptor next, + int maxSize, + int minSize, + int blockingTimeoutMilliseconds, + int idleTimeoutMinutes, + boolean selectOneAssumeMatch) { + super(next, maxSize, minSize, blockingTimeoutMilliseconds, idleTimeoutMinutes); pool = new PoolDeque(maxSize); this.selectOneAssumeMatch = selectOneAssumeMatch; } - public void getConnection(ConnectionInfo connectionInfo) throws ResourceException { - ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); - if (mci.getManagedConnection() != null) { - return; - } - try { - if (permits.attempt(blockingTimeout)) { - ManagedConnectionInfo newMCI = null; - synchronized (pool) { - if (pool.isEmpty()) { - next.getConnection(connectionInfo); - connectionCount++; - if (log.isTraceEnabled()) { - log.trace("Returning new connection " + connectionInfo.getManagedConnectionInfo()); - } - return; - } else { - newMCI = pool.removeLast(); - } - if (selectOneAssumeMatch) { - connectionInfo.setManagedConnectionInfo(newMCI); - if (log.isTraceEnabled()) { - log.trace("Returning pooled connection without checking matching " + connectionInfo.getManagedConnectionInfo()); - } - return; - } - try { - ManagedConnection matchedMC = -// newMCI.getManagedConnection(); - newMCI - .getManagedConnectionFactory() - .matchManagedConnections( - Collections.singleton( - newMCI.getManagedConnection()), - mci.getSubject(), - mci.getConnectionRequestInfo()); - if (matchedMC != null) { - connectionInfo.setManagedConnectionInfo(newMCI); - if (log.isTraceEnabled()) { - log.trace("Returning pooled connection " + connectionInfo.getManagedConnectionInfo()); - } - return; - } else { - //matching failed. - ConnectionInfo returnCI = new ConnectionInfo(); - returnCI.setManagedConnectionInfo(newMCI); - returnConnection( - returnCI, - ConnectionReturnAction.RETURN_HANDLE); - throw new ResourceException("The pooling strategy does not match the MatchManagedConnections implementation. Please investigate and reconfigure this pool"); - } - } catch (ResourceException e) { - //something is wrong: destroy connection, rethrow, release permit - ConnectionInfo returnCI = new ConnectionInfo(); - returnCI.setManagedConnectionInfo(newMCI); - returnConnection( - returnCI, - ConnectionReturnAction.DESTROY); - throw e; - } // end of try-catch + protected void internalGetConnection(ConnectionInfo connectionInfo) throws ResourceException { + synchronized (pool) { + ManagedConnectionInfo newMCI = null; + if (pool.isEmpty()) { + next.getConnection(connectionInfo); + connectionCount++; + if (log.isTraceEnabled()) { + log.trace("Returning new connection " + connectionInfo.getManagedConnectionInfo()); } + return; } else { - throw new ResourceException( - "No ManagedConnections available " - + "within configured blocking timeout ( " - + blockingTimeout - + " [ms] )"); - - } // end of else - - } catch (InterruptedException ie) { - throw new ResourceException("Interrupted while requesting permit!"); - } // end of try-catch - } - - public void returnConnection( - ConnectionInfo connectionInfo, - ConnectionReturnAction connectionReturnAction) { - if (log.isTraceEnabled()) { - log.trace("returning connection" + connectionInfo.getConnectionHandle()); - } - boolean wasInPool = false; - ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); - if (connectionReturnAction == ConnectionReturnAction.DESTROY) { - synchronized (pool) { - wasInPool = pool.remove(mci); + newMCI = pool.removeLast(); + } + if (connectionCount < minSize) { + timer.schedule(new FillTask(connectionInfo), 10); } - } else { - if (mci.hasConnectionHandles()) { + if (selectOneAssumeMatch) { + connectionInfo.setManagedConnectionInfo(newMCI); + if (log.isTraceEnabled()) { + log.trace("Returning pooled connection without checking matching " + connectionInfo.getManagedConnectionInfo()); + } return; } - } // end of else + try { + ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); + ManagedConnection matchedMC = + newMCI + .getManagedConnectionFactory() + .matchManagedConnections(Collections.singleton(newMCI.getManagedConnection()), + mci.getSubject(), + mci.getConnectionRequestInfo()); + if (matchedMC != null) { + connectionInfo.setManagedConnectionInfo(newMCI); + if (log.isTraceEnabled()) { + log.trace("Returning pooled connection " + connectionInfo.getManagedConnectionInfo()); + } + return; + } else { + //matching failed. + ConnectionInfo returnCI = new ConnectionInfo(); + returnCI.setManagedConnectionInfo(newMCI); + returnConnection(returnCI, + ConnectionReturnAction.RETURN_HANDLE); + throw new ResourceException("The pooling strategy does not match the MatchManagedConnections implementation. Please investigate and reconfigure this pool"); + } + } catch (ResourceException e) { + //something is wrong: destroy connection, rethrow, release permit + ConnectionInfo returnCI = new ConnectionInfo(); + returnCI.setManagedConnectionInfo(newMCI); + returnConnection(returnCI, + ConnectionReturnAction.DESTROY); + throw e; + } + } + } + protected boolean internalReturn(ConnectionInfo connectionInfo, ConnectionReturnAction connectionReturnAction) { + ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); ManagedConnection mc = mci.getManagedConnection(); try { mc.cleanup(); } catch (ResourceException e) { connectionReturnAction = ConnectionReturnAction.DESTROY; } - - if (connectionReturnAction == ConnectionReturnAction.DESTROY) { - next.returnConnection(connectionInfo, connectionReturnAction); - connectionCount--; - } else { - synchronized (pool) { + boolean wasInPool = false; + synchronized (pool) { + if (shrinkLater > 0) { + //nothing can get in the pool while shrinkLater > 0, so wasInPool is false here. + connectionReturnAction = ConnectionReturnAction.DESTROY; + shrinkLater--; + } else if (connectionReturnAction == ConnectionReturnAction.RETURN_HANDLE) { mci.setLastUsed(System.currentTimeMillis()); - pool.addLast(mci); + pool.add(mci); + return wasInPool; + } else { + wasInPool = pool.remove(mci); } - - } // end of else - - if (!wasInPool) { - permits.release(); } - } - - public int getPartitionCount() { - return 1; + //we must destroy connection. + next.returnConnection(connectionInfo, connectionReturnAction); + connectionCount--; + return wasInPool; } public int getPartitionMaxSize() { return pool.capacity(); } + protected void transferConnections(int maxSize, int shrinkNow) { + //1st example: copy 0 (none) + //2nd example: copy 10 (all) + PoolDeque oldPool = pool; + pool = new PoolDeque(maxSize); + //since we have replaced pool already, pool.remove will be very fast:-) + for (int i = 0; i < shrinkNow; i++) { + ConnectionInfo killInfo = new ConnectionInfo(oldPool.peek(i)); + internalReturn(killInfo, ConnectionReturnAction.DESTROY); + } + for (int i = shrinkNow; i < connectionCount; i++) { + pool.add(oldPool.peek(i)); + } + } + public int getIdleConnectionCount() { return pool.currentSize(); } - public int getConnectionCount() { - return connectionCount; + + protected void getExpiredManagedConnectionInfos(long threshold, ArrayList killList) { + synchronized (pool) { + for (int i = 0; i < pool.currentSize(); i++) { + ManagedConnectionInfo mci = pool.peek(i); + if (mci.getLastUsed() < threshold) { + killList.add(mci); + } + } + } } + protected boolean addToPool(ManagedConnectionInfo mci) { + boolean added; + synchronized (pool) { + connectionCount++; + added = getPartitionMaxSize() > getIdleConnectionCount(); + if (added) { + pool.add(mci); + } + } + return added; + } + + static class PoolDeque { private final ManagedConnectionInfo[] deque; - private int first = 0; + private final int first = 0; private int last = -1; public PoolDeque(int size) { deque = new ManagedConnectionInfo[size]; } + //internal public boolean isEmpty() { return first > last; } - - public void addLast(ManagedConnectionInfo mci) { + //internal + public void add(ManagedConnectionInfo mci) { if (last == deque.length - 1) { throw new IllegalStateException("deque is full"); } @@ -221,14 +208,15 @@ deque[++last] = mci; } - public ManagedConnectionInfo peekLast() { - if (isEmpty()) { - throw new IllegalStateException("deque is empty"); + //internal + public ManagedConnectionInfo peek(int i) { + if (i < first || i > last) { + throw new IllegalStateException("index is out of current range"); } - - return deque[last]; + return deque[i]; } + //internal public ManagedConnectionInfo removeLast() { if (isEmpty()) { throw new IllegalStateException("deque is empty"); @@ -237,6 +225,7 @@ return deque[last--]; } + //internal public boolean remove(ManagedConnectionInfo mci) { for (int i = first; i <= last; i++) { if (deque[i] == mci) { @@ -251,13 +240,15 @@ return false; } + //internal public int capacity() { return deque.length; } + //internal public int currentSize() { return last - first + 1; } } -} // SinglePoolConnectionInterceptor +} Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/SinglePoolMatchAllConnectionInterceptor.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/SinglePoolMatchAllConnectionInterceptor.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/SinglePoolMatchAllConnectionInterceptor.java Mon Nov 1 09:34:13 2004 @@ -17,18 +17,14 @@ package org.apache.geronimo.connector.outbound; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; - import javax.resource.ResourceException; import javax.resource.spi.ManagedConnection; import javax.resource.spi.ManagedConnectionFactory; -import EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** * This pool is the most spec-compliant pool. It can be used by itself with no partitioning. * It is apt to be the slowest pool. @@ -38,112 +34,136 @@ * * @version $Rev$ $Date$ */ -public class SinglePoolMatchAllConnectionInterceptor implements ConnectionInterceptor, PoolingAttributes { +public class SinglePoolMatchAllConnectionInterceptor extends AbstractSinglePoolConnectionInterceptor { +// implements ConnectionInterceptor, PoolingAttributes { + +// private static Log log = LogFactory.getLog(SinglePoolMatchAllConnectionInterceptor.class.getName()); - private static Log log = LogFactory.getLog(SinglePoolMatchAllConnectionInterceptor.class.getName()); +// private final ConnectionInterceptor next; - private final ConnectionInterceptor next; +// private Timer timer = PoolIdleReleaserTimer.getTimer(); - private FIFOSemaphore permits; +// private FIFOSemaphore permits; private HashMap pool; private int maxSize; - private int blockingTimeout; - private int actualConnections = 0; +// private int blockingTimeoutMilliseconds; + +// private long idleTimeoutMilliseconds; + +// private int connectionCount = 0; + +// private int minSize = 0; - public SinglePoolMatchAllConnectionInterceptor( - final ConnectionInterceptor next, - int maxSize, - int blockingTimeout) { - this.next = next; +// private IdleReleaser idleReleaser; +// private int shrinkLater = 0; + + public SinglePoolMatchAllConnectionInterceptor(final ConnectionInterceptor next, + int maxSize, + int minSize, + int blockingTimeoutMilliseconds, + int idleTimeoutMinutes) { + + super(next, maxSize, minSize, blockingTimeoutMilliseconds, idleTimeoutMinutes); +// this.next = next; this.maxSize = maxSize; - this.blockingTimeout = blockingTimeout; - permits = new FIFOSemaphore(maxSize); +// this.blockingTimeoutMilliseconds = blockingTimeoutMilliseconds; +// permits = new FIFOSemaphore(maxSize); pool = new HashMap(maxSize); +// setIdleTimeoutMinutes(idleTimeoutMinutes); } - public void getConnection(ConnectionInfo connectionInfo) throws ResourceException { - ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); - if (mci.getManagedConnection() != null) { - return; - } - ManagedConnectionFactory managedConnectionFactory = mci.getManagedConnectionFactory(); - try { - if (permits.attempt(blockingTimeout)) { - synchronized (pool) { - try { - if (!pool.isEmpty()) { - ManagedConnection matchedMC = - managedConnectionFactory - .matchManagedConnections( - pool.keySet(), - mci.getSubject(), - mci.getConnectionRequestInfo()); - if (matchedMC != null) { - connectionInfo.setManagedConnectionInfo((ManagedConnectionInfo) pool.get(matchedMC)); - pool.remove(matchedMC); - if (log.isTraceEnabled()) { - log.trace("Returning pooled connection " + connectionInfo.getManagedConnectionInfo()); - } - return; - } - //matching failed or pool is empty - //if pool is at maximum size, pick a cx to kill - if (actualConnections == maxSize) { - Iterator iterator = pool.entrySet().iterator(); - ManagedConnectionInfo kill = (ManagedConnectionInfo) ((Map.Entry) iterator.next()).getValue(); - iterator.remove(); - ConnectionInfo killInfo = new ConnectionInfo(kill); - returnConnection(killInfo, ConnectionReturnAction.DESTROY); - } - next.getConnection(connectionInfo); - actualConnections++; - if (log.isTraceEnabled()) { - log.trace("Returning new connection " + connectionInfo.getManagedConnectionInfo()); - } - return; +// public void getConnection(ConnectionInfo connectionInfo) throws ResourceException { +// if (connectionInfo.getManagedConnectionInfo().getManagedConnection() != null) { +// return; +// } +// try { +// if (permits.attempt(blockingTimeoutMilliseconds)) { +// internalGetConnection(connectionInfo); +// } else { +// throw new ResourceException("No ManagedConnections available " +// + "within configured blocking timeout ( " +// + blockingTimeoutMilliseconds +// + " [ms] )"); +// +// } // end of else +// +// } catch (InterruptedException ie) { +// throw new ResourceException("Interrupted while requesting permit!"); +// } // end of try-catch +// } + + protected void internalGetConnection(ConnectionInfo connectionInfo) throws ResourceException { + synchronized (pool) { + try { + if (!pool.isEmpty()) { + ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); + ManagedConnectionFactory managedConnectionFactory = mci.getManagedConnectionFactory(); + ManagedConnection matchedMC = + managedConnectionFactory + .matchManagedConnections(pool.keySet(), + mci.getSubject(), + mci.getConnectionRequestInfo()); + if (matchedMC != null) { + connectionInfo.setManagedConnectionInfo((ManagedConnectionInfo) pool.get(matchedMC)); + pool.remove(matchedMC); + if (log.isTraceEnabled()) { + log.trace("Returning pooled connection " + connectionInfo.getManagedConnectionInfo()); + } + if (connectionCount < minSize) { + timer.schedule(new FillTask(connectionInfo), 10); } - } catch (ResourceException e) { - //something is wrong: rethrow, release permit - permits.release(); - throw e; + return; } } - } else { - throw new ResourceException( - "No ManagedConnections available " - + "within configured blocking timeout ( " - + blockingTimeout - + " [ms] )"); - - } // end of else - - } catch (InterruptedException ie) { - throw new ResourceException("Interrupted while requesting permit!"); - } // end of try-catch - } - - public void returnConnection( - ConnectionInfo connectionInfo, - ConnectionReturnAction connectionReturnAction) { - if (log.isTraceEnabled()) { - log.trace("returning connection" + connectionInfo.getConnectionHandle()); - } - boolean wasInPool = false; - ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); - if (connectionReturnAction == ConnectionReturnAction.DESTROY) { - synchronized (pool) { - wasInPool = (pool.remove(mci.getManagedConnection()) != null); - } - } else { - if (mci.hasConnectionHandles()) { - return; + //matching failed or pool is empty + //if pool is at maximum size, pick a cx to kill + if (connectionCount == maxSize) { + Iterator iterator = pool.entrySet().iterator(); + ManagedConnectionInfo kill = (ManagedConnectionInfo) ((Map.Entry) iterator.next()).getValue(); + iterator.remove(); + ConnectionInfo killInfo = new ConnectionInfo(kill); + internalReturn(killInfo, ConnectionReturnAction.DESTROY); + } + next.getConnection(connectionInfo); + connectionCount++; + if (log.isTraceEnabled()) { + log.trace("Returning new connection " + connectionInfo.getManagedConnectionInfo()); + } + if (connectionCount < minSize) { + timer.schedule(new FillTask(connectionInfo), 10); + } + + } catch (ResourceException e) { + //something is wrong: rethrow, release permit + permits.release(); + throw e; } - } // end of else + } + } +// public void returnConnection(ConnectionInfo connectionInfo, +// ConnectionReturnAction connectionReturnAction) { +// if (log.isTraceEnabled()) { +// log.trace("returning connection" + connectionInfo.getConnectionHandle()); +// } +// ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); +// if (connectionReturnAction == ConnectionReturnAction.RETURN_HANDLE && mci.hasConnectionHandles()) { +// return; +// } +// +// boolean wasInPool = internalReturn(connectionInfo, connectionReturnAction); +// +// if (!wasInPool) { +// permits.release(); +// } +// } + + protected boolean internalReturn(ConnectionInfo connectionInfo, ConnectionReturnAction connectionReturnAction) { + ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); ManagedConnection mc = mci.getManagedConnection(); try { mc.cleanup(); @@ -151,24 +171,30 @@ connectionReturnAction = ConnectionReturnAction.DESTROY; } - if (connectionReturnAction == ConnectionReturnAction.DESTROY) { - actualConnections--; - next.returnConnection(connectionInfo, connectionReturnAction); - } else { - synchronized (pool) { + boolean wasInPool = false; + synchronized (pool) { + if (shrinkLater > 0) { + //nothing can get in the pool while shrinkLater > 0, so wasInPool is false here. + connectionReturnAction = ConnectionReturnAction.DESTROY; + shrinkLater--; + } else if (connectionReturnAction == ConnectionReturnAction.RETURN_HANDLE) { mci.setLastUsed(System.currentTimeMillis()); pool.put(mci.getManagedConnection(), mci); + return wasInPool; + } else { + wasInPool = pool.remove(mci.getManagedConnection()) != null; } } - if (!wasInPool) { - permits.release(); - } + //we must destroy connection. + next.returnConnection(connectionInfo, connectionReturnAction); + connectionCount--; + return wasInPool; } //PoolingAttributes implementation - public int getPartitionCount() { - return 1; - } +// public int getPartitionCount() { +// return 1; +// } public int getPartitionMaxSize() { return maxSize; @@ -178,7 +204,136 @@ return pool.size(); } - public int getConnectionCount() { - return actualConnections; + protected void transferConnections(int maxSize, int shrinkNow) { + //1st example: copy 0 (none) + //2nd example: copy 10 (all) + HashMap oldPool = pool; + pool = new HashMap(maxSize); + //since we have replaced pool already, pool.remove will be very fast:-) + assert oldPool.size() == connectionCount; + Iterator it = oldPool.entrySet().iterator(); + for (int i = 0; i < shrinkNow; i++) { + ConnectionInfo killInfo = new ConnectionInfo((ManagedConnectionInfo) ((Map.Entry)it.next()).getValue()); + internalReturn(killInfo, ConnectionReturnAction.DESTROY); + } + for (; it.hasNext(); ) { + Map.Entry entry = (Map.Entry) it.next(); + pool.put(entry.getKey(), entry.getValue()); + } + } + + protected void getExpiredManagedConnectionInfos(long threshold, ArrayList killList) { + synchronized (pool) { + for (Iterator iterator = pool.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + ManagedConnectionInfo mci = (ManagedConnectionInfo) entry.getValue(); + if (mci.getLastUsed() < threshold) { + killList.add(mci); + } + } + } + + } + + protected boolean addToPool(ManagedConnectionInfo mci) { + boolean added; + synchronized (pool) { + connectionCount++; + added = getPartitionMaxSize() > getIdleConnectionCount(); + if (added) { + pool.put(mci.getManagedConnection(), mci); + } + } + return added; + } + +// public int getConnectionCount() { +// return connectionCount; +// } + +// public int getBlockingTimeoutMilliseconds() { +// return blockingTimeoutMilliseconds; +// } +// +// public void setBlockingTimeoutMilliseconds(int timeoutMilliseconds) { +// this.blockingTimeoutMilliseconds = timeoutMilliseconds; +// } + +// public int getIdleTimeoutMinutes() { +// return (int) idleTimeoutMilliseconds / (1000 * 60); +// } + +// public void setIdleTimeoutMinutes(int idleTimeoutMinutes) { +// this.idleTimeoutMilliseconds = idleTimeoutMinutes * 60 * 1000; +// if (idleReleaser != null) { +// idleReleaser.cancel(); +// } +// idleReleaser = new IdleReleaser(); +// timer.schedule(idleReleaser, this.idleTimeoutMilliseconds, this.idleTimeoutMilliseconds); +// } + + +// private class IdleReleaser extends TimerTask { +// +// public void run() { +// long threshold = System.currentTimeMillis() - idleTimeoutMilliseconds; +// ManagedConnectionInfo[] killList = new ManagedConnectionInfo[pool.size()]; +// int j = 0; +// synchronized (pool) { +// for (Iterator iterator = pool.entrySet().iterator(); iterator.hasNext();) { +// Map.Entry entry = (Map.Entry) iterator.next(); +// ManagedConnectionInfo mci = (ManagedConnectionInfo) entry.getValue(); +// if (mci.getLastUsed() < threshold) { +// killList[j] = mci; +// j++; +// } +// } +// } +// for (int i = 0; i < j; i++) { +// ManagedConnectionInfo managedConnectionInfo = killList[i]; +// ConnectionInfo killInfo = new ConnectionInfo(managedConnectionInfo); +// internalReturn(killInfo, ConnectionReturnAction.DESTROY); +// } +// permits.release(j); +// } +// } +// +// private class FillTask extends TimerTask { +// private final ManagedConnectionFactory managedConnectionFactory; +// private final Subject subject; +// private final ConnectionRequestInfo cri; +// +// public FillTask(ConnectionInfo connectionInfo) { +// managedConnectionFactory = connectionInfo.getManagedConnectionInfo().getManagedConnectionFactory(); +// subject = connectionInfo.getManagedConnectionInfo().getSubject(); +// cri = connectionInfo.getManagedConnectionInfo().getConnectionRequestInfo(); +// } +// +// public void run() { +// while (connectionCount < minSize) { +// ManagedConnectionInfo mci = new ManagedConnectionInfo(managedConnectionFactory, cri); +// mci.setSubject(subject); +// ConnectionInfo ci = new ConnectionInfo(mci); +// try { +// next.getConnection(ci); +// } catch (ResourceException e) { +// return; +// } +// boolean added = false; +// synchronized (pool) { +// connectionCount++; +// added = maxSize > pool.size(); +// if (added) { +// pool.put(mci.getManagedConnection(), mci); +// } +// } +// if (!added) { +// internalReturn(ci, ConnectionReturnAction.DESTROY); +// return; +// } +// } +// } +// } + } Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/NoPool.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/NoPool.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/NoPool.java Mon Nov 1 09:34:13 2004 @@ -34,15 +34,43 @@ return 0; } + public int getIdleConnectionCount() { + return 0; + } + + public int getConnectionCount() { + return 0; + } + public int getPartitionMaxSize() { return 0; } - public int getIdleConnectionCount() { + public void setPartitionMaxSize(int maxSize) { + + } + + public int getPartitionMinSize() { return 0; } - public int getConnectionCount() { + public void setPartitionMinSize(int minSize) { + + } + + public int getBlockingTimeoutMilliseconds() { + return 0; + } + + public void setBlockingTimeoutMilliseconds(int timeoutMilliseconds) { + + } + + public int getIdleTimeoutMinutes() { return 0; + } + + public void setIdleTimeoutMinutes(int idleTimeoutMinutes) { + } } Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/PartitionedPool.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/PartitionedPool.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/PartitionedPool.java Mon Nov 1 09:34:13 2004 @@ -36,8 +36,8 @@ private PoolingAttributes poolingAttributes; - public PartitionedPool(boolean partitionByConnectionRequestInfo, boolean partitionBySubject, int maxSize, int blockingTimeoutMilliseconds, boolean matchOne, boolean matchAll, boolean selectOneAssumeMatch) { - singlePool = new SinglePool(maxSize, blockingTimeoutMilliseconds, matchOne, matchAll, selectOneAssumeMatch); + public PartitionedPool(int maxSize, int minSize, int blockingTimeoutMilliseconds, int idleTimeoutMinutes, boolean matchOne, boolean matchAll, boolean selectOneAssumeMatch, boolean partitionByConnectionRequestInfo, boolean partitionBySubject) { + singlePool = new SinglePool(maxSize, minSize, blockingTimeoutMilliseconds, idleTimeoutMinutes, matchOne, matchAll, selectOneAssumeMatch); this.partitionByConnectionRequestInfo = partitionByConnectionRequestInfo; this.partitionBySubject = partitionBySubject; } @@ -67,11 +67,19 @@ } public int getBlockingTimeoutMilliseconds() { - return singlePool.getBlockingTimeoutMilliseconds(); + return poolingAttributes.getBlockingTimeoutMilliseconds(); } public void setBlockingTimeoutMilliseconds(int blockingTimeoutMilliseconds) { - singlePool.setBlockingTimeoutMilliseconds(blockingTimeoutMilliseconds); + poolingAttributes.setBlockingTimeoutMilliseconds(blockingTimeoutMilliseconds); + } + + public int getIdleTimeoutMinutes() { + return poolingAttributes.getIdleTimeoutMinutes(); + } + + public void setIdleTimeoutMinutes(int idleTimeoutMinutes) { + poolingAttributes.setIdleTimeoutMinutes(idleTimeoutMinutes); } public boolean isMatchOne() { @@ -114,6 +122,18 @@ public int getPartitionMaxSize() { return poolingAttributes.getPartitionMaxSize(); + } + + public void setPartitionMaxSize(int maxSize) throws InterruptedException { + poolingAttributes.setPartitionMaxSize(maxSize); + } + + public int getPartitionMinSize() { + return poolingAttributes.getPartitionMinSize(); + } + + public void setPartitionMinSize(int minSize) { + poolingAttributes.setPartitionMinSize(minSize); } public int getIdleConnectionCount() { Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/SinglePool.java ============================================================================== --- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/SinglePool.java (original) +++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/connectionmanagerconfig/SinglePool.java Mon Nov 1 09:34:13 2004 @@ -23,23 +23,24 @@ import org.apache.geronimo.connector.outbound.PoolingAttributes; /** - * - * * @version $Rev$ $Date$ - * - * */ + */ public class SinglePool implements PoolingSupport { private int maxSize; + private int minSize; private int blockingTimeoutMilliseconds; + private int idleTimeoutMinutes; private boolean matchOne; private boolean matchAll; private boolean selectOneAssumeMatch; private PoolingAttributes pool; - public SinglePool(int maxSize, int blockingTimeoutMilliseconds, boolean matchOne, boolean matchAll, boolean selectOneAssumeMatch) { + public SinglePool(int maxSize, int minSize, int blockingTimeoutMilliseconds, int idleTimeoutMinutes, boolean matchOne, boolean matchAll, boolean selectOneAssumeMatch) { this.maxSize = maxSize; + this.minSize = minSize; this.blockingTimeoutMilliseconds = blockingTimeoutMilliseconds; + this.idleTimeoutMinutes = idleTimeoutMinutes; this.matchOne = matchOne; this.matchAll = matchAll; this.selectOneAssumeMatch = selectOneAssumeMatch; @@ -53,12 +54,34 @@ this.maxSize = maxSize; } + public int getMinSize() { + return minSize; + } + + public void setMinSize(int minSize) { + this.minSize = minSize; + } + public int getBlockingTimeoutMilliseconds() { return blockingTimeoutMilliseconds; } public void setBlockingTimeoutMilliseconds(int blockingTimeoutMilliseconds) { this.blockingTimeoutMilliseconds = blockingTimeoutMilliseconds; + if (pool != null) { + pool.setBlockingTimeoutMilliseconds(blockingTimeoutMilliseconds); + } + } + + public int getIdleTimeoutMinutes() { + return idleTimeoutMinutes; + } + + public void setIdleTimeoutMinutes(int idleTimeoutMinutes) { + this.idleTimeoutMinutes = idleTimeoutMinutes; + if (pool != null) { + pool.setIdleTimeoutMinutes(idleTimeoutMinutes); + } } public boolean isMatchOne() { @@ -87,18 +110,20 @@ public ConnectionInterceptor addPoolingInterceptors(ConnectionInterceptor tail) { if (isMatchAll()) { - SinglePoolMatchAllConnectionInterceptor pool = new SinglePoolMatchAllConnectionInterceptor( - tail, + SinglePoolMatchAllConnectionInterceptor pool = new SinglePoolMatchAllConnectionInterceptor(tail, getMaxSize(), - getBlockingTimeoutMilliseconds()); + getMinSize(), + getBlockingTimeoutMilliseconds(), + getIdleTimeoutMinutes()); this.pool = pool; return pool; } else { - SinglePoolConnectionInterceptor pool = new SinglePoolConnectionInterceptor( - tail, + SinglePoolConnectionInterceptor pool = new SinglePoolConnectionInterceptor(tail, getMaxSize(), + getMinSize(), getBlockingTimeoutMilliseconds(), + getIdleTimeoutMinutes(), isSelectOneAssumeMatch()); this.pool = pool; return pool; @@ -110,14 +135,32 @@ } public int getPartitionMaxSize() { - return pool == null? maxSize: pool.getPartitionMaxSize(); + return maxSize; + } + + public void setPartitionMaxSize(int maxSize) throws InterruptedException { + if (pool != null) { + pool.setPartitionMaxSize(maxSize); + } + this.maxSize = maxSize; + } + + public int getPartitionMinSize() { + return minSize; + } + + public void setPartitionMinSize(int minSize) { + if (pool != null) { + pool.setPartitionMinSize(minSize); + } + this.minSize = minSize; } public int getIdleConnectionCount() { - return pool.getIdleConnectionCount(); + return pool == null ? 0 : pool.getIdleConnectionCount(); } public int getConnectionCount() { - return pool.getConnectionCount(); + return pool == null ? 0 : pool.getConnectionCount(); } } Modified: geronimo/trunk/modules/connector/src/schema/geronimo-connector_1_5.xsd ============================================================================== --- geronimo/trunk/modules/connector/src/schema/geronimo-connector_1_5.xsd (original) +++ geronimo/trunk/modules/connector/src/schema/geronimo-connector_1_5.xsd Mon Nov 1 09:34:13 2004 @@ -287,8 +287,10 @@ <xsd:complexType name="singlepool-Type"> <xsd:sequence> - <xsd:element name="max-size" type="xsd:int"/> - <xsd:element name="blocking-timeout-milliseconds" type="xsd:int"/> + <xsd:element name="max-size" type="xsd:int" minOccurs="0"/> + <xsd:element name="min-size" type="xsd:int" minOccurs="0"/> + <xsd:element name="blocking-timeout-milliseconds" type="xsd:int" minOccurs="0"/> + <xsd:element name="idle-timeout-minutes" type="xsd:int" minOccurs="0"/> <xsd:choice> <xsd:element name="match-one"/> <xsd:element name="match-all"/> Modified: geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/deployment/RAR_1_0ConfigBuilderTest.java ============================================================================== --- geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/deployment/RAR_1_0ConfigBuilderTest.java (original) +++ geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/deployment/RAR_1_0ConfigBuilderTest.java Mon Nov 1 09:34:13 2004 @@ -176,7 +176,7 @@ ObjectName connectionTrackerName = new ObjectName("geronimo.connector:service=ConnectionTracker"); Kernel kernel = new Kernel("testServer"); - ConnectorModuleBuilder moduleBuilder = new ConnectorModuleBuilder(kernel); + ConnectorModuleBuilder moduleBuilder = new ConnectorModuleBuilder(10, 0, 5000, 15, kernel); File rarFile = action.getRARFile(); ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); @@ -230,7 +230,7 @@ JarFile rarFile = null; try { rarFile = DeploymentUtil.createJarFile(new File(basedir, "target/test-ear-noger.ear")); - EARConfigBuilder configBuilder = new EARConfigBuilder(j2eeServer, null, connectionTrackerName, null, null, null, null, null, null, new ConnectorModuleBuilder(kernel), null, null, kernel); + EARConfigBuilder configBuilder = new EARConfigBuilder(j2eeServer, null, connectionTrackerName, null, null, null, null, null, null, new ConnectorModuleBuilder(10, 0, 5000, 15, kernel), null, null, kernel); File tempDir = null; try { tempDir = DeploymentUtil.createTempDir(); Modified: geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/deployment/RAR_1_5ConfigBuilderTest.java ============================================================================== --- geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/deployment/RAR_1_5ConfigBuilderTest.java (original) +++ geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/deployment/RAR_1_5ConfigBuilderTest.java Mon Nov 1 09:34:13 2004 @@ -121,7 +121,7 @@ ObjectName connectionTrackerName = new ObjectName("geronimo.connector:service=ConnectionTracker"); Kernel kernel = new Kernel("testServer"); - ConnectorModuleBuilder moduleBuilder = new ConnectorModuleBuilder(kernel); + ConnectorModuleBuilder moduleBuilder = new ConnectorModuleBuilder(10, 0, 5000, 15, kernel); File rarFile = action.getRARFile(); ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); Modified: geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/ConnectionManagerTestUtils.java ============================================================================== --- geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/ConnectionManagerTestUtils.java (original) +++ geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/ConnectionManagerTestUtils.java Mon Nov 1 09:34:13 2004 @@ -53,7 +53,9 @@ protected boolean useThreadCaching = false; protected boolean useTransactions = true; protected int maxSize = 10; + protected int minSize = 0; protected int blockingTimeout = 100; + protected int idleTimeoutMinutes = 15; protected boolean useConnectionRequestInfo = false; protected boolean useSubject = true; private boolean matchOne = true; @@ -75,7 +77,7 @@ protected Subject subject; protected UserTransactionImpl userTransaction; protected TransactionSupport transactionSupport = new XATransactions(useTransactionCaching, useThreadCaching); - protected PoolingSupport poolingSupport = new PartitionedPool(useConnectionRequestInfo, useSubject, maxSize, blockingTimeout, matchOne, matchAll, selectOneNoMatch); + protected PoolingSupport poolingSupport = new PartitionedPool(maxSize, minSize, blockingTimeout, idleTimeoutMinutes, matchOne, matchAll, selectOneNoMatch, useConnectionRequestInfo, useSubject); protected DefaultInterceptor mockComponent = new DefaultInterceptor() { public Object invoke(InstanceContext newInstanceContext) throws Throwable { Modified: geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/PoolDequeTest.java ============================================================================== --- geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/PoolDequeTest.java (original) +++ geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/PoolDequeTest.java Mon Nov 1 09:34:13 2004 @@ -40,7 +40,7 @@ public void testFill() throws Exception { SinglePoolConnectionInterceptor.PoolDeque pool = new SinglePoolConnectionInterceptor.PoolDeque(MAX_SIZE); for (int i = 0; i < MAX_SIZE; i++) { - pool.addLast(new ManagedConnectionInfo(null, null)); + pool.add(new ManagedConnectionInfo(null, null)); } } @@ -50,11 +50,11 @@ ManagedConnectionInfo[] mcis = new ManagedConnectionInfo[MAX_SIZE]; for (int i = 0; i < MAX_SIZE; i++) { mcis[i] = new ManagedConnectionInfo(null, null); - pool.addLast(mcis[i]); + pool.add(mcis[i]); } for (int i = MAX_SIZE - 1; i >= 0; i--) { - assertTrue("Expected to get corresponding MCI from pool", mcis[i] == pool.peekLast()); + assertTrue("Expected to get corresponding MCI from pool", mcis[i] == pool.peek(i)); assertTrue("Expected to get corresponding MCI from pool", mcis[i] == pool.removeLast()); } assertTrue("Expected pool to be empty!", pool.isEmpty()); @@ -65,7 +65,7 @@ ManagedConnectionInfo[] mcis = new ManagedConnectionInfo[MAX_SIZE]; for (int i = 0; i < MAX_SIZE; i++) { mcis[i] = new ManagedConnectionInfo(null, null); - pool.addLast(mcis[i]); + pool.add(mcis[i]); } for (int i = 0; i < MAX_SIZE; i++) {