FileDocCategorySizeDatePackage
AbstractResourcePool.javaAPI DocGlassfish v2 API88532Thu Jul 26 09:00:32 BST 2007com.sun.enterprise.resource

AbstractResourcePool

public abstract class AbstractResourcePool extends Object implements MonitorableResourcePool
this resource pool does not allow sharing A resource is only given out if it is not used by any enterprise bean and it does not have any pending transaction
author
Aditya Gore
since
9.0

Fields Summary
protected static final com.sun.enterprise.util.i18n.StringManager
localStrings
protected ArrayList
resources
protected ArrayList
free
list of ResourceHandles that are free and unenlisted
protected long
idletime
protected String
name
protected ResourceSpec
resourceSpec
protected ResourceAllocator
allocator
protected int
maxPoolSize
protected int
steadyPoolSize
protected int
resizeQuantity
protected int
maxWaitTime
protected boolean
failAllConnections
protected boolean
matchConnections
protected boolean
poolInitialized
protected Timer
timer
protected TimerTask
resizerTask
protected boolean
monitoringEnabled
protected PoolCounters
poolCounters
protected boolean
validation
protected final LinkedList
waitQueue
given a Transaction, get a Set of resources enlisted in that transaction (Transaction -> Set of ResourceHandle)
protected boolean
connectionLeakTracing_
protected long
connectionLeakTimeoutInMilliSeconds_
protected boolean
connectionLeakReclaim_
protected boolean
connectionCreationRetry_
protected int
connectionCreationRetryAttempts_
protected long
conCreationRetryInterval_
protected long
validateAtmostPeriodInMilliSeconds_
protected int
maxConnectionUsage_
private final Object
connectionLeakLock
private HashMap
connectionLeakThreadStackHashMap
private HashMap
connectionLeakTimerTaskHashMap
private boolean
selfManaged_
private boolean
validateAtmostEveryIdleSecs
protected static final Logger
_logger
Constructors Summary
public AbstractResourcePool(String poolName)

    

      //Commented from 9.1 as it is not used
   /* private boolean inTx() {
        com.sun.enterprise.ComponentInvocation inv =
                Switch.getSwitch().getInvocationManager().getCurrentInvocation();
        if (inv == null) {
            throw new com.sun.enterprise.InvocationException();
        }
        Transaction tran = inv.getTransaction();
        return (tran != null);
    }*/

        
        this.name = poolName;
        setPoolConfiguration();
        monitoringEnabled = false;
        resources = new ArrayList<ResourceHandle>(maxPoolSize);
        free = new ArrayList<ResourceHandle>(maxPoolSize);
        connectionLeakThreadStackHashMap = new HashMap<ResourceHandle, StackTraceElement[]>();
        connectionLeakTimerTaskHashMap = new HashMap<ResourceHandle, ConnectionLeakTask>();
        connectionLeakLock = new Object();
    
Methods Summary
public synchronized voidaddResource(ResourceSpec spec, ResourceHandle h)
add a resource with status busy and not enlisted

        if (_logger.isLoggable( Level.FINE ) ) {
            _logger.log(Level.FINE,"Pool: resource added: " + spec + "," + h);
        }
        // all resources in this pool have the same resource spec
        ResourceState state = new ResourceState();
        resources.add(h);
        h.setResourceState(state);
        state.setEnlisted(false);
        setResourceStateToBusy(h);
    
public synchronized voidcancelResizerTask()

        
        if (_logger.isLoggable( Level.FINE ) ) {
            _logger.finest("Cancelling resizer");
        }
        if (resizerTask != null ) {
            resizerTask.cancel();
        }
        resizerTask = null;
        
        if (timer != null){
            timer.purge();
        }
    
private voidclearAllConnectionLeakTasks()
Clear all connection leak tracing tasks in case of connection leak tracing being turned off

        synchronized(connectionLeakLock){
            Iterator<ResourceHandle> iter = connectionLeakTimerTaskHashMap.keySet().iterator();
            while(iter.hasNext()){
                ResourceHandle resourceHandle = iter.next();
                ConnectionLeakTask connectionLeakTask = connectionLeakTimerTaskHashMap.get(resourceHandle);
                connectionLeakTask.cancel();
            }
            if(timer != null)
                timer.purge();
            connectionLeakThreadStackHashMap.clear();
            connectionLeakTimerTaskHashMap.clear();
        }
    
private voidcreateResourceAndAddToPool(ResourceAllocator alloc)

throws
PoolingException

        ResourceHandle resourceHandle = createSingleResource(alloc);
        //addResource() will also increment numResourcesInPool	
        addResource(resourceSpec, resourceHandle);
        
        // addResource() does not add the resource to the free pool!!!
        // so we need to do that.
        setResourceStateToFree(resourceHandle);
        free.add(resourceHandle);
        
        if ( monitoringEnabled ) {
            poolCounters.incrementNumConnCreated();
        }
    
private synchronized voidcreateResources(ResourceAllocator alloc, int size)

        for (int i = 0; i < size; i++) {
            createResourceAndAddToPool(alloc);
        }
    
protected ResourceHandlecreateSingleResource(ResourceAllocator resourceAllocator)
Method to be used to create resource, instead of calling ResourceAllocator.createResource(). This method handles the connection creation retrial in case of failure

        ResourceHandle resourceHandle = null;
        int count = 0;
        while(true){
            try{
                count++;
                resourceHandle = resourceAllocator.createResource();
                if(validation || validateAtmostEveryIdleSecs)
                    resourceHandle.setLastValidated(System.currentTimeMillis());
                break;
            }catch(Exception ex){
                _logger.log(Level.FINE, "Connection creation failed for " + count + " time. It will be retried, "
                        + "if connection creation retrial is enabled.", ex);
                if(!connectionCreationRetry_ || count >= connectionCreationRetryAttempts_)
                    throw new PoolingException(ex);
                try {
                    Thread.sleep(conCreationRetryInterval_);
                } catch (InterruptedException ie) {
                    //ignore this exception
                }
            }
        }
        return resourceHandle;
    
protected ResourceHandlecreateSingleResourceAndAdjustPool(ResourceAllocator alloc, ResourceSpec spec)
This method will be called from the getUnenlistedResource method if we detect a failAllConnection flag. Here we simply create a new resource and replace a free resource in the pool by this resource and then give it out. This 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

        if ( free.size() != 0 ) {
            //resources.size() could be 0 if we were to run into
            //trouble while createResources(0 was called in
            //doFailAllConnectionsProcessing
            ResourceHandle rHandle =  free.get(0);
            resources.remove( rHandle );
            free.remove( rHandle );
        }
        ResourceHandle result = createSingleResource(alloc);
        addResource( spec, result );
        alloc.fillInResourceObjects( result );
        if ( monitoringEnabled ) {
            poolCounters.incrementNumConnCreated();
        }
        
        return result;
        
    
