KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > resource > AbstractResourcePool


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.resource;
24
25 import java.util.*;
26
27 import javax.resource.ResourceException JavaDoc;
28 import javax.resource.spi.ManagedConnection JavaDoc;
29 import javax.transaction.*;
30 import java.util.logging.*;
31 import com.sun.logging.*;
32
33 import javax.naming.Context JavaDoc;
34 import javax.naming.NamingException JavaDoc;
35 import com.sun.enterprise.Switch;
36 import com.sun.enterprise.connectors.*;
37 import com.sun.enterprise.distributedtx.*;
38 import com.sun.enterprise.util.i18n.StringManager;
39
40 /**
41  * this resource pool does not allow sharing
42  * A resource is only given out if it is not used by
43  * any enterprise bean and it does not have any pending transaction
44  *
45  * @author Aditya Gore
46  * @since 9.0
47  */

48 public abstract class AbstractResourcePool implements MonitorableResourcePool {
49
50     protected static StringManager localStrings =
51         StringManager.getManager(AbstractResourcePool.class);
52
53     protected ArrayList resources;
54     
55     /**
56      * list of ResourceHandles that are free and unenlisted
57      */

58     protected ArrayList free;
59     
60     // time (in ms) before destroying a free resource
61
protected long idletime;
62     
63     protected String JavaDoc name;
64     
65     // adding resourceSpec and allocator
66
protected ResourceSpec resourceSpec;
67     // Note: This resource allocator may not be the same as the allocator
68
// passed in to getResource()
69
protected ResourceAllocator allocator;
70     
71     //config properties
72

73     protected int maxPoolSize; // Max size of the pool
74

75     protected int steadyPoolSize; // Steady size of the pool
76

77     protected int resizeQuantity; // used by resizer to downsize the pool
78

79     protected int maxWaitTime; // The total time a thread is willing to wait
80
// for a resource object.
81

82     protected boolean failAllConnections = false;
83
84     protected boolean matchConnections = false;
85     
86     protected boolean poolInitialized = false;
87  
88     protected Timer timer;
89     
90     // hold on to the resizer task so we can cancel/reschedule it.
91
protected TimerTask resizerTask;
92     
93     protected boolean monitoringEnabled; //Indicates if monitoring is on
94

95     protected PoolCounters poolCounters = null;
96     
97     protected boolean validation = false;
98     /**
99      * given a Transaction, get a Set of resources enlisted in that
100      * transaction (Transaction -> Set of ResourceHandle)
101      */

102     
103     protected LinkedList waitQueue = new LinkedList();
104    
105     protected boolean lazyConnectionAssoc_;
106     protected boolean lazyConnectionEnlist_;
107     protected boolean associateWithThread_;
108     protected boolean connectionLeakTracing_;
109
110     private boolean selfManaged_;
111
112     //To validate a Sun RA Pool Connection if it hasnot been validated in the past x sec. (x=idle-timeout)
113
//The property will be set from system property - com.sun.enterprise.connectors.ValidateAtmostEveryIdleSecs=true
114
private boolean validateAtmostEveryIdleSecs = false;
115
116
117     private boolean inTx() {
118         com.sun.enterprise.ComponentInvocation inv =
119         Switch.getSwitch().getInvocationManager().getCurrentInvocation();
120         if (inv == null) {
121             throw new com.sun.enterprise.InvocationException();
122         }
123         Transaction tran = inv.getTransaction();
124         return (tran != null);
125     }
126
127     public AbstractResourcePool(String JavaDoc poolName) throws PoolingException{
128         this.name = poolName;
129         setPoolConfiguration();
130         monitoringEnabled = false;
131         resources = new ArrayList(maxPoolSize);
132         free = new ArrayList(maxPoolSize);
133     }
134     
135     static Logger _logger = LogDomains.getLogger(LogDomains.RSR_LOGGER);
136     
137     private void setPoolConfiguration() throws PoolingException{
138         Context JavaDoc ic = Switch.getSwitch().getNamingManager().getInitialContext();
139         ConnectorConnectionPool poolResource;
140         try {
141             String JavaDoc jndiNameOfPool = ConnectorAdminServiceUtils.
142                 getReservePrefixedJNDINameForPool(name);
143             poolResource = (ConnectorConnectionPool)ic.lookup( jndiNameOfPool );
144         } catch (NamingException JavaDoc ex) {
145             throw new PoolingException(ex);
146         }
147         idletime = Integer.parseInt(poolResource.getIdleTimeoutInSeconds()) * 1000;
148         maxPoolSize = Integer.parseInt(poolResource.getMaxPoolSize());
149         steadyPoolSize = Integer.parseInt(poolResource.getSteadyPoolSize());
150
151         if (maxPoolSize < steadyPoolSize ) {
152             maxPoolSize = steadyPoolSize;
153         }
154         resizeQuantity = Integer.parseInt(poolResource.getPoolResizeQuantity());
155         
156         maxWaitTime = Integer.parseInt(poolResource.getMaxWaitTimeInMillis());
157         //Make sure it's not negative.
158
if (maxWaitTime < 0) {
159             maxWaitTime = 0;
160         }
161         
162         failAllConnections = poolResource.isFailAllConnections();
163         matchConnections = poolResource.matchConnections();
164     validation = poolResource.isIsConnectionValidationRequired();
165     lazyConnectionAssoc_ = poolResource.isLazyConnectionAssoc();
166     lazyConnectionEnlist_ = poolResource.isLazyConnectionEnlist();
167     associateWithThread_ = poolResource.isAssociateWithThread();
168     connectionLeakTracing_ = poolResource.isConnectionLeakTracing();
169     validateAtmostEveryIdleSecs = poolResource.isValidateAtmostEveryIdleSecs();
170     }
171     
172     
173     // This method does not need to be synchronized since all caller methods are,
174
// but it does not hurt. Just to be safe.
175
protected synchronized void initPool(ResourceSpec resourceSpec,
176     ResourceAllocator allocator)
177     throws PoolingException {
178         
179         if (poolInitialized) {
180             return;
181         }
182         
183         this.resourceSpec = resourceSpec;
184         this.allocator = allocator;
185
186         createResources(steadyPoolSize);
187         
188         // if the idle time out is 0, then don't schedule the resizer task
189
if (idletime > 0) {
190             scheduleResizerTask();
191         }
192         poolInitialized = true;
193     }
194     
195     /**
196      * Schedules the resizer timer task. If a task is currently scheduled,
197      * it would be canceled and a new one is scheduled.
198      */

199     private void scheduleResizerTask() {
200         if (resizerTask != null) {
201             //cancel the current task
202
resizerTask.cancel();
203         resizerTask = null;
204         }
205        
206         resizerTask = new Resizer();
207         
208         if (timer == null){
209             timer = Switch.getSwitch().getTimer();
210         }
211
212         timer.scheduleAtFixedRate(resizerTask, idletime, idletime);
213         if (_logger.isLoggable( Level.FINEST ) ) {
214             _logger.finest("schduled resizer task");
215         }
216     }
217     
218     
219     /**
220      * add a resource with status busy and not enlisted
221      */

222     synchronized
223     public void addResource(ResourceSpec spec,
224     ResourceHandle h) {
225         if (_logger.isLoggable( Level.FINE ) ) {
226                 _logger.log(Level.FINE,"Pool: resource added: " + spec + "," + h);
227         }
228         // all resources in this pool have the same resource spec
229
ResourceState state = new ResourceState();
230         resources.add(h);
231         h.setResourceState(state);
232         state.setEnlisted(false);
233         state.setBusy(true);
234
235     }
236     
237     /**
238      * returns resource from the pool.
239      *
240      * @return a free pooled resource object matching the ResourceSpec
241      *
242      * @throws PoolingException
243      * - if any error occurrs
244      * - or the pool has reached its max size and the
245      * max-connection-wait-time-in-millis has expired.
246      */

247     public ResourceHandle getResource(ResourceSpec spec,
248     ResourceAllocator alloc,
249     Transaction tran) throws PoolingException {
250         //Note: this method should not be synchronized or the
251
// startTime would be incorrect for threads waiting to enter
252

253         /*
254      * Here are all the comments for the method put togethar for
255      * easy reference.
256      * 1.
257             // - Try to get a free resource. Note: internalGetResource()
258             // will create a new resource if none is free and the max has
259             // not been reached.
260             // - If can't get one, get on the wait queue.
261             // - Repeat this until maxWaitTime expires.
262             // - If maxWaitTime == 0, repeat indefinitely.
263        
264         2.
265         //the doFailAllConnectionsProcessing method would already
266         //have been invoked by now.
267         //We simply go ahead and create a new resource here
268         //from the allocator that we have and adjust the resources
269         //list accordingly so as to not exceed the maxPoolSize ever
270         //(i.e if steadyPoolSize == maxPoolSize )
271         ///Also since we are creating the resource out of the allocator
272         //that we came into this method with, we need not worry about
273         //matching
274      */

275         ResourceHandle result = null;
276         
277         long startTime = 0;
278         long elapsedWaitTime = 0;
279         long remainingWaitTime = 0;
280
281         Object JavaDoc waitMonitor = new Object JavaDoc();
282         
283         if (maxWaitTime > 0) {
284             startTime = System.currentTimeMillis();
285         }
286     
287         while (true) {
288             //See comment #1 above
289
result = internalGetResource(spec, alloc, tran);
290
291             if (result != null) {
292                 // got one, return it
293
if (monitoringEnabled) {
294                     poolCounters.incrementNumConnAcquired();
295                     elapsedWaitTime = System.currentTimeMillis() - startTime;
296                     poolCounters.setWaitTime(elapsedWaitTime);
297                 }
298
299
300         //got one - seems we are not doing validation or matching
301
//return it
302
break;
303             } else {
304                 // did not get a resource.
305
if (maxWaitTime > 0) {
306                     elapsedWaitTime = System.currentTimeMillis() - startTime;
307                     if (elapsedWaitTime < maxWaitTime) {
308                         // time has not expired, determine remaining wait time.
309
remainingWaitTime = maxWaitTime - elapsedWaitTime;
310                     } else {
311                         // wait time has expired
312
if (monitoringEnabled) {
313                             poolCounters.incrementNumConnTimedOut();
314                         }
315                         String JavaDoc msg = localStrings.getString(
316                         "poolmgr.no.available.resource",
317                         "No available resource. Wait-time expired.");
318                         throw new PoolingException(msg);
319                     }
320                 }
321                 
322                 synchronized (waitMonitor) {
323                     synchronized (waitQueue) {
324                         waitQueue.addLast(waitMonitor);
325                     }
326                     try {
327                         if (_logger.isLoggable( Level.FINE) ) {
328                             _logger.log(Level.FINE,"Resource Pool: getting on wait queue");
329                         }
330                         //numConnWaited++;
331
waitMonitor.wait(remainingWaitTime);
332                         
333                     } catch (InterruptedException JavaDoc ex) {
334                         //Could be system shutdown.
335
break;
336                     }
337                     
338                     //try to remove in case that the monitor has timed
339
// out. We dont expect the queue to grow to great numbers
340
// so the overhead for removing inexistant objects is low.
341
synchronized( waitQueue ) {
342                         waitQueue.remove(waitMonitor);
343             }
344                 }
345             }
346         }
347
348     alloc.fillInResourceObjects(result);
349         return result;
350     }
351    
352     //Overridden in AssocWithThreadResourcePool to fetch the resource
353
//cached in the ThreadLocal
354
//In SJSASResourcePool this simply returns null
355
protected abstract ResourceHandle prefetch( ResourceSpec spec,
356         ResourceAllocator alloc, Transaction tran );
357         
358     protected ResourceHandle internalGetResource(ResourceSpec spec,
359     ResourceAllocator alloc,
360     Transaction tran) throws PoolingException {
361         if (!poolInitialized) {
362             initPool(spec, alloc);
363         }
364         ResourceHandle result = null;
365         
366         result = prefetch( spec, alloc, tran );
367         if ( result != null ) {
368             return result;
369         }
370
371         try {
372         //comment-1: sharing is possible only if caller is marked
373
//shareable, so abort right here if that's not the case
374
if (tran != null && alloc.shareableWithinComponent() ) {
375                 J2EETransaction j2eetran = (J2EETransaction) tran;
376                 // case 1. look for free and enlisted in same tx
377
Set set = (Set) j2eetran.getResources(name);
378                 if (set != null) {
379                     Iterator iter = set.iterator();
380                     while (iter.hasNext()) {
381                         ResourceHandle h = (ResourceHandle) iter.next();
382             if (h.hasConnectionErrorOccurred()) {
383                 iter.remove();
384                 continue;
385             }
386
387                         ResourceState state = h.getResourceState();
388             /*
389              * One can share a resource only for the following conditions:
390              * 1. The caller resource is shareable (look at the outermost
391              * if marked comment-1
392              * 2. The resource enlisted inside the transaction is shareable
393              * 3. We are dealing with XA resources OR
394              * We are deling with a non-XA resource that's not in use
395              * Note that sharing a non-xa resource that's in use involves
396              * associating physical connections.
397              * 4. The credentials of the resources match
398              */

399             if (h.getResourceAllocator().shareableWithinComponent() &&
400                     ( state.isFree() || spec.isXA())) {
401                             if (matchConnections) {
402                                 if ( !alloc.matchConnection( h )) {
403                                     if (monitoringEnabled){
404                                        poolCounters.incrementNumConnNotSuccessfullyMatched();
405                                     }
406                                     continue;
407                                 }
408                                 if (h.hasConnectionErrorOccurred() ) {
409                                     if ( failAllConnections ) {
410                                         //if failAllConnections has happened, we flushed the
411
//pool, so we don't have to do iter.remove else we
412
//will get a ConncurrentModificationException
413
result = null;
414                                         break;
415                                     }
416                                     iter.remove();
417                                     continue;
418                                 }
419                                 if (monitoringEnabled){
420                                     poolCounters.incrementNumConnSuccessfullyMatched();
421                                 }
422                             }
423                             state.setBusy(true);
424                             result = h;
425                             break;
426                         }
427                     }
428                 }
429             }
430         } catch(ClassCastException JavaDoc e) {
431             _logger.log(Level.FINE, "Pool: getResource : " +
432             "transaction is not J2EETransaction but a " + tran.getClass().getName() , e);
433         }
434
435      
436         // We didnt get a connections that is already enlisted in a transaction.
437
if (result == null) {
438             result = getUnenlistedResource(spec, alloc, tran);
439             //Only getting of an unenlisted resource results in
440
//an increment of the connection used stat
441
if ((result != null) && monitoringEnabled) {
442                 poolCounters.incrementNumConnUsed();
443             }
444         }
445         return result;
446
447     }
448
449     // this is the RI getResource() with some modifications
450
/**
451      * return resource in free list. If none is found, returns null
452      * This method needs to be synchronized in the child class
453      *
454      */

455     synchronized protected ResourceHandle getUnenlistedResource(ResourceSpec spec,
456     ResourceAllocator alloc,
457     Transaction tran) throws PoolingException {
458         
459         // the order of serving a resource request
460
// 1. free and enlisted in the same transaction
461
// 2. free and unenlisted
462
// Do NOT give out a connection that is
463
// free and enlisted in a different transaction
464
ResourceHandle result = null;
465         
466         Iterator iter = free.iterator();
467         while (iter.hasNext()) {
468         boolean matched = false;
469             ResourceHandle h = (ResourceHandle) iter.next();
470             if (h.hasConnectionErrorOccurred()) {
471                 iter.remove();
472                 continue;
473             }
474
475             //h.isAssociated can only be true for
476
//AssocWithThreadResourcePool
477
if ( h.isAssociated() ) {
478                 //Don't touch it then
479
continue;
480             }
481
482             boolean connectionValid = true;
483
484             long timeSinceValidation = System.currentTimeMillis() - h.getLastValidated();
485             if (validation || (validateAtmostEveryIdleSecs && timeSinceValidation > idletime)) {
486                 if (!alloc.isConnectionValid(h)) {
487                     connectionValid = false;
488                 } else {
489                     h.setLastValidated(System.currentTimeMillis());
490                 }
491             }
492
493             if (connectionValid) {
494                 if (matchConnections) {
495                     matched = alloc.matchConnection(h);
496                     if (monitoringEnabled) {
497                         if (matched) {
498                             poolCounters.incrementNumConnSuccessfullyMatched();
499                         } else {
500                             poolCounters.incrementNumConnNotSuccessfullyMatched();
501                         }
502                     }
503                 } else {
504                     matched = true; //always
505
}
506             }
507
508             if (h.hasConnectionErrorOccurred() || !connectionValid) {
509                 if (failAllConnections) {
510                     result = createSingleResourceAndAdjustPool(alloc, spec);
511                     //no need to match since we came from the same allocator as the caller
512
break;
513                 } else {
514                     iter.remove();
515                     continue;
516                 }
517             }
518
519             if (matched) {
520                 result = h;
521                 break;
522             }
523
524         }
525         
526         if (result != null) {
527             // set correct state
528
ResourceState state = result.getResourceState();
529             state.setBusy(true);
530             free.remove(result);
531         } else {
532             if(resources.size() < steadyPoolSize ){
533                 // May be all invalid resources are destroyed as
534
// a result no free resource found and no. of resources is less than steady-pool-size
535
createResources(steadyPoolSize - resources.size());
536                 if(free.size() != 0){
537                     result = (ResourceHandle)free.remove(0);
538                     ResourceState state = result.getResourceState();
539                     state.setBusy(true);
540                 }
541             }
542             else if (resources.size() < maxPoolSize) {
543                 // Either no free resource found or an invalid resource has
544
// been destroyed. Let's see if we can add one.
545
// changed to use resources.size instead of independent counter
546
result = alloc.createResource();
547                 addResource(spec, result);
548                 if ( monitoringEnabled ) {
549                     poolCounters.incrementNumConnCreated();
550                 }
551             }
552         }
553
554         return result;
555     }
556
557     /**
558      * This method will be called from the getUnenlistedResource method if
559      * we detect a failAllConnection flag.
560      * Here we simply create a new resource and replace a free resource in
561      * the pool by this resource and then give it out.
562      * This replacement is required since the steadypoolsize might equal
563      * maxpoolsize and in that case if we were not to remove a resource
564      * from the pool, our resource would be above maxPoolSize
565      */

566     protected ResourceHandle createSingleResourceAndAdjustPool(
567         ResourceAllocator alloc, ResourceSpec spec)
568     throws PoolingException
569     {
570         if ( free.size() != 0 ) {
571         //resources.size() could be 0 if we were to run into
572
//trouble while createResources(0 was called in
573
//doFailAllConnectionsProcessing
574
ResourceHandle rHandle = (ResourceHandle) free.get(0);
575             resources.remove( rHandle );
576                 free.remove( rHandle );
577         }
578     ResourceHandle result = alloc.createResource();
579     addResource( spec, result );
580     alloc.fillInResourceObjects( result );
581     if ( monitoringEnabled ) {
582         poolCounters.incrementNumConnCreated();
583     }
584
585     return result;
586
587     }
588     
589     /*
590      * Create resources upto steadyPoolSize
591      */

592     
593     //synchronized method, eliminated block sync
594
private synchronized void createResources(int size) throws PoolingException {
595         for (int i = 0; i < size; i++) {
596             createResourceAndAddToPool();
597         }
598     }
599
600     
601     protected void destroyResource(ResourceHandle resourceHandle) {
602         try {
603             resourceHandle.getResourceAllocator().destroyResource(resourceHandle);
604         } catch (Exception JavaDoc ex) {
605             _logger.log(Level.WARNING,"poolmgr.destroy_resource_failed");
606             if (_logger.isLoggable( Level.FINE ) ) {
607                 _logger.log(Level.FINE,"poolmgr.destroy_resource_failed",ex);
608             }
609         } finally {
610             if (monitoringEnabled) {
611                 poolCounters.incrementNumConnDestroyed();
612                 if (resourceHandle.getResourceState().isBusy()){
613                     //Destroying a Connection due to error
614
poolCounters.decrementNumConnUsed(true);
615                 } else {
616                     //Destroying a free Connection
617
poolCounters.decrementNumConnFree();
618                 }
619             }
620         }
621     }
622
623     /**
624      * this method is called to indicate that the resource is
625      * not used by a bean anymore
626      */

627     public void resourceClosed(ResourceHandle h)
628     throws IllegalStateException JavaDoc {
629         if (_logger.isLoggable( Level.FINE ) ) {
630             _logger.log(Level.FINE,"Pool: resourceClosed: " + h);
631         }
632         
633         ResourceState state = getResourceState(h);
634         if (state == null || state.isBusy() == false) {
635             throw new IllegalStateException JavaDoc("state is null : " + (state == null)
636             + " ::: state.isBusy() : " + state.isBusy() );
637         }
638
639         state.setBusy(false); // mark as not busy
640
state.touchTimestamp();
641
642         if (state.isUnenlisted()) {
643             freeUnenlistedResource(h);
644             //only unenlisted
645
if(monitoringEnabled){
646                 poolCounters.decrementNumConnUsed(false);
647             }
648         }
649         
650         if (monitoringEnabled){
651             poolCounters.incrementNumConnReleased();
652         }
653
654         if (_logger.isLoggable( Level.FINE ) ) {
655             _logger.log(Level.FINE,"Pool: resourceFreed: " + h);
656         }
657     }
658
659     protected synchronized void freeUnenlistedResource(ResourceHandle h) {
660
661         // Put it back to the free collection.
662
free.add(h);
663         notifyWaitingThreads();
664     }
665     
666     synchronized
667     public void resourceErrorOccurred(ResourceHandle h)
668     throws IllegalStateException JavaDoc {
669         logFine("Pool: resourceErrorOccurred: " + h);
670
671     if ( failAllConnections ) {
672         doFailAllConnectionsProcessing();
673         return;
674     }
675     
676         if (monitoringEnabled) {
677             poolCounters.incrementNumConnFailedValidation(1);
678         }
679         ResourceState state = getResourceState(h);
680         //GJCINT - commenting out below
681
/**
682          * The reason is that normally connection error is expected
683          * to occur only when the connection is in use by the application.
684          * When there is connection validation involved, the connection
685          * can be checked for validity "before" it is passed to the
686          * application i.e. when the resource is still free. Since,
687          * the connection error can occur when the resource
688          * is free, the following is being commented out.
689          */

690         /*
691         if (state == null ||
692         state.isBusy() == false) {
693             throw new IllegalStateException();
694         }
695         */

696         if (state == null) {
697             throw new IllegalStateException JavaDoc();
698         }
699         
700         // changed order of commands
701

702     //Commenting resources.remove() out since we will call an iter.remove()
703
//in the getUnenlistedResource method in the if check after
704
//matchManagedConnections or in the internalGetResource method
705
//If we were to call remove directly here there is always the danger
706
//of a ConcurrentModificationExceptionbeing thrown when we return
707
//
708
//In case of this method being called asynchronously, since
709
//the resource has been marked as "errorOccured", it will get
710
//removed in the next iteration of getUnenlistedResource
711
//or internalGetResource
712
resources.remove(h);
713         destroyResource(h);
714     }
715     
716     private void doFailAllConnectionsProcessing() {
717     logFine(" @@@@ doFailAllConnectionsProcessing entered");
718     cancelResizerTask();
719         if ( monitoringEnabled ) {
720         poolCounters.incrementNumConnFailedValidation(resources.size());
721     }
722     
723         emptyPool();
724     try {
725         createResources(steadyPoolSize);
726     } catch(PoolingException pe) {
727         //Ignore and hope the resizer does its stuff
728
logFine( "in doFailAllConnectionsProcessing couldn't create steady resources");
729     }
730     scheduleResizerTask();
731     logFine(" @@@@ doFailAllConnectionsProcessing done - created new resources");
732     
733     }
734     
735     /**
736      * this method is called when a resource is enlisted in
737      * transation tran
738      */

739     public void resourceEnlisted(Transaction tran, ResourceHandle resource)
740     throws IllegalStateException JavaDoc {
741         try {
742             J2EETransaction j2eetran = (J2EETransaction) tran;
743             Set set = (Set) j2eetran.getResources(name);
744             if (set == null) {
745                 set = new HashSet();
746                 j2eetran.setResources(set, name);
747             }
748             set.add(resource);
749         } catch(ClassCastException JavaDoc e) {
750             _logger.log(Level.FINE, "Pool: resourceEnlisted:" +
751             "transaction is not J2EETransaction but a " + tran.getClass().getName() , e);
752         }
753         ResourceState state = getResourceState(resource);
754         state.setEnlisted(true);
755         if (_logger.isLoggable( Level.FINE ) ) {
756             _logger.log(Level.FINE,"Pool: resourceEnlisted: " + resource);
757         }
758     }
759     
760     /**
761      * this method is called when transaction tran is completed
762      */

763     synchronized
764     public void transactionCompleted(Transaction tran, int status)
765     throws IllegalStateException JavaDoc {
766         try {
767             J2EETransaction j2eetran = (J2EETransaction) tran;
768             Set set = (Set) j2eetran.getResources(name);
769             if (set == null) return;
770     
771             Iterator iter = set.iterator();
772             while (iter.hasNext()) {
773                 ResourceHandle resource = (ResourceHandle) iter.next();
774                 ResourceState state = getResourceState(resource);
775                 state.setEnlisted(false);
776                 // Application might not have closed the connection.
777
if ( isResourceUnused(resource) ){
778                     free.add(resource);
779                     if(monitoringEnabled){
780                         poolCounters.decrementNumConnUsed(false);
781                     }
782                 }
783                 iter.remove();
784                 notifyWaitingThreads();
785                 if (_logger.isLoggable( Level.FINE ) ) {
786                     _logger.log(Level.FINE,"Pool: transactionCompleted: " + resource);
787                 }
788             }
789         } catch (ClassCastException JavaDoc e) {
790             _logger.log(Level.FINE, "Pool: transactionCompleted: " +
791             "transaction is not J2EETransaction but a " + tran.getClass().getName() , e);
792         }
793     }
794   
795     protected boolean isResourceUnused(ResourceHandle h){
796         return getResourceState(h).isFree();
797     }
798
799     protected void notifyWaitingThreads() {
800         // notify the first thread in the waitqueue
801
Object JavaDoc waitMonitor = null;
802         synchronized (waitQueue) {
803             if (waitQueue.size() > 0) {
804                 waitMonitor = waitQueue.removeFirst();
805             }
806         }
807         if (waitMonitor != null) {
808             synchronized (waitMonitor) {
809                 waitMonitor.notify();
810             }
811         }
812     }
813     
814     // Start of methods related to Pool Monitoring
815
/**
816      * Return the number of threads that are waiting
817      * to obtain a connection from the pool
818      */

819     public int getNumThreadWaiting() {
820         return waitQueue.size();
821     }
822     
823     /**
824      * Return the number of connections that have failed validation
825      */

826     public long getNumConnFailedValidation() {
827         return poolCounters.numConnFailedValidation;
828     }
829     
830     /**
831      * Return the number of threads that have time out after
832      * waiting to obtain a connection from the pool.
833      */

834     public long getNumConnTimedOut() {
835         return poolCounters.numConnTimedOut;
836     }
837     
838     /**
839      * Return the number of free connections in the pool
840      */

841     public synchronized long getNumConnFree() {
842         return poolCounters.currNumConnFree;
843     }
844     
845     public long getMaxNumConnFree(){
846         return poolCounters.maxNumConnFree;
847     }
848     
849     public long getMinNumConnFree(){
850         if (poolCounters.minNumConnFree != Long.MAX_VALUE) {
851             return poolCounters.minNumConnFree;
852         } else {
853             return 0;
854         }
855     }
856     
857     /**
858      * Return the number of connections in use
859      */

860     public synchronized long getNumConnInUse() {
861         return poolCounters.currNumConnUsed;
862     }
863     
864     /**
865      * Return the maximum number of connections ever used in
866      * this pool
867      */

868     public long getMaxNumConnUsed() {
869         return poolCounters.maxNumConnUsed;
870     }
871     
872     
873     //8.1 monitoring
874
public long getCurrentConnRequestWaitTime(){
875         return poolCounters.currConnectionRequestWait;
876     }
877     
878     public long getMaxConnRequestWaitTime(){
879         return poolCounters.maxConnectionRequestWait;
880     }
881     
882     public long getMinConnRequestWaitTime(){
883         if(poolCounters.minConnectionRequestWait != Long.MAX_VALUE) {
884             return poolCounters.minConnectionRequestWait;
885         } else {
886             return 0;
887         }
888     }
889
890     public long getTotalConnectionRequestWaitTime() {
891        return poolCounters.totalConnectionRequestWait;
892     }
893     
894     public long getMinNumConnUsed(){
895         if (poolCounters.minNumConnUsed != Long.MAX_VALUE) {
896             return poolCounters.minNumConnUsed;
897         } else {
898             return 0;
899         }
900     }
901     
902     public long getNumConnCreated(){
903         return poolCounters.numConnCreated;
904     }
905
906     public long getNumConnDestroyed(){
907         return poolCounters.numConnDestroyed;
908     }
909
910     public long getNumConnAcquired() {
911         return poolCounters.numConnAcquired;
912     }
913
914     public long getNumConnReleased() {
915         return poolCounters.numConnReleased;
916     }
917
918     public long getNumConnSuccessfullyMatched(){
919        return poolCounters.numConnSuccessfullyMatched;
920     }
921
922     public long getNumConnNotSuccessfullyMatched(){
923        return poolCounters.numConnNotSuccessfullyMatched;
924     }
925
926     
927     // end of methods related to pool monitoring
928

929     // Modifications on resizePool() from RI:
930
// - Use destroyResource()
931
// - Reuse-variable optimization.
932
// - Add steady pool size check.
933

934     synchronized public void resizePool(boolean forced) {
935         
936         // Mods:
937
// - If the wait queue is NOT empty, don't do anything.
938
// - Only destroy resources if current-size > steady-pool-size
939
// - Only destroy the lesser of:
940
// - pool-resize-quantity
941
// - numResoucesInPool - steady-pool-size
942

943         synchronized (waitQueue) {
944             if (waitQueue.size() > 0) {
945                 return;
946             }
947         }
948
949         if(validation){
950             _logger.log(Level.FINE, "CP.Resizer.Validation-Turned-On");
951             removeInvalidResources();
952         }
953         
954         // changed to use resources.size() instead of counter
955
// eliminated block sync
956
int overSize = resources.size() - steadyPoolSize;
957         
958         if (overSize > 0) {
959             int numResourcesToBeDestroyed =
960             (resizeQuantity < overSize ? resizeQuantity : overSize);
961             
962             ResourceHandle h;
963             ResourceState state;
964             
965             Iterator iter = free.iterator();
966             // let's cache the current time since precision is not required here.
967
long currentTime = System.currentTimeMillis();
968             
969             while ( (numResourcesToBeDestroyed > 0) && iter.hasNext()) {
970                 h = (ResourceHandle) iter.next();
971                 state = getResourceState(h);
972                 if (forced || (currentTime - state.getTimestamp() > idletime)) {
973                     // changed order of instructions
974
resources.remove(h);
975                     destroyResource(h);
976                     iter.remove();
977                     numResourcesToBeDestroyed--;
978                 }
979             }
980         }
981         // Now make sure that the steady pool size is met.
982

983         // changed to use resources.size() instead of counter
984
// eliminated block sync
985
if (resources.size() < steadyPoolSize) {
986             // Create resources to match the steady pool size
987
// changed to use resources.size() instead of counter
988
for (int i = resources.size(); i < steadyPoolSize; i++) {
989                 try {
990                     createResourceAndAddToPool();
991                 } catch (PoolingException ex) {
992                     _logger.log(Level.WARNING,
993                     "resource_pool.resize_pool_error",
994                 (ex.getMessage() != null ? ex.getMessage() : " ") );
995                     continue;
996                 }
997             }
998         }
999         
1000        if (_logger.isLoggable(Level.FINE)) {
1001            _logger.log(Level.FINE,"Pool: Name = " + name);
1002            _logger.log(Level.FINE,"Pool: Resource held: "
1003            + resources.size());
1004        }
1005    }
1006    
1007    /**
1008     * Removes invalid resource handles in the pool while resizing the pool.
1009     * Uses the Connector 1.5 spec 6.5.3.4 optional RA feature to obtain
1010     * invalid ManagedConnections
1011     */

1012    private void removeInvalidResources() {
1013        try {
1014            //Find all ManagedConnections that are free/not-in-use
1015
Set freeManagedConnections = new HashSet();
1016            for (Iterator iter = free.iterator(); iter.hasNext();) {
1017                ResourceHandle element = (ResourceHandle) iter.next();
1018                freeManagedConnections.add(element.getResource());
1019            }
1020            
1021            _logger.log(Level.FINE, "Sending to RA a set of free connections " +
1022                    "of size", new Integer JavaDoc(freeManagedConnections.size()));
1023            
1024            //get Invalid ManagedConnections from the resource-adapter
1025
Set invalidManagedConnections =
1026                this.allocator.getInvalidConnections(freeManagedConnections);
1027            
1028            //Find the appropriate ResourceHandle for a returned invalid
1029
//ManagedConnection and destroy the Resourcehandle and references to
1030
//it in resources and free list.
1031
if (invalidManagedConnections != null) {
1032                _logger.log(Level.FINE, "Received from RA invalid connections # ",
1033                                new Integer JavaDoc(invalidManagedConnections.size()));
1034                
1035                for (Iterator iter = invalidManagedConnections.iterator();
1036                                              iter.hasNext();) {
1037                    ManagedConnection JavaDoc invalidManagedConnection =
1038                                            (ManagedConnection JavaDoc)iter.next();
1039                    for (Iterator freeResourcesIter = free.iterator();
1040                                            freeResourcesIter.hasNext();) {
1041                        ResourceHandle handle =
1042                            (ResourceHandle) freeResourcesIter.next();
1043                        if (invalidManagedConnection.equals
1044                                        (handle.getResource())) {
1045                            resources.remove(handle);
1046                            destroyResource(handle);
1047                            freeResourcesIter.remove();
1048                        }
1049                    }
1050                }
1051            } else {
1052                _logger.log(Level.FINE, "RA does not support " +
1053                        "ValidatingManagedConnectionFactory");
1054            }
1055        } catch (ResourceException JavaDoc re) {
1056            _logger.log(Level.FINE, "ResourceException while trying to " +
1057                    "get invalid connections from MCF", re);
1058        } catch (Exception JavaDoc e) {
1059            _logger.log(Level.FINE, "Exception while trying " +
1060                    "to get invalid connections from MCF", e);
1061        }
1062    }
1063
1064    private ResourceState getResourceState(ResourceHandle h) {
1065        return h.getResourceState();
1066    }
1067    
1068    synchronized public void emptyPool() {
1069        logFine("EmptyPool: Name = " + name);
1070        
1071        Iterator iter = resources.iterator();
1072        while(iter.hasNext()) {
1073            ResourceHandle h = (ResourceHandle) iter.next();
1074            destroyResource(h);
1075        }
1076        free.clear();
1077        resources.clear();
1078    }
1079
1080    synchronized public void emptyFreeConnectionsInPool() {
1081    if (_logger.isLoggable(Level.FINE)) {
1082        _logger.fine( "Emptying free connections in pool : " + name );
1083    }
1084        Iterator iter = free.iterator();
1085    while( iter.hasNext() ) {
1086        ResourceHandle h = (ResourceHandle) iter.next();
1087        resources.remove( h );
1088        destroyResource( h );
1089    }
1090    free.clear();
1091    }
1092    
1093    class Resizer extends TimerTask {
1094        public void run() {
1095
1096        if (_logger.isLoggable( Level.FINE ) ) {
1097                _logger.log(Level.FINE,"AbstractResourcePool: resize pool "
1098            + name);
1099            }
1100            resizePool(false);
1101        }
1102    }
1103    
1104    public String JavaDoc toString() {
1105        StringBuffer JavaDoc sb = new StringBuffer JavaDoc("Pool [");
1106        sb.append(name);
1107        sb.append("] PoolSize=");
1108        sb.append(resources.size());
1109        sb.append(" FreeResources=");
1110        sb.append(free.size());
1111        sb.append(" QueueSize=");
1112        sb.append(waitQueue.size());
1113    sb.append(" matching=");
1114    sb.append( (matchConnections ? "on" : "off") );
1115    sb.append(" validation=");
1116    sb.append( (validation ? "on" : "off") );
1117        return sb.toString();
1118    }
1119
1120
1121    public boolean isMonitoringEnabled() {
1122        return monitoringEnabled;
1123    }
1124    public void disableMonitoring() {
1125        monitoringEnabled = false;
1126    }
1127
1128    public void setMonitoringEnabledHigh() {
1129        logFine("Enabling monitoring to level : HIGH");
1130        int numConnFree = (this.poolInitialized) ? this.free.size() : this.steadyPoolSize;
1131        if ( poolCounters == null ){
1132            poolCounters = new HighPoolCounters(numConnFree);
1133        }
1134        poolCounters.reset(numConnFree);
1135        monitoringEnabled = true;
1136    }
1137    
1138    public void setMonitoringEnabledLow() {
1139        logFine("Enabling monitoring to level : LOW");
1140        if ( poolCounters == null ){
1141            poolCounters = new LowPoolCounters(0);
1142        }
1143        poolCounters.reset(0);
1144        monitoringEnabled = true;
1145    }
1146
1147    /**
1148     * Reconfigure the Pool's properties. The reconfigConnectorConnectionPool
1149     * method in the ConnectorRuntime will use this method (through PoolManager)
1150     * if it needs to just change pool properties and not recreate the pool
1151     *
1152     * @param poolResource - the ConnectorConnectionPool javabean that holds
1153     * the new pool properties
1154     * @throws PoolingException if the pool resizing fails
1155     */

1156    public synchronized void reconfigPoolProperties( ConnectorConnectionPool poolResource )
1157            throws PoolingException
1158    {
1159        int _idleTime = Integer.parseInt(poolResource.getIdleTimeoutInSeconds())
1160                * 1000;
1161        if (_idleTime != idletime && _idleTime != 0) {
1162            scheduleResizerTask();
1163        }
1164        if (_idleTime == 0 ) {
1165            //resizerTask.cancel();
1166
cancelResizerTask();
1167        }
1168        
1169        idletime = _idleTime;
1170        
1171
1172        resizeQuantity = Integer.parseInt(poolResource.getPoolResizeQuantity());
1173        
1174        maxWaitTime = Integer.parseInt(poolResource.getMaxWaitTimeInMillis());
1175        //Make sure it's not negative.
1176
if (maxWaitTime < 0) {
1177            maxWaitTime = 0;
1178        }
1179    
1180    validation = poolResource.isIsConnectionValidationRequired();
1181        failAllConnections = poolResource.isFailAllConnections();
1182    matchConnections = poolResource.matchConnections();
1183    lazyConnectionAssoc_ = poolResource.isLazyConnectionAssoc();
1184    lazyConnectionEnlist_ = poolResource.isLazyConnectionEnlist();
1185    associateWithThread_ = poolResource.isAssociateWithThread();
1186    connectionLeakTracing_ = poolResource.isConnectionLeakTracing();
1187        
1188        //Self managed quantities. These are ignored if self management
1189
//is on
1190
if ( ! isSelfManaged() ) {
1191            int _maxPoolSize = Integer.parseInt(poolResource.getMaxPoolSize());
1192            if (_maxPoolSize < maxPoolSize ) {
1193                //In this case we need to kill extra connections in the pool
1194
//For the case where the value is increased, we need not
1195
//do anything
1196
//num resources to kill is decided by the resources in the pool.
1197
//if we have less than current maxPoolSize resources, we need to
1198
//kill less.
1199
int toKill = resources.size() - _maxPoolSize;
1200            
1201                killExtraResources( toKill );
1202            }
1203
1204            if (_maxPoolSize < steadyPoolSize ) {
1205                maxPoolSize = steadyPoolSize;
1206            } else {
1207                maxPoolSize = _maxPoolSize;
1208            }
1209    
1210            int _steadyPoolSize = Integer.parseInt(
1211                poolResource.getSteadyPoolSize());
1212            if ( _steadyPoolSize > steadyPoolSize ) {
1213                increaseSteadyPoolSize( _steadyPoolSize );
1214            }
1215
1216            if (_steadyPoolSize > maxPoolSize ) {
1217                steadyPoolSize = maxPoolSize;
1218            } else {
1219                steadyPoolSize = _steadyPoolSize;
1220            }
1221        }
1222
1223    }
1224    
1225    /*
1226     * Kill the extra resources at the end of the Hashtable
1227     * The maxPoolSize being reduced causes this method to
1228     * be called
1229     */

1230    private void killExtraResources(int numToKill) {
1231        cancelResizerTask();
1232
1233        Iterator iter = free.iterator();
1234        for( int i = 0; iter.hasNext() && i < numToKill ; i++ ) {
1235            ResourceHandle h = (ResourceHandle) iter.next();
1236            ResourceState s = getResourceState(h);
1237            resources.remove(h);
1238            destroyResource( h );
1239            iter.remove();
1240        }
1241
1242        scheduleResizerTask();
1243    }
1244
1245    /*
1246     * Increase the number of steady resources in the pool
1247     * if we detect that the steadyPoolSize has been increased
1248     */

1249    private void increaseSteadyPoolSize( int newSteadyPoolSize )
1250            throws PoolingException
1251    {
1252        cancelResizerTask();
1253        for (int i = resources.size(); i < newSteadyPoolSize; i++) {
1254            createResourceAndAddToPool();
1255        }
1256        scheduleResizerTask();
1257    }
1258
1259    /**
1260     * @throws PoolingException
1261     */

1262    private void createResourceAndAddToPool() throws PoolingException {
1263        ResourceHandle resourceHandle = allocator.createResource();
1264        //addResource() will also increment numResourcesInPool
1265
addResource(resourceSpec, resourceHandle);
1266        
1267        // addResource() does not add the resource to the free pool!!!
1268
// so we need to do that.
1269
getResourceState(resourceHandle).setBusy(false);
1270        free.add(resourceHandle);
1271        
1272        if ( monitoringEnabled ) {
1273            poolCounters.incrementNumConnCreated();
1274        }
1275    }
1276
1277    /**
1278     * Switch on matching of connections in the pool.
1279     */

1280    public void switchOnMatching() {
1281        matchConnections = true;
1282    }
1283
1284    /**
1285     * query the name of this pool. Required by monitoring
1286     *
1287     * @return the name of this pool
1288     */

1289    public String JavaDoc getPoolName() {
1290        return name;
1291    }
1292
1293    public synchronized void cancelResizerTask() {
1294    
1295    if (_logger.isLoggable( Level.FINE ) ) {
1296            _logger.finest("Cancelling resizer");
1297    }
1298    if (resizerTask != null ) {
1299            resizerTask.cancel();
1300    }
1301        resizerTask = null;
1302
1303       if (timer != null){
1304        timer.purge();
1305       }
1306    }
1307
1308
1309    public synchronized void dumpPoolStatus() {
1310        _logger.log(Level.INFO, "Name of pool :" + name);
1311        _logger.log(Level.INFO, "Free connections :" + free.size());
1312        _logger.log(Level.INFO, "Total connections :" + resources.size());
1313        _logger.log(Level.INFO, "Pool's matching is :" + matchConnections);
1314        _logger.log(Level.INFO, "Free Table is :" + free);
1315        _logger.log(Level.INFO, "Resource Table is :" + resources);
1316    }
1317    
1318    //Accessor to aid debugging
1319
public PoolCounters getPoolCounters(){
1320        return this.poolCounters;
1321    }
1322    
1323    private void logFine( String JavaDoc msg ) {
1324        if ( _logger.isLoggable( Level.FINE) ) {
1325        _logger.fine( msg );
1326    }
1327    }
1328    
1329    //Self management methods
1330
public int getMaxPoolSize() {
1331        return maxPoolSize;
1332    }
1333
1334    public int getSteadyPoolSize() {
1335        return steadyPoolSize;
1336    }
1337
1338
1339    public void setMaxPoolSize( int size ) {
1340        if ( size < resources.size() ) {
1341            synchronized( this ) {
1342                int toKill = resources.size() - size;
1343                if ( toKill > 0 ) {
1344                    try {
1345                        killExtraResources( toKill );
1346                    } catch( Exception JavaDoc re ) {
1347                        //ignore for now
1348
if (_logger.isLoggable(Level.FINE) ) {
1349                            _logger.fine( "setMaxPoolSize:: killExtraResources " +
1350                                "throws exception: " + re.getMessage() );
1351                        }
1352                    }
1353                }
1354            }
1355        }
1356        maxPoolSize = size;
1357    }
1358
1359    public void setSteadyPoolSize( int size ) {
1360        steadyPoolSize = size;
1361    }
1362    
1363    public void setSelfManaged( boolean selfManaged ) {
1364        logFine( "Setting selfManaged to : " +selfManaged+" in pool : "+name );
1365        selfManaged_ = selfManaged;
1366    }
1367
1368    protected boolean isSelfManaged() {
1369        return selfManaged_;
1370    }
1371    
1372    class PoolCounters {
1373        // No need to synchronize these counters, since it is not vital
1374
// information , and we avoid performance penalties
1375
long numConnFailedValidation = 0;
1376        long numConnTimedOut = 0;
1377        long numConnAcquired = 0;
1378        long numConnReleased = 0;
1379
1380        long maxNumConnUsed = 0; //The max number of connections ever used
1381
long minNumConnUsed = Long.MAX_VALUE;
1382        long currNumConnUsed = 0;
1383        
1384        //8.1 new monitoring statistics
1385
long currConnectionRequestWait = 0;
1386        long maxConnectionRequestWait = 0;
1387        long minConnectionRequestWait = Long.MAX_VALUE;
1388        long totalConnectionRequestWait = 0; //to compute Avg Conn Req wait time
1389

1390        long maxNumConnFree = 0;
1391        long minNumConnFree = Long.MAX_VALUE;
1392        long currNumConnFree = 0;
1393        
1394        long numConnCreated = 0;
1395        long numConnDestroyed = 0;
1396
1397    long numConnSuccessfullyMatched = 0;
1398    long numConnNotSuccessfullyMatched = 0;
1399
1400        PoolCounters(int freePoolSize) {
1401            currNumConnFree = freePoolSize;
1402        }
1403
1404
1405        protected void reset(int freePoolSize) {
1406            maxNumConnUsed = 0;
1407            minNumConnUsed = Long.MAX_VALUE;
1408            currNumConnUsed = 0;
1409            
1410            numConnFailedValidation = 0;
1411            numConnTimedOut = 0;
1412
1413            maxConnectionRequestWait = 0;
1414            minConnectionRequestWait = Long.MAX_VALUE;
1415            totalConnectionRequestWait = 0;
1416
1417            maxNumConnFree = 0;
1418            minNumConnFree = Long.MAX_VALUE;
1419            currNumConnFree = freePoolSize;
1420                
1421            numConnCreated = 0;
1422            numConnDestroyed = 0;
1423    
1424            numConnSuccessfullyMatched = 0;
1425            numConnNotSuccessfullyMatched = 0;
1426        }
1427        
1428        protected synchronized void setWaitTime(long elapsedWaitTime) {}
1429        protected synchronized void incrementNumConnUsed(){}
1430        protected synchronized void decrementNumConnUsed(boolean isConnectionDestroyed){}
1431        protected synchronized void decrementNumConnFree(){}
1432        protected void setNumConnUsed(long numConnInUse){}
1433        protected void setNumConnFree(long numConnFree){}
1434        protected void incrementNumConnCreated(){}
1435        protected void incrementNumConnDestroyed(){}
1436        protected void incrementNumConnMatched() {}
1437        protected void incrementNumConnNotMatched() {}
1438        protected void incrementNumConnAcquired() {}
1439        protected void incrementNumConnTimedOut() {}
1440        protected void incrementNumConnReleased() {}
1441        protected void incrementNumConnFailedValidation(int incr) {}
1442        protected void incrementNumConnSuccessfullyMatched() {}
1443        protected void incrementNumConnNotSuccessfullyMatched() {}
1444        
1445        public String JavaDoc toString(){
1446            String JavaDoc str = "PoolCounters: ";
1447            str += "\n numConnFailedValidation = " + numConnFailedValidation;
1448            str += "\n numConnTimedOut = " + numConnTimedOut;
1449            str += "\n numConnAcquired = " + numConnAcquired;
1450            str += "\n numConnReleased = " + numConnReleased;
1451            
1452            str += "\n maxNumConnUsed = " + maxNumConnUsed;
1453            str += "\n minNumConnUsed = " + minNumConnUsed;
1454            str += "\n currNumConnUsed = " + currNumConnUsed;
1455            
1456            str += "\n maxConnectionRequestWait = " + maxConnectionRequestWait;
1457            str += "\n minConnectionRequestWait = " + minConnectionRequestWait;
1458            str += "\n maxNumConnFree = = " + maxNumConnFree;
1459            str += "\n minNumConnFree = " + minNumConnFree;
1460
1461            str += "\n currNumConnFree = " + currNumConnFree;
1462            str += "\n numConnCreated = " + numConnCreated;
1463            str += "\n numConnDestroyed = " + numConnDestroyed;
1464            
1465            str += "\n numConnSuccessfullyMatched = " + numConnSuccessfullyMatched;
1466            str += "\n numConnNotSuccessfullyMatched = " + numConnNotSuccessfullyMatched;
1467            return str;
1468        }
1469    }
1470
1471    class LowPoolCounters extends PoolCounters {
1472
1473        LowPoolCounters( int freePoolSize ) {
1474            super( freePoolSize );
1475        }
1476
1477        @Override JavaDoc
1478        protected void incrementNumConnCreated(){
1479            numConnCreated++;
1480        }
1481
1482        @Override JavaDoc
1483        protected void incrementNumConnDestroyed(){
1484            numConnDestroyed++;
1485        }
1486
1487        @Override JavaDoc
1488        protected synchronized void incrementNumConnUsed(){
1489            this.setNumConnUsed(++this.currNumConnUsed);
1490            this.setNumConnFree(--this.currNumConnFree);
1491        }
1492
1493        @Override JavaDoc
1494        //Called while a connection is removed from the pool
1495
//or a connection is closed/transaction completed
1496
protected synchronized void decrementNumConnUsed(boolean isConnectionDestroyed){
1497            this.setNumConnUsed(--this.currNumConnUsed);
1498            
1499            if (isConnectionDestroyed) {
1500                //If pool is being pruned by resizer thread
1501
//latch total number of connections in pool (conn free + conn used) to
1502
//steady-pool size
1503
if((poolCounters.currNumConnFree + poolCounters.currNumConnUsed)
1504                        < steadyPoolSize) {
1505                    this.setNumConnFree(++this.currNumConnFree);
1506                }
1507            } else {
1508                //donot latch here as this is a simple connection close
1509
//or tx completed and the pool size could
1510
//be greater than steady pool size
1511
this.setNumConnFree(++this.currNumConnFree);
1512            }
1513        }
1514        
1515        //Called while a free connection is destroyed from the
1516
//pool by the resizer.
1517
@Override JavaDoc
1518        protected synchronized void decrementNumConnFree(){
1519            //Latch total number of connections [free+used] to
1520
//steady pool size
1521
if((poolCounters.currNumConnFree + poolCounters.currNumConnUsed)
1522                    > steadyPoolSize)
1523                this.setNumConnFree(--this.currNumConnFree);
1524        }
1525
1526        @Override JavaDoc
1527        protected void setNumConnUsed(long numConnInUse){
1528            //latch max
1529
if ( numConnInUse > maxNumConnUsed ) {
1530                maxNumConnUsed = numConnInUse;
1531            }
1532            //latch min
1533
if ( numConnInUse < minNumConnUsed ) {
1534                if (numConnInUse <= 0) {
1535                    minNumConnUsed = 0;
1536                } else {
1537                    minNumConnUsed = numConnInUse;
1538                }
1539            }
1540            //set current
1541
this.currNumConnUsed = numConnInUse;
1542        }
1543        
1544        @Override JavaDoc
1545        protected void setNumConnFree(long numConnFree){
1546            //latch max
1547
if ( numConnFree > maxNumConnFree ) {
1548                maxNumConnFree = numConnFree;
1549            }
1550            
1551            //latch min
1552
if ( numConnFree < minNumConnFree ) {
1553                if (numConnFree <= 0) {
1554                    minNumConnFree = 0;
1555                } else {
1556                    minNumConnFree = numConnFree;
1557                }
1558            }
1559            
1560            //set current - number of connections free cannot be less than zero
1561
this.currNumConnFree = (numConnFree >= 0) ? numConnFree : 0;
1562        }
1563    }
1564
1565    class HighPoolCounters extends LowPoolCounters {
1566
1567        HighPoolCounters( int freePoolSize ) {
1568            super( freePoolSize );
1569        }
1570        
1571        @Override JavaDoc
1572        public synchronized void setWaitTime(long elapsedWaitTime) {
1573            //latch max
1574
currConnectionRequestWait = elapsedWaitTime;
1575            if (elapsedWaitTime > maxConnectionRequestWait)
1576                maxConnectionRequestWait= elapsedWaitTime;
1577            //latch min
1578
if (elapsedWaitTime < minConnectionRequestWait)
1579                minConnectionRequestWait = elapsedWaitTime;
1580            totalConnectionRequestWait += elapsedWaitTime;
1581        }
1582        
1583        @Override JavaDoc
1584        protected void incrementNumConnAcquired() {
1585            numConnAcquired++;
1586        }
1587
1588        @Override JavaDoc
1589        protected void incrementNumConnTimedOut() {
1590            numConnTimedOut++;
1591        }
1592
1593        @Override JavaDoc
1594        protected void incrementNumConnReleased() {
1595            numConnReleased++;
1596        }
1597
1598        @Override JavaDoc
1599        protected void incrementNumConnFailedValidation( int incr ) {
1600            numConnFailedValidation += incr;
1601        }
1602    
1603        @Override JavaDoc
1604        protected void incrementNumConnSuccessfullyMatched() {
1605            numConnSuccessfullyMatched++;
1606        }
1607        
1608        @Override JavaDoc
1609        protected void incrementNumConnNotSuccessfullyMatched() {
1610            numConnNotSuccessfullyMatched++;
1611        }
1612    }
1613
1614}
1615
Popular Tags