From 120fddd35fc4c8afbe769b2e53f6cf86d7563468 Mon Sep 17 00:00:00 2001 From: "R.M. Morrien" Date: Thu, 4 Apr 2024 14:00:04 +0200 Subject: [PATCH] Part 1 for issue #24900 Document and rename some ResourceHandle fields. Document and rename some ConnectionPool fields. Remove some unused methods and constructor parameters. Functional / possible incompatibility changes in DataStructureFactory and in ResourceHandle due to constructor changes. --- .../inbound/BasicResourceAllocator.java | 8 +- .../inbound/ConnectorMessageBeanClient.java | 4 +- .../internal/api/ResourceHandle.java | 59 ++++- .../internal/api/TransactedPoolManager.java | 6 +- .../connectors/ConnectorConnectionPool.java | 11 +- .../AssocWithThreadResourceHandle.java | 7 +- .../resource/ConnectorXAResource.java | 14 +- .../enterprise/resource/ResourceHandle.java | 245 ++++++++++++------ .../sun/enterprise/resource/ResourceSpec.java | 19 +- .../enterprise/resource/ResourceState.java | 32 ++- .../allocator/AbstractConnectorAllocator.java | 17 +- .../allocator/ConnectorAllocator.java | 14 +- .../allocator/LocalTxConnectorAllocator.java | 13 +- .../allocator/NoTxConnectorAllocator.java | 19 +- .../resource/allocator/ResourceAllocator.java | 16 +- .../pool/AssocWithThreadResourcePool.java | 4 +- .../resource/pool/ConnectionPool.java | 85 +++--- .../resource/pool/PoolManagerImpl.java | 5 +- .../resource/pool/ResourcePool.java | 14 + .../resource/pool/UnpooledResource.java | 6 +- .../datastructure/DataStructureFactory.java | 22 +- .../pool/datastructure/ListDataStructure.java | 10 +- .../datastructure/RWLockDataStructure.java | 13 +- .../resizer/AssocWithThreadPoolResizer.java | 2 +- .../resource/pool/resizer/Resizer.java | 2 +- .../rm/LazyEnlistableResourceManagerImpl.java | 4 +- .../LocalTxConnectionEventListenerTest.java | 2 +- .../resource/pool/ConnectionPoolTest.java | 3 + .../RWLockDataStructureTest.java | 27 +- .../api/JavaEETransactionManager.java | 9 +- .../spi/TransactionalResource.java | 68 ++++- .../JavaEETransactionManagerSimplified.java | 7 - .../jts/JavaEETransactionManagerTest.java | 22 +- 33 files changed, 500 insertions(+), 289 deletions(-) diff --git a/appserver/connectors/connectors-inbound-runtime/src/main/java/com/sun/enterprise/connectors/inbound/BasicResourceAllocator.java b/appserver/connectors/connectors-inbound-runtime/src/main/java/com/sun/enterprise/connectors/inbound/BasicResourceAllocator.java index b7f4ffe9ef2..28e4f6a3509 100755 --- a/appserver/connectors/connectors-inbound-runtime/src/main/java/com/sun/enterprise/connectors/inbound/BasicResourceAllocator.java +++ b/appserver/connectors/connectors-inbound-runtime/src/main/java/com/sun/enterprise/connectors/inbound/BasicResourceAllocator.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 @@ -42,13 +42,11 @@ public final class BasicResourceAllocator extends AbstractConnectorAllocator { public BasicResourceAllocator() { } - @Override public ResourceHandle createResource() throws PoolingException { throw new UnsupportedOperationException(); } - public ResourceHandle createResource(XAResource xaResource) throws PoolingException { ResourceHandle resourceHandle = null; ResourceSpec spec = new ResourceSpec(JMS_RESOURCE_FACTORY, ResourceSpec.JMS); @@ -56,7 +54,7 @@ public ResourceHandle createResource(XAResource xaResource) throws PoolingExcept if (xaResource != null) { logger.logp(Level.FINEST, "BasicResourceAllocator", "createResource", "NOT NULL", xaResource); try { - resourceHandle = new ResourceHandle(null, spec, this, null); + resourceHandle = new ResourceHandle(null, spec, this); if (logger.isLoggable(Level.FINEST)) { xaResource = new XAResourceWrapper(xaResource); } @@ -71,14 +69,12 @@ public ResourceHandle createResource(XAResource xaResource) throws PoolingExcept return resourceHandle; } - @Override public void closeUserConnection(ResourceHandle resourceHandle) throws PoolingException { throw new UnsupportedOperationException(); } - @Override public boolean matchConnection(ResourceHandle resourceHandle) { return false; diff --git a/appserver/connectors/connectors-inbound-runtime/src/main/java/com/sun/enterprise/connectors/inbound/ConnectorMessageBeanClient.java b/appserver/connectors/connectors-inbound-runtime/src/main/java/com/sun/enterprise/connectors/inbound/ConnectorMessageBeanClient.java index 62978708c44..35425716ee2 100755 --- a/appserver/connectors/connectors-inbound-runtime/src/main/java/com/sun/enterprise/connectors/inbound/ConnectorMessageBeanClient.java +++ b/appserver/connectors/connectors-inbound-runtime/src/main/java/com/sun/enterprise/connectors/inbound/ConnectorMessageBeanClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 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 @@ -353,7 +353,7 @@ private EjbMessageBeanDescriptor getDescriptor() { */ @Override public MessageEndpoint createEndpoint(XAResource xa) throws UnavailableException { - // This is a temporary workaround for blocking the the create enpoint + // This is a temporary workaround for blocking the created endpoint // until the deployment completes. One thread would wait for maximum a // a minute. return createEndpoint(xa, WAIT_TIME); diff --git a/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/ResourceHandle.java b/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/ResourceHandle.java index 8462afe9977..574007f6aaf 100644 --- a/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/ResourceHandle.java +++ b/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/ResourceHandle.java @@ -1,4 +1,5 @@ /* + * 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 @@ -19,33 +20,85 @@ import javax.transaction.xa.XAResource; /** - * ResourceHandle interface to be used by transaction manager components + * ResourceHandle interface to be used by transaction manager components. * * @author Marina Vatkina */ public interface ResourceHandle { + /** + * Returns true if the resource is part of a transaction. + * + * @return true if the resource is part of a transaction. + */ public boolean isTransactional(); - //TODO V3 not needed as of now. + /** + * To check whether lazy enlistment is suspended or not.
+ * If {@code true}, transaction manager will not do enlist/lazy enlist. + * + * @return true if enlistment is suspended, otherwise false. + */ public boolean isEnlistmentSuspended(); + /** + * Allows a ResourceManager to change the enlistement suspended state of a resource to enlist a resource in a + * transaction. + * + * @param enlistmentSuspended true if enlistment in a transaction is suspended, false if enlistment is not suspended. + */ public void setEnlistmentSuspended(boolean enlistmentSuspended); + /** + * Returns the (optional) XAResource reference for this resource handle. + * + * @return the XAResource reference for this resource handle or null if no reference is set. + */ public XAResource getXAResource(); + /** + * Returns true if the ResourceHandle is supported in an XA transaction. + * + * @return true if the ResourceHandle is supported in an XA transaction, otherwise false. + */ public boolean supportsXA(); + /** + * Returns the component instance holding this resource handle. + * + * @return the component instance holding this resource handle. + */ public Object getComponentInstance(); + /** + * Sets the component instance holding this resource handle. + * + * @param instance the component instance holding this resource handle. + */ public void setComponentInstance(Object instance); + /** + * Closes the (optional) 'userConnection' / 'connection handle' (used by the application code to refer to the underlying + * physical connection). Example: the ManagedConnection represented by this ResourceHandle is closed / cleaned up. + * + * @throws PoolingException wrapping any 'userConnection' specific exception that might occur during the close call. + * @throws UnsupportedOperationException when the method is not implemented. + */ public void closeUserConnection() throws PoolingException; + /** + * Returns true if the resource handle is enlisted in a transaction. + * + * @return true if the resource handle is enlisted in a transaction. + */ public boolean isEnlisted(); + /** + * Returns true if the resource handle is sharable within the component. + * + * @return true if the resource handle is sharable within the component. + */ public boolean isShareable(); - public void destroyResource(); } 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 6e8440bfe78..272d4a2ac13 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 @@ -29,7 +29,11 @@ public interface TransactedPoolManager { /** - * Indicate that a resource is enlisted. + * Indicate that a resource is enlisted.
+ * Expecting this method is called from the + * {@link com.sun.enterprise.resource.ResourceHandle#enlistedInTransaction(Transaction)} method and not directly from a + * pool manager. + * * @param tran Transaction to which the resource is enlisted * @param res Resource that is enlisted * @throws IllegalStateException when unable to enlist the resource diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/ConnectorConnectionPool.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/ConnectorConnectionPool.java index f8ecd208552..6abb6bd8c8b 100755 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/ConnectorConnectionPool.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/ConnectorConnectionPool.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 @@ -75,7 +75,6 @@ public class ConnectorConnectionPool implements Serializable { private String poolWaitQueue; private String dataStructureParameters; private String resourceGatewayClass; - private String resourceSelectionStrategyClass; private boolean nonTransactional_; private boolean nonComponent_; @@ -774,14 +773,6 @@ public void setResourceGatewayClass(String resourceGatewayClass) { this.resourceGatewayClass = resourceGatewayClass; } - public String getResourceSelectionStrategyClass() { - return resourceSelectionStrategyClass; - } - - public void setResourceSelectionStrategyClass(String resourceSelectionStrategyClass) { - this.resourceSelectionStrategyClass = resourceSelectionStrategyClass; - } - public boolean isPreferValidateOverRecreate() { return preferValidateOverRecreate_; } diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/AssocWithThreadResourceHandle.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/AssocWithThreadResourceHandle.java index a81d34acf60..98d6a99d7b3 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/AssocWithThreadResourceHandle.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/AssocWithThreadResourceHandle.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 @@ -18,6 +18,7 @@ package com.sun.enterprise.resource; import com.sun.enterprise.resource.allocator.ResourceAllocator; +import jakarta.resource.spi.ManagedConnection; /** * ResourceHandle with state related to assoc-with-thread pool @@ -30,8 +31,8 @@ public class AssocWithThreadResourceHandle extends ResourceHandle { private long threadId_; private boolean dirty_; - public AssocWithThreadResourceHandle(Object resource, ResourceSpec spec, ResourceAllocator alloc, ClientSecurityInfo info) { - super(resource, spec, alloc, info); + public AssocWithThreadResourceHandle(ManagedConnection resource, ResourceSpec spec, ResourceAllocator alloc) { + super(resource, spec, alloc); } public boolean isDirty() { diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ConnectorXAResource.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ConnectorXAResource.java index b172bec0c6d..24f6ec460bd 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ConnectorXAResource.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ConnectorXAResource.java @@ -81,7 +81,7 @@ private void handleResourceException(Exception ex) throws XAException { @Override public void commit(Xid xid, boolean onePhase) throws XAException { try { - ManagedConnection managedConnection = (ManagedConnection) getResourceHandle().getResource(); + ManagedConnection managedConnection = getResourceHandle().getResource(); managedConnection.getLocalTransaction().commit(); } catch (Exception ex) { handleResourceException(ex); @@ -96,7 +96,7 @@ public void start(Xid xid, int flags) throws XAException { try { ResourceHandle handle = getResourceHandle(); if (!localHandle_.equals(handle)) { - ManagedConnection managedConnection = (ManagedConnection) handle.getResource(); + ManagedConnection managedConnection = handle.getResource(); managedConnection.associateConnection(userHandle); LocalTxConnectionEventListener listener = (LocalTxConnectionEventListener) handle.getListener(); @@ -122,7 +122,7 @@ public void end(Xid xid, int flags) throws XAException { ResourceHandle handle = listener.removeAssociation(userHandle); if (handle != null) { // not needed, just to be sure. - ManagedConnection associatedConnection = (ManagedConnection) handle.getResource(); + ManagedConnection associatedConnection = handle.getResource(); associatedConnection.associateConnection(userHandle); _logger.log(FINE, "connection_sharing_reset_association", userHandle); } @@ -177,7 +177,7 @@ public Xid[] recover(int flag) throws XAException { public void rollback(Xid xid) throws XAException { try { ResourceHandle handle = getResourceHandle(); - ManagedConnection managedConnection = (ManagedConnection) handle.getResource(); + ManagedConnection managedConnection = handle.getResource(); managedConnection.getLocalTransaction().rollback(); } catch (Exception ex) { handleResourceException(ex); @@ -211,7 +211,7 @@ private ResourceHandle getResourceHandle() throws PoolingException { } if (resourceHandle.getResourceState().isUnenlisted()) { - ManagedConnection managedConnection = (ManagedConnection) resourceHandle.getResource(); + ManagedConnection managedConnection = resourceHandle.getResource(); // Begin the local transaction if first time // this ManagedConnection is used in this JTA transaction @@ -236,8 +236,8 @@ private void resetAssociation() throws XAException { // Clear the associations and Map all associated handles back to their actual Managed Connection. Map associatedHandles = listener.getAssociatedHandlesAndClearMap(); for (Entry userHandleEntry : associatedHandles.entrySet()) { - ResourceHandle associatedHandle = (ResourceHandle) userHandleEntry.getValue(); - ManagedConnection associatedConnection = (ManagedConnection) associatedHandle.getResource(); + ResourceHandle associatedHandle = userHandleEntry.getValue(); + ManagedConnection associatedConnection = associatedHandle.getResource(); associatedConnection.associateConnection(userHandleEntry.getKey()); _logger.log(FINE, "connection_sharing_reset_association", userHandleEntry.getKey()); } diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceHandle.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceHandle.java index 98e02488ed9..0ac1f7f0cc5 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceHandle.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 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 @@ -27,11 +27,11 @@ import jakarta.resource.spi.ConnectionEventListener; import jakarta.resource.spi.DissociatableManagedConnection; import jakarta.resource.spi.LazyEnlistableManagedConnection; +import jakarta.resource.spi.ManagedConnection; import jakarta.transaction.Transaction; import java.util.logging.Logger; -import javax.security.auth.Subject; import javax.transaction.xa.XAResource; import static java.util.logging.Level.FINEST; @@ -47,38 +47,146 @@ public class ResourceHandle implements com.sun.appserv.connectors.internal.api.R private static final Logger logger = LogDomains.getLogger(ResourceHandle.class, LogDomains.RSR_LOGGER); - // unique ID for resource handles + /** + * Unique Id sequence generator value for generating unique ResourceHandle ids. + */ static private long idSequence; + /** + * The unique Id of this ResourceHandle instance. + */ private final long id; - private final ClientSecurityInfo info; - private final Object resource; // represents ManagedConnection - private ResourceSpec spec; - private XAResource xaRes; - private Object userConnection; // represents connection-handle to user + + /** + * The (optional) object represented by this handle. Normally the ManagedConnection object.
+ * THe object is known to be null in case of the BasicResourrceAllocator. + */ + private final ManagedConnection resource; + + /** + * The ResourceSpec reference, which can be used to find the correct connection pool for the resource handle.
+ * Note: this value is set in the constructor, but can be overwritten later during the lifetime of the resource handle, + * while {@link #resourceAllocator} is not overwritten. + */ + private ResourceSpec resourceSpec; + + /** + * The (optional) XAResource reference for this resource handle. The value is set in this resource handle together with + * the {@link #userConnection}. + */ + private XAResource xaResource; + + /** + * The (optional) 'userConnection' / 'connection handle', used by the application code to refer to the underlying + * physical connection.
+ * The value is set in this resource handle together with the {@link #xaResource}. + *

+ * TODO: consider renaming userConnection to connectionHandle + */ + private Object userConnection; + + /** + * The ResourceAllocator that created this resource handle instance. + */ private final ResourceAllocator resourceAllocator; - private Object instance; // the component instance holding this resource - private int shareCount; // sharing within a component (XA only) - private final boolean supportsXAResource; - private Subject subject; + /** + * The component instance holding this resource handle. + */ + private Object instance; + + /** + * Sharing within a component (XA only). For XA-capable connections, multiple connections within a component are + * collapsed into one. shareCount keeps track of the number of additional shared connections + */ + private int shareCount; + + /** + * Resource state class providing 'timestamp', 'enlisted' and 'busy' fields.
+ * Other state fields like 'enlistmentSuspended', 'shareCount', 'usageCount', 'lastValidated' and others are directly + * part of this class as a field. + */ + private ResourceState state = new ResourceState(); - private ResourceState state; + /** + * Used by LocalTxConnectorAllocator to save a listener for the resource handle. + */ private ConnectionEventListener listener; + /** + * Used by LazyEnlistableResourceManagerImpl to keep track of the enlistment suspended state of a resource handle. + * LazyEnlistableResourceManagerImpl is used when setting "lazy-connection-enlistment" to enabled in the connection + * pool.
+ * Default: false, false means: every resource is enlisted to a transaction. + */ private boolean enlistmentSuspended; - private boolean supportsLazyEnlistment_; - private boolean supportsLazyAssoc_; + /** + * False if the ResourceAllocator is of the type LocalTxConnectorAllocator, otherwise true. + */ + private final boolean supportsXAResource; + + /** + * True if the Resource object ManagedConnection is of the type LazyEnlistableManagedConnection, otherwise false. + */ + private boolean supportsLazyEnlistment; + /** + * True if the Resource object ManagedConnection is of the type DissociatableManagedConnection, otherwise false. + */ + private boolean supportsLazyAssociation; + + /** + * Resource handle specific lock, which can be used to lock the resource handle when state of the resource needs to be + * changed. This is currently only used in the AssocWithThreadResourcePool implementation. + */ public final Object lock = new Object(); - private long lastValidated; // holds the latest time at which the connection was validated. - private int usageCount; // holds the no. of times the handle(connection) is used so far. - private int partition; - private int index; + + /** + * Holds the latest time at which the connection was validated.
+ * Could also be seen as part of ResourceState. + */ + private long lastValidated; + + /** + * Holds the number of times the handle(connection) is used so far. It is used by the ConnectionPool logic in case the + * "max-connection-usage-count" option is set in the connection pool.
+ * Could also be seen as part of ResourceState. + */ + private int usageCount; + + /** + * Index of this ResourceHandle in the RWLockDataStructure internal ResourceHandle[]. RWLockDataStructure uses this + * index value for optimistic locking of the resource. + */ + private int rwLockDataStructureResourceIndex; + + /** + * Value isDestroyByLeakTimeOut is set to true if ConnectionPool reclaimConnection logic was called when a potential + * leak was found. The value is used when a resource is freed or closed by the poolLifeCycleListener to update + * statistics.
+ * Could also be seen as part of ResourceState. + */ private boolean isDestroyByLeakTimeOut; + + /** + * The connectionErrorOccurred field is set to true when a connection was aborted, or a connection error occurred, or + * when a connection being closes is bad.
+ * Could also be seen as part of ResourceState. + */ private boolean connectionErrorOccurred; + /** + * Value markedReclaim is set by the + * {@link com.sun.enterprise.resource.pool.ConnectionLeakDetector#potentialConnectionLeakFound(ResourceHandle)} method + * when the resource is set to be reclaimed. Note: this value is only used to update statistics, the resource itself is + * already removed from the pool the moment it is marked for reclaim. Code seems to suggest that this is also set when + * {@link #isDestroyByLeakTimeOut} is set. Perhaps this boolean is not needed, statistics could perhaps be updated + * immediately when isDestroyByLeakTimeOut is updated.
+ * Could also be seen as part of ResourceState. + */ + private boolean markedReclaim; + static private long getNextId() { synchronized (ResourceHandle.class) { idSequence++; @@ -86,27 +194,31 @@ static private long getNextId() { } } - private boolean markedReclaim; - - public ResourceHandle(Object resource, ResourceSpec spec, ResourceAllocator alloc, ClientSecurityInfo info) { + /** + * ResourceHandle constructor + * + * @param resource the (optional) object represented by this handle. Normally the ManagedConnection object. + * @param resourceSpec the ResourceSpec reference, allowing this resource handle to find the correct connection pool. + * @param resourceAllocator the ResourceAllocator that is creating this resource handle instance. + */ + public ResourceHandle(ManagedConnection resource, ResourceSpec resourceSpec, ResourceAllocator resourceAllocator) { this.id = getNextId(); - this.spec = spec; - this.info = info; this.resource = resource; - this.resourceAllocator = alloc; + this.resourceSpec = resourceSpec; + this.resourceAllocator = resourceAllocator; - if (alloc instanceof LocalTxConnectorAllocator) { + if (resourceAllocator instanceof LocalTxConnectorAllocator) { supportsXAResource = false; } else { supportsXAResource = true; } if (resource instanceof LazyEnlistableManagedConnection) { - supportsLazyEnlistment_ = true; + supportsLazyEnlistment = true; } if (resource instanceof DissociatableManagedConnection) { - supportsLazyAssoc_ = true; + supportsLazyAssociation = true; } } @@ -118,13 +230,6 @@ public boolean isTransactional() { return resourceAllocator.isTransactional(); } - /** - * To check whether lazy enlistment is suspended or not. - * - *

If {@code true}, TM will not do enlist/lazy enlist. - * - * @return boolean - */ @Override public boolean isEnlistmentSuspended() { return enlistmentSuspended; @@ -157,25 +262,21 @@ public ResourceAllocator getResourceAllocator() { return resourceAllocator; } - public Object getResource() { + public ManagedConnection getResource() { return resource; } - public ClientSecurityInfo getClientSecurityInfo() { - return info; - } - - public void setResourceSpec(ResourceSpec spec) { - this.spec = spec; + public void setResourceSpec(ResourceSpec resourceSpec) { + this.resourceSpec = resourceSpec; } public ResourceSpec getResourceSpec() { - return spec; + return resourceSpec; } @Override public XAResource getXAResource() { - return xaRes; + return xaResource; } public Object getUserConnection() { @@ -201,30 +302,27 @@ public long getId() { return id; } - public void fillInResourceObjects(Object userConnection, XAResource xaRes) { + public void fillInResourceObjects(Object userConnection, XAResource xaResource) { if (userConnection != null) { this.userConnection = userConnection; } - if (xaRes != null) { + if (xaResource != null) { if (logger.isLoggable(FINEST)) { // When Log level is Finest, XAResourceWrapper is used to log // all XA interactions - Don't wrap XAResourceWrapper if it is // already wrapped - if ((xaRes instanceof XAResourceWrapper) || (xaRes instanceof ConnectorXAResource)) { - this.xaRes = xaRes; + if ((xaResource instanceof XAResourceWrapper) || (xaResource instanceof ConnectorXAResource)) { + this.xaResource = xaResource; } else { - this.xaRes = new XAResourceWrapper(xaRes); + this.xaResource = new XAResourceWrapper(xaResource); } } else { - this.xaRes = xaRes; + this.xaResource = xaResource; } } } - // For XA-capable connections, multiple connections within a - // component are collapsed into one. shareCount keeps track of - // the number of additional shared connections public void incrementCount() { shareCount++; } @@ -241,14 +339,6 @@ public int getShareCount() { return shareCount; } - public void setSubject(Subject subject) { - this.subject = subject; - } - - public Subject getSubject() { - return subject; - } - @Override public boolean equals(Object other) { if (other == null) { @@ -280,10 +370,6 @@ public boolean hasConnectionErrorOccurred() { return connectionErrorOccurred; } - public void setResourceState(ResourceState state) { - this.state = state; - } - public ResourceState getResourceState() { return state; } @@ -301,14 +387,9 @@ public boolean isShareable() { return resourceAllocator.shareableWithinComponent(); } - @Override - public void destroyResource() { - throw new UnsupportedOperationException("Transaction is not supported yet"); - } - @Override public boolean isEnlisted() { - return state != null && state.isEnlisted(); + return state.isEnlisted(); } public long getLastValidated() { @@ -327,33 +408,25 @@ public void incrementUsageCount() { usageCount++; } - public int getPartition() { - return partition; - } - - public void setPartition(int partition) { - this.partition = partition; - } - - public int getIndex() { - return index; + public int getRwLockDataStructureResourceIndex() { + return rwLockDataStructureResourceIndex; } - public void setIndex(int index) { - this.index = index; + public void setRwLockDataStructureResourceIndex(int rwLockDataStructureResourceIndex) { + this.rwLockDataStructureResourceIndex = rwLockDataStructureResourceIndex; } @Override public String getName() { - return spec.getResourceId(); + return resourceSpec.getResourceId(); } public boolean supportsLazyEnlistment() { - return supportsLazyEnlistment_; + return supportsLazyEnlistment; } public boolean supportsLazyAssociation() { - return supportsLazyAssoc_; + return supportsLazyAssociation; } @Override diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceSpec.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceSpec.java index 565b186f221..8ea4df9cf51 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceSpec.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceSpec.java @@ -183,15 +183,16 @@ public Object getConnectionToAssociate() { @Override public String toString() { - StringBuffer sb = new StringBuffer("ResourceSpec :- "); - sb.append("\nconnectionPoolName : ").append(poolInfo); - sb.append("\nisXA_ : ").append(isXA_); - sb.append("\nresoureId : ").append(resourceId); - sb.append("\nresoureIdType : ").append(resourceIdType); - sb.append("\npmResource : ").append(pmResource); - sb.append("\nnonTxResource : ").append(nonTxResource); - sb.append("\nlazyEnlistable : ").append(lazyEnlistable_); - sb.append("\nlazyAssociatable : ").append(lazyAssociatable_); + StringBuffer sb = new StringBuffer(""); return sb.toString(); } } diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceState.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceState.java index 724f4ae58ba..2ff073ef280 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceState.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/ResourceState.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 @@ -18,8 +18,27 @@ package com.sun.enterprise.resource; public class ResourceState { + + /** + * Indicates that a resource has been enlisted in a transaction. + * + * @see jakarta.transaction.Transaction#enlistResource(XAResource) + */ private boolean enlisted; + + /** + * The busy state reflects the moment the resource is taken from the connection pool. It should be set to {@code true} + * once it is taken from the pool, and it should be set to {@code false} once it is returned to the pool. + *

+ * Setting to {@code true} happens at the moment the resource is taken from the pool (getResourceFromPool).
+ * Setting to {@code false} happens at the moment the connection is returned to the pool (resourceClosed). + */ private boolean busy; + + /** + * Timestamp represents the time of resource creation, or the time the resource usage was complete and is handed back to + * the pool. The timestamp value is used in the remove idle and invalid resources logic of the resource pool resizer. + */ private long timestamp; public boolean isEnlisted() { @@ -58,8 +77,17 @@ public ResourceState() { touchTimestamp(); } + /** + * Resets all fields, representing the constructor call situation. + */ + public void reset() { + touchTimestamp(); + setBusy(false); + setEnlisted(false); + } + @Override public String toString() { - return "Enlisted :" + enlisted + " Busy :" + busy; + return ""; } } diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/AbstractConnectorAllocator.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/AbstractConnectorAllocator.java index b88dae71b1b..2519da4160f 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/AbstractConnectorAllocator.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/AbstractConnectorAllocator.java @@ -93,7 +93,7 @@ public Set getInvalidConnections(Set connectionSet) throws ResourceException { @Override public boolean isConnectionValid(ResourceHandle h) { HashSet conn = new HashSet<>(); - conn.add((ManagedConnection) h.getResource()); + conn.add(h.getResource()); Set invalids = null; try { invalids = getInvalidConnections(conn); @@ -135,7 +135,7 @@ public boolean isTransactional() { @Override public void cleanup(ResourceHandle h) throws PoolingException { try { - ManagedConnection mc = (ManagedConnection) h.getResource(); + ManagedConnection mc = h.getResource(); mc.cleanup(); } catch (Exception ex) { _logger.log(Level.WARNING, "managed_con.cleanup-failed", ex); @@ -146,7 +146,7 @@ public void cleanup(ResourceHandle h) throws PoolingException { @Override public boolean matchConnection(ResourceHandle h) { Set set = new HashSet<>(); - set.add((ManagedConnection) h.getResource()); + set.add(h.getResource()); try { ManagedConnection mc = mcf.matchManagedConnections(set, subject, reqInfo); return mc != null; @@ -157,9 +157,8 @@ public boolean matchConnection(ResourceHandle h) { @Override public void closeUserConnection(ResourceHandle resource) throws PoolingException { - try { - ManagedConnection mc = (ManagedConnection) resource.getResource(); + ManagedConnection mc = resource.getResource(); mc.cleanup(); } catch (ResourceException ex) { throw new PoolingException(ex); @@ -177,8 +176,8 @@ public Object getSharedConnection(ResourceHandle h) throw new UnsupportedOperationException(); } - protected ResourceHandle createResourceHandle(Object resource, ResourceSpec spec, - ResourceAllocator alloc, ClientSecurityInfo info) { + protected ResourceHandle createResourceHandle(ManagedConnection resource, ResourceSpec spec, + ResourceAllocator alloc) { ConnectorConstants.PoolType pt = ConnectorConstants.PoolType.STANDARD_POOL; try { @@ -187,9 +186,9 @@ protected ResourceHandle createResourceHandle(Object resource, ResourceSpec spec _logger.log(Level.WARNING,"unable_to_determine_pool_type", spec.getPoolInfo()); } if (pt == ConnectorConstants.PoolType.ASSOCIATE_WITH_THREAD_POOL) { - return new AssocWithThreadResourceHandle(resource, spec, alloc, info); + return new AssocWithThreadResourceHandle(resource, spec, alloc); } else { - return new ResourceHandle(resource, spec, alloc, info); + return new ResourceHandle(resource, spec, alloc); } } diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/ConnectorAllocator.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/ConnectorAllocator.java index bef99a9e274..446142095b0 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/ConnectorAllocator.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/ConnectorAllocator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 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 @@ -34,8 +34,12 @@ import javax.security.auth.Subject; import javax.transaction.xa.XAResource; - /** + * XATransaction Connector Allocator, used for transaction level: + * {@link com.sun.appserv.connectors.internal.api.ConnectorConstants#XA_TRANSACTION_INT}. + *

+ * TODO: Rename class to reflect XATransaction + * * @author Tony Ng */ public class ConnectorAllocator extends AbstractConnectorAllocator { @@ -143,7 +147,7 @@ public ConnectorAllocator(PoolManager poolMgr, public ResourceHandle createResource() throws PoolingException { try { ManagedConnection mc = mcf.createManagedConnection(subject, reqInfo); - ResourceHandle resource = createResourceHandle(mc, spec, this, info); + ResourceHandle resource = createResourceHandle(mc, spec, this); ConnectionEventListener l = new ConnectionListenerImpl(resource); mc.addConnectionEventListener(l); return resource; @@ -156,7 +160,7 @@ public ResourceHandle createResource() throws PoolingException { public void fillInResourceObjects(ResourceHandle resource) throws PoolingException { try { - ManagedConnection mc = (ManagedConnection) resource.getResource(); + ManagedConnection mc = resource.getResource(); Object con = mc.getConnection(subject, reqInfo); resource.incrementCount(); XAResource xares = mc.getXAResource(); @@ -177,7 +181,7 @@ public void destroyResource(ResourceHandle resource) } try { - ManagedConnection mc = (ManagedConnection) resource.getResource(); + ManagedConnection mc = resource.getResource(); mc.destroy(); } catch (Exception ex) { throw new PoolingException(ex); diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/LocalTxConnectorAllocator.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/LocalTxConnectorAllocator.java index be7220a682c..ad47a63b9cc 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/LocalTxConnectorAllocator.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/LocalTxConnectorAllocator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2021, 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 @@ -41,6 +41,9 @@ import javax.transaction.xa.XAResource; /** + * LocalTransaction Connector Allocator, used for transaction level: + * {@link com.sun.appserv.connectors.internal.api.ConnectorConstants#LOCAL_TRANSACTION_INT}. + * * @author Tony Ng */ public class LocalTxConnectorAllocator extends AbstractConnectorAllocator { @@ -70,7 +73,7 @@ public ResourceHandle createResource() throws PoolingException { try { ManagedConnection mc = mcf.createManagedConnection(subject, reqInfo); - ResourceHandle resource = createResourceHandle(mc, spec, this, info); + ResourceHandle resource = createResourceHandle(mc, spec, this); ConnectionEventListener l = new LocalTxConnectionEventListener(resource); mc.addConnectionEventListener(l); resource.setListener(l); @@ -88,10 +91,8 @@ public ResourceHandle createResource() throws PoolingException { public void fillInResourceObjects(ResourceHandle resource) throws PoolingException { try { - ManagedConnection mc = (ManagedConnection) resource.getResource(); - + ManagedConnection mc = resource.getResource(); Object con = mc.getConnection(subject, reqInfo); - ConnectorXAResource xares = (ConnectorXAResource) resource.getXAResource(); xares.setUserHandle(con); resource.fillInResourceObjects(con, xares); @@ -104,7 +105,7 @@ public void fillInResourceObjects(ResourceHandle resource) public void destroyResource(ResourceHandle resource) throws PoolingException { try { - ManagedConnection mc = (ManagedConnection) resource.getResource(); + ManagedConnection mc = resource.getResource(); XAResource xares = resource.getXAResource(); forceTransactionCompletion(xares); mc.destroy(); diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/NoTxConnectorAllocator.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/NoTxConnectorAllocator.java index 8dfd7600a46..c6de51b6d3b 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/NoTxConnectorAllocator.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/allocator/NoTxConnectorAllocator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 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 @@ -34,6 +34,9 @@ import javax.security.auth.Subject; /** + * NoTransaction Connector Allocator, used for transaction level: + * {@link com.sun.appserv.connectors.internal.api.ConnectorConstants#NO_TRANSACTION_INT}. + * * @author Tony Ng */ public class NoTxConnectorAllocator extends AbstractConnectorAllocator { @@ -104,12 +107,11 @@ public NoTxConnectorAllocator(PoolManager poolMgr, super(poolMgr, mcf, spec, subject, reqInfo, info, desc); } - @Override public ResourceHandle createResource() throws PoolingException { try { ManagedConnection mc = mcf.createManagedConnection(subject, reqInfo); - ResourceHandle resource = createResourceHandle(mc, spec, this, info); + ResourceHandle resource = createResourceHandle(mc, spec, this); ConnectionEventListener l = new ConnectionListenerImpl(resource); mc.addConnectionEventListener(l); return resource; @@ -119,10 +121,9 @@ public ResourceHandle createResource() throws PoolingException { } @Override - public void fillInResourceObjects(ResourceHandle resource) - throws PoolingException { + public void fillInResourceObjects(ResourceHandle resource) throws PoolingException { try { - ManagedConnection mc = (ManagedConnection) resource.getResource(); + ManagedConnection mc = resource.getResource(); Object con = mc.getConnection(subject, reqInfo); resource.fillInResourceObjects(con, null); } catch (ResourceException ex) { @@ -131,11 +132,9 @@ public void fillInResourceObjects(ResourceHandle resource) } @Override - public void destroyResource(ResourceHandle resource) - throws PoolingException { - + public void destroyResource(ResourceHandle resource) throws PoolingException { try { - ManagedConnection mc = (ManagedConnection) resource.getResource(); + ManagedConnection mc = resource.getResource(); mc.destroy(); } catch (Exception ex) { throw new PoolingException(ex); 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 cb312fdb5fe..4b26a4f6113 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 @@ -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 @@ -38,7 +38,19 @@ public interface ResourceAllocator { void destroyResource(ResourceHandle resource) throws PoolingException; - boolean matchConnection(ResourceHandle h); + /** + * Represents the "match-connections" configuration value of a connection pool.
+ * If true, enables connection matching. You can set to false if connections are homogeneous. + *

+ * Jakarta documentation: + * {@link jakarta.resource.spi.ManagedConnectionFactory#matchManagedConnections(Set, Subject, ConnectionRequestInfo)} + * mentions: "criteria used for matching is specific to a resource adapter and is not prescribed by the Connector + * specification." + * + * @param handle The resource handle to be matched. + * @return True if matching applies to this handle, otherwise false + */ + boolean matchConnection(ResourceHandle handle); boolean isTransactional(); diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/AssocWithThreadResourcePool.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/AssocWithThreadResourcePool.java index 3fbfd34e4e7..ecbcb0e8c27 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/AssocWithThreadResourcePool.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/AssocWithThreadResourcePool.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 @@ -49,7 +49,7 @@ public AssocWithThreadResourcePool(PoolInfo poolInfo, Hashtable env) throws Pool @Override protected void initializePoolDataStructure() throws PoolingException { dataStructure = DataStructureFactory.getDataStructure("com.sun.enterprise.resource.pool.datastructure.ListDataStructure", - dataStructureParameters, maxPoolSize, this, resourceSelectionStrategyClass); + dataStructureParameters, maxPoolSize, this); } /** 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 6a99a0f12cb..4fcd48d927d 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024 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 @@ -128,10 +128,8 @@ public class ConnectionPool implements ResourcePool, ConnectionLeakListener, Res * Specifies whether connections have to be validated before being given to the application. If a resource’s validation * fails, it is destroyed, and a new resource is created and returned.
* Default: false - * - * TODO: rename to 'connectionValidationRequired' */ - protected boolean validation; + protected boolean connectionValidationRequired; /** * Represents the "prefer-validate-over-recreate property" configuration value.
@@ -142,11 +140,20 @@ public class ConnectionPool implements ResourcePool, ConnectionLeakListener, Res */ protected boolean preferValidateOverRecreate; - // hold on to the resizer task so we can cancel/reschedule it. + /** + * True if the pool is initialized + */ + protected volatile boolean poolInitialized; + + /** + * Reference to a resizer task to be able to cancel/reschedule it. + */ protected Resizer resizerTask; - protected volatile boolean poolInitialized; - protected Timer timer; + /** + * Timer for the resizerTask. Runs every {@link #idletime} milliseconds. + */ + protected Timer resizerTaskTimer; // advanced pool config properties /** @@ -173,6 +180,7 @@ public class ConnectionPool implements ResourcePool, ConnectionLeakListener, Res * Represents the "validate-atmost-once-period-in-seconds" configuration, but in millis.
* Specifies the time interval within which a connection is validated at most once. Minimizes the number of validation * calls. A value of zero allows unlimited validation calls.
+ * This value is used when {@link #connectionValidationRequired} is set to true.
* Default: 10.000ms. */ protected long validateAtmostPeriodInMilliSeconds_; @@ -185,21 +193,16 @@ public class ConnectionPool implements ResourcePool, ConnectionLeakListener, Res */ protected int maxConnectionUsage_; - // To validate a Sun RA Pool Connection if it has not been validated - // in the past x sec. (x=idle-timeout) - // The property will be set from system property - - // com.sun.enterprise.connectors.ValidateAtmostEveryIdleSecs=true /** - * Represents the "validate-atmost-once-period-in-seconds" configuration.
- * Specifies the time interval within which a connection is validated at most once. Minimizes the number of validation - * calls. A value of zero allows unlimited validation calls.
- * Default: 0 + * To validate a Sun RA Pool Connection if it has not been validated in the past x sec. (x=idle-timeout). The property + * will be set from system property: com.sun.enterprise.connectors.ValidateAtmostEveryIdleSecs=true
+ * Default: false */ private boolean validateAtmostEveryIdleSecs; - // TODO document - protected String resourceSelectionStrategyClass; - + /** + * Listener for pool monitoring statistics. + */ protected PoolLifeCycleListener poolLifeCycleListener; // Gateway used to control the concurrency within the round-trip of resource access. @@ -208,7 +211,11 @@ public class ConnectionPool implements ResourcePool, ConnectionLeakListener, Res protected ConnectionLeakDetector leakDetector; + /** + * The datastructure containing the pooled resources. + */ protected DataStructure dataStructure; + protected String dataStructureType; protected String dataStructureParameters; @@ -224,8 +231,15 @@ public class ConnectionPool implements ResourcePool, ConnectionLeakListener, Res // NOTE: This resource allocator may not be the same as the allocator passed in to getResource() protected ResourceAllocator allocator; + // TODO: selfManaged_ does not seem to be set to true in glassfish code. Remove it from ResourcePool interface. + // Glassfish 2.1 had a management-rule / self-management part, but it no longer exists in domain.xml. + // See for example package "selfmanagement" and logger "SELF_MANAGEMENT_LOGGER" in the codeline. private boolean selfManaged_; + /** + * Blocked state is true during connection pool recreation. Once blocked is set to true only resources from the pool can + * be reused which are already part of the current transaction. + */ private boolean blocked; /** @@ -257,8 +271,7 @@ protected void initializePoolDataStructure() throws PoolingException { dataStructure = DataStructureFactory.getDataStructure( dataStructureType, - dataStructureParameters, maxPoolSize, this, - resourceSelectionStrategyClass); + dataStructureParameters, maxPoolSize, this); } protected void initializeResourceSelectionStrategy() { @@ -285,13 +298,12 @@ private void setPoolConfiguration(Hashtable env) throws PoolingException { failAllConnections = poolResource.isFailAllConnections(); - validation = poolResource.isIsConnectionValidationRequired(); + connectionValidationRequired = poolResource.isIsConnectionValidationRequired(); validateAtmostEveryIdleSecs = poolResource.isValidateAtmostEveryIdleSecs(); dataStructureType = poolResource.getPoolDataStructureType(); dataStructureParameters = poolResource.getDataStructureParameters(); poolWaitQueueClass = poolResource.getPoolWaitQueue(); - resourceSelectionStrategyClass = poolResource.getResourceSelectionStrategyClass(); resourceGatewayClass = poolResource.getResourceGatewayClass(); reconfigWaitTime = poolResource.getDynamicReconfigWaitTimeout(); @@ -340,7 +352,7 @@ protected synchronized void initPool(ResourceAllocator allocator) throws Pooling } /** - * Schedules the resizer timer task. If a task is currently scheduled, it would be canceled and a new one is scheduled. + * Schedules the resizer timer task. If a task is currently scheduled, it would be cancelled and a new one is scheduled. */ private void scheduleResizerTask() { if (resizerTask != null) { @@ -351,11 +363,11 @@ private void scheduleResizerTask() { resizerTask = initializeResizer(); - if (timer == null) { - timer = ConnectorRuntime.getRuntime().getTimer(); + if (resizerTaskTimer == null) { + resizerTaskTimer = ConnectorRuntime.getRuntime().getTimer(); } - timer.scheduleAtFixedRate(resizerTask, idletime, idletime); + resizerTaskTimer.scheduleAtFixedRate(resizerTask, idletime, idletime); LOG.log(FINE, "Scheduled resizer task with the idle time {0} ms", idletime); } @@ -706,11 +718,11 @@ protected ResourceHandle getUnenlistedResource(ResourceSpec resourceSpec, Resour protected boolean isConnectionValid(ResourceHandle resourceHandle, ResourceAllocator resourceAllocator) { boolean connectionValid = true; - if (validation || validateAtmostEveryIdleSecs) { + if (connectionValidationRequired || validateAtmostEveryIdleSecs) { long validationPeriod; // validation period is idle timeout if validateAtmostEveryIdleSecs is set to true // else it is validateAtmostPeriodInMilliSeconds_ - if (validation) { + if (connectionValidationRequired) { validationPeriod = validateAtmostPeriodInMilliSeconds_; } else { validationPeriod = idletime; @@ -972,7 +984,7 @@ protected ResourceHandle createSingleResource(ResourceAllocator resourceAllocato LOG.log(FINE, () -> "Time taken to create a single resource: " + resourceHandle.getResourceSpec().getResourceId() + " and adding to the pool: " + (now - startTime) + " ms."); - if (validation || validateAtmostEveryIdleSecs) { + if (connectionValidationRequired || validateAtmostEveryIdleSecs) { resourceHandle.setLastValidated(now); } return resourceHandle; @@ -1113,6 +1125,7 @@ protected void freeResource(ResourceHandle resourceHandle) { if (cleanupResource(resourceHandle)) { // Only when resource handle usage count is more than maxConnUsage if (maxConnectionUsage_ > 0 && resourceHandle.getUsageCount() >= maxConnectionUsage_) { + // Remove the resource handle from the pool and update the monitoring data performMaxConnectionUsageOperation(resourceHandle); } else { // Put it back to the free collection. @@ -1246,11 +1259,7 @@ protected boolean isResourceUnused(ResourceHandle h) { public ResourceHandle createResource(ResourceAllocator alloc) throws PoolingException { // NOTE : Pool should not call this method directly, it should be called only by pool-datastructure ResourceHandle result = createSingleResource(alloc); - - ResourceState state = new ResourceState(); - state.setBusy(false); - state.setEnlisted(false); - result.setResourceState(state); + result.getResourceState().reset(); if (poolLifeCycleListener != null) { poolLifeCycleListener.connectionCreated(); @@ -1342,7 +1351,7 @@ public String toString() { sb.append(" matching="); sb.append((matchConnections ? "on" : "off")); sb.append(" validation="); - sb.append((validation ? "on" : "off")); + sb.append((connectionValidationRequired ? "on" : "off")); return sb.toString(); } @@ -1419,7 +1428,7 @@ public synchronized void reconfigurePool(ConnectorConnectionPool poolResource) t maxWaitTime = 0; } - validation = poolResource.isIsConnectionValidationRequired(); + connectionValidationRequired = poolResource.isIsConnectionValidationRequired(); failAllConnections = poolResource.isFailAllConnections(); setAdvancedPoolConfiguration(poolResource); @@ -1567,8 +1576,8 @@ public synchronized void cancelResizerTask() { resizerTask.cancel(); } resizerTask = null; - if (timer != null) { - timer.purge(); + if (resizerTaskTimer != null) { + resizerTaskTimer.purge(); } } 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 7a926156e2c..df200ea13a6 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 @@ -158,7 +158,7 @@ public Object getResource(ResourceSpec resourceSpec, ResourceAllocator resourceA // we need to associate a new connection with it try { Object connection = resourceSpec.getConnectionToAssociate(); - ManagedConnection managedConnection = (ManagedConnection) resourceHandle.getResource(); + ManagedConnection managedConnection = resourceHandle.getResource(); managedConnection.associateConnection(connection); } catch (ResourceException e) { putbackDirectToPool(resourceHandle, resourceSpec.getPoolInfo()); @@ -172,6 +172,9 @@ public Object getResource(ResourceSpec resourceSpec, ResourceAllocator resourceA resourceSpec.setLazyEnlistable(false); } + // Overwrite the resourceSpec value in the resourceHandle. + // TODO: explain why this is done and why resourceAllocator in the resourceHandle is not overwritten with this + // resourceAllocator. resourceHandle.setResourceSpec(resourceSpec); try { 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 455c9817ec2..c437168a166 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 @@ -38,6 +38,12 @@ public interface ResourcePool { // Modify getResource() to throw PoolingException ResourceHandle getResource(ResourceSpec spec, ResourceAllocator alloc, Transaction transaction) throws PoolingException, RetryableUnavailableException; + /** + * Indicate that the resource is not used by a bean/application anymore. + * + * @param resource The resource that is not used anymore. After the call the resource is also marked as 'not busy' / + * 'free'. + */ void resourceClosed(ResourceHandle resource); void resourceErrorOccurred(ResourceHandle resource); @@ -47,6 +53,14 @@ public interface ResourcePool { // Get status of pool PoolStatus getPoolStatus(); + /** + * Called when a transaction is completed.
+ * 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 tran The transaction + * @param status The jakarta.transaction.Status value of the transaction. + */ void transactionCompleted(Transaction tran, int status); void resizePool(boolean forced); diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/UnpooledResource.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/UnpooledResource.java index a02d9a13eb2..a01ee55a8b5 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/UnpooledResource.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/UnpooledResource.java @@ -20,7 +20,6 @@ import com.sun.appserv.connectors.internal.api.PoolingException; import com.sun.enterprise.resource.ResourceHandle; import com.sun.enterprise.resource.ResourceSpec; -import com.sun.enterprise.resource.ResourceState; import com.sun.enterprise.resource.allocator.ResourceAllocator; import jakarta.transaction.Transaction; @@ -81,10 +80,7 @@ protected ResourceHandle getUnenlistedResource(ResourceSpec spec, ResourceAlloca this.poolSize.decrement(); throw ex; } - - ResourceState state = new ResourceState(); - handle.setResourceState(state); - state.setEnlisted(false); + handle.getResourceState().reset(); setResourceStateToBusy(handle); return handle; } diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/DataStructureFactory.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/DataStructureFactory.java index 860da482041..fc11622701f 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/DataStructureFactory.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/DataStructureFactory.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 @@ -39,33 +39,33 @@ public class DataStructureFactory { // TODO synchronize datastructure creation ? protected final static Logger _logger = LogDomains.getLogger(DataStructureFactory.class, LogDomains.RSR_LOGGER); - public static DataStructure getDataStructure(String className, String parameters, int maxPoolSize, ResourceHandler handler, String strategyClass) throws PoolingException { + public static DataStructure getDataStructure(String className, String parameters, int maxPoolSize, ResourceHandler handler) throws PoolingException { DataStructure dataStructure; if (className != null) { if (className.equals(ListDataStructure.class.getName())) { - dataStructure = new ListDataStructure(parameters, maxPoolSize, handler, strategyClass); + dataStructure = new ListDataStructure(parameters, maxPoolSize, handler); } else if (className.equals(RWLockDataStructure.class.getName())) { - dataStructure = new RWLockDataStructure(parameters, maxPoolSize, handler, strategyClass); + dataStructure = new RWLockDataStructure(parameters, maxPoolSize, handler); } else { - dataStructure = initializeCustomDataStructureInPrivilegedMode(className, parameters, maxPoolSize, handler, strategyClass); + dataStructure = initializeCustomDataStructureInPrivilegedMode(className, parameters, maxPoolSize, handler); } } else { debug("Initializing RWLock DataStructure"); - dataStructure = new RWLockDataStructure(parameters, maxPoolSize, handler, strategyClass); + dataStructure = new RWLockDataStructure(parameters, maxPoolSize, handler); } return dataStructure; } - private static DataStructure initializeCustomDataStructureInPrivilegedMode(final String className, final String parameters, final int maxPoolSize, final ResourceHandler handler, final String strategyClass) throws PoolingException { + private static DataStructure initializeCustomDataStructureInPrivilegedMode(final String className, final String parameters, final int maxPoolSize, final ResourceHandler handler) throws PoolingException { Object result = AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { Object result = null; try { - result = initializeDataStructure(className, parameters, maxPoolSize, handler, strategyClass); + result = initializeDataStructure(className, parameters, maxPoolSize, handler); } catch (Exception e) { _logger.log(WARNING, "pool.datastructure.init.failure", className); _logger.log(WARNING, "pool.datastructure.init.failure.exception", e); @@ -80,12 +80,12 @@ public Object run() { } } - private static DataStructure initializeDataStructure(String className, String parameters, int maxPoolSize, ResourceHandler handler, String strategyClass) throws Exception { + private static DataStructure initializeDataStructure(String className, String parameters, int maxPoolSize, ResourceHandler handler) throws Exception { DataStructure ds; - Object[] constructorParameters = new Object[] { parameters, maxPoolSize, handler, strategyClass }; + Object[] constructorParameters = new Object[] { parameters, maxPoolSize, handler }; Class class1 = Thread.currentThread().getContextClassLoader().loadClass(className); - Constructor constructor = class1.getConstructor(String.class, int.class, ResourceHandler.class, String.class); + Constructor constructor = class1.getConstructor(String.class, int.class, ResourceHandler.class); ds = (DataStructure) constructor.newInstance(constructorParameters); _logger.log(FINEST, "Using Pool Data Structure : ", className); diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/ListDataStructure.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/ListDataStructure.java index 7747abd8e69..a44d6177ed3 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/ListDataStructure.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/ListDataStructure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 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 @@ -44,16 +44,14 @@ public class ListDataStructure implements DataStructure { private ResourceHandler handler; private ResourceSelectionStrategy strategy; - public ListDataStructure(String parameters, int maxSize, ResourceHandler handler, String strategyClass) { + public ListDataStructure(String parameters, int maxSize, ResourceHandler handler) { resources = new ArrayList<>((maxSize > 1000) ? 1000 : maxSize); free = new ArrayList<>((maxSize > 1000) ? 1000 : maxSize); this.handler = handler; - initializeStrategy(strategyClass); dynSemaphore = new DynamicSemaphore(); setMaxSize(maxSize); } - /** * Set maxSize based on the new max pool size set on the connection pool * during a reconfiguration. @@ -86,10 +84,6 @@ public synchronized void setMaxSize(int newMaxSize) { this.maxSize = newMaxSize; } - private void initializeStrategy(String strategyClass) { - //TODO - } - /** * creates a new resource and adds to the datastructure. * diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/RWLockDataStructure.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/RWLockDataStructure.java index cde98b9007e..22fb2b3a09a 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/RWLockDataStructure.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/datastructure/RWLockDataStructure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 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 @@ -54,7 +54,7 @@ public class RWLockDataStructure implements DataStructure { private volatile int maxSize; - public RWLockDataStructure(String parameters, int maxSize, ResourceHandler handler, String strategyClass) { + public RWLockDataStructure(String parameters, int maxSize, ResourceHandler handler) { this.availableResources = new DataStructureSemaphore(maxSize); this.useMask = new BitSet(maxSize); this.resources = new ResourceHandle[maxSize]; @@ -64,7 +64,6 @@ public RWLockDataStructure(String parameters, int maxSize, ResourceHandler handl LOG.log(Level.FINEST, "pool.datastructure.rwlockds.init"); } - @Override public int addResource(ResourceAllocator allocator, int count) throws PoolingException { int numResAdded = 0; @@ -96,7 +95,7 @@ public int addResource(ResourceAllocator allocator, int count) throws PoolingExc newResources = Arrays.copyOf(resources, currentMaxSize); } - resource.setIndex(size); + resource.setRwLockDataStructureResourceIndex(size); stamp = lock.tryConvertToWriteLock(stamp); if (stamp == 0L) { @@ -167,7 +166,7 @@ public void removeResource(ResourceHandle resource) { } int currentSize = size; - int removeIndex = resource.getIndex(); + int removeIndex = resource.getRwLockDataStructureResourceIndex(); if (!lock.validate(stamp)) { continue; } @@ -196,7 +195,7 @@ public void removeResource(ResourceHandle resource) { if (removeIndex < lastIndex) { // Move last resource in place of removed ResourceHandle lastResource = resources[lastIndex]; - lastResource.setIndex(removeIndex); + lastResource.setRwLockDataStructureResourceIndex(removeIndex); resources[removeIndex] = lastResource; useMask.set(removeIndex, useMask.get(lastIndex)); } @@ -228,7 +227,7 @@ public void returnResource(ResourceHandle resource) { } int currentSize = size; - int returnIndex = resource.getIndex(); + int returnIndex = resource.getRwLockDataStructureResourceIndex(); if (!lock.validate(stamp)) { continue; } diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/resizer/AssocWithThreadPoolResizer.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/resizer/AssocWithThreadPoolResizer.java index 722a1b825b9..f76b2591ada 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/resizer/AssocWithThreadPoolResizer.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/resizer/AssocWithThreadPoolResizer.java @@ -186,7 +186,7 @@ private int removeInvalidResources(Set freeConnectionsToValidate for (ResourceHandle handle : freeConnectionsToValidate) { if (handle != null) { Set connectionsToTest = new HashSet<>(); - connectionsToTest.add((ManagedConnection) handle.getResource()); + connectionsToTest.add(handle.getResource()); Set invalidConnections = handler.getInvalidConnections(connectionsToTest); if (invalidConnections != null && !invalidConnections.isEmpty()) { invalidConnectionsCount = validateAndRemoveResource(handle, invalidConnections); diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/resizer/Resizer.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/resizer/Resizer.java index 64fe247456f..4e255f99996 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/resizer/Resizer.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/resource/pool/resizer/Resizer.java @@ -232,7 +232,7 @@ private void removeInvalidResources(Set freeConnectionsToValidate) { // validate if the connection is one in the freeConnectionsToValidate if (freeConnectionsToValidate.contains(handle.toString())) { Set connectionsToTest = new HashSet<>(); - connectionsToTest.add((ManagedConnection) handle.getResource()); + connectionsToTest.add(handle.getResource()); Set invalidConnections = handler.getInvalidConnections(connectionsToTest); if (invalidConnections != null && !invalidConnections.isEmpty()) { invalidConnectionsCount = validateAndRemoveResource(handle, invalidConnections); 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 b50b8e96e8a..fe7b16f0496 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 @@ -96,7 +96,7 @@ public void lazyEnlist(ManagedConnection managedConnection) throws ResourceExcep ListIterator it = l.listIterator(); while (it.hasNext()) { ResourceHandle hand = (ResourceHandle) it.next(); - ManagedConnection toEnlist = (ManagedConnection) hand.getResource(); + ManagedConnection toEnlist = hand.getResource(); if (managedConnection.equals(toEnlist)) { resourceHandle = hand; break; @@ -114,7 +114,7 @@ public void lazyEnlist(ManagedConnection managedConnection) throws ResourceExcep // The other case might or might not work if (resourceHandle != null && resourceHandle.getResourceState().isUnenlisted()) { try { - // Enable the suspended lazyenlistment so as to enlist the resource. + // Enable enlistment to be able to enlist the resource. resourceHandle.setEnlistmentSuspended(false); transactionManager.enlistResource(transaction, resourceHandle); diff --git a/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/listener/LocalTxConnectionEventListenerTest.java b/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/listener/LocalTxConnectionEventListenerTest.java index ee02d2a19af..1e3bce1872b 100644 --- a/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/listener/LocalTxConnectionEventListenerTest.java +++ b/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/listener/LocalTxConnectionEventListenerTest.java @@ -82,6 +82,6 @@ public void getAssociatedHandlesAndClearMapTest() throws ResourceException { private ResourceHandle createResourceHandle(int i) throws ResourceException { ManagedConnection managedConnection = createNiceMock(ManagedConnection.class); replay(); - return new ResourceHandle(managedConnection, new ResourceSpec(new SimpleJndiName("testResource" + i), 0), null, null); + return new ResourceHandle(managedConnection, new ResourceSpec(new SimpleJndiName("testResource" + i), 0), null); } } diff --git a/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/ConnectionPoolTest.java b/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/ConnectionPoolTest.java index e45c5d96214..0f970ce1fd7 100644 --- a/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/ConnectionPoolTest.java +++ b/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/ConnectionPoolTest.java @@ -443,6 +443,9 @@ private void cleanupConnectionPool() { // Clean the pool connectionPool.emptyPool(); assertResourcesSize(0); + + PoolStatus poolStatus = connectionPool.getPoolStatus(); + assertEquals(0, poolStatus.getNumConnFree()); } public static class MyConnectionPool extends ConnectionPool { diff --git a/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/datastructure/RWLockDataStructureTest.java b/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/datastructure/RWLockDataStructureTest.java index 5dbd7930a68..2d1d2edd799 100644 --- a/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/datastructure/RWLockDataStructureTest.java +++ b/appserver/connectors/connectors-runtime/src/test/java/com/sun/enterprise/resource/pool/datastructure/RWLockDataStructureTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Eclipse Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -17,12 +17,13 @@ package com.sun.enterprise.resource.pool.datastructure; import com.sun.appserv.connectors.internal.api.PoolingException; -import com.sun.enterprise.resource.ClientSecurityInfo; import com.sun.enterprise.resource.ResourceHandle; import com.sun.enterprise.resource.ResourceSpec; import com.sun.enterprise.resource.allocator.ResourceAllocator; import com.sun.enterprise.resource.pool.ResourceHandler; +import jakarta.resource.spi.ManagedConnection; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -80,9 +81,9 @@ public void createAndPopulateMocks() throws PoolingException { // We use constructor to generate ResourceHandle mock // because we depend on an internal state of this object. createMockBuilder(ResourceHandle.class) - .withConstructor(Object.class, ResourceSpec.class, ResourceAllocator.class, ClientSecurityInfo.class) + .withConstructor(ManagedConnection.class, ResourceSpec.class, ResourceAllocator.class) // Actual constructor arguments does not matter - .withArgs(null, null, null, null) + .withArgs(null, null, null) .createNiceMock()); } @@ -107,7 +108,7 @@ public void testAddResource() throws Exception { int resourceCount = RESOURCE_COUNT / 2; int taskCount = TASK_COUNT / 2; - DataStructure dataStructure = new RWLockDataStructure(null, resourceCount, handler, null); + DataStructure dataStructure = new RWLockDataStructure(null, resourceCount, handler); List> tasks = new ArrayList<>(taskCount); for (int i = 0; i < taskCount; i++) { @@ -158,8 +159,8 @@ public void testAddResourceWithException() throws Exception { allocator = createNiceMock(ResourceAllocator.class); ResourceHandle resource = createMockBuilder(ResourceHandle.class) - .withConstructor(Object.class, ResourceSpec.class, ResourceAllocator.class, ClientSecurityInfo.class) - .withArgs(null, null, null, null) + .withConstructor(ManagedConnection.class, ResourceSpec.class, ResourceAllocator.class) + .withArgs(null, null, null) .createNiceMock(); expect(handler.createResource(allocator)).andThrow(new PoolingException()); @@ -169,7 +170,7 @@ public void testAddResourceWithException() throws Exception { replay(resource, handler, allocator); - DataStructure dataStructure = new RWLockDataStructure(null, 1, handler, null); + DataStructure dataStructure = new RWLockDataStructure(null, 1, handler); assertAll( () -> assertThrows(PoolingException.class, () -> dataStructure.addResource(allocator, 1)), @@ -188,7 +189,7 @@ public void testAddResourceWithException() throws Exception { @Timeout(value = 10, threadMode = ThreadMode.SEPARATE_THREAD) public void testGetResource() throws Exception { - DataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler, null); + DataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler); assertThat("Add Resources", dataStructure.addResource(allocator, RESOURCE_COUNT), equalTo(RESOURCE_COUNT)); @@ -223,7 +224,7 @@ public void testGetResource() throws Exception { @Timeout(value = 10, threadMode = ThreadMode.SEPARATE_THREAD) public void testReturnResource() throws Exception { - DataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler, null); + DataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler); assertThat("Add Resources", dataStructure.addResource(allocator, RESOURCE_COUNT), equalTo(RESOURCE_COUNT)); assertThat("Free List Size", dataStructure.getFreeListSize(), equalTo(RESOURCE_COUNT)); @@ -261,7 +262,7 @@ public void testReturnResource() throws Exception { @Timeout(value = 10, threadMode = ThreadMode.SEPARATE_THREAD) public void testRemoveResource() throws Exception { - DataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler, null); + DataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler); assertThat("Add Resources", dataStructure.addResource(allocator, RESOURCE_COUNT), equalTo(RESOURCE_COUNT)); @@ -295,7 +296,7 @@ public void testRemoveResource() throws Exception { @Test public void testRemoveAll() throws PoolingException { - DataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler, null); + DataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler); dataStructure.addResource(allocator, RESOURCE_COUNT); assertThat("Resources Size", dataStructure.getResourcesSize(), equalTo(RESOURCE_COUNT)); @@ -313,7 +314,7 @@ public void testRemoveAll() throws PoolingException { @Timeout(value = 10, threadMode = ThreadMode.SEPARATE_THREAD) public void testRaceConditions() throws Exception { - RWLockDataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler, null); + RWLockDataStructure dataStructure = new RWLockDataStructure(null, RESOURCE_COUNT, handler); for (int i = 0; i < RESOURCE_COUNT; i++) { // requires handler.createResource(allocator) diff --git a/appserver/transaction/internal-api/src/main/java/com/sun/enterprise/transaction/api/JavaEETransactionManager.java b/appserver/transaction/internal-api/src/main/java/com/sun/enterprise/transaction/api/JavaEETransactionManager.java index a1550d7556f..4f9d77d5f89 100644 --- a/appserver/transaction/internal-api/src/main/java/com/sun/enterprise/transaction/api/JavaEETransactionManager.java +++ b/appserver/transaction/internal-api/src/main/java/com/sun/enterprise/transaction/api/JavaEETransactionManager.java @@ -49,7 +49,7 @@ public interface JavaEETransactionManager extends TransactionManager { /** - * register a synchronization object with the transaction + * Register a synchronization object with the transaction * associated with the current thread * * @param sync the synchronization object @@ -68,12 +68,9 @@ void registerSynchronization(Synchronization sync) /** * Enlist the resource specified with the transaction * - * * @param tran The transaction object - * * @param h The resource handle object - * - * @return true if the resource was enlisted successfully; otherwise * false. + * @return true if the resource was enlisted successfully; otherwise false. * * @exception RollbackException Thrown to indicate that * the transaction has been marked for rollback only. @@ -94,9 +91,7 @@ boolean enlistResource(Transaction tran, * Delist the resource specified from the transaction * * @param tran The transaction object - * * @param h The resource handle object - * * @param flag One of the values of TMSUCCESS, TMSUSPEND, or TMFAIL. * * @exception IllegalStateException Thrown if the transaction in the diff --git a/appserver/transaction/internal-api/src/main/java/com/sun/enterprise/transaction/spi/TransactionalResource.java b/appserver/transaction/internal-api/src/main/java/com/sun/enterprise/transaction/spi/TransactionalResource.java index 929d0caae0a..0c843c2642e 100644 --- a/appserver/transaction/internal-api/src/main/java/com/sun/enterprise/transaction/spi/TransactionalResource.java +++ b/appserver/transaction/internal-api/src/main/java/com/sun/enterprise/transaction/spi/TransactionalResource.java @@ -1,4 +1,5 @@ /* + * 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 @@ -20,44 +21,91 @@ import javax.transaction.xa.XAResource; /** - * TransactionalResource interface to be implemented by the resource handlers - * to be able to communicate with used the transaction manager components + * TransactionalResource interface to be implemented by the resource handlers to be able to communicate with the + * transaction manager components. * * @author Marina Vatkina */ - public interface TransactionalResource { + /** + * Returns true if the resource is part of a transaction. + * + * @return true if the resource is part of a transaction. + */ public boolean isTransactional(); - //TODO V3 not needed as of now. + /** + * To check whether lazy enlistment is suspended or not.
+ * If {@code true}, transaction manager will not do enlist/lazy enlist. + * + * @return true if enlistment is suspended, otherwise false. + */ public boolean isEnlistmentSuspended(); + /** + * Returns the (optional) XAResource reference for this resource handle. + * + * @return the XAResource reference for this resource handle or null if no reference is set. + */ public XAResource getXAResource(); + /** + * Returns true if the ResourceHandle is supported in an XA transaction. + * + * @return true if the ResourceHandle is supported in an XA transaction, otherwise false. + */ public boolean supportsXA(); + /** + * Returns the component instance holding this resource handle. + * + * @return the component instance holding this resource handle. + */ public Object getComponentInstance(); + /** + * Sets the component instance holding this resource handle. + * + * @param instance the component instance holding this resource handle. + */ public void setComponentInstance(Object instance); + /** + * Closes the (optional) 'userConnection' / 'connection handle' (used by the application code to refer to the underlying + * physical connection). Example: the ManagedConnection represented by this ResourceHandle is closed / cleaned up. + * + * @throws PoolingException wrapping any 'userConnection' specific exception that might occur during the close call. + * @throws UnsupportedOperationException when the method is not implemented. + */ public void closeUserConnection() throws Exception; + /** + * Returns true if the resource handle is enlisted in a transaction. + * + * @return true if the resource handle is enlisted in a transaction. + */ public boolean isEnlisted(); + /** + * Returns true if the resource handle is sharable within the component. + * + * @return true if the resource handle is sharable within the component. + */ public boolean isShareable(); - public void destroyResource(); - /** - * @return the String that can identify this resource + * Returns the String that can identify this resource. + * + * @return the String that can identify this resource. */ public String getName(); /** * Indicates that a resource has been enlisted in the transaction. - * @param tran Transaction to which the resource is enlisted - * @throws IllegalStateException when unable to enlist the resource + * + * @param transaction the Transaction to which the resource is enlisted. + * @throws IllegalStateException when unable to enlist the resource. */ - void enlistedInTransaction(Transaction tran) throws IllegalStateException; + void enlistedInTransaction(Transaction transaction) throws IllegalStateException; } diff --git a/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java b/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java index adc6bfcb0c7..ea725c72886 100644 --- a/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java +++ b/appserver/transaction/jta/src/main/java/com/sun/enterprise/transaction/JavaEETransactionManagerSimplified.java @@ -1404,13 +1404,6 @@ private void handleResourceError(TransactionalResource h, Exception ex, Transact } catch (Exception ex2) { // Log.err.println(ex2); } - } else { - // destroy resource. RM Error. - try { - h.destroyResource(); - } catch (Exception ex2) { - // Log.err.println(ex2); - } } } diff --git a/appserver/transaction/jts/src/test/java/com/sun/enterprise/transaction/jts/JavaEETransactionManagerTest.java b/appserver/transaction/jts/src/test/java/com/sun/enterprise/transaction/jts/JavaEETransactionManagerTest.java index eedf7a052cb..7fd9764118c 100644 --- a/appserver/transaction/jts/src/test/java/com/sun/enterprise/transaction/jts/JavaEETransactionManagerTest.java +++ b/appserver/transaction/jts/src/test/java/com/sun/enterprise/transaction/jts/JavaEETransactionManagerTest.java @@ -18,7 +18,6 @@ package com.sun.enterprise.transaction.jts; import com.sun.enterprise.config.serverbeans.ServerTags; -import com.sun.enterprise.resource.ClientSecurityInfo; import com.sun.enterprise.resource.ResourceHandle; import com.sun.enterprise.resource.ResourceSpec; import com.sun.enterprise.resource.allocator.ResourceAllocator; @@ -39,7 +38,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; - +import jakarta.resource.spi.ManagedConnection; import jakarta.transaction.HeuristicMixedException; import jakarta.transaction.HeuristicRollbackException; import jakarta.transaction.InvalidTransactionException; @@ -1034,12 +1033,12 @@ private int getStatus(String name) { } static class TestResourceHandle extends ResourceHandle { - private final XAResource resource; + private final XAResource xaResource; private static PoolManagerImpl poolMgr = new PoolManagerImpl(); - public TestResourceHandle(XAResource resource) { - super(null,new ResourceSpec(new SimpleJndiName("testResource"),0) ,null,null); - this.resource = resource; + public TestResourceHandle(XAResource xaResource) { + super(null, new ResourceSpec(new SimpleJndiName("testResource"), 0), null); + this.xaResource = xaResource; } @Override @@ -1063,13 +1062,13 @@ public ResourceAllocator getResourceAllocator() { } @Override - public Object getResource() { - return resource; + public ManagedConnection getResource() { + return null; } @Override public XAResource getXAResource() { - return resource; + return xaResource; } @Override @@ -1077,11 +1076,6 @@ public Object getUserConnection() { return null; } - @Override - public ClientSecurityInfo getClientSecurityInfo() { - return null; - } - @Override public void fillInResourceObjects(Object userConnection, XAResource xares) { }