protected voiddestroyResource(ResourceHandle resourceHandle)

        try {
            resourceHandle.getResourceAllocator().destroyResource(resourceHandle);
        } catch (Exception ex) {
            _logger.log(Level.WARNING,"poolmgr.destroy_resource_failed");
            if (_logger.isLoggable( Level.FINE ) ) {
                _logger.log(Level.FINE,"poolmgr.destroy_resource_failed",ex);
            }
        } finally {
            //if connection leak tracing is running on connection being
            //destroyed due to error, then stop it
            if(resourceHandle.getResourceState().isBusy())
                stopConnectionLeakTracing(resourceHandle);
            if (monitoringEnabled) {
                poolCounters.incrementNumConnDestroyed();
                if (resourceHandle.getResourceState().isBusy()){
                    //Destroying a Connection due to error
                    poolCounters.decrementNumConnUsed(true);
                } else {
                    //Destroying a free Connection
                    poolCounters.decrementNumConnFree();
                }
            }
        }
    
public voiddisableMonitoring()

        monitoringEnabled = false;
    
private voiddoFailAllConnectionsProcessing()

        logFine("doFailAllConnectionsProcessing entered");
        cancelResizerTask();
        if ( monitoringEnabled ) {
            poolCounters.incrementNumConnFailedValidation(resources.size());
        }
        
        emptyPool();
	try {
	    createResources(allocator, steadyPoolSize);
	} catch(PoolingException pe) {
	    //Ignore and hope the resizer does its stuff
	    logFine( "in doFailAllConnectionsProcessing couldn't create steady resources");
	}
	scheduleResizerTask();
	logFine("doFailAllConnectionsProcessing done - created new resources");

    
public synchronized voiddumpPoolStatus()
This method can be used for debugging purposes

        _logger.log(Level.INFO, "Name of pool :" + name);
        _logger.log(Level.INFO, "Free connections :" + free.size());
        _logger.log(Level.INFO, "Total connections :" + resources.size());
        _logger.log(Level.INFO, "Pool's matching is :" + matchConnections);
        _logger.log(Level.INFO, "Free Table is :" + free);
        _logger.log(Level.INFO, "Resource Table is :" + resources);
    
public synchronized voidemptyFreeConnectionsInPool()

        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine( "Emptying free connections in pool : " + name );
        }
        for (Object aFree : free) {
            ResourceHandle h = (ResourceHandle) aFree;
            resources.remove(h);
            destroyResource(h);
        }
        free.clear();
    
public synchronized voidemptyPool()

        logFine("EmptyPool: Name = " + name);
        
        Iterator iter = resources.iterator();
        while(iter.hasNext()) {
            ResourceHandle h = (ResourceHandle) iter.next();
            destroyResource(h);
        }
        free.clear();
        resources.clear();
    
private synchronized voidenforceDelistment(ResourceHandle h)
Remove the resource from book-keeping

param
h ResourceHandle to be delisted

            J2EETransaction  txn = (J2EETransaction)Switch.getSwitch().getTransactionManager().getTransaction();
            if(txn != null){
                Set set = txn.getResources(name);
                if(set != null)
                    set.remove(h);
            }
    
protected synchronized voidfreeResource(ResourceHandle resourceHandle)

        // Put it back to the free collection.
        free.add(resourceHandle);
        //update the monitoring data
        if(monitoringEnabled){
            poolCounters.decrementNumConnUsed(false);
        }

        if (maxConnectionUsage_ > 0) {
            performMaxConnectionUsageOperation(resourceHandle);
        }

        //for both the cases of free.add and maxConUsageOperation, a free resource is added.
        // Hence notify waiting threads
        notifyWaitingThreads();
    
protected synchronized voidfreeUnenlistedResource(ResourceHandle h)

        freeResource(h);
    
public longgetCurrentConnRequestWaitTime()

        return poolCounters.currConnectionRequestWait;
    
public longgetMaxConnRequestWaitTime()

        return poolCounters.maxConnectionRequestWait;
    
public longgetMaxNumConnFree()

        return poolCounters.maxNumConnFree;
    
public longgetMaxNumConnUsed()
Return the maximum number of connections ever used in this pool

        return poolCounters.maxNumConnUsed;
    
public intgetMaxPoolSize()

        return maxPoolSize;
    
public longgetMinConnRequestWaitTime()

        if(poolCounters.minConnectionRequestWait != Long.MAX_VALUE) {
            return  poolCounters.minConnectionRequestWait;
        } else {
            return 0;
        }
    
public longgetMinNumConnFree()

        if (poolCounters.minNumConnFree != Long.MAX_VALUE) {
            return poolCounters.minNumConnFree;
        } else {
            return 0;
        }
    
public longgetMinNumConnUsed()

        if (poolCounters.minNumConnUsed != Long.MAX_VALUE) {
            return poolCounters.minNumConnUsed;
        } else {
            return 0;
        }
    
public longgetNumConnAcquired()

        return poolCounters.numConnAcquired;
    
public longgetNumConnCreated()

        return poolCounters.numConnCreated;
    
public longgetNumConnDestroyed()

        return poolCounters.numConnDestroyed;
    
public longgetNumConnFailedValidation()
Return the number of connections that have failed validation

        return poolCounters.numConnFailedValidation;
    
public synchronized longgetNumConnFree()
Return the number of free connections in the pool

        return poolCounters.currNumConnFree;
    
public synchronized longgetNumConnInUse()
Return the number of connections in use

        return poolCounters.currNumConnUsed;
    
public longgetNumConnNotSuccessfullyMatched()

        return poolCounters.numConnNotSuccessfullyMatched;
    
public longgetNumConnReleased()

        return poolCounters.numConnReleased;
    
public longgetNumConnSuccessfullyMatched()

        return poolCounters.numConnSuccessfullyMatched;
    
public longgetNumConnTimedOut()
Return the number of threads that have time out after waiting to obtain a connection from the pool.

        return poolCounters.numConnTimedOut;
    
public longgetNumPotentialConnLeak()

        return poolCounters.numPotentialConnLeak;
    
public intgetNumThreadWaiting()
Return the number of threads that are waiting to obtain a connection from the pool

        return waitQueue.size();
    
public com.sun.enterprise.resource.AbstractResourcePool$PoolCountersgetPoolCounters()

        return this.poolCounters;
    
public java.lang.StringgetPoolName()
query the name of this pool. Required by monitoring

return
the name of this pool

        return name;
    
public ResourceHandlegetResource(ResourceSpec spec, ResourceAllocator alloc, javax.transaction.Transaction tran)
returns resource from the pool.

