KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > resource > connectionmanager > JBossManagedConnectionPool


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.resource.connectionmanager;
23
24 import java.security.AccessController JavaDoc;
25 import java.security.PrivilegedAction JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Map JavaDoc;
28
29 import javax.management.Notification JavaDoc;
30 import javax.management.NotificationFilter JavaDoc;
31 import javax.management.NotificationListener JavaDoc;
32 import javax.management.ObjectName JavaDoc;
33 import javax.resource.ResourceException JavaDoc;
34 import javax.resource.spi.ConnectionRequestInfo JavaDoc;
35 import javax.resource.spi.ManagedConnectionFactory JavaDoc;
36 import javax.security.auth.Subject JavaDoc;
37 import javax.transaction.Transaction JavaDoc;
38 import javax.transaction.TransactionManager JavaDoc;
39
40 import org.jboss.deployment.DeploymentException;
41 import org.jboss.logging.Logger;
42 import org.jboss.mx.util.JMXExceptionDecoder;
43 import org.jboss.resource.JBossResourceException;
44 import org.jboss.resource.connectionmanager.InternalManagedConnectionPool.PoolParams;
45 import org.jboss.resource.statistic.JBossStatistics;
46 import org.jboss.resource.statistic.StatisticsReporter;
47 import org.jboss.resource.statistic.formatter.StatisticsFormatter;
48 import org.jboss.resource.statistic.pool.JBossDefaultSubPoolStatisticFormatter;
49 import org.jboss.resource.statistic.pool.JBossManagedConnectionPoolStatistics;
50 import org.jboss.resource.statistic.pool.JBossSubPoolStatistics;
51 import org.jboss.resource.statistic.pool.ManagedConnectionPoolStatistics;
52 import org.jboss.system.ServiceMBeanSupport;
53 import org.jboss.tm.TransactionLocal;
54
55 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
56
57 /**
58  * The JBossManagedConnectionPool mbean configures and supplies pooling of
59  * JBossConnectionEventListeners to the BaseConnectionManager2 mbean.<p>
60  *
61  * It may be replaced by any mbean with a readable ManagedConnectionPool attribute
62  * of type ManagedConnectionPool. Normal pooling parameters are supplied,
63  * and the criteria to distinguish ManagedConnections is set in the Criteria attribute.
64  *
65  * @author <a HREF="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
66  * @author <a HREF="mailto:adrian@jboss.org">Adrian Brock</a>
67  * @author <a HREF="mailto:weston.price@jboss.com">Weston Price</a>
68  *
69  * @version $Revision: 57098 $
70  */

