KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > appserver > server > sql > standard > StandardConnectionAllocator


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  * Mark Diekhans
21  * Kyle Clark
22  * Paul Morgan
23  * Predrag Djojic
24  *
25  * $Id: StandardConnectionAllocator.java,v 1.8 2005/05/26 08:08:10 predrag Exp $
26  */

27 package com.lutris.appserver.server.sql.standard;
28
29 import java.lang.reflect.Constructor JavaDoc;
30 import java.sql.SQLException JavaDoc;
31 import java.util.Date JavaDoc;
32 import java.util.LinkedList JavaDoc;
33 import java.util.NoSuchElementException JavaDoc;
34
35 import org.enhydra.dods.CommonConstants;
36 import org.enhydra.dods.DODS;
37
38 import com.lutris.appserver.server.sql.AbstractDBConnectionFactory;
39 import com.lutris.appserver.server.sql.ConnectionAllocator;
40 import com.lutris.appserver.server.sql.DBConnection;
41 import com.lutris.appserver.server.sql.ExtendedConnectionAllocator;
42 import com.lutris.appserver.server.sql.ExtendedDBConnection;
43 import com.lutris.appserver.server.sql.LogicalDatabase;
44 import com.lutris.appserver.server.sql.StandardDBConnectionFactory;
45 import com.lutris.logging.Logger;
46 import com.lutris.util.Config;
47 import com.lutris.util.ConfigException;
48 import com.lutris.util.KeywordValueException;
49
50 /**
51  * Manages a pool (set) of connections to a database. The pool is owned by
52  * logical database. A connection considered part of the pool, even if its
53  * allocated to a thread. These objects are all publicly accessed via the
54  * Database Manager, not directly.
55  * <P>
56  * If an error occurs in a connection, it is dropped from the pool.
57  * A generation number is used to close down all connections that were open
58  * when the error occured, allowing new connections to be allocated.
59  * <P>
60  * The configuration data is specified in the section: <B><CODE>
61  * DatabaseManager.DB. <I>dbName </I>.Connection</CODE> </B>
62  * <P>
63  * <I>Configuration sub fields are: </I>
64  * <UL>
65  * <LI><B><CODE>Url</CODE> </B>- The JDBC URLof the database. Manditary.
66  * E.g. "jdbc:sequelink://dbHost:4000/[Informix];Database=dummy"
67  * <LI><B><CODE>User</CODE> </B>- The database users used to access the
68  * database. Manditary.
69  * <LI><B><CODE>Password</CODE> </B>- The database user's password.
70  * Manditary.
71  * <LI><B><CODE>MaxPoolSize</CODE> </B>- The maximum number of open
72  * connections to the database. Optional, if not specified, then it default to
73  * 0. A value of 0 means that connections are allocated indefinitely or until
74  * the database (JDBC) refuses any new connections.
75  * <LI><B><CODE>Logging</CODE> </B>- Specify true to enable SQL logging,
76  * false to disable it. Optional, false if not specified.
77  * <LI><B><CODE>AllocationTimeout</CODE> </B>- The Maximum amount of time
78  * that a thread will wait for a connection from the connection allocator before
79  * an exception is thrown. This will prevent possible dead locks. The time out
80  * is in milliseconds. If the time out is <= 0, the allocation of connections
81  * will wait indefinitely. Optional, if not specified, then it defaults to 1000
82  * (ms).
83  * <LI><B><CODE>QueryTimeout</CODE> </B>- The amount of time (in seconds)
84  * that a query will block before throwing an exception. If <= 0 then the query
85  * will not block. Optional, if not specified, then the value defaults to 0.
86  * This is not implemented by all logical databases.
87  * <LI><B><CODE>TransactionTimeout</CODE> </B>- The amount of time (in
88  * seconds) that a transaction will block before throwing an exception. If <= 0
89  * then the transaction will not block. Optional, if not specified, then the
90  * value defaults to 0. This is not implemented by all logical databases.
91  * <LI><B><CODE>MaxPreparedStatements</CODE> </B>- If specified, overrides
92  * the JDBC <CODE>Connection.getMetaData().getMaxStatements()</CODE> value. If
93  * less than zero, use the meta data value. Optional, default is to use the meta
94  * data.
95  * </UL>
96  *
97  * @since LBS1.8
98  * @version $Revision: 1.8 $
99  *
100  */