return
a free pooled resource object matching the ResourceSpec
throws
PoolingException - if any error occurrs - or the pool has reached its max size and the max-connection-wait-time-in-millis has expired.

        //Note: this method should not be synchronized or the
        //      startTime would be incorrect for threads waiting to enter
        
        /*
         * Here are all the comments for the method put togethar for
         * easy reference.
         *  1.
            // - Try to get a free resource. Note: internalGetResource()
            // will create a new resource if none is free and the max has
            // not been reached.
            // - If can't get one, get on the wait queue.
            // - Repeat this until maxWaitTime expires.
            // - If maxWaitTime == 0, repeat indefinitely.
         
            2.
            //the doFailAllConnectionsProcessing method would already
            //have been invoked by now.
            //We simply go ahead and create a new resource here
            //from the allocator that we have and adjust the resources
            //list accordingly so as to not exceed the maxPoolSize ever
            //(i.e if steadyPoolSize == maxPoolSize )
            ///Also since we are creating the resource out of the allocator
            //that we came into this method with, we need not worry about
            //matching
         */
        ResourceHandle result = null;
        
        long startTime = 0;
        long elapsedWaitTime = 0;
        long remainingWaitTime = 0;
        
        Object waitMonitor = new Object();
        
        if (maxWaitTime > 0) {
            startTime = System.currentTimeMillis();
        }
        
        while (true) {
            //See comment #1 above
            result = internalGetResource(spec, alloc, tran);
            
            if (result != null) {
                // got one, return it
                if (monitoringEnabled) {
                    poolCounters.incrementNumConnAcquired();
                    elapsedWaitTime = System.currentTimeMillis() - startTime;
                    poolCounters.setWaitTime(elapsedWaitTime);
                }
                
                
                //got one - seems we are not doing validation or matching
                //return it
                break;
            } else {
                // did not get a resource.
                if (maxWaitTime > 0) {
                    elapsedWaitTime = System.currentTimeMillis() - startTime;
                    if (elapsedWaitTime < maxWaitTime) {
                        // time has not expired, determine remaining wait time.
                        remainingWaitTime = maxWaitTime - elapsedWaitTime;
                    } else {
                        // wait time has expired
                        if (monitoringEnabled) {
                            poolCounters.incrementNumConnTimedOut();
                        }
                        String msg = localStrings.getStringWithDefault(
                                "poolmgr.no.available.resource",
                                "No available resource. Wait-time expired.");
                        throw new PoolingException(msg);
                    }
                }
                
                synchronized (waitMonitor) {
                    synchronized (waitQueue) {
                        waitQueue.addLast(waitMonitor);
                    }
                    try {
                        if (_logger.isLoggable( Level.FINE) ) {
                            _logger.log(Level.FINE,"Resource Pool: getting on wait queue");
                        }
                        //numConnWaited++;
                        waitMonitor.wait(remainingWaitTime);
                        
                    } catch (InterruptedException ex) {
                        //Could be system shutdown.
                        break;
                    }
                    
                    //try to remove in case that the monitor has timed
                    // out.  We dont expect the queue to grow to great numbers
                    // so the overhead for removing inexistant objects is low.
                    synchronized( waitQueue ) {
                        waitQueue.remove(waitMonitor);
                    }
                }
            }
        }
        
        alloc.fillInResourceObjects(result);
        return result;
    
protected synchronized ResourceHandlegetResourceFromPool(ResourceSpec spec, ResourceAllocator alloc, javax.transaction.Transaction tran)
return resource in free list. If none is found, try to scale up the pool/purge pool and
return a new resource. returns null if the pool new resources cannot be created.

param
spec ResourceSpec
param
alloc ResourceAllocator
param
tran Transaction
return
ResourceHandle resource from pool
throws
PoolingException if unable to create a new resource

        
        // the order of serving a resource request
        // 1. free and enlisted in the same transaction
        // 2. free and unenlisted
        // Do NOT give out a connection that is
        // free and enlisted in a different transaction
        ResourceHandle result = null;
        
        Iterator iter = free.iterator();
        while (iter.hasNext()) {
            ResourceHandle h = (ResourceHandle) iter.next();
            if (h.hasConnectionErrorOccurred()) {
                iter.remove();
                continue;
            }
            // This check does not seem to be needed. 
            // TODO: Evaluate and remove this check
            //h.isAssociated can only be true for
            //AssocWithThreadResourcePool
            if ( h.isAssociated() ) {
                //Don't touch it then
                continue;
            }

            if (matchConnection(h, alloc)) {
                result = h;
                break;
            }
        }
        
        if (result != null) {
            // set correct state
            setResourceStateToBusy(result);
            free.remove(result);
        } else {
            result = resizePoolAndGetNewResource(alloc);
        }
        return result;
    
private ResourceStategetResourceState(ResourceHandle h)

        return h.getResourceState();
    
public intgetSteadyPoolSize()

        return steadyPoolSize;
    
public longgetTotalConnectionRequestWaitTime()

        return poolCounters.totalConnectionRequestWait;
    
protected ResourceHandlegetUnenlistedResource(ResourceSpec spec, ResourceAllocator alloc, javax.transaction.Transaction tran)
To provide an unenlisted, valid, matched resource from pool.

param
spec ResourceSpec
param
alloc ResourceAllocator
param
tran Transaction
return
ResourceHandle resource from pool
throws
PoolingException Exception while getting resource from pool

        ResourceHandle resource ;
        while((resource=getResourceFromPool(spec, alloc, tran))!=null){
        boolean isValid = isConnectionValid(resource, alloc);

            if (resource.hasConnectionErrorOccurred() || !isValid) {
                synchronized (this) {
                    if (failAllConnections) {
                        resource = createSingleResourceAndAdjustPool(alloc, spec);
                        //no need to match since the resource is created with the allocator of caller.
                        break;
                    } else {
                        resources.remove(resource);
                        destroyResource(resource);
                        //resource is invalid, continue iteration.
                        continue;
                    }
                }
            }
            // got a matched, valid resource
            break;
        }
        return resource;
    
private voidincreaseSteadyPoolSize(int newSteadyPoolSize)

        cancelResizerTask();
        for (int i = resources.size(); i < newSteadyPoolSize; i++) {
            createResourceAndAddToPool(allocator);
        }
        scheduleResizerTask();
    
private voidincrementNumConnFailedValidation()

        if (monitoringEnabled) {
            poolCounters.incrementNumConnFailedValidation(1);
        }
    
