diff --git a/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/TransactedPoolManager.java b/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/TransactedPoolManager.java
index 826fab1ae41..fbcd5e9986e 100644
--- a/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/TransactedPoolManager.java
+++ b/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/TransactedPoolManager.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2024 Eclipse Foundation and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -35,22 +36,24 @@ public interface TransactedPoolManager {
* pool manager.
*
* @param tran Transaction to which the resource is enlisted
- * @param res Resource that is enlisted
+ * @param resource Resource that is enlisted
* @throws IllegalStateException when unable to enlist the resource
*/
- void resourceEnlisted(Transaction tran, ResourceHandle res) throws IllegalStateException;
+ void resourceEnlisted(Transaction tran, ResourceHandle resource) throws IllegalStateException;
/**
- * registers the provided resource with the component & enlists the resource in the transaction
- * @param handle resource-handle
+ * Registers the provided resource with the component & enlists the resource in the transaction
+ *
+ * @param resource Resource to be registered.
* @throws PoolingException when unable to register the resource
*/
- void registerResource(ResourceHandle handle) throws PoolingException;
+ void registerResource(ResourceHandle resource) throws PoolingException;
/**
- * unregisters the resource from the component and delists the resource from the transaction
- * @param resource resource-handle
- * @param xaresFlag
+ * Unregisters the resource from the component and delists the resource from the transaction
+ *
+ * @param resource Resource to be unregistered.
+ * @param xaresFlag flag indicating transaction success. This can be XAResource.TMSUCCESS or XAResource.TMFAIL
*/
void unregisterResource(ResourceHandle resource, int xaresFlag);
}
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/util/ConnectionPoolReconfigHelper.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/util/ConnectionPoolReconfigHelper.java
index fa4d513d6c5..578ff3a2e4a 100644
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/util/ConnectionPoolReconfigHelper.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/util/ConnectionPoolReconfigHelper.java
@@ -34,8 +34,17 @@ public final class ConnectionPoolReconfigHelper {
LogDomains.RSR_LOGGER);
public enum ReconfigAction {
+ /**
+ * Recreate connection pool
+ */
RECREATE_POOL,
+ /**
+ * Update ManagedConnectionFactory and attributes
+ */
UPDATE_MCF_AND_ATTRIBUTES,
+ /**
+ * No operation
+ */
NO_OP
}
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/ResourceAllocator.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/ResourceAllocator.java
index e06fb2b6174..774c48f51d2 100644
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/ResourceAllocator.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/ResourceAllocator.java
@@ -54,6 +54,12 @@ public interface ResourceAllocator {
boolean isTransactional();
+ /**
+ * Forces the cleanup of the ManagedConnection associated to the given resource.
+ *
+ * @param resource the resource referencing a ManagedConnection
+ * @throws PoolingException in case the cleanup failed
+ */
void cleanup(ResourceHandle resource) throws PoolingException;
boolean shareableWithinComponent();
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/AbstractPoolManager.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/AbstractPoolManager.java
index 151df17f5bf..e8b8c557417 100644
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/AbstractPoolManager.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/AbstractPoolManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Contributors to the Eclipse Foundation
+ * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -17,33 +17,40 @@
package com.sun.enterprise.resource.pool;
+<<<<<<< Upstream, based on origin/master
import com.sun.enterprise.resource.ResourceSpec;
import java.util.concurrent.ConcurrentHashMap;
import org.glassfish.resourcebase.resources.api.PoolInfo;
+=======
+>>>>>>> f4ffa0b Part 3 for issue #24900 More documentation and more unit test coverage.
/**
* Abstract Pool manager for unimplemented features. Throws UnsupportedOperationException when invoked.
*/
public abstract class AbstractPoolManager implements PoolManager {
- @Override
- public void emptyResourcePool(ResourceSpec spec) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void killAllPools() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setSelfManaged(PoolInfo poolInfo, boolean flag) {
- throw new UnsupportedOperationException();
- }
-
- public ConcurrentHashMap getMonitoredPoolTable() {
- throw new UnsupportedOperationException();
- }
+// Not used in the code
+// @Override
+// public void emptyResourcePool(ResourceSpec spec) {
+// throw new UnsupportedOperationException();
+// }
+
+// Not used in the code
+// @Override
+// public void killAllPools() {
+// throw new UnsupportedOperationException();
+// }
+
+// Not used in the code
+// @Override
+// public void setSelfManaged(PoolInfo poolInfo, boolean flag) {
+// throw new UnsupportedOperationException();
+// }
+
+// Not used in the code
+// public ConcurrentHashMap getMonitoredPoolTable() {
+// throw new UnsupportedOperationException();
+// }
}
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/ConnectionPool.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/ConnectionPool.java
index 9457688b2d9..799f2aad290 100644
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/ConnectionPool.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/ConnectionPool.java
@@ -379,12 +379,12 @@ protected Resizer initializeResizer() {
}
/**
- * add a resource with status busy and not enlisted
+ * Add a resource to the pool with status busy and not enlisted.
*
- * @param alloc ResourceAllocator
+ * @param alloc the ResourceAllocator to be used
* @throws PoolingException when unable to add a resource
*/
- public void addResource(ResourceAllocator alloc) throws PoolingException {
+ private void addResource(ResourceAllocator alloc) throws PoolingException {
int numResCreated = dataStructure.addResource(alloc, 1);
if (numResCreated > 0) {
for (int i = 0; i < numResCreated; i++) {
@@ -568,7 +568,7 @@ public ResourceHandle getResource(ResourceSpec spec, ResourceAllocator alloc, Tr
* Overridden in AssocWithThreadResourcePool to fetch the resource cached in the ThreadLocal In ConnectionPool this
* simply returns null.
*
- * @param spec ResourceSpec
+ * @param spec the ResourceSpec used to locate the correct resource pool
* @param alloc ResourceAllocator to create a resource
* @param tran Transaction
* @return ResourceHandle resource from ThreadLocal
@@ -613,7 +613,7 @@ protected ResourceHandle internalGetResource(ResourceSpec resourceSpec, Resource
*
* @param transaction Current Transaction
* @param resourceAllocator ResourceAllocator
- * @param resourceSpec ResourceSpec
+ * @param resourceSpec the ResourceSpec used to locate the correct resource pool
* @return result ResourceHandle
*/
private ResourceHandle getResourceFromTransaction(Transaction transaction, ResourceAllocator resourceAllocator, ResourceSpec resourceSpec) {
@@ -706,7 +706,7 @@ private ResourceHandle getResourceFromTransaction(Transaction transaction, Resou
/**
* To provide an unenlisted, valid, matched resource from pool.
*
- * @param resourceSpec ResourceSpec
+ * @param resourceSpec the ResourceSpec used to locate the correct resource pool
* @param resourceAllocator ResourceAllocator
* @param transaction Transaction
* @return ResourceHandle resource from pool
@@ -793,6 +793,7 @@ protected boolean matchConnection(ResourceHandle resource, ResourceAllocator all
* return a new resource. returns null if the pool new resources cannot be created.
*
* @param resourceAllocator ResourceAllocator
+ * @param resourceSpec the ResourceSpec used to locate the correct resource pool
* @return ResourceHandle resource from pool
* @throws PoolingException if unable to create a new resource
*/
@@ -941,7 +942,7 @@ private ResourceHandle getMatchedResourceFromPool(ResourceAllocator alloc) {
}
/**
- * Try to purge resources by size <= quantity
+ * Try to purge resources by size <= quantity
*
* @param quantity maximum no. of resources to remove.
* @return resourceCount No. of resources actually removed.
@@ -970,14 +971,16 @@ private int purgeResources(int quantity) {
* replacement is required since the steadypoolsize might equal maxpoolsize and in that case if we were not to remove a
* resource from the pool, our resource would be above maxPoolSize
*
- * @param resourceAllocator ResourceAllocator to create resource
- * @param resourceSpec ResourceSpec
+ * @param resourceAllocator the resource allocator to be used to create the new resource
+ * @param resourceSpec the ResourceSpec used to locate the correct resource pool
* @return newly created resource
* @throws PoolingException when unable to create a resource
*/
protected ResourceHandle createSingleResourceAndAdjustPool(ResourceAllocator resourceAllocator, ResourceSpec resourceSpec) throws PoolingException {
+ // TODO document in getResource when a return value can be null
ResourceHandle handle = dataStructure.getResource();
if (handle != null) {
+ // TODO document why it is removed / add unit test to show the behavior described in the javadoc of the method
dataStructure.removeResource(handle);
}
@@ -986,9 +989,9 @@ protected ResourceHandle createSingleResourceAndAdjustPool(ResourceAllocator res
/**
* Method to be used to create resource, instead of calling ResourceAllocator.createConfigBean(). This method handles
- * the connection creation retrial in case of failure
+ * the connection creation retry in case of failure.
*
- * @param resourceAllocator ResourceAllocator
+ * @param resourceAllocator the resource allocator to be used to create the new resource
* @return ResourceHandle newly created resource
* @throws PoolingException when unable create a resource
*/
@@ -1023,9 +1026,9 @@ protected ResourceHandle createSingleResource(ResourceAllocator resourceAllocato
}
/**
- * Create specified number of resources.
+ * Create specified number of resources using the given resource allocater.
*
- * @param alloc ResourceAllocator
+ * @param alloc the resource allocator to be used to create the new resource
* @param size number of resources to create.
* @throws PoolingException When unable to create a resource
*/
@@ -1162,16 +1165,22 @@ protected void freeResource(ResourceHandle resourceHandle) {
}
- protected boolean cleanupResource(ResourceHandle handle) {
+ /**
+ * Asks the resource allocator to cleanup the resource
+ *
+ * @param resource the resource to be cleaned up
+ * @return true if cleanup was successful, otherwise false
+ */
+ protected boolean cleanupResource(ResourceHandle resource) {
boolean cleanupSuccessful = true;
// cleanup resource
try {
- ResourceAllocator alloc = handle.getResourceAllocator();
- alloc.cleanup(handle);
+ ResourceAllocator alloc = resource.getResourceAllocator();
+ alloc.cleanup(resource);
} catch (PoolingException ex) {
LOG.log(WARNING, "Cleanup of a resource from pool [" + poolInfo.getName() + "] failed.", ex);
cleanupSuccessful = false;
- resourceErrorOccurred(handle);
+ resourceErrorOccurred(resource);
}
return cleanupSuccessful;
}
@@ -1245,12 +1254,6 @@ private void doFailAllConnectionsProcessing() {
scheduleResizerTask();
}
- /**
- * This method is called when a resource is enlisted in a transaction.
- *
- * @param tran Transaction
- * @param resource ResourceHandle
- */
@Override
public void resourceEnlisted(Transaction tran, ResourceHandle resource) throws IllegalStateException {
poolTxHelper.resourceEnlisted(tran, resource);
@@ -1346,6 +1349,7 @@ private void incrementNumConnFailedValidation() {
}
}
+ // TODO: this method name should be createAndGetNewResource, but it is only used once, to it could be removed
private ResourceHandle getNewResource(ResourceAllocator alloc) throws PoolingException {
addResource(alloc);
return dataStructure.getResource();
@@ -1364,6 +1368,9 @@ public void emptyPool() {
@Override
public void emptyFreeConnectionsInPool() {
LOG.log(FINE, "Emptying free connections in the pool {0}", poolInfo.getName());
+
+ // TODO this is not completely thread safe, between getResource and removeResource
+ // the dataStructure can be altered by other threads
ResourceHandle h;
while ((h = dataStructure.getResource()) != null) {
dataStructure.removeResource(h);
@@ -1408,11 +1415,6 @@ public long getReconfigWaitTime() {
return reconfigWaitTime;
}
- /**
- * Reinitialize connections established in the connection pool and bring the pool to steady pool size.
- *
- * @throws com.sun.appserv.connectors.internal.api.PoolingException
- */
@Override
public synchronized boolean flushConnectionPool() throws PoolingException {
LOG.log(FINE, "Flushing Connection Pool {0}", poolInfo);
@@ -1430,13 +1432,6 @@ public synchronized boolean flushConnectionPool() throws PoolingException {
return true;
}
- /**
- * Reconfigure the Pool's properties. The reconfigConnectorConnectionPool method in the ConnectorRuntime will use this
- * method (through PoolManager) if it needs to just change pool properties and not recreate the pool
- *
- * @param poolResource - the ConnectorConnectionPool JavaBean that holds the new pool properties
- * @throws PoolingException if the pool resizing fails
- */
@Override
public synchronized void reconfigurePool(ConnectorConnectionPool poolResource) throws PoolingException {
int _idleTime = Integer.parseInt(poolResource.getIdleTimeoutInSeconds()) * 1000;
@@ -1564,8 +1559,13 @@ private void killExtraResources(int numToKill) {
scheduleResizerTask();
}
- /*
- * Increase the number of steady resources in the pool if we detect that the steadyPoolSize has been increased
+ /**
+ * Increase the number of steady resources in the pool if we detect that the steadyPoolSize has been increased.
+ * Note: if the newSteadyPoolSize is smaller than the current pool size, no changes are made directly. The resizer task
+ * is updated in all cases and will resize the pool in the future.
+ *
+ * @param newSteadyPoolSize The new steady pool size
+ * @throws PoolingException when unable to add new resources to the pool
*/
private void increaseSteadyPoolSize(int newSteadyPoolSize) throws PoolingException {
cancelResizerTask();
@@ -1575,27 +1575,16 @@ private void increaseSteadyPoolSize(int newSteadyPoolSize) throws PoolingExcepti
scheduleResizerTask();
}
- /**
- * @param alloc ResourceAllocator
- * @throws PoolingException when unable to create a resource
- */
+ // TODO is this private method needed? Why not call addResource directly?
private void createResourceAndAddToPool(ResourceAllocator alloc) throws PoolingException {
addResource(alloc);
}
- /**
- * Switch on matching of connections in the pool.
- */
@Override
public void switchOnMatching() {
matchConnections = true;
}
- /**
- * query the name of this pool. Required by monitoring
- *
- * @return the name of this pool
- */
@Override
public final PoolInfo getPoolInfo() {
return poolInfo;
@@ -1707,12 +1696,6 @@ public void reclaimConnection(ResourceHandle handle) {
notifyWaitingThreads();
}
- /**
- * Get Connection Pool status by computing the free/used values of the connections in the pool. Computations are based
- * on whether the pool is initialized or not when this method is invoked.
- *
- * @return PoolStatus object
- */
@Override
public PoolStatus getPoolStatus() {
PoolStatus poolStatus = new PoolStatus(this.poolInfo);
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManager.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManager.java
index ddd4c0fe7e1..0d8a1b194d1 100644
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManager.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManager.java
@@ -46,62 +46,142 @@
public interface PoolManager extends TransactedPoolManager {
// transaction support levels
- int NO_TRANSACTION = 0;
- int LOCAL_TRANSACTION = 1;
- int XA_TRANSACTION = 2;
+ // int NO_TRANSACTION = 0;
+ // int LOCAL_TRANSACTION = 1;
+ // int XA_TRANSACTION = 2;
// Authentication mechanism levels
- int BASIC_PASSWORD = 0;
- int KERBV5 = 1;
+ // int BASIC_PASSWORD = 0;
+ // int KERBV5 = 1;
// Credential Interest levels
- String PASSWORD_CREDENTIAL = "jakarta.resource.spi.security.PasswordCredential";
- String GENERIC_CREDENTIAL = "jakarta.resource.spi.security.GenericCredential";
+ // String PASSWORD_CREDENTIAL = "jakarta.resource.spi.security.PasswordCredential";
+ // String GENERIC_CREDENTIAL = "jakarta.resource.spi.security.GenericCredential";
/**
* Flush Connection pool by reinitializing the connections established in the pool.
*
- * @param poolInfo
- * @throws com.sun.appserv.connectors.internal.api.PoolingException
+ * @param poolInfo the pool identifier for which the status needs to be flushed.
+ * @throws com.sun.appserv.connectors.internal.api.PoolingException in case the given pool is not initialized.
*/
boolean flushConnectionPool(PoolInfo poolInfo) throws PoolingException;
/**
- * @return connection pool status.
+ * Returns the pool status for the pool identified by the given poolInfo.
+ *
+ * @param poolInfo the pool identifier for which the status needs to be returned.
+ * @return pool status information if the pool is found based on the provided poolInfo, otherwise null is returned.
*/
PoolStatus getPoolStatus(PoolInfo poolInfo);
ResourceHandle getResourceFromPool(ResourceSpec spec, ResourceAllocator alloc, ClientSecurityInfo info,
- Transaction transaction) throws PoolingException, RetryableUnavailableException;
+ Transaction transaction) throws PoolingException, RetryableUnavailableException;
- void createEmptyConnectionPool(PoolInfo poolInfo, PoolType pt, Hashtable env) throws PoolingException;
+ /**
+ * Creates an empty connection pool with the given pool info and pool type.
+ *
+ * @param poolInfo the pool identifier of the new pool
+ * @param poolType the type of the connection pool
+ * @param env hashtable used to find the connection pool ConnectorConnectionPool information to set parameters like
+ * maximum number of connections
+ * @throws PoolingException when unable to create/initialize pool
+ */
+ void createEmptyConnectionPool(PoolInfo poolInfo, PoolType poolType, Hashtable env) throws PoolingException;
+ /**
+ * Returns the resource back to the pool IF errorOccurred is false. If errorOccurred is true the resource is removed
+ * from the pool.
+ *
+ * Note: The resource object may not be used anymore by the calling code after this call. + * + * @param resourceHandle the resource handle. + * @param errorOccurred true if an error occurred and the resource should not be returned to the pool, otherwise use + * false + *
+ * TODO The method name is misleading
+ * TODO Why is NoTxConnectorAllocator the only one calling this interface method and the rest of the calls are using
+ * resourceClosed / resourceErrorOccurred and resourceAbortOccurred ? Is the difference between resourceClosed and
+ * putbackResourceToPool that resourceClosed informs the transaction and putbackResourceToPool does not?
+ */
void putbackResourceToPool(ResourceHandle resourceHandle, boolean errorOccurred);
- void putbackBadResourceToPool(ResourceHandle resourceHandle);
-
+ /**
+ * Notifies the pool the resource is not used by a bean/application anymore.
+ * The resource is returned to the pool and the state of the resource is no longer busy.
+ * The resource is NOT delisted / unenlisted from the current transaction.
+ *
+ * Note: The resource object may not be used anymore by the calling code after this call. + * + * @param resourceHandle the resource handle + * @param poolInfo the pool information of the pool where the resource is expected to be removed from. If the given pool + * info is not found no exception is thrown. + *
+ * TODO Why is this method public available and only used internal in PoolManagerImpl and externally in
+ * LazyEnlistableResourceManagerImpl. Why can't LazyEnlistableResourceManagerImpl just call resourceClosed? If poolInfo
+ * = resourceHandle.getResourceSpec().getPoolInfo() then LazyEnlistableResourceManagerImpl could just as well call
+ * resourceClosed and then this method can be removed from the interface.
+ */
void putbackDirectToPool(ResourceHandle resourceHandle, PoolInfo poolInfo);
+ /**
+ * Closes the resource handle and returns it back to the connection pool.
+ * The resource is returned to the pool and the state of the resource is no longer busy.
+ * The resource is also delisted / unenlisted from the current transaction.
+ *
+ * Note: The resource object may not be used anymore by the calling code after this call.
+ *
+ * @param resourceHandle the resource handle to be closed and returned to the pool.
+ */
void resourceClosed(ResourceHandle resourceHandle);
+ // TODO Why is this method public available? Why is it not called via resourceErrorOccurred or resourceAbortOccurred?
void badResourceClosed(ResourceHandle resourceHandle);
void resourceErrorOccurred(ResourceHandle resourceHandle);
void resourceAbortOccurred(ResourceHandle resourceHandle);
+ /**
+ * Inform all the connection pools using this transaction that the transaction has completed. This method is called by
+ * the EJB Transaction Manager.
+ // com.sun.gjc.spi.ManagedConnectionImpl.transactionCompleted()
+ // performs: badConnectionEventListener.connectionAbortOccurred -> jdbc.markedForRemoval_conAborted
+ //
+ // com.sun.gjc.spi.jdbc40.ConnectionHolder40.abort(Executor) documents: "Abort operation to mark the connection
+ // internally as a bad connection for removal and to close the connection. This ensures that at the end of the
+ // transaction, the connection is destroyed. A running thread holding a connection will run to completion before the
+ // connection is destroyed"
getResourceManager(resource.getResourceSpec()).delistResource(resource, TMSUCCESS);
+
+ // TODO: Why is resourceHandle.setConnectionErrorOccurred() not performed?
+ // Added example in unit test PoolManagerImplTest that shows connection error is not updated
putbackResourceToPool(resource, true);
}
- @Override
- public void putbackBadResourceToPool(ResourceHandle resourceHandle) {
+ private void putbackBadResourceToPool(ResourceHandle resourceHandle) {
// Notify pool
PoolInfo poolInfo = resourceHandle.getResourceSpec().getPoolInfo();
if (poolInfo != null) {
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/ResourcePool.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/ResourcePool.java
index 17f941d612f..f9d79d3d896 100644
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/ResourcePool.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/ResourcePool.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Contributors to the Eclipse Foundation
+ * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation.
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -46,11 +46,28 @@ public interface ResourcePool {
*/
void resourceClosed(ResourceHandle resource);
+ /**
+ * Updates the resource to be marked as not busy / free, remove the resource from the connection pool and inform any
+ * waiting threads that a resource has become available.
+ *
+ * @param resource the resource that will be removed from the connection pool
+ */
void resourceErrorOccurred(ResourceHandle resource);
+ /**
+ * This method is called when a resource is enlisted in a transaction.
+ *
+ * @param tran the Transaction to enlist the resource in
+ * @param resource the ResourceHandle that will be enlisted in the given transaction
+ */
void resourceEnlisted(Transaction tran, ResourceHandle resource);
- // Get status of pool
+ /**
+ * Get the Pool status by computing the free/used values of the connections in the pool. Computations are based on
+ * whether the pool is initialized or not when this method is invoked.
+ *
+ * @return the PoolStatus object
+ */
PoolStatus getPoolStatus();
/**
@@ -63,20 +80,43 @@ public interface ResourcePool {
*/
void transactionCompleted(Transaction tran, int status);
+ /**
+ * Resize the pool by removing idle and invalid resources.
+ * All resource handles associated to the given transaction are delisted.
+ * All resource handles associated to the given transaction handed back to the connection pool.
+ *
+ * @param transaction the transaction that is completed
+ * @param status the status of the transaction
+ */
void transactionCompleted(Transaction transaction, int status);
- void emptyResourcePool(ResourceSpec spec);
+ // Not used in the code
+ // void emptyResourcePool(ResourceSpec spec);
+ /**
+ * Kills the pool for the given PoolInfo.
+ * Note: if the pool is not found the method ends with success.
+ *
+ * @param poolInfo the pool identifier for which the pool needs to be killed.
+ */
void killPool(PoolInfo poolInfo);
+ /**
+ * Reconfigures the connection pool to apply the given properties.
+ * Note: if the pool is not found the method ends with success.
+ *
+ * @param ccp the object containing the new connection pool properties that will be applied to the existing pool
+ * @throws PoolingException if reconfiguration of the pool failed
+ */
void reconfigPoolProperties(ConnectorConnectionPool ccp) throws PoolingException;
+ /**
+ * Switch on matching in the pool.
+ *
+ * @param poolInfo the pool identifier for which the pool matching needs to be switched on.
+ */
boolean switchOnMatching(PoolInfo poolInfo);
/**
- * Obtain a transactional resource such as JDBC connection
+ * Obtain a transactional resource such as JDBC connection from the connection pool. The caller is blocked until a
+ * resource is acquired or the max-wait-time of the connection pool expires.
*
* @param spec Specification for the resource
* @param alloc Allocator for the resource
@@ -113,17 +193,39 @@ ResourceHandle getResourceFromPool(ResourceSpec spec, ResourceAllocator alloc, C
ResourceReferenceDescriptor getResourceReference(SimpleJndiName jndiName, SimpleJndiName logicalName);
- void killAllPools();
-
+ /**
+ * Kills all free connections in the registered connection pools. The pools are not killed.
+ */
void killFreeConnectionsInPools();
+ /**
+ * Returns the ResourcePool for the given PoolInfo
+ *
+ * @param poolInfo the pool identifier
+ * @return the ResourcePool if found, otherwise null
+ */
ResourcePool getPool(PoolInfo poolInfo);
- void setSelfManaged(PoolInfo poolInfo, boolean flag);
-
- void lazyEnlist(ManagedConnection mc) throws ResourceException;
+ /**
+ * This method gets called by the LazyEnlistableConnectionManagerImpl when a connection needs enlistment, i.e on use of
+ * a Statement etc. Based on the given managagedConneciton the transaction manager is found and used to find the
+ * transaction. If no transaction was found this method returns without an error.
+ *
+ * @param managedConnection the managedConnection that needs to be enlisted in the transaction
+ * @throws ResourceException in case enlistment to the transaction failed.
+ */
+ void lazyEnlist(ManagedConnection managedConnection) throws ResourceException;
+ /**
+ * Registers a PoolLifeCycle listener in the pool manager. The listener is used to keep track of statistics of the pool
+ * life cycle: pool created and pool destroyed events.
+ *
+ * @param poolListener the listener instance
+ */
void registerPoolLifeCycleListener(PoolLifeCycle poolListener);
+ /**
+ * Unregisters the PoolLifeCycle listener in the pool manager.
+ */
void unregisterPoolLifeCycleListener();
}
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManagerImpl.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManagerImpl.java
index ac8f40565e3..3b6875b4d98 100644
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManagerImpl.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/PoolManagerImpl.java
@@ -225,11 +225,6 @@ public ResourceHandle getResourceFromPool(ResourceSpec resourceSpec, ResourceAll
return getPool(resourceSpec.getPoolInfo()).getResource(resourceSpec, resourceAllocator, transaction);
}
- /**
- * Switch on matching in the pool.
- *
- * @param poolInfo Name of the pool
- */
@Override
public boolean switchOnMatching(PoolInfo poolInfo) {
ResourcePool pool = getPool(poolInfo);
@@ -276,7 +271,6 @@ private void addSyncListener(Transaction transaction) {
}
}
- // called by EJB Transaction Manager
@Override
public void transactionCompleted(Transaction transaction, int status) throws IllegalStateException {
Set
+ * Only when forced is true the pool size is scaled down with the pool resize quantity.
+ *
+ * @param forced when force is true, scale down the pool with the pool resize quantity.
+ */
void resizePool(boolean forced);
- // forcefully destroy all connections in the pool even if
- // connections have transactions in progress
+ /**
+ * Forcefully destroy all connections in the pool even if connections have transactions in progress
+ */
void emptyPool();
- // reconfig the pool's properties
+ /**
+ * Reconfigure the Pool's properties. The reconfigConnectorConnectionPool method in the ConnectorRuntime will use this
+ * method (through PoolManager) if it needs to just change pool properties and not recreate the pool
+ *
+ * @param poolResource - the ConnectorConnectionPool JavaBean that holds the new pool properties
+ * @throws PoolingException if the pool resizing fails
+ */
void reconfigurePool(ConnectorConnectionPool ccp) throws PoolingException;
- // cancel the resizer task in the pool
+ /**
+ * Cancel the resizer task in the pool if it exists.
+ */
void cancelResizerTask();
+ /**
+ * Switch on matching of connections in the pool.
+ */
void switchOnMatching();
+ /**
+ * Get the PoolInfo unique identifier of this pool.
+ *
+ * @return the PoolInfo unique identifier of this pool
+ */
PoolInfo getPoolInfo();
void emptyFreeConnectionsInPool();
@@ -131,22 +171,23 @@ public interface ResourcePool {
void setSelfManaged(boolean selfManaged);
/**
- * set pool life cycle listener
+ * Set the pool life cycle listener
*
- * @param listener
+ * @param listener the new PoolLifeCycleListener
*/
void setPoolLifeCycleListener(PoolLifeCycleListener listener);
/**
- * remove pool life cycle listener
+ * Remove the pool life cycle listener
*/
void removePoolLifeCycleListener();
/**
- * Flush Connection pool by reinitializing the connections established in the pool.
+ * Flush Connection pool by removing all resources established in the connection pool and bring the pool to steady pool
+ * size.
*
* @return boolean indicating whether flush operation was successful or not
- * @throws com.sun.appserv.connectors.internal.api.PoolingException
+ * @throws PoolingException in case the pool was not initialized
*/
boolean flushConnectionPool() throws PoolingException;
@@ -174,7 +215,7 @@ public interface ResourcePool {
/**
* returns the reconfig-wait-time
*
- * @return long
+ * @return the reconfig-wait-time
*/
long getReconfigWaitTime();
}
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/DataStructure.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/DataStructure.java
index 83245b0d4fa..58861730bfa 100644
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/DataStructure.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/DataStructure.java
@@ -43,11 +43,11 @@ public interface DataStructure {
void setMaxSize(int maxSize);
/**
- * creates a new resource and adds to the datastructure.
+ * Create a new resource using the given resource-allocator and add it to the datastructure.
*
- * @param allocator ResourceAllocator
- * @param count Number (units) of resources to create
- * @return int number of resources added.
+ * @param allocator the resource-allocator to be used
+ * @param count the number (units) of resources to create
+ * @return the number of resources added
* @throws PoolingException when unable to create a resource
*/
int addResource(ResourceAllocator allocator, int count) throws PoolingException;
@@ -93,11 +93,11 @@ public interface DataStructure {
int getResourcesSize();
/**
- * Get all resources in the datastructure Note : do not use this for normal usages as it can potentially represent all
- * resources (including the ones in use). This is used under special circumstances where there is a need to process all
- * resources.
+ * Get all resources in the datastructure
+ * Note: do not use this for normal usages as it can potentially represent all resources (including the ones in use).
+ * This is used under special circumstances where there is a need to process all resources.
*
- * @return List
+ * Only when forced is true the pool size is scaled down with the pool resize quantity.
*
- * @param forced when force is true, scale down the pool.
+ * @param forced when force is true, scale down the pool with the pool resize quantity.
*/
public void resizePool(boolean forced) {
@@ -125,13 +126,14 @@ private void ensureSteadyPool() {
}
/**
- * Scale down pool by a size <= pool-resize-quantity
+ * Scale down pool by a size <= pool-resize-quantity
but only if forced is true
*
- * @param forced scale-down only when forced
- * @param scaleDownQuantity no. of resources to remove
+ * @param scaleDownQuantity the number of resources to remove
+ * @param forced scale-down only when forced value is true
+ *
+ * TODO: move forced parameter out of this method and move it to the calling code
*/
protected void scaleDownPool(int scaleDownQuantity, boolean forced) {
-
if (pool.getResizeQuantity() > 0 && forced) {
scaleDownQuantity = (scaleDownQuantity <= (dataStructure.getResourcesSize() - pool.getSteadyPoolSize())) ? scaleDownQuantity : 0;
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/rm/LazyEnlistableResourceManagerImpl.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/rm/LazyEnlistableResourceManagerImpl.java
index 9fb3d0eac26..77a3ea17a1e 100755
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/rm/LazyEnlistableResourceManagerImpl.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/rm/LazyEnlistableResourceManagerImpl.java
@@ -17,6 +17,13 @@
package com.sun.enterprise.resource.rm;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.logging.Logger;
+
+import org.glassfish.api.invocation.ComponentInvocation;
+import org.glassfish.resourcebase.resources.api.PoolInfo;
+
import com.sun.appserv.connectors.internal.api.PoolingException;
import com.sun.enterprise.connectors.ConnectorRuntime;
import com.sun.enterprise.resource.ResourceHandle;
@@ -28,12 +35,6 @@
import jakarta.transaction.SystemException;
import jakarta.transaction.Transaction;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.logging.Logger;
-
-import org.glassfish.api.invocation.ComponentInvocation;
-
import static com.sun.logging.LogDomains.RSR_LOGGER;
import static java.util.logging.Level.WARNING;
@@ -123,10 +124,11 @@ public void lazyEnlist(ManagedConnection managedConnection) throws ResourceExcep
} catch (Exception e) {
// In the rare cases where enlistResource throws exception, we
// should return the resource to the pool
- ConnectorRuntime.getRuntime().getPoolManager().putbackDirectToPool(resourceHandle,
- resourceHandle.getResourceSpec().getPoolInfo());
+ // TODO: Why not call resourceClosed instead of putbackDirectToPool?
+ PoolInfo poolInfo = resourceHandle.getResourceSpec().getPoolInfo();
+ ConnectorRuntime.getRuntime().getPoolManager().putbackDirectToPool(resourceHandle, poolInfo);
- LOG.log(WARNING, "poolmgr.err_enlisting_res_in_getconn", resourceHandle.getResourceSpec().getPoolInfo());
+ LOG.log(WARNING, "poolmgr.err_enlisting_res_in_getconn", poolInfo);
LOG.fine("rm.enlistResource threw Exception. Returning resource to pool");
// And rethrow the exception
diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/rm/ResourceManager.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/rm/ResourceManager.java
index 8911987ad2b..b93f7ef22c4 100755
--- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/rm/ResourceManager.java
+++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/rm/ResourceManager.java
@@ -71,7 +71,7 @@ public interface ResourceManager {
* Delist the resource from the transaction.
*
* @param resource Resource to be delisted.
- * @param xaresFlag XA Flag
+ * @param xaresFlag flag indicating transaction success. This can be XAResource.TMSUCCESS or XAResource.TMFAIL
*/
void delistResource(ResourceHandle resource, int xaresFlag);
@@ -79,7 +79,7 @@ public interface ResourceManager {
* Unregister the resource from a transaction's list.
*
* @param resource Resource to be unregistered.
- * @param xaresFlag XA Flag
+ * @param xaresFlag flag indicating transaction success. This can be XAResource.TMSUCCESS or XAResource.TMFAIL
*/
void unregisterResource(ResourceHandle resource, int xaresFlag);
}
diff --git a/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/PoolManagerImplTest.java b/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/PoolManagerImplTest.java
index 9ace3d5b60e..5adbe6da1d1 100644
--- a/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/PoolManagerImplTest.java
+++ b/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/PoolManagerImplTest.java
@@ -1,309 +1,511 @@
-/*
- * Copyright (c) 2024 Eclipse Foundation and/or its affiliates. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0, which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * This Source Code may also be made available under the following Secondary
- * Licenses when the conditions for such availability set forth in the
- * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
- * version 2 with the GNU Classpath Exception, which is available at
- * https://www.gnu.org/software/classpath/license.html.
- *
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
- */
-
-package com.sun.enterprise.resource.pool;
-
-import static com.sun.enterprise.resource.pool.ConnectionPoolTest.getPoolInfo;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.isNull;
-import static org.easymock.EasyMock.notNull;
-import static org.easymock.EasyMock.replay;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import com.sun.appserv.connectors.internal.api.ConnectorConstants.PoolType;
-import com.sun.appserv.connectors.internal.api.PoolingException;
-import com.sun.enterprise.connectors.ConnectorRuntime;
-import com.sun.enterprise.resource.ClientSecurityInfo;
-import com.sun.enterprise.resource.ResourceHandle;
-import com.sun.enterprise.resource.ResourceSpec;
-import com.sun.enterprise.resource.allocator.ConnectorAllocator;
-import com.sun.enterprise.resource.allocator.LocalTxConnectorAllocator;
-import com.sun.enterprise.resource.allocator.NoTxConnectorAllocator;
-import com.sun.enterprise.resource.allocator.ResourceAllocator;
-import com.sun.enterprise.resource.pool.mock.JavaEETransactionMock;
-import com.sun.enterprise.transaction.api.JavaEETransaction;
-import com.sun.enterprise.transaction.api.JavaEETransactionManager;
-import jakarta.resource.spi.ManagedConnection;
-import jakarta.resource.spi.ManagedConnectionFactory;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Set;
-import org.glassfish.api.admin.ProcessEnvironment;
-import org.glassfish.api.invocation.InvocationManager;
-import org.glassfish.api.invocation.InvocationManagerImpl;
-import org.glassfish.api.naming.GlassfishNamingManager;
-import org.glassfish.api.naming.SimpleJndiName;
-import org.glassfish.resourcebase.resources.api.PoolInfo;
-import org.glassfish.resourcebase.resources.naming.ResourceNamingService;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-public class PoolManagerImplTest {
-
- // Mocked instances
- private GlassfishNamingManager glassfishNamingManager;
- private JavaEETransactionManager javaEETransactionManager;
- private ManagedConnection managedConnection;
- private ManagedConnectionFactory managedConnectionFactory;
-
- // Regular fields
- private ClientSecurityInfo clientSecurityInfo = null;
- private PoolManagerImpl poolManagerImpl = new MyPoolManagerImpl();
- private PoolInfo poolInfo = getPoolInfo();
- private JavaEETransaction javaEETransaction = new MyJavaEETransaction();
-
- @BeforeEach
- public void createAndPopulateMocks() throws Exception {
- List