101
102
103 public class StandardConnectionAllocator implements ExtendedConnectionAllocator {
104
105     /**
106      * Reference to the logical database for easy access to the connection pool.
107      */

108     protected LogicalDatabase logicalDatabase = null;
109
110     /**
111      * JDBC URL of database.
112      */

113     protected String JavaDoc url;
114
115     /**
116      * SQL user name.
117      */

118     protected String JavaDoc user;
119
120     /**
121      * SQL password..
122      */

123     protected String JavaDoc password;
124
125     /**
126      * database "ShutDown" string
127      */

128     protected String JavaDoc shutDownStr;
129     
130     /**
131      * Maximum number of connections in the pool. If this value is <= zero, then
132      * create as many connections as possible.
133      */

134     private int maxPoolSize;
135
136     /**
137      * Current size of the pool; includes allocated connections.
138      */

139     private int currentPoolSize;
140
141     /**
142      * Maximum size the pool ever got to, regardless of generation.
143      */

144     private int biggestPoolSize;
145
146     /**
147      * Date at which the biggest pool size occured.
148      */

149     private Date JavaDoc biggestPoolDate;
150
151     /**
152      * Number of queries or transactions on this logical database.
153      */

154     protected long numRequests;
155
156     /**
157      * The actual pool of DBConnection objects ready for allocate.
158      */

159     private ConnectionPool allocatePool;
160
161     /**
162      * Maximum time that connection will wait in connection pool before they
163      * will be closed;
164      */

165     private long connectionIdileTimeout = -1;
166
167     /**
168      * The dealloate pool.
169      */

170     private ConnectionPool releasePool;
171
172     private int requestCounter = 0;
173
174     private int waitCounter = 0;
175
176     private CountMonitor waitConnectionMonitor;
177
178     private Object JavaDoc allocateMonitor;
179
180     private Object JavaDoc releaseMonitor;
181
182     /**
183      * JP Patch Maximum number of DBConnections that will be waiting in the pool
184      */

185     protected int maxWaitingConnections;
186
187     protected int initWaitingConnections;
188
189     /**
190      * Maximum number of times a particular connection is allowed to be
191      * allocated before it is closed and replaced with a new one. If this value
192      * is <= zero, then the number of allocations is unlimited.
193      */

194     private int maxConnectionUsages = -1;
195
196  
197     /**
198      * Indicates if logging is enabled.
199      */

200     protected boolean sqlLogging;
201
202     /**
203      * Maximum amount of time in milliseconds to wait for a connection.
204      */

205     private int timeOut;
206
207     /**
208      * Maximum amount of time in seconds to block on a query. The DBQuery object
209      * will retrieve this value from the connection.
210      */

211     protected int queryTimeOut;
212
213     /**
214      * Maximum amount of time in seconds to block on a transaction. The
215      * DBTransaction object will retrieve this value from the connection.
216      */

217     protected int transactionTimeOut;
218
219     /**
220      * Maximum number of prepared statements to use; if less-than zero, then
221      * JDBC is queried for this value.
222      */

223     protected int maxPreparedStatements;
224
225     /**
226      * Generation number. When an SQL error occurs, all objects of the same
227      * generation or earlier are dropped.
228      */

229     protected int generation = 1;
230
231     
232     /**
233      * Internal ConnectionPool class, encapsulate LinkedList
234      * with addition of drop counter.
235      */

236     class ConnectionPool {
237
238         int dropCount = 0;
239
240         LinkedList JavaDoc pool;
241
242         /**
243          *
244          */

245         public ConnectionPool() {
246             pool = new LinkedList JavaDoc();
247
248         }
249
250     }
251     
252     
253     /**
254      * Internal CountMonitor class, implements
255      * Monitor synchronization mechanism.
256      */

257     class CountMonitor {
258
259         int waitCounter = 0;
260
261         int notifyCounter = 0;
262
263         int maxPoolSize = 0;
264
265         public CountMonitor(int pSize) {
266             maxPoolSize = pSize;
267         }
268
269         public synchronized void countNotify(int maxNotify) {
270             if ((maxPoolSize == 0) && (waitCounter <= 0)) {
271                 if (notifyCounter < maxNotify) {
272                     notifyCounter++;
273                 } else {
274                     notifyCounter = maxNotify;
275                 }
276             } else if ((notifyCounter < maxPoolSize) && (waitCounter <= 0)) {
277                 if (notifyCounter < maxNotify) {
278                     notifyCounter++;
279                 } else {
280                     notifyCounter = maxNotify;
281                 }
282             }
283             this.notify();
284         }
285
286         public synchronized void countWait() throws InterruptedException JavaDoc {
287             if (notifyCounter > 0) {
288                 notifyCounter--;
289                 if ((waitCounter > 0) && (notifyCounter > 0)) {
290                     int countX = waitCounter;
291                     if (waitCounter > notifyCounter) {
292                         countX = notifyCounter;
293                     }
294                     for (int i = 0; i < countX; i++) {
295                         this.notify();
296                     }
297                 }
298             } else {
299                 waitCounter++;
300                 try {
301                     this.wait();
302                 } finally {
303                     waitCounter--;
304                     if ((waitCounter > 0) && (notifyCounter > 0)) {
305                         int countX = waitCounter;
306                         if (waitCounter > notifyCounter) {
307                             countX = notifyCounter;
308                         }
309                         for (int i = 0; i < countX; i++) {
310                             this.notify();
311                             notifyCounter--;
312                         }
313                     }
314
315                 }
316             }
317         }
318
319         public synchronized long countWait(long timeout) throws InterruptedException JavaDoc {
320             long ret = timeout;
321             if (notifyCounter > 0) {
322                 notifyCounter--;
323                 if ((waitCounter > 0) && (notifyCounter > 0)) {
324                     int countX = waitCounter;
325                     if (waitCounter > notifyCounter) {
326                         countX = notifyCounter;
327                     }
328                     for (int i = 0; i < countX; i++) {
329                         this.notify();
330                         notifyCounter--;
331                     }
332                 }
333                 return ret;
334             } else {
335                 ret = System.currentTimeMillis();
336                 waitCounter++;
337                 try {
338                     this.wait(timeout);
339                 }catch (Exception JavaDoc e) {
340                     e.printStackTrace();
341                 } finally {
342                     waitCounter--;
343                     ret = timeout - (System.currentTimeMillis() - ret);
344                     if (ret < 0) {
345                         ret = 0;
346                     }
347                     if ((notifyCounter > 0) && (ret > 0)) {
348                         notifyCounter--;
349                     }
350                     if ((waitCounter > 0) && (notifyCounter > 0)) {
351                         int countX = waitCounter;
352                         if (waitCounter > notifyCounter) {
353                             countX = notifyCounter;
354                         }
355                         for (int i = 0; i < countX; i++) {
356                             this.notify();
357                             notifyCounter--;
358                         }
359                     }
360                     //-dp: return ret;
361
}
362                 return ret; //+dp:
363
}
364         }
365     }
366
367     /**
368      * Internal ConnectionFactory object.
369      */

370     private AbstractDBConnectionFactory dbConnectionFactory = null;
371
372     
373     /**
374      * Internal ConnectionFactory class name.
375      */

376     private String JavaDoc dbConnectionFactoryName = null;
377
378     
379     
380     /**
381      * Creates Internal ConnectionFactory object as instance of factoryName class
382      * @param factoryName ConnectionFactory class name.
383      * @return ConnectionFactory object.
384      */

385     private AbstractDBConnectionFactory createDBConnectionFactory(String JavaDoc factoryName) {
386         Class JavaDoc connectionFactoryClass = null;
387         Constructor JavaDoc connectionFactoryConstructor = null;
388         Class JavaDoc[] methodTypes = {};
389         Object JavaDoc[] methodArgs = {};
390         AbstractDBConnectionFactory factory = null;
391         if (factoryName != null) {
392             try {
393                 connectionFactoryClass = Class.forName(factoryName);
394                 factory = (AbstractDBConnectionFactory) connectionFactoryClass.newInstance();
395             } catch (Exception JavaDoc e) {
396                 DODS.getLogChannel().write(
397                                 Logger.INFO,
398                                 "Faild to make Connection Factory :"
399                                         + factoryName
400                                         + " creating StandardDBConnectionFactory insted");
401                 factory = null;
402             }
403         }
404         if (factoryName == null || factory == null) {
405             factory = new StandardDBConnectionFactory();
406         }
407         return factory;
408     }
409
410     /**
411      * Create a new connection in the pool.
412      *
413      * @exception java.sql.SQLException
414      * If a SQL error occures.
415      */

416     protected DBConnection createConnection() throws java.sql.SQLException JavaDoc {
417         DBConnection dbConnection = dbConnectionFactory.createConnection(
418                 (ConnectionAllocator) this, url, user, password,
419                  maxPreparedStatements, sqlLogging, generation);
420         return dbConnection;
421     }
422
423
424     
425     /**
426      * Creates instance of StandardConnectionAllocator object.
427      * @param logicalDatabase LogicalDatabase that is owner of this ConnectionAllocator object.
428      * @param conConfig Connection allocator configuration object.
429      * @throws ConfigException
430      */

431     public StandardConnectionAllocator(LogicalDatabase logicalDatabase,
432             Config conConfig) throws ConfigException {
433         this.logicalDatabase = logicalDatabase;
434         try {
435             url = conConfig.getString("Url");
436             user = conConfig.getString("User");
437             password = conConfig.getString("Password");
438             timeOut = conConfig.getInt("AllocationTimeout", 1000);
439             maxPoolSize = conConfig.getInt("MaxPoolSize", 0);
440             sqlLogging = conConfig.getBoolean("Logging", false);
441             queryTimeOut = conConfig.getInt("QueryTimeout", 0);
442             shutDownStr = conConfig.getString("ShutDownString",null);
443             transactionTimeOut = conConfig.getInt ("TransactionTimeout", 0);
444             maxPreparedStatements = conConfig.getInt ("MaxPreparedStatements", -1);
445             maxConnectionUsages = conConfig.getInt ("MaxConnectionUsages", -1);
446             maxWaitingConnections = conConfig.getInt ("MaxWaitingConnections", Integer.MAX_VALUE);
447             initWaitingConnections = conConfig.getInt ("InitConnectionsPoolSize", -1);
448             connectionIdileTimeout = conConfig.getLong("ConnectionIdleTimeout", -1);
449
450             
451             dbConnectionFactoryName = conConfig.getString(CommonConstants.CONNECTION_FACTORY,null);
452             dbConnectionFactory = createDBConnectionFactory(dbConnectionFactoryName);
453
454         } catch (KeywordValueException except) {
455             throw new ConfigException("Bad DatabaseManager.DB."
456                     + logicalDatabase.getName()
457                     + ".Connection section defined in config file.");
458         }
459         currentPoolSize = 0;
460
461         allocatePool = new ConnectionPool();
462         releasePool = new ConnectionPool();
463
464         waitConnectionMonitor = new CountMonitor(maxPoolSize);
465         allocateMonitor = new Object JavaDoc();
466         releaseMonitor = new Object JavaDoc();
467
468         biggestPoolSize = 0;
469         biggestPoolDate = new Date JavaDoc();
470         numRequests = 0;
471         
472         try {
473             initConnectionPool(initWaitingConnections);
474         } catch (SQLException JavaDoc e) {
475         }
476     }
477
478     /**
479      * Initially fills connection allocator pool with initWaitingConnections number of connections.
480      * @param initWaitingConnections Number of connections that will be initially added to pool.
481      */

482     private void initConnectionPool(int initWaitingConnections)
483             throws SQLException JavaDoc {
484         if (initWaitingConnections > maxPoolSize) {
485             initWaitingConnections = maxPoolSize;
486         }
487         if (initWaitingConnections > 0) {
488             DBConnection newConnection;
489             for (int i = 1; i <= initWaitingConnections; i++) {
490                 newConnection = createConnection();
491                 if (!newConnection.getConnection().isClosed()) {
492                     if (maxConnectionUsages > 0) {
493                         ((ExtendedDBConnection) newConnection)
494                                 .setConnectionUsageCounter(maxConnectionUsages);
495                     } else {
496                         ((ExtendedDBConnection) newConnection)
497                                 .setConnectionUsageCounter(Integer.MAX_VALUE);
498                     }
499                     allocatePool.pool.addLast(newConnection);
500                     currentPoolSize++;
501                     waitConnectionMonitor.countNotify(initWaitingConnections);
502                     if (currentPoolSize > biggestPoolSize) {
503                         biggestPoolSize = currentPoolSize;
504                         biggestPoolDate = new Date JavaDoc();
505                     }
506                 }
507             }
508         }
509     }
510
511     
512     /**
513      * Allocate new connection from pool.
514      * @see com.lutris.appserver.server.sql.ConnectionAllocator#allocate()
515      */

516     public DBConnection allocate() throws SQLException JavaDoc {
517         boolean createNewConn = true;
518         boolean connected = false;
519         DBConnection conn = null;
520         long enterWaitTime = 0;
521         long timeToWait = -1;
522         boolean newConn = false;
523         if (timeOut > 0) {
524             timeToWait = timeOut;
525         }
526         while (conn == null) {
527             connected = false;
528             newConn = false;
529             synchronized (allocateMonitor) {
530                 if (allocatePool.pool.isEmpty()) {
531                     switchPools();
532                 }
533                 if (allocatePool.pool.isEmpty()) {
534                     if (createNewConn && ((currentPoolSize < maxPoolSize) || (maxPoolSize <= 0))) {
535                         try {
536                             conn = createConnection();
537                             if (maxConnectionUsages > 0) {
538                                 ((ExtendedDBConnection) conn)
539                                         .setConnectionUsageCounter(maxConnectionUsages);
540                             } else {
541                                 ((ExtendedDBConnection) conn)
542                                         .setConnectionUsageCounter(Integer.MAX_VALUE);
543                             }
544                             currentPoolSize++;
545                             newConn = true;
546                             if (currentPoolSize > biggestPoolSize) {
547                                 biggestPoolSize = currentPoolSize;
548                                 biggestPoolDate = new Date JavaDoc();
549                             }
550                         } catch (SQLException JavaDoc e) {
551                             conn = null;
552                             if (currentPoolSize > 0) {
553                                 DODS.getLogChannel().write(
554                                                 Logger.INFO,
555                                                 "ConnectionAllocator: "
556                                                         + "failed to allocate a new connection due to"
557                                                         + e.toString()
558                                                         + "Error code: "
559                                                         + e.getErrorCode()
560                                                         + "\n"
561                                                         + "SQLState: "
562                                                         + e.getSQLState()
563                                                         + "\n"
564                                                         + "\nCurrent pool size is: "
565                                                         + currentPoolSize
566                                                         + "\nMaximum configured pool size is now "
567                                                         + maxPoolSize
568                                                         + "\nContinuing...\n");
569                                 createNewConn = false;
570                             } else {
571                                 DODS.getLogChannel().write(
572                                                 Logger.EMERGENCY,
573                                                 "ConnectionAllocator: "
574                                                         + "failed to allocate a new connection"
575                                                             + "\nThe connection pool is empty!\n"
576                                                             + e.toString()
577                                                             + "Error code: "
578                                                             + e.getErrorCode()
579                                                             + "\n"
580                                                             + "SQLState: "
581                                                             + e.getSQLState()
582                                                             + "\n"
583                                                             + "\nCurrent pool size is: "
584                                                             + currentPoolSize
585                                                             + "\nMaximum configured pool size is now "
586                                                             + maxPoolSize
587                                                             + "\nContinuing...\n");
588                                 throw e;
589                             }
590                         }
591                     }
592                 }
593                 try {
594                     if (conn == null) {
595                         conn = (ExtendedDBConnection) allocatePool.pool.removeFirst();
596                     }
597                 } catch (NoSuchElementException JavaDoc e) {
598                 }
599
600                 if (conn != null) {
601                     connected = true;
602                     if (maxConnectionUsages > 0) {
603             int connUsages = ((ExtendedDBConnection)conn).getConnectionUsageCounter();
604                         if (connUsages > 0) {
605                             ((ExtendedDBConnection) conn)
606                                  .setConnectionUsageCounter(--connUsages);
607                         } else {
608                             // the usages limit is over, close the connection
609
conn.close();
610                             currentPoolSize--;
611                             DODS.getLogChannel().write(
612                                     Logger.DEBUG,
613                                     "ConnectionAllocator: connection closed due to usage counter. currentPoolSize="
614                                             + currentPoolSize + "\n");
615                             conn = null;
616                         }
617                     }
618                     if (conn != null) {
619                         if (((ExtendedDBConnection) conn).isDroped()
620                                 || conn.getConnection().isClosed()
621                                 || (conn.getGeneration() < generation)
622                                 || conn.isMarkedForDrop()) {
623                             conn.close();
624                             currentPoolSize--;
625                             DODS.getLogChannel().write(
626                                             Logger.DEBUG,
627                                             "ConnectionAllocator: Inactiv connection closed due allocate() operation. Geting new one. currentPoolSize="
628                                                     + currentPoolSize + "\n");
629                             conn = null;
630                         }
631                     }
632                     if ((conn != null) && (connectionIdileTimeout > 0)) {
633                         if ((System.currentTimeMillis() - ((ExtendedDBConnection) conn)
634                                 .getConnectionEnterPoolTime()) > connectionIdileTimeout) {
635                             conn.close();
636                             currentPoolSize--;
637                             DODS.getLogChannel().write(
638                                             Logger.DEBUG,
639                                             "ConnectionAllocator: Connection closed due allocate() operation - long connection idile time. Geting new one. currentPoolSize="
640                                                     + currentPoolSize + "\n");
641                             conn = null;
642                         }
643                     }
644                 }
645             }
646             if (conn == null) {
647                 try {
648                     if (timeToWait == 0) {
649                         DODS.getLogChannel().write(
650                                         Logger.EMERGENCY,
651                                         "ConnectionAllocator:"
652                                                 + "allocation of a new connection timed out."
653                                                 + "Possible dead lock avoided.");
654                         String JavaDoc msg = "Connections are currently unavailable.\n"
655                                 + "Possible dead lock avoided.";
656                         throw new SQLException JavaDoc(msg);
657
658                     } else if (timeToWait > 0) {
659                         timeToWait = waitConnectionMonitor.countWait(timeToWait);
660                     } else {
661                         waitConnectionMonitor.countWait();
662                     }
663
664                 } catch (InterruptedException JavaDoc intEx) {
665                 }
666             }
667         }
668         conn.allocate();
669         return conn;
670     }
671
672     /**
673      * Mutually switch allocatePool with releasePool
674      */

675     private void switchPools() {
676         synchronized (releaseMonitor) {
677             if (releasePool.pool.size() > allocatePool.pool.size()) {
678                 LinkedList JavaDoc tmp = allocatePool.pool;
679                 allocatePool.pool = releasePool.pool;
680                 releasePool.pool = tmp;
681             }
682         }
683     }
684
685     /**
686      * Release connection back to pool.
687      *
688      * @see com.lutris.appserver.server.sql.ConnectionAllocator#release(com.lutris.appserver.server.sql.DBConnection)
689      */

690     public void release(DBConnection dbConnection) {
691         if (dbConnection != null) {
692             int releaseSize = 0;
693             synchronized (releaseMonitor) {
694                 if (connectionIdileTimeout > 0) {
695                     ((ExtendedDBConnection) dbConnection).setConnectionEnterPoolTime(System.currentTimeMillis());
696                 }
697                 releasePool.pool.addLast(dbConnection);
698                 releaseSize = releasePool.pool.size();
699             }
700             waitConnectionMonitor.countNotify(releaseSize);
701         }
702
703     }
704
705     /**
706      * Called when a connection in this pool has an SQL error.
707      * All unallocated connections in the pool are dropped if
708      * they have a generation number less
709      * than or equal to the error connection.
710      * If the current generation number
711      * is the same as this generation number, increment it.
712      * This way so that all outstanding connections
713      * (including the one passed in) of the same generation
714      * are dropped when returned.
715      *
716      * @param dbConnection The connection object to drop.
717      * The connection should be
718      * returned to the pool after this function returns.
719      */

720     public void drop(DBConnection dbConnection) {
721         int releasedCounter = 1;
722         LinkedList JavaDoc newAllocatePool = new LinkedList JavaDoc();
723         LinkedList JavaDoc newReleasePool = new LinkedList JavaDoc();
724         LinkedList JavaDoc tmpPool;
725         synchronized (allocateMonitor) {
726             if (generation <= dbConnection.getGeneration()) {
727                 generation++; // new generation
728
}
729             synchronized (releaseMonitor) {
730                 tmpPool = releasePool.pool;
731                 releasePool.pool = newReleasePool;
732             }
733             try {
734                 while (!tmpPool.isEmpty()) {
735                     DBConnection connect = (DBConnection) tmpPool.removeFirst();
736                     if (connect.getGeneration() < generation) {
737                         connect.close();
738                         releasedCounter++;
739                         currentPoolSize--;
740                     } else {
741                         newAllocatePool.addLast(connect);
742                     }
743                 }
744             } catch (NoSuchElementException JavaDoc e) {
745             }
746             try {
747                 while (!allocatePool.pool.isEmpty()) {
748                     DBConnection connect = (DBConnection) allocatePool.pool
749                             .removeFirst();
750                     if (connect.getGeneration() < generation) {
751                         connect.close();
752                         releasedCounter++;
753                         currentPoolSize--;
754                     } else {
755                         newAllocatePool.addLast(connect);
756                     }
757                 }
758             } catch (NoSuchElementException JavaDoc e) {
759             }
760             allocatePool.pool = newAllocatePool;
761             dbConnection.close();
762             currentPoolSize--;
763         }
764         for (int i = 0; i < releasedCounter; i++) {
765             waitConnectionMonitor.countNotify(releasedCounter);
766         }
767     }
768
769     /**
770      * Called when the database manager is shutting down:
771      * Close all connections immediately.
772      */

773     public void dropAllNow() {
774         if (shutDownStr!=null) {
775             try {
776                 DBConnection tmpConn = allocate();
777                 tmpConn.execute(shutDownStr);
778                 tmpConn.release();
779             } catch (SQLException JavaDoc e1) {}
780         }
781         synchronized (releaseMonitor) {
782             synchronized (allocateMonitor) {
783                 try {
784                     while (!allocatePool.pool.isEmpty()) {
785                         DBConnection connect = (DBConnection) allocatePool.pool.removeFirst();
786                         connect.close();
787                         currentPoolSize--;
788                     }
789                 } catch (NoSuchElementException JavaDoc e) {}
790             }
791             try {
792                 while (!releasePool.pool.isEmpty()) {
793                     DBConnection connect = (DBConnection) releasePool.pool.removeFirst();
794                     connect.close();
795                     currentPoolSize--;
796                 }
797             } catch (NoSuchElementException JavaDoc e) {}
798         }
799     }
800
801     /**
802      * Return the number of currently active connections.
803      *
804      * @return The number of connections.
805      */

806     public int getActiveCount() {
807         return currentPoolSize;
808     }
809
810     /**
811      * Return the maximum number of connections active at one time.
812      *
813      * @return The number of connections.
814      */

815     public int getMaxCount() {
816         return biggestPoolSize;
817     }
818
819     /**
820      * Return the time when the maximum connection count occured.
821      *
822      * @return The <CODE>Date</CODE> when the maximum connection
823      * count occured.
824      */

825     public Date JavaDoc getMaxCountDate() {
826         return biggestPoolDate;
827     }
828
829     /**
830      * Reset the maximum connection count and date.
831      */

832     public void resetMaxCount() {
833         biggestPoolSize = currentPoolSize;
834         biggestPoolDate = new Date JavaDoc();
835     }
836
837     /**
838      * Return the number of database requests.
839      *
840      * @return The number of database requests (queries or transactions).
841      */

842     public long getRequestCount() {
843         return numRequests;
844     }
845
846     /**
847      * Finalizer.
848      * If any connections allocated by this object have not been closed,
849      * this method ensures that garbage collection does so.
850      */

851     protected void finalize() {
852         dropAllNow();
853     }
854
855     /**
856      * Database name of logicalDatabase that is owner of pool.
857      * @return Database name of logicalDatabase that is owner of pool.
858      */

859     public String JavaDoc getDatabaseName() {
860         return logicalDatabase.getName();
861     }
862
863     
864     /*
865      * Increments, numRequests, request counter
866      */

867     public void IncrementRequesteCount() {
868         numRequests++;
869     }
870 }
Popular Tags