protected synchronized voidinitPool(ResourceSpec resourceSpec, ResourceAllocator allocator)

        
        if (poolInitialized) {
            return;
        }
        
        this.resourceSpec = resourceSpec;
        this.allocator = allocator;
        
        createResources(this.allocator, steadyPoolSize);
        
        // if the idle time out is 0, then don't schedule the resizer task
        if (idletime > 0) {
            scheduleResizerTask();
        }
        poolInitialized = true;
    
protected ResourceHandleinternalGetResource(ResourceSpec spec, ResourceAllocator alloc, javax.transaction.Transaction tran)

        if (!poolInitialized) {
            initPool(spec, alloc);
        }
        ResourceHandle result = null;
        
        result = prefetch( spec, alloc, tran );
        if ( result != null ) {
            return result;
        }
        
        try {
            //comment-1: sharing is possible only if caller is marked
            //shareable, so abort right here if that's not the case
            if (tran != null && alloc.shareableWithinComponent() ) {
                J2EETransaction j2eetran = (J2EETransaction) tran;
                // case 1. look for free and enlisted in same tx
                Set set =  j2eetran.getResources(name);
                if (set != null) {
                    Iterator iter = set.iterator();
                    while (iter.hasNext()) {
                        ResourceHandle h = (ResourceHandle) iter.next();
                        if (h.hasConnectionErrorOccurred()) {
                            iter.remove();
                            continue;
                        }
                        
                        ResourceState state = h.getResourceState();
                        /*
                         * One can share a resource only for the following conditions:
                         * 1. The caller resource is shareable (look at the outermost
                         *    if marked comment-1
                         * 2. The resource enlisted inside the transaction is shareable
                         * 3. We are dealing with XA resources OR
                         *    We are deling with a non-XA resource that's not in use
                         *    Note that sharing a non-xa resource that's in use involves
                         *    associating physical connections.
                         * 4. The credentials of the resources match
                         */
                        if (h.getResourceAllocator().shareableWithinComponent()) {
                            if (spec.isXA() || isNonXAResourceAndFree(j2eetran, h)) {
                                if (matchConnections) {
                                    if (!alloc.matchConnection(h)) {
                                        if (monitoringEnabled) {
                                            poolCounters.incrementNumConnNotSuccessfullyMatched();
                                        }
                                        continue;
                                    }
                                    if (h.hasConnectionErrorOccurred()) {
                                        if (failAllConnections) {
                                            //if failAllConnections has happened, we flushed the
                                            //pool, so we don't have to do iter.remove else we
                                            //will get a ConncurrentModificationException
                                            result = null;
                                            break;
                                        }
                                        iter.remove();
                                        continue;
                                    }
                                    if (monitoringEnabled) {
                                        poolCounters.incrementNumConnSuccessfullyMatched();
                                    }
                                }
                                if (state.isFree())
                                    setResourceStateToBusy(h);
                                result = h;
                                break;
                            }
                        }
                    }
                }
            }
        } catch(ClassCastException e) {
            _logger.log(Level.FINE, "Pool: getResource : " +
                    "transaction is not J2EETransaction but a " + tran.getClass().getName() , e);
        }
        
        
        // We didnt get a connections that is already enlisted in a transaction.
        if (result == null) {
            result = getUnenlistedResource(spec, alloc, tran);
            //Only getting of an unenlisted resource results in
            //an increment of the connection used stat
            if (result != null){

                if(maxConnectionUsage_ > 0){
	                result.incrementUsageCount();
                }
                if(monitoringEnabled) {
                    poolCounters.incrementNumConnUsed();
                }
            }
        }
        return result;
        
    
private booleanisConnectionValid(ResourceHandle h, ResourceAllocator alloc)
Check whether the connection is valid

param
h Resource to be validated
param
alloc Allocator to validate the resource
return
boolean representing validation result

         boolean connectionValid = true;

         if (validation || validateAtmostEveryIdleSecs) {
             long validationPeriod;
             //validation period is idle timeout if validateAtmostEveryIdleSecs is set to true
             //else it is validateAtmostPeriodInMilliSeconds_
             if (validation)
                 validationPeriod = validateAtmostPeriodInMilliSeconds_;
             else
                 validationPeriod = idletime;
             boolean validationRequired = true;
             long currentTime = h.getLastValidated();
             if (validationPeriod > 0) {
                 currentTime = System.currentTimeMillis();
                 long timeSinceValidation = currentTime - h.getLastValidated();
                 if (timeSinceValidation < validationPeriod)
                     validationRequired = false;
             }
             if (validationRequired) {
                 if (!alloc.isConnectionValid(h)) {
                     connectionValid = false;
                     incrementNumConnFailedValidation();
                 } else {
                     h.setLastValidated(currentTime);
                 }
             }
         }
         return connectionValid;
     
private booleanisLocalResourceEligibleForReuse(ResourceHandle h)
Check whether the local resource can be put back to pool If true, unenlist the resource

param
h ResourceHandle to be verified
return
boolean

        boolean result = false;
        if((!isLocalResourceInTransaction(h))){
            try{
                enforceDelistment(h);
            }catch(SystemException se){
                _logger.log(Level.FINE,"Exception while delisting the local resource forcibily from transaction",se);
                return result;
            }
            h.getResourceState().setEnlisted(false);
            result = true;
        }
        return result;
    
private booleanisLocalResourceInTransaction(ResourceHandle h)
Check whether the local resource in question is the one participating in transaction.

param
h ResourceHandle
return
true if the resource is participating in the transaction

        boolean result = true;
               try{
                       J2EETransaction  txn = (J2EETransaction)Switch.getSwitch().getTransactionManager().getTransaction();
                       if(txn != null)
                          result = isNonXAResourceInTransaction(txn,h);
               }catch(SystemException e){
                _logger.log(Level.FINE,"Exception while checking whether the resource is nonxa " +
                        "and is enlisted in transaction : ",e); 
               }
        return result;
    
public booleanisMonitoringEnabled()

        return monitoringEnabled;
    
private booleanisNonXAResource(ResourceHandle resource)
Check whether the resource is non-xa

param
resource Resource to be verified
return
boolean indicating whether the resource is non-xa

            return !resource.getResourceSpec().isXA() ;
        
private booleanisNonXAResourceAndFree(J2EETransaction tran, ResourceHandle resource)
Check whether the resource is non-xa, free and is enlisted in transaction.

param
tran Transaction
param
resource Resource to be verified
return
boolean indicating whether the resource is free, non-xa and is enlisted in transaction

          return resource.getResourceState().isFree() &&  isNonXAResource(resource) && isNonXAResourceInTransaction(tran, resource);
        
private booleanisNonXAResourceInTransaction(J2EETransaction tran, ResourceHandle resource)
Check whether the non-xa resource is enlisted in transaction.

param
tran Transaction
param
resource Resource to be verified
return
boolean indicating whether thegiven non-xa resource is in transaction


           return  resource.equals(tran.getNonXAResource());
        
protected booleanisResourceUnused(ResourceHandle h)

        return getResourceState(h).isFree();
    
protected booleanisSelfManaged()

        return selfManaged_;
    
private voidkillExtraResources(int numToKill)

        cancelResizerTask();
        
        Iterator iter = free.iterator();
        for( int i = 0; iter.hasNext() && i < numToKill ; i++ ) {
            ResourceHandle h = (ResourceHandle) iter.next();
            resources.remove(h);
            destroyResource( h );
            iter.remove();
        }
        
        scheduleResizerTask();
    
private voidlogFine(java.lang.String msg)

        if ( _logger.isLoggable( Level.FINE) ) {
            _logger.fine( msg );
        }
    
protected booleanmatchConnection(ResourceHandle resource, ResourceAllocator alloc)
check whether the connection retrieved from the pool matches with the request.

param
resource Resource to be matched
param
alloc ResourceAllocator used to match the connection
return
boolean representing the match status of the connection

        boolean matched = true;
        if (matchConnections) {
            matched = alloc.matchConnection(resource);
            if (monitoringEnabled) {
                if (matched) {
                    poolCounters.incrementNumConnSuccessfullyMatched();
                } else {
                    poolCounters.incrementNumConnNotSuccessfullyMatched();
                }
            }
        }
        return matched;
    
protected voidnotifyWaitingThreads()

        // notify the first thread in the waitqueue
        Object waitMonitor = null;
        synchronized (waitQueue) {
            if (waitQueue.size() > 0) {
                waitMonitor = waitQueue.removeFirst();
            }
        }
        if (waitMonitor != null) {
            synchronized (waitMonitor) {
                waitMonitor.notify();
            }
        }
    
protected voidperformMaxConnectionUsageOperation(ResourceHandle handle)
If the resource is used for maxConnectionUsage times, destroy and create one

param
handle

        if (handle.getUsageCount() >= maxConnectionUsage_) {
            resources.remove(handle);
            free.remove(handle);
            destroyResource(handle);
            _logger.log(Level.INFO, "resource_pool.remove_max_used_conn", handle.getUsageCount());

            //compensate with a new resource only when the pool-size is less than steady-pool-size
            if(resources.size() < steadyPoolSize){
                try {
                    createResourceAndAddToPool(handle.getResourceAllocator());
                } catch (Exception e) {
                    _logger.log(Level.WARNING, "resource_pool.failed_creating_resource", e);
                }
            }
        }
    
private voidpotentialConnectionLeakFound(ResourceHandle resourceHandle)
Logs the potential connection leaks

        synchronized(connectionLeakLock){
            if(connectionLeakThreadStackHashMap.containsKey(resourceHandle)){
                StackTraceElement[] threadStack = connectionLeakThreadStackHashMap.remove(resourceHandle);
                printConnectionLeakTrace(threadStack);
                connectionLeakTimerTaskHashMap.remove(resourceHandle);
                if(connectionLeakReclaim_)
                    freeResource(resourceHandle);
                if(monitoringEnabled)
                    poolCounters.incrementNumPotentialConnLeak();
            }
        }
    
protected abstract ResourceHandleprefetch(ResourceSpec spec, ResourceAllocator alloc, javax.transaction.Transaction tran)

private voidprintConnectionLeakTrace(java.lang.StackTraceElement[] threadStackTrace)
Prints the stack trace of thread leaking connection to server logs

        StringBuffer stackTrace = new StringBuffer();
        String msg = localStrings.getStringWithDefault(
                "potential.connection.leak.msg",
                "A potential connection leak detected for connection pool " + name +
                ". The stack trace of the thread is provided below : ",
                new Object[]{name});
        stackTrace.append(msg + "\n");
        for(int i=2; i < threadStackTrace.length; i++)
            stackTrace.append(threadStackTrace[i].toString() + "\n");
        if(monitoringEnabled){
            msg = localStrings.getStringWithDefault("monitoring.statistics", "Monitoring Statistics :");
            stackTrace.append("\n" + msg + "\n");
            stackTrace.append(poolCounters.toString());
        }
        _logger.log(Level.WARNING, stackTrace.toString(), "ConnectionPoolName=" + name);
    
private intpurgeResources(int quantity)
Try to purge resources by size <= quantity

param
quantity maximum no. of resources to remove.
return
resourceCount No. of resources actually removed.

        //Must be called from the thread holding the lock to this pool.
        int freeResourcesCount = free.size();
        int resourcesCount = (freeResourcesCount>=quantity) ?
                quantity : freeResourcesCount;
        if(_logger.isLoggable(Level.FINE)){
            _logger.log(Level.FINE, "Purging resources of size : " + resourcesCount);
        }
        for(int i=resourcesCount-1; i>=0;i--){
            ResourceHandle resource = free.remove(i);
            resources.remove(resource);
            destroyResource(resource);
        }
        return resourcesCount;
    
public synchronized voidreconfigPoolProperties(ConnectorConnectionPool poolResource)
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

        int _idleTime = Integer.parseInt(poolResource.getIdleTimeoutInSeconds())
                * 1000;
        if(poolInitialized){
            if (_idleTime != idletime && _idleTime != 0) {
                scheduleResizerTask();
            }
            if (_idleTime == 0) {
                //resizerTask.cancel();
                cancelResizerTask();
            }
        }
        idletime = _idleTime;

        resizeQuantity = Integer.parseInt(poolResource.getPoolResizeQuantity());

        maxWaitTime = Integer.parseInt(poolResource.getMaxWaitTimeInMillis());
        //Make sure it's not negative.
        if (maxWaitTime < 0) {
            maxWaitTime = 0;
        }

        validation = poolResource.isIsConnectionValidationRequired();
        failAllConnections = poolResource.isFailAllConnections();
        boolean oldConnectionLeakTracing_ = connectionLeakTracing_;
        setAdvancedPoolConfiguration(poolResource);

            //in case of connection leak tracing being turned off clear
            //all connection leak tracing tasks
            if (!connectionLeakTracing_ && oldConnectionLeakTracing_ && poolInitialized) {
                clearAllConnectionLeakTasks();
            }

        //Self managed quantities. These are ignored if self management
        //is on
        if (!isSelfManaged()) {
            int _maxPoolSize = Integer.parseInt(poolResource.getMaxPoolSize());

            if (_maxPoolSize < steadyPoolSize) {
                //should not happen, admin must throw exception when this condition happens.
                //as a precaution set max pool size to steady pool size
                maxPoolSize = steadyPoolSize;
            } else {
                maxPoolSize = _maxPoolSize;
            }


            int _steadyPoolSize = Integer.parseInt(poolResource.getSteadyPoolSize());
            int oldSteadyPoolSize = steadyPoolSize;

            if (_steadyPoolSize > maxPoolSize) {
                //should not happen, admin must throw exception when this condition happens.
                //as a precaution set steady pool size to max pool size
                steadyPoolSize = maxPoolSize;
            } else {
                steadyPoolSize = _steadyPoolSize;
            }

            if(poolInitialized){
                //In this case we need to kill extra connections in the pool
                //For the case where the value is increased, we need not
                //do anything
                //num resources to kill is decided by the resources in the pool.
                //if we have less than current maxPoolSize resources, we need to
                //kill less.
                int toKill = resources.size() - maxPoolSize;

                if(toKill >0)
                    killExtraResources(toKill);
            }

              if (oldSteadyPoolSize != steadyPoolSize) {
                if(poolInitialized){
                    if(oldSteadyPoolSize < steadyPoolSize)
                        increaseSteadyPoolSize(_steadyPoolSize);
                } else if(monitoringEnabled){
                        poolCounters.setNumConnFree(steadyPoolSize);
                }
            }
        }
    