71 public class JBossManagedConnectionPool extends ServiceMBeanSupport
72    implements JBossManagedConnectionPoolMBean, NotificationListener JavaDoc
73 {
74    
75    static Logger log = Logger.getLogger(JBossManagedConnectionPool.class);
76    
77    /** The managed connection factory name */
78    private ObjectName JavaDoc managedConnectionFactoryName;
79
80    /** The pooling criteria */
81    private String JavaDoc criteria;
82
83    /** The pooling strategy */
84    private ManagedConnectionPool poolingStrategy;
85
86    /** The pooling parameters */
87    private final InternalManagedConnectionPool.PoolParams poolParams = new InternalManagedConnectionPool.PoolParams();
88
89    /** Whether to use separate pools for transactional and non-transaction use */
90    private boolean noTxSeparatePools;
91
92    /** The statisticsFormatter
93     *
94     * */

95    private String JavaDoc statisticsFormatter;
96    
97    private String JavaDoc poolJndiName;
98    
99    public JBossManagedConnectionPool()
100    {
101    }
102    
103    public Object JavaDoc listFormatttedSubPoolStatistics(String JavaDoc formatClassName)
104    {
105       final JBossStatistics stats = (JBossStatistics)listStatistics();
106       final ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
107       Class JavaDoc clazz;
108       StatisticsFormatter formatter = null;
109       
110       try
111       {
112          clazz = cl.loadClass(formatClassName);
113          formatter = (StatisticsFormatter)clazz.newInstance();
114       }
115       catch (Exception JavaDoc e)
116       {
117          log.warn("warn: statistics formatter not found, setting to " + statisticsFormatter);
118          formatter = new JBossDefaultSubPoolStatisticFormatter();
119          
120       }
121    
122       return formatter.formatStatistics(stats);
123    }
124    
125    public Object JavaDoc listFormattedSubPoolStatistics(){
126       
127       Object JavaDoc formatted = listFormatttedSubPoolStatistics(statisticsFormatter);
128       return formatted;
129    }
130    
131    public Object JavaDoc listStatistics()
132    {
133       ManagedConnectionPoolStatistics stats = null;
134       
135       if (poolingStrategy instanceof StatisticsReporter)
136       {
137          
138          StatisticsReporter reporter = (StatisticsReporter) poolingStrategy;
139          stats = (ManagedConnectionPoolStatistics)reporter.listStatistics();
140          stats.setCriteria(getCriteria());
141          stats.setName(getManagedConnectionFactoryName().toString());
142          
143       }
144       
145       return stats;
146    }
147    
148    public ManagedConnectionPool getManagedConnectionPool()
149    {
150       return poolingStrategy;
151    }
152
153    public ObjectName JavaDoc getManagedConnectionFactoryName()
154    {
155       return managedConnectionFactoryName;
156    }
157
158    public void setManagedConnectionFactoryName(ObjectName JavaDoc newManagedConnectionFactoryName)
159    {
160       this.managedConnectionFactoryName = newManagedConnectionFactoryName;
161    }
162
163    public long getAvailableConnectionCount()
164    {
165       return (poolingStrategy == null) ? 0 : poolingStrategy.getAvailableConnectionCount();
166    }
167
168    public long getMaxConnectionsInUseCount()
169    {
170       return (poolingStrategy == null) ? 0 : poolingStrategy.getMaxConnectionsInUseCount();
171    }
172
173    public long getInUseConnectionCount ()
174    {
175       return (poolingStrategy == null) ? 0 : poolingStrategy.getInUseConnectionCount();
176    }
177
178    public int getMinSize()
179    {
180       return poolParams.minSize;
181    }
182
183    public void setMinSize(int newMinSize)
184    {
185       poolParams.minSize = newMinSize;
186    }
187
188    public int getMaxSize()
189    {
190       return poolParams.maxSize;
191    }
192
193    public void setMaxSize(int newMaxSize)
194    {
195       poolParams.maxSize = newMaxSize;
196    }
197
198    public int getBlockingTimeoutMillis()
199    {
200       return poolParams.blockingTimeout;
201    }
202
203    public void setBlockingTimeoutMillis(int newBlockingTimeout)
204    {
205       poolParams.blockingTimeout = newBlockingTimeout;
206    }
207
208    public long getIdleTimeoutMinutes()
209    {
210       return poolParams.idleTimeout / (1000 * 60);
211    }
212
213    public void setIdleTimeoutMinutes(long newIdleTimeoutMinutes)
214    {
215       poolParams.idleTimeout = newIdleTimeoutMinutes * 1000 * 60;
216    }
217
218    /**
219     * Get the IdleTimeout value.
220     *
221     * @return the IdleTimeout value.
222     */

223    public long getIdleTimeout()
224    {
225       return poolParams.idleTimeout;
226    }
227
228    /**
229     * Set the IdleTimeout value.
230     *
231     * @param newIdleTimeout The new IdleTimeout value.
232     */

233    public void setIdleTimeout(long newIdleTimeout)
234    {
235       poolParams.idleTimeout = newIdleTimeout;
236    }
237
238    public String JavaDoc getCriteria()
239    {
240       return criteria;
241    }
242
243    public void setCriteria(String JavaDoc newCriteria)
244    {
245       this.criteria = newCriteria;
246    }
247
248    public boolean getNoTxSeparatePools()
249    {
250       return noTxSeparatePools;
251    }
252
253    public void setNoTxSeparatePools(boolean value)
254    {
255       this.noTxSeparatePools = value;
256    }
257
258    public boolean getPreFill(){
259       
260       return poolParams.prefill;
261       
262    }
263    
264    public void setPreFill(boolean prefill){
265       
266       poolParams.prefill = prefill;
267    }
268    
269    public void setStrictMin(boolean strictMin)
270    {
271       poolParams.stictMin = strictMin;
272       
273    }
274    
275    public boolean getStrictMin()
276    {
277          
278       return poolParams.stictMin;
279       
280    }
281    
282    public void flush()
283    {
284        if (poolingStrategy == null)
285          throw new IllegalStateException JavaDoc("The connection pool is not started");
286
287       poolingStrategy.flush();
288
289       if (poolingStrategy instanceof PreFillPoolSupport)
290       {
291          final PreFillPoolSupport pfs = (PreFillPoolSupport) poolingStrategy;
292
293          if (pfs.shouldPreFill())
294             pfs.prefill(noTxSeparatePools);
295
296       }
297    }
298
299    public int getConnectionCount()
300    {
301       return (poolingStrategy == null)? 0: poolingStrategy.getConnectionCount();
302    }
303
304    public int getConnectionCreatedCount()
305    {
306       return (poolingStrategy == null)? 0: poolingStrategy.getConnectionCreatedCount();
307    }
308
309    public int getConnectionDestroyedCount()
310    {
311       return (poolingStrategy == null)? 0: poolingStrategy.getConnectionDestroyedCount();
312    }
313
314    public String JavaDoc getName()
315    {
316       return "JBossManagedConnectionPool";
317    }
318    public String JavaDoc getStatisticsFormatter()
319    {
320       return statisticsFormatter;
321    }
322
323    public void setStatisticsFormatter(String JavaDoc statisticsFormatter)
324    {
325       this.statisticsFormatter = statisticsFormatter;
326    }
327    public String JavaDoc getPoolJndiName()
328    {
329       return this.poolJndiName;
330    }
331
332    public void setPoolJndiName(String JavaDoc poolName)
333    {
334       this.poolJndiName = poolName;
335    }
336   
337    public boolean getBackGroundValidation()
338    {
339       return poolParams.backgroundValidation;
340    }
341
342    public void setBackGroundValidation(boolean backgroundValidation)
343    {
344
345       poolParams.backgroundValidation = backgroundValidation;
346
347    }
348
349    public long getBackGroundValidationMinutes()
350    {
351
352       return poolParams.backgroundInterval / (1000 * 60);
353    }
354
355    public void setBackGroundValidationMinutes(long backgroundValidationInterval)
356    {
357
358       poolParams.backgroundInterval = backgroundValidationInterval * 1000 * 60;
359
360    }
361
362    protected void startService() throws Exception JavaDoc
363    {
364       ManagedConnectionFactory JavaDoc mcf = null;
365       
366       if (managedConnectionFactoryName == null)
367          throw new DeploymentException("ManagedConnectionFactory not set!");
368
369       try
370       {
371          //We are getting the actual mcf instance itself. This will require
372
//some work if the mcf is an xmbean of itself.
373
mcf = (ManagedConnectionFactory JavaDoc)server.getAttribute(managedConnectionFactoryName, "McfInstance");
374       }
375       catch (Exception JavaDoc e)
376       {
377          JMXExceptionDecoder.rethrow(e);
378       }
379
380       getServer().addNotificationListener
381       (
382          managedConnectionFactoryName,
383          this,
384          new NotificationFilter JavaDoc()
385          {
386             private static final long serialVersionUID = -9211456539783257343L;
387
388             public boolean isNotificationEnabled(Notification JavaDoc n)
389             {
390                return RARDeployment.MCF_ATTRIBUTE_CHANGED_NOTIFICATION.equals(n.getType())
391                       && managedConnectionFactoryName.equals(n.getSource());
392             }
393          },
394          null
395       );
396
397       if ("ByContainerAndApplication".equals(criteria))
398          poolingStrategy = new PoolBySubjectAndCri(mcf, poolParams, noTxSeparatePools, log);
399       else if ("ByContainer".equals(criteria))
400          poolingStrategy = new PoolBySubject(mcf, poolParams, noTxSeparatePools, log);
401       else if ("ByApplication".equals(criteria))
402          poolingStrategy = new PoolByCri(mcf, poolParams, noTxSeparatePools, log);
403       else if ("ByNothing".equals(criteria))
404          poolingStrategy = new OnePool(mcf, poolParams, noTxSeparatePools, log);
405       else
406          throw new DeploymentException("Unknown pooling criteria: " + criteria);
407    }
408
409    protected void stopService() throws Exception JavaDoc
410    {
411       if (poolingStrategy != null)
412          poolingStrategy.shutdown();
413       getServer().removeNotificationListener(managedConnectionFactoryName, this);
414       poolingStrategy = null;
415    }
416
417    public void handleNotification(Notification JavaDoc notification,
418                                   Object JavaDoc handback)
419    {
420       flush();
421    }
422
423    public static class SubPoolContext
424    {
425       /** The subpool */
426       private InternalManagedConnectionPool subPool;
427       
428       /** The track by transaction transaction local */
429       private TransactionLocal trackByTx;
430
431       /**
432        * Create a new SubPoolContext.
433        *
434        * @param tm the transaction manager
435        * @param mcf the managed connection factory
436        * @param clf the connection listener factory
437        * @param subject the subject
438        * @param cri the connection request info
439        * @param poolParams the pool parameters
440        * @param log the log
441        */

442       public SubPoolContext(TransactionManager JavaDoc tm, ManagedConnectionFactory JavaDoc mcf, ConnectionListenerFactory clf, Subject JavaDoc subject,
443             ConnectionRequestInfo JavaDoc cri, PoolParams poolParams, Logger log)
444       {
445          subPool = new InternalManagedConnectionPool(mcf, clf, subject, cri, poolParams, log);
446          if (tm != null)
447             trackByTx = new TransactionLocal(tm);
448       }
449       
450       /**
451        * Get the sub pool
452        *
453        * @return the sub pool
454        */

455       public InternalManagedConnectionPool getSubPool()
456       {
457          return subPool;
458       }
459       
460       /**
461        * Get the track by transaction
462        *
463        * @return the transaction local
464        */

465       public TransactionLocal getTrackByTx()
466       {
467          return trackByTx;
468       }
469       
470       /**
471        * Initialize the subpool context
472        */

473       public void initialize()
474       {
475          subPool.initialize();
476       }
477    }
478    
479    /**
480     * The base pool implementation
481     */

482    public abstract static class BasePool implements ManagedConnectionPool, StatisticsReporter, PreFillPoolSupport
483    {
484       /** The subpools */
485       private final Map JavaDoc subPools = new ConcurrentReaderHashMap();
486
487       /** The managed connection factory */
488       private final ManagedConnectionFactory JavaDoc mcf;
489       
490       /** The connection listener factory */
491       private ConnectionListenerFactory clf;
492
493       /** The pool parameters */
494       private final InternalManagedConnectionPool.PoolParams poolParams;
495
496       /** Whether to use separate pools for transactional and non-transaction use */
497       private boolean noTxSeparatePools;
498
499       /** The poolName */
500       private String JavaDoc poolName;
501       /** The logger */
502       private final Logger log;
503
504       /** Is trace enabled */
505       private boolean traceEnabled = false;
506
507       /**
508        * Create a new base pool
509        *
510        * @param mcf the managed connection factory
511        * @param poolParams the pooling parameters
512        * @param log the log
513        */

514       public BasePool(final ManagedConnectionFactory JavaDoc mcf, final InternalManagedConnectionPool.PoolParams poolParams,
515                       final boolean noTxSeparatePools, final Logger log)
516       {
517          this.mcf = mcf;
518          this.poolParams = poolParams;
519          this.noTxSeparatePools = noTxSeparatePools;
520          this.log = log;
521          this.traceEnabled = log.isTraceEnabled();
522       }
523
524       /**
525        * Retrieve the key for this request
526        *
527        * @param subject the subject
528        * @param cri the connection request information
529        * @return the key
530        * @throws ResourceException for any error
531        */

532       protected abstract Object JavaDoc getKey(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri, boolean separateNoTx) throws ResourceException JavaDoc;
533       
534      
535       public ManagedConnectionFactory JavaDoc getManagedConnectionFactory()
536       {
537          return mcf;
538       }
539
540       public void setConnectionListenerFactory(ConnectionListenerFactory clf)
541       {
542          this.clf = clf;
543       }
544      
545       public ConnectionListener getConnection(Transaction JavaDoc trackByTransaction, Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri)
546          throws ResourceException JavaDoc
547       {
548          // Determine the pool key for this request
549
boolean separateNoTx = false;
550          if (noTxSeparatePools)
551             separateNoTx = clf.isTransactional();
552          Object JavaDoc key = getKey(subject, cri, separateNoTx);
553          SubPoolContext subPool = getSubPool(key, subject, cri);
554          
555          InternalManagedConnectionPool mcp = subPool.getSubPool();
556          
557          // Are we doing track by connection?
558
TransactionLocal trackByTx = subPool.getTrackByTx();
559
560          // Simple case
561
if (trackByTransaction == null || trackByTx == null)
562          {
563             ConnectionListener cl = mcp.getConnection(subject, cri);
564             if (traceEnabled)
565                dump("Got connection from pool " + cl);
566             return cl;
567          }
568
569          // Track by transaction
570
try
571          {
572             trackByTx.lock(trackByTransaction);
573          }
574          catch (Throwable JavaDoc t)
575          {
576             JBossResourceException.rethrowAsResourceException("Unable to get connection from the pool for tx=" + trackByTransaction, t);
577          }
578          try
579          {
580             // Already got one
581
ConnectionListener cl = (ConnectionListener) trackByTx.get(trackByTransaction);
582             if (cl != null)
583             {
584                if (traceEnabled)
585                   dump("Previous connection tracked by transaction " + cl + " tx=" + trackByTransaction);
586                return cl;
587             }
588          }
589          finally
590          {
591             trackByTx.unlock(trackByTransaction);
592          }
593
594          // Need a new one for this transaction
595
// This must be done outside the tx local lock, otherwise
596
// the tx timeout won't work and get connection can do a lot of other work
597
// with many opportunities for deadlocks.
598
// Instead we do a double check after we got the transaction to see
599
// whether another thread beat us to the punch.
600
ConnectionListener cl = mcp.getConnection(subject, cri);
601          if (traceEnabled)
602             dump("Got connection from pool tracked by transaction " + cl + " tx=" + trackByTransaction);
603          
604          // Relock and check/set status
605
try
606          {
607             trackByTx.lock(trackByTransaction);
608          }
609          catch (Throwable JavaDoc t)
610          {
611             mcp.returnConnection(cl, false);
612             if (traceEnabled)
613                dump("Had to return connection tracked by transaction " + cl + " tx=" + trackByTransaction + " error=" + t.getMessage());
614             JBossResourceException.rethrowAsResourceException("Unable to get connection from the pool for tx=" + trackByTransaction, t);
615          }
616          try
617          {
618             // Check we weren't racing with another transaction
619
ConnectionListener other = (ConnectionListener) trackByTx.get(trackByTransaction);
620             if (other != null)
621             {
622                mcp.returnConnection(cl, false);
623                if (traceEnabled)
624                   dump("Another thread already got a connection tracked by transaction " + other + " tx=" + trackByTransaction);
625                return other;
626             }
627             
628             // This is the connection for this transaction
629
cl.setTrackByTx(true);
630             trackByTx.set(cl);
631             if (traceEnabled)
632                dump("Using connection from pool tracked by transaction " + cl + " tx=" + trackByTransaction);
633             return cl;
634          }
635          finally
636          {
637             trackByTx.unlock(trackByTransaction);
638          }
639       }
640
641       public void returnConnection(ConnectionListener cl, boolean kill) throws ResourceException JavaDoc
642       {
643          cl.setTrackByTx(false);
644          InternalManagedConnectionPool mcp = (InternalManagedConnectionPool) cl.getContext();
645          mcp.returnConnection(cl, kill);
646          if (traceEnabled)
647             dump("Returning connection to pool " + cl);
648       }
649       
650       /**
651        * Return the inuse count
652        *
653        * @return the count
654        */

655       public int getInUseConnectionCount()
656       {
657          int count = 0;
658          synchronized (subPools)
659          {
660             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
661             {
662                SubPoolContext subPool = (SubPoolContext) i.next();
663                count += subPool.getSubPool().getConnectionInUseCount();
664             }
665          }
666          return count;
667       }
668       public boolean getPreFill()
669       {
670          return this.poolParams.prefill;
671
672       }
673
674       public boolean shouldPreFill()
675       {
676          return getPreFill();
677       }
678
679       public void prefill()
680       {
681
682          prefill(null, null, false);
683
684       }
685
686       public void prefill(boolean noTxSeperatePool)
687       {
688
689          prefill(null, null, noTxSeperatePool);
690
691       }
692
693       public void prefill(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri, boolean noTxSeperatePool)
694       {
695          if (getPreFill())
696          {
697
698             log.debug("Attempting to prefill pool for pool with jndi name" + poolName);
699
700             try
701             {
702
703                getSubPool(getKey(subject, cri, noTxSeparatePools), subject, cri);
704
705             }
706             catch (Throwable JavaDoc t)
707             {
708                //No real need to throw here being that pool remains in the same state as before.
709
log.error("Unable to prefill pool with jndi name" + getPoolName(), t);
710
711             }
712
713          }
714
715       }
716
717       public int getConnectionCount()
718       {
719          int count = 0;
720          synchronized (subPools)
721          {
722             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
723             {
724                SubPoolContext subPool = (SubPoolContext) i.next();
725                count += subPool.getSubPool().getConnectionCount();
726             }
727          }
728          return count;
729       }
730       
731       public String JavaDoc getPoolName()
732       {
733          return poolName;
734       }
735       public int getConnectionCreatedCount()
736       {
737          int count = 0;
738          synchronized (subPools)
739          {
740             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
741             {
742                SubPoolContext subPool = (SubPoolContext) i.next();
743                count += subPool.getSubPool().getConnectionCreatedCount();
744             }
745          }
746          return count;
747       }
748
749       public int getConnectionDestroyedCount()
750       {
751          int count = 0;
752          synchronized (subPools)
753          {
754             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
755             {
756                SubPoolContext subPool = (SubPoolContext) i.next();
757                count += subPool.getSubPool().getConnectionDestroyedCount();
758             }
759          }
760          return count;
761       }
762
763       public long getAvailableConnectionCount()
764       {
765          long count = 0;
766          synchronized (subPools)
767          {
768             if (subPools.size() == 0)
769                return poolParams.maxSize;
770             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
771             {
772                SubPoolContext subPool = (SubPoolContext) i.next();
773                count += subPool.getSubPool().getAvailableConnections();
774             }
775          }
776          return count;
777       }
778
779       public int getMaxConnectionsInUseCount()
780       {
781          int count = 0;
782          synchronized (subPools)
783          {
784             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
785             {
786                SubPoolContext subPool = (SubPoolContext) i.next();
787                count += subPool.getSubPool().getMaxConnectionsInUseCount();
788             }
789          }
790          return count;
791       }
792       
793       public void shutdown()
794       {
795          synchronized (subPools)
796          {
797             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
798             {
799                SubPoolContext subPool = (SubPoolContext) i.next();
800                subPool.getSubPool().shutdown();
801             }
802             subPools.clear();
803          }
804       }
805
806       public void flush()
807       {
808          synchronized (subPools)
809          {
810             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
811             {
812                SubPoolContext subPool = (SubPoolContext) i.next();
813                subPool.getSubPool().shutdown();
814             }
815             subPools.clear();
816          }
817       }
818
819       /**
820        * For testing
821        */

822       protected void shutdownWithoutClear()
823       {
824          synchronized (subPools)
825          {
826             for (Iterator JavaDoc i = subPools.values().iterator(); i.hasNext(); )
827             {
828                SubPoolContext subPool = (SubPoolContext) i.next();
829                subPool.getSubPool().shutdown();
830             }
831          }
832       }
833       
834       /**
835        * Get any transaction manager associated with the pool
836        *
837        * @return the transaction manager
838        */

839       protected TransactionManager JavaDoc getTransactionManager()
840       {
841          if (clf != null)
842             return clf.getTransactionManagerInstance();
843          else
844             return null;
845       }
846
847       /**
848        * Determine the correct pool for this request,
849        * creates a new one when necessary
850        *
851        * @param key the key to the pool
852        * @param subject the subject of the pool
853        * @param cri the connection request info
854        * @return the subpool context
855        * @throws ResourceException for any error
856        */

857       protected SubPoolContext getSubPool(Object JavaDoc key, Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri) throws ResourceException JavaDoc
858       {
859          SubPoolContext subPool = (SubPoolContext) subPools.get(key);
860          if (subPool == null)
861          {
862             TransactionManager JavaDoc tm = getTransactionManager();
863             subPool = new SubPoolContext(tm, mcf, clf, subject, cri, poolParams, log);
864             synchronized (subPools)
865             {
866                if (subPools.containsKey(key))
867                   subPool = (SubPoolContext) subPools.get(key);
868                else
869                {
870                   subPool.initialize();
871                   subPools.put(key, subPool);
872                }
873             }
874          }
875          return subPool;
876       }
877
878       /**
879        * Dump the stats to the trace log
880        *
881        * @param info some context
882        */

883       private void dump(String JavaDoc info)
884       {
885          if (traceEnabled)
886          {
887             StringBuffer JavaDoc toLog = new StringBuffer JavaDoc(100);
888             toLog.append(info).append(" [InUse/Available/Max]: [");
889             toLog.append(this.getInUseConnectionCount()).append("/");
890             toLog.append(this.getAvailableConnectionCount()).append("/");
891             toLog.append(this.poolParams.maxSize);
892             toLog.append("]");;
893             log.trace(toLog);
894          }
895       }
896          
897       public JBossStatistics listStatistics(){
898          
899          final ManagedConnectionPoolStatistics subPoolStats = new JBossManagedConnectionPoolStatistics(subPools.size());
900          
901          subPoolStats.setBlockingTimeout(poolParams.blockingTimeout);
902          subPoolStats.setIdleTimeout(poolParams.idleTimeout);
903          subPoolStats.setMax(poolParams.maxSize);
904          subPoolStats.setMin(poolParams.minSize);
905          subPoolStats.setPrefill(poolParams.prefill);
906          subPoolStats.setNoTxnSeperatePool(noTxSeparatePools);
907          
908          
909          
910          for(Iterator JavaDoc iter = subPools.values().iterator(); iter.hasNext();){
911             
912             JBossSubPoolStatistics stat = new JBossSubPoolStatistics();
913             SubPoolContext subContext = (SubPoolContext)iter.next();
914             Boolean JavaDoc trackByTxn = (subContext.getTrackByTx() != null) ? Boolean.TRUE : Boolean.FALSE;
915             stat.setTrackByTxn(trackByTxn);
916             final InternalManagedConnectionPool internalPool = subContext.getSubPool();
917             stat.setAvailableConnections(internalPool.getAvailableConnections());
918             stat.setConnectionsDestroyed(internalPool.getConnectionDestroyedCount());
919             stat.setConnectionsInUse(internalPool.getMaxConnectionsInUseCount());
920             stat.setMaxConnectionsInUse(internalPool.getMaxConnectionsInUseCount());
921             stat.setTotalBlockTime(internalPool.getTotalBlockTime());
922             subPoolStats.addSubPool(stat);
923             
924             
925          }
926
927          return (JBossStatistics)subPoolStats;
928       }
929    }
930
931    /**
932     * Pooling by subject and connection request information
933     */

934    public static class PoolBySubjectAndCri
935       extends BasePool
936    {
937       public PoolBySubjectAndCri(final ManagedConnectionFactory JavaDoc mcf,
938                                  final InternalManagedConnectionPool.PoolParams poolParams,
939                                  final boolean noTxSeparatePools,
940                                  final Logger log)
941       {
942          super(mcf, poolParams, noTxSeparatePools, log);
943       
944       }
945
946       protected Object JavaDoc getKey(final Subject JavaDoc subject, final ConnectionRequestInfo JavaDoc cri, final boolean separateNoTx) throws ResourceException JavaDoc
947       {
948          return new SubjectCriKey(subject, cri, separateNoTx);
949       }
950    
951       public void prefill()
952       {
953          prefill(null, null, false);
954       }
955
956       public void prefill(boolean noTxSeperatePool)
957       {
958          prefill(null, null, noTxSeperatePool);
959       }
960
961       public void prefill(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri)
962       {
963          prefill(subject, cri, false);
964
965       }
966
967       public void prefill(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri, boolean noTxSeperatePool)
968       {
969          if (getPreFill())
970          {
971             log.warn("Prefill pool option was selected for pool with JNDI name " + getPoolName()
972                   + " that does not support this feature.");
973             log
974                   .warn("Please verify your *-ds.xml file that corresponds with this resource and either remove the <prefill>true|false</prefill element or explicitly set this value to false.");
975
976          }
977       }
978    }
979
980    /**
981     * Pool by subject and criteria
982     */

983    private static class SubjectCriKey
984    {
985       /** Identifies no subject */
986       private static final Subject JavaDoc NOSUBJECT = new Subject JavaDoc();
987       
988       /** Identifies no connection request information */
989       private static final Object JavaDoc NOCRI = new Object JavaDoc();
990
991       /** The subject */
992       private final Subject JavaDoc subject;
993       
994       /** The connection request information */
995       private final Object JavaDoc cri;
996       
997       /** The cached hashCode */
998       private int hashCode = Integer.MAX_VALUE;
999
1000      /** Separate no tx */
1001      private boolean separateNoTx;
1002
1003      SubjectCriKey(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri, boolean separateNoTx)
1004      {
1005         this.subject = (subject == null)? NOSUBJECT:subject;
1006         this.cri = (cri == null)? NOCRI:cri;
1007         this.separateNoTx = separateNoTx;
1008      }
1009
1010      public int hashCode()
1011      {
1012         if (hashCode == Integer.MAX_VALUE)
1013            hashCode = SubjectActions.hashCode(subject) ^ cri.hashCode();
1014         return hashCode;
1015      }
1016
1017      public boolean equals(Object JavaDoc obj)
1018      {
1019         if (this == obj)
1020            return true;
1021         if (obj == null || (obj instanceof SubjectCriKey) == false)
1022            return false;
1023         SubjectCriKey other = (SubjectCriKey) obj;
1024         return SubjectActions.equals(subject, other.subject)
1025            && cri.equals(other.cri)
1026            && separateNoTx == other.separateNoTx;
1027      }
1028   }
1029
1030   /**
1031    * Pool by subject
1032    */

1033   public static class PoolBySubject
1034      extends BasePool
1035   {
1036
1037      public PoolBySubject(final ManagedConnectionFactory JavaDoc mcf,
1038                           final InternalManagedConnectionPool.PoolParams poolParams,
1039                           final boolean noTxSeparatePools,
1040                           final Logger log)
1041      {
1042         super(mcf, poolParams, noTxSeparatePools, log);
1043      }
1044
1045      protected Object JavaDoc getKey(final Subject JavaDoc subject, final ConnectionRequestInfo JavaDoc cri, boolean separateNoTx)
1046      {
1047         return new SubjectKey(subject, separateNoTx);
1048      }
1049   
1050      public void prefill()
1051      {
1052         prefill(null, null, false);
1053      }
1054
1055      public void prefill(boolean noTxSeperatePool)
1056      {
1057         prefill(null, null, noTxSeperatePool);
1058      }
1059
1060      public void prefill(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri)
1061      {
1062         prefill(subject, cri, false);
1063
1064      }
1065
1066      public void prefill(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri, boolean noTxSeperatePool)
1067      {
1068         if (getPreFill())
1069         {
1070            log.warn("Prefill pool option was selected for pool with JNDI name " + getPoolName()
1071                  + " that does not support this feature.");
1072            log
1073                  .warn("Please verify your *-ds.xml file that corresponds with this resource and either remove the <prefill>true|false</prefill element or explicitly set this value to false.");
1074
1075         }
1076      }
1077   }
1078
1079   /**
1080    * Pool by subject
1081    */

1082   private static class SubjectKey
1083   {
1084      /** Identifies no subject */
1085      private static final Subject JavaDoc NOSUBJECT = new Subject JavaDoc();
1086
1087      /** The subject */
1088      private final Subject JavaDoc subject;
1089
1090      /** Separate no tx */
1091      private boolean separateNoTx;
1092      
1093      /** The cached hashCode */
1094      private int hashCode = Integer.MAX_VALUE;
1095
1096      SubjectKey(Subject JavaDoc subject, boolean separateNoTx)
1097      {
1098         this.subject = (subject == null)? NOSUBJECT:subject;
1099         this.separateNoTx = separateNoTx;
1100      }
1101
1102      public int hashCode()
1103      {
1104         if (hashCode == Integer.MAX_VALUE)
1105            hashCode = SubjectActions.hashCode(subject);
1106         return hashCode;
1107      }
1108
1109      public boolean equals(Object JavaDoc obj)
1110      {
1111         if (this == obj)
1112            return true;
1113         if (obj == null || (obj instanceof SubjectKey) == false)
1114            return false;
1115         SubjectKey other = (SubjectKey) obj;
1116         return SubjectActions.equals(subject, other.subject)
1117            && separateNoTx == other.separateNoTx;
1118      }
1119   }
1120
1121   /**
1122    * Pool by connection request information
1123    */

1124   public static class PoolByCri
1125      extends BasePool
1126   {
1127      public PoolByCri(final ManagedConnectionFactory JavaDoc mcf,
1128                       final InternalManagedConnectionPool.PoolParams poolParams,
1129                       final boolean noTxSeparatePools,
1130                       final Logger log)
1131      {
1132         super(mcf, poolParams, noTxSeparatePools, log);
1133      }
1134
1135      protected Object JavaDoc getKey(final Subject JavaDoc subject, final ConnectionRequestInfo JavaDoc cri, boolean separateNoTx)
1136      {
1137         return new CriKey(cri, separateNoTx);
1138      }
1139   
1140      public void prefill()
1141      {
1142         prefill(null, null, false);
1143      }
1144
1145      public void prefill(boolean noTxSeperatePool)
1146      {
1147         prefill(null, null, noTxSeperatePool);
1148      }
1149
1150      public void prefill(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri)
1151      {
1152         prefill(subject, cri, false);
1153
1154      }
1155
1156      public void prefill(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri, boolean noTxSeperatePool)
1157      {
1158         if (getPreFill())
1159         {
1160            log.warn("Prefill pool option was selected for pool with JNDI name " + getPoolName()
1161                  + " that does not support this feature.");
1162            log
1163                  .warn("Please verify your *-ds.xml file that corresponds with this resource and either remove the <prefill>true|false</prefill element or explicitly set this value to false.");
1164
1165         }
1166      }
1167   }
1168
1169   /**
1170    * Pool by subject and criteria
1171    */

1172   private static class CriKey
1173   {
1174      /** Identifies no connection request information */
1175      private static final Object JavaDoc NOCRI = new Object JavaDoc();
1176      
1177      /** The connection request information */
1178      private final Object JavaDoc cri;
1179
1180      /** Separate no tx */
1181      private boolean separateNoTx;
1182      
1183      /** The cached hashCode */
1184      private int hashCode = Integer.MAX_VALUE;
1185
1186      CriKey(ConnectionRequestInfo JavaDoc cri, boolean separateNoTx)
1187      {
1188         this.cri = (cri == null)? NOCRI : cri;
1189         this.separateNoTx = separateNoTx;
1190      }
1191
1192      public int hashCode()
1193      {
1194         if (hashCode == Integer.MAX_VALUE)
1195            hashCode = cri.hashCode();
1196         return hashCode;
1197      }
1198
1199      public boolean equals(Object JavaDoc obj)
1200      {
1201         if (this == obj)
1202            return true;
1203         if (obj == null || (obj instanceof CriKey) == false)
1204            return false;
1205         CriKey other = (CriKey) obj;
1206         return cri.equals(other.cri) && separateNoTx == other.separateNoTx;
1207      }
1208   }
1209
1210   /**
1211    * One pool
1212    */

1213   public static class OnePool
1214      extends BasePool
1215   {
1216      public OnePool(final ManagedConnectionFactory JavaDoc mcf,
1217                     final InternalManagedConnectionPool.PoolParams poolParams,
1218                     final boolean noTxSeparatePools,
1219                     final Logger log)
1220      {
1221         super(mcf, poolParams, noTxSeparatePools, log);
1222      }
1223
1224      protected Object JavaDoc getKey(final Subject JavaDoc subject, final ConnectionRequestInfo JavaDoc cri, boolean separateNoTx)
1225      {
1226         if (separateNoTx)
1227            return Boolean.TRUE;
1228         else
1229            return Boolean.FALSE;
1230      }
1231
1232      public void prefill(Subject JavaDoc sub){
1233         
1234         log.debug("Attempting to prefill pool" + getClass());
1235         
1236         try
1237         {
1238            //WMP is this really the best way to do this?
1239
getSubPool(getKey(null, null, false), null, null);
1240
1241         }
1242
1243         catch (ResourceException JavaDoc e)
1244         {
1245            log.error("Prefill failed for pool instance " + getClass(), e);
1246            
1247         }
1248         
1249      }
1250   }
1251
1252   private static class SubjectActions implements PrivilegedAction JavaDoc
1253   {
1254      Subject JavaDoc subject;
1255      Subject JavaDoc other;
1256      SubjectActions(Subject JavaDoc subject, Subject JavaDoc other)
1257      {
1258         this.subject = subject;
1259         this.other = other;
1260      }
1261      public Object JavaDoc run()
1262      {
1263         Object JavaDoc value = null;
1264         if( other == null )
1265            value = new Integer JavaDoc(subject.hashCode());
1266         else
1267            value = new Boolean JavaDoc(subject.equals(other));
1268         return value;
1269      }
1270      static int hashCode(Subject JavaDoc subject)
1271      {
1272         SubjectActions action = new SubjectActions(subject, null);
1273         Integer JavaDoc hash = (Integer JavaDoc) AccessController.doPrivileged(action);
1274         return hash.intValue();
1275      }
1276      static boolean equals(Subject JavaDoc subject, Subject JavaDoc other)
1277      {
1278         SubjectActions action = new SubjectActions(subject, other);
1279         Boolean JavaDoc equals = (Boolean JavaDoc) AccessController.doPrivileged(action);
1280         return equals.booleanValue();
1281      }
1282   }
1283
1284  
1285
1286 
1287}
1288
Popular Tags