private voidremoveInvalidAndIdleResources()

        
        //Find all ManagedConnections that are free/not-in-use
        Set freeManagedConnections = new HashSet();
        ResourceState state;
        int size = free.size();
        // let's cache the current time since precision is not required here.
        long currentTime = System.currentTimeMillis();
        
        for (Iterator iter = free.iterator(); iter.hasNext();) {
            ResourceHandle element = (ResourceHandle) iter.next();
            
            state = getResourceState(element);
            //remove all idle-time lapsed resources.
            if (currentTime - state.getTimestamp() > idletime) {
                resources.remove(element);
                destroyResource(element);
                iter.remove();
            } else {
                freeManagedConnections.add(element.getResource());
            }
        }
        
        removeInvalidResources(freeManagedConnections);
        
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Pool: " + name + " -- Idle resources freed: " + (size - freeManagedConnections.size()));
            _logger.log(Level.FINE, "Pool: " + name + " -- Invalid resources removed: " + (freeManagedConnections.size() - free.size()));
        }
    
private voidremoveInvalidResources(java.util.Set freeManagedConnections)
Removes invalid resource handles in the pool while resizing the pool. Uses the Connector 1.5 spec 6.5.3.4 optional RA feature to obtain invalid ManagedConnections

        try {
            
            _logger.log(Level.FINE, "Sending to RA a set of free connections " +
                    "of size : " + freeManagedConnections.size());
            
            //get Invalid ManagedConnections from the resource-adapter
            Set invalidManagedConnections =
                    this.allocator.getInvalidConnections(freeManagedConnections);
            
            //Find the appropriate ResourceHandle for a returned invalid
            //ManagedConnection and destroy the Resourcehandle and references to
            //it in resources and free list.
            if (invalidManagedConnections != null) {
                _logger.log(Level.FINE, "Received from RA invalid connections : "+
                        invalidManagedConnections.size());
                
                for (Iterator iter = invalidManagedConnections.iterator();
                iter.hasNext();) {
                    ManagedConnection invalidManagedConnection =
                            (ManagedConnection) iter.next();
                    for (Iterator freeResourcesIter = free.iterator();
                    freeResourcesIter.hasNext();) {
                        ResourceHandle handle =
                                (ResourceHandle) freeResourcesIter.next();
                        if (invalidManagedConnection.equals
                                (handle.getResource())) {
                            resources.remove(handle);
                            destroyResource(handle);
                            freeResourcesIter.remove();
                            incrementNumConnFailedValidation();
                        }
                    }
                }
            } else {
                _logger.log(Level.FINE, "RA does not support " +
                        "ValidatingManagedConnectionFactory");
            }
        } catch (ResourceException re) {
            _logger.log(Level.FINE, "ResourceException while trying to " +
                    "get invalid connections from MCF", re);
        } catch (Exception e) {
            _logger.log(Level.FINE, "Exception while trying " +
                    "to get invalid connections from MCF", e);
        }
    
public synchronized voidresizePool(boolean forced)

        
        //Following will be the resizers behavior
        // a) If the wait queue is NOT empty, don't do anything.
        // b) It should try to scale down the pool by "pool-resize" value
        // c) First, Remove all invalid and idle resources, as a result one of the following may happen
        //      i)   equivalent to "pool-reize" quantity of resources are removed
        //      ii)  less than "pool-reize" quantity of resources are removed
        //           remove more resources to match pool-resize quantity, atmost to scale down till steady-pool-size
        //      iii) more than "pool-resize" quantity of resources are removed
        //           (1) if pool-size is less than steady-pool-size, bring it back to steady-pool-size.
        //           (2) if pool-size is greater than steady-pool-size, don't do anything.
        
        synchronized (waitQueue) {
            if (waitQueue.size() > 0) {
                return;
            }
        }
        
        int poolSize = resources.size();
        //remove invalid and idle resource(s)
        removeInvalidAndIdleResources();
        
        int noOfResourcesRemoved = poolSize - resources.size();
        
        if (resizeQuantity > 0 && forced) {
            int moreResourcesToRemove = resizeQuantity - noOfResourcesRemoved;
            moreResourcesToRemove = (moreResourcesToRemove <= resources.size() - steadyPoolSize) ? moreResourcesToRemove : 0;
            
            ResourceHandle h;
            if (moreResourcesToRemove > 0) {
                Iterator iter = free.iterator();
                while (iter.hasNext() && moreResourcesToRemove > 0) {
                    h = (ResourceHandle) iter.next();
                    resources.remove(h);
                    destroyResource(h);
                    iter.remove();
                    moreResourcesToRemove--;
                }
            }
        }
        
        // Now make sure that the steady pool size is met.
        
        // eliminated block sync
        if (resources.size() < steadyPoolSize) {
            // Create resources to match the steady pool size
            // changed to use resources.size() instead of counter
            for (int i = resources.size(); i < steadyPoolSize; i++) {
                try {
                    createResourceAndAddToPool(allocator);
                } catch (PoolingException ex) {
                    _logger.log(Level.WARNING,
                            "resource_pool.resize_pool_error", ex.getMessage());
                }
            }
        }
        
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Pool: " + name + " -- Resource held: " + resources.size());
        }
    
private ResourceHandleresizePoolAndGetNewResource(ResourceAllocator alloc)
Scale-up the pool to serve the new request.
If pool is at max-pool-size and free resources are found, purge unmatched
resources, create new connections and serve the request.

param
alloc ResourceAllocator used to create new resources
return
ResourceHandle newly created resource
throws
PoolingException when not able to create resources

        //Must be called from the thread holding the lock to this pool.
        ResourceHandle result = null ;
        int numOfConnsToCreate = 0;
        if (resources.size() < steadyPoolSize) {
            // May be all invalid resources are destroyed as
            // a result no free resource found and no. of resources is less than steady-pool-size
            numOfConnsToCreate = steadyPoolSize - resources.size();
        } else if (resources.size() + resizeQuantity <= maxPoolSize) {
            //Create and add resources of quantity "resizeQuantity"
            numOfConnsToCreate = resizeQuantity;
        } else if (resources.size() < maxPoolSize) {
            // This else if "test condition" is not needed. Just to be safe.
            // still few more connections (less than "resizeQuantity" and to reach the count of maxPoolSize)
            // can be added
            numOfConnsToCreate = maxPoolSize - resources.size();
        }
        if (numOfConnsToCreate > 0) {
            createResources(alloc, numOfConnsToCreate);

            int newResourcesIndex = free.size() - numOfConnsToCreate;
            result =  free.remove(newResourcesIndex);
            setResourceStateToBusy(result);
        }else if(free.size() > 0){
            //pool cannot create more connections as it is at max-pool-size.
            //If there are free resources at max-pool-size, then none of the free resources
            //has matched this allocator's request (credential). Hence purge free resources
            //of size <=resizeQuantity
            purgeResources(resizeQuantity);
            result = resizePoolAndGetNewResource(alloc);
        }
        return result;
public voidresourceClosed(ResourceHandle h)
this method is called to indicate that the resource is not used by a bean anymore

        if (_logger.isLoggable( Level.FINE ) ) {
            _logger.log(Level.FINE,"Pool: resourceClosed: " + h);
        }

        ResourceState state = getResourceState(h);
        if(state == null){
            throw new IllegalStateException("State is null");
        }

        if(!state.isBusy()){
            throw new IllegalStateException("state.isBusy() : false");
        }

        setResourceStateToFree(h);  // mark as not busy
        state.touchTimestamp();


        if (state.isUnenlisted() || (isNonXAResource(h) && isLocalResourceEligibleForReuse(h))) {
            freeUnenlistedResource(h);
        }
        
        if (monitoringEnabled){
            poolCounters.incrementNumConnReleased();
        }
        
        _logger.log(Level.FINE,"Pool: resourceFreed: " + h);
    
public voidresourceEnlisted(javax.transaction.Transaction tran, ResourceHandle resource)
this method is called when a resource is enlisted in transation tran

        try {
            J2EETransaction j2eetran = (J2EETransaction) tran;
            Set set = j2eetran.getResources(name);
            if (set == null) {
                set = new HashSet();
                j2eetran.setResources(set, name);
            }
            set.add(resource);
        } catch(ClassCastException e) {
            _logger.log(Level.FINE, "Pool: resourceEnlisted:" +
                    "transaction is not J2EETransaction but a " + tran.getClass().getName() , e);
        }
        ResourceState state = getResourceState(resource);
        state.setEnlisted(true);
        if (_logger.isLoggable( Level.FINE ) ) {
            _logger.log(Level.FINE,"Pool: resourceEnlisted: " + resource);
        }
    
public synchronized voidresourceErrorOccurred(ResourceHandle h)


        if(_logger.isLoggable(Level.FINE)){
            _logger.fine("Pool: resourceErrorOccurred: " + h);
        }
        
        if ( failAllConnections ) {
            doFailAllConnectionsProcessing();
            return;
        }
        
        ResourceState state = getResourceState(h);
        //GJCINT - commenting out below
        /**
         * The reason is that normally connection error is expected
         * to occur only when the connection is in use by the application.
         * When there is connection validation involved, the connection
         * can be checked for validity "before" it is passed to the
         * application i.e. when the resource is still free. Since,
         * the connection error can occur when the resource
         * is free, the following is being commented out.
         */
        /*
        if (state == null ||
        state.isBusy() == false) {
            throw new IllegalStateException();
        }
         */
        if (state == null) {
            throw new IllegalStateException();
        }
        
        // changed order of commands
        
        //Commenting resources.remove() out since we will call an iter.remove()
        //in the getUnenlistedResource method in the if check after
        //matchManagedConnections or in the internalGetResource method
        //If we were to call remove directly here there is always the danger
        //of a ConcurrentModificationExceptionbeing thrown when we return
        //
        //In case of this method being called asynchronously, since
        //the resource has been marked as "errorOccured", it will get
        //removed in the next iteration of getUnenlistedResource
        //or internalGetResource
        resources.remove(h);
        destroyResource(h);
    
private voidscheduleResizerTask()
Schedules the resizer timer task. If a task is currently scheduled, it would be canceled and a new one is scheduled.

        if (resizerTask != null) {
            //cancel the current task
            resizerTask.cancel();
            resizerTask = null;
        }
        
        resizerTask = new Resizer();
        
        if (timer == null){
            timer = Switch.getSwitch().getTimer();
        }
        
        timer.scheduleAtFixedRate(resizerTask, idletime, idletime);
        if (_logger.isLoggable( Level.FINEST ) ) {
            _logger.finest("schduled resizer task");
        }
    
private voidsetAdvancedPoolConfiguration(ConnectorConnectionPool poolResource)
sets advanced pool properties
used during pool configuration (initialization) and re-configuration

param
poolResource Connector Connection Pool

        matchConnections = poolResource.matchConnections();

      //Commented from 9.1 as it is not used
/*
        lazyConnectionAssoc_ = poolResource.isLazyConnectionAssoc();
        lazyConnectionEnlist_ = poolResource.isLazyConnectionEnlist();
        associateWithThread_ = poolResource.isAssociateWithThread();
*/
        maxConnectionUsage_ = Integer.parseInt(poolResource.getMaxConnectionUsage());
        connectionCreationRetryAttempts_ = Integer.parseInt
                (poolResource.getConCreationRetryAttempts());
        //Converting seconds to milliseconds as TimerTask will take input in milliseconds
        conCreationRetryInterval_ =
                Integer.parseInt(poolResource.getConCreationRetryInterval()) * 1000;
        connectionCreationRetry_ = connectionCreationRetryAttempts_ > 0;

        validateAtmostPeriodInMilliSeconds_ =
                Integer.parseInt(poolResource.getValidateAtmostOncePeriod()) * 1000;
        connectionLeakReclaim_ = poolResource.isConnectionReclaim();
        connectionLeakTimeoutInMilliSeconds_ = Integer.parseInt(
                poolResource.getConnectionLeakTracingTimeout()) * 1000;

        connectionLeakTracing_ = connectionLeakTimeoutInMilliSeconds_ > 0;
    
public voidsetMaxPoolSize(int size)

        if ( size < resources.size() ) {
            synchronized( this ) {
                int toKill =  resources.size() - size;
                if ( toKill > 0 ) {
                    try {
                        killExtraResources( toKill );
                    } catch( Exception re ) {
                        //ignore for now
                        if (_logger.isLoggable(Level.FINE) ) {
                            _logger.fine( "setMaxPoolSize:: killExtraResources " +
                                    "throws exception: " + re.getMessage() );
                        }
                    }
                }
            }
        }
        maxPoolSize = size;
    
public voidsetMonitoringEnabledHigh()

        logFine("Enabling monitoring to level : HIGH");
        int numConnFree = (this.poolInitialized) ? this.free.size() : this.steadyPoolSize;
        if ( poolCounters == null ){
            poolCounters = new HighPoolCounters(numConnFree);
        }
        poolCounters.reset(numConnFree);
        monitoringEnabled = true;
    
public voidsetMonitoringEnabledLow()

        logFine("Enabling monitoring to level : LOW");
        if ( poolCounters == null ){
            poolCounters = new LowPoolCounters(0);
        }
        poolCounters.reset(0);
        monitoringEnabled = true;
    
private voidsetPoolConfiguration()


         
        Context ic = Switch.getSwitch().getNamingManager().getInitialContext();
        ConnectorConnectionPool poolResource;
        try {
            String jndiNameOfPool = ConnectorAdminServiceUtils.
                    getReservePrefixedJNDINameForPool(name);
            poolResource = (ConnectorConnectionPool) ic.lookup(jndiNameOfPool);
        } catch (NamingException ex) {
            throw new PoolingException(ex);
        }
        idletime = Integer.parseInt(poolResource.getIdleTimeoutInSeconds()) * 1000;
        maxPoolSize = Integer.parseInt(poolResource.getMaxPoolSize());
        steadyPoolSize = Integer.parseInt(poolResource.getSteadyPoolSize());

        if (maxPoolSize < steadyPoolSize) {
            maxPoolSize = steadyPoolSize;
        }
        resizeQuantity = Integer.parseInt(poolResource.getPoolResizeQuantity());

        maxWaitTime = Integer.parseInt(poolResource.getMaxWaitTimeInMillis());
        //Make sure it's not negative.
        if (maxWaitTime < 0) {
            maxWaitTime = 0;
        }

        failAllConnections = poolResource.isFailAllConnections();

        validation = poolResource.isIsConnectionValidationRequired();

        validateAtmostEveryIdleSecs = poolResource.isValidateAtmostEveryIdleSecs();

        setAdvancedPoolConfiguration(poolResource);
    
protected voidsetResourceStateToBusy(ResourceHandle resourceHandle)
marks resource as busy. This method should be used instead of directly calling resoureHandle.getResourceState().setBusy(true) OR getResourceState(resourceHandle).setBusy(true) as this method handles starting of connection leak tracing If connection leak tracing is enabled, takes care of starting connection leak tracing

        getResourceState(resourceHandle).setBusy(true);
        if(connectionLeakTracing_)
            startConnectionLeakTracing(resourceHandle);
    
protected voidsetResourceStateToFree(ResourceHandle resourceHandle)
marks resource as free. This method should be used instead of directly calling resoureHandle.getResourceState().setBusy(false) OR getResourceState(resourceHandle).setBusy(false) as this method handles stopping of connection leak tracing If connection leak tracing is enabled, takes care of stopping connection leak tracing

        getResourceState(resourceHandle).setBusy(false);
        if(connectionLeakTracing_)
            stopConnectionLeakTracing(resourceHandle);
    
public voidsetSelfManaged(boolean selfManaged)

        logFine( "Setting selfManaged to : " +selfManaged+" in pool : "+name );
        selfManaged_ = selfManaged;
    
public voidsetSteadyPoolSize(int size)

        steadyPoolSize = size;
    
private voidstartConnectionLeakTracing(ResourceHandle resourceHandle)
starts connection leak tracing

        synchronized(connectionLeakLock){
            if(!connectionLeakThreadStackHashMap.containsKey(resourceHandle)){
                connectionLeakThreadStackHashMap.put(resourceHandle, Thread.currentThread().getStackTrace());
                ConnectionLeakTask connectionLeakTask = new ConnectionLeakTask(resourceHandle);
                connectionLeakTimerTaskHashMap.put(resourceHandle, connectionLeakTask);
                if(timer == null)
                    timer = Switch.getSwitch().getTimer();
                timer.schedule(connectionLeakTask, connectionLeakTimeoutInMilliSeconds_);
            }
        }
    
private voidstopConnectionLeakTracing(ResourceHandle resourceHandle)
stops connection leak tracing

        synchronized(connectionLeakLock){
            if(connectionLeakThreadStackHashMap.containsKey(resourceHandle)){
                connectionLeakThreadStackHashMap.remove(resourceHandle);
                ConnectionLeakTask connectionLeakTask = connectionLeakTimerTaskHashMap.remove(resourceHandle);
                connectionLeakTask.cancel();
                timer.purge();
            }
        }
    
public voidswitchOnMatching()
Switch on matching of connections in the pool.

        matchConnections = true;
    
public java.lang.StringtoString()

        StringBuffer sb = new StringBuffer("Pool [");
        sb.append(name);
        sb.append("] PoolSize=");
        sb.append(resources.size());
        sb.append("  FreeResources=");
        sb.append(free.size());
        sb.append("  QueueSize=");
        sb.append(waitQueue.size());
        sb.append(" matching=");
        sb.append( (matchConnections ? "on" : "off") );
        sb.append(" validation=");
        sb.append( (validation ? "on" : "off") );
        return sb.toString();
    
public synchronized voidtransactionCompleted(javax.transaction.Transaction tran, int status)
this method is called when transaction tran is completed

        try {
            J2EETransaction j2eetran = (J2EETransaction) tran;
            Set set =  j2eetran.getResources(name);
            if (set == null) return;
            
            Iterator iter = set.iterator();
            while (iter.hasNext()) {
                ResourceHandle resource = (ResourceHandle) iter.next();
                ResourceState state = getResourceState(resource);
                state.setEnlisted(false);
                // Application might not have closed the connection.
                if ( isResourceUnused(resource) ){
                    freeResource(resource);
                }
                iter.remove();
                if (_logger.isLoggable( Level.FINE ) ) {
                    _logger.log(Level.FINE,"Pool: transactionCompleted: " + resource);
                }
            }
        } catch (ClassCastException e) {
            _logger.log(Level.FINE, "Pool: transactionCompleted: " +
                    "transaction is not J2EETransaction but a " + tran.getClass().getName() , e);
        }