KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > appserver > server > sql > datasource > SimpleDataSourceConnectionAllocator


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

23 package com.lutris.appserver.server.sql.datasource;
24
25 import java.lang.reflect.Constructor JavaDoc;
26 import java.sql.SQLException JavaDoc;
27 import java.util.Date JavaDoc;
28 import java.util.Hashtable JavaDoc;
29 import java.util.LinkedList JavaDoc;
30 import java.util.NoSuchElementException JavaDoc;
31
32 import javax.sql.DataSource JavaDoc;
33 import javax.naming.Context JavaDoc;
34 import javax.naming.InitialContext JavaDoc;
35 import javax.naming.NamingException JavaDoc;
36
37 import org.enhydra.dods.CommonConstants;
38 import org.enhydra.dods.DODS;
39
40 import com.lutris.appserver.server.sql.AbstractDBConnectionFactory;
41 import com.lutris.appserver.server.sql.ConnectionAllocator;
42 import com.lutris.appserver.server.sql.DBConnection;
43 import com.lutris.appserver.server.sql.ExtendedConnectionAllocator;
44 import com.lutris.appserver.server.sql.ExtendedDBConnection;
45 import com.lutris.appserver.server.sql.LogicalDatabase;
46 import com.lutris.logging.Logger;
47 import com.lutris.util.Config;
48 import com.lutris.util.ConfigException;
49 import com.lutris.util.KeywordValueException;
50
51 /**
52  * Manages a pool (set) of connections to a database. The pool is named as a
53  * logical database. By naming a pool, this allows connection resource control
54  * to be on a finer grain that a database and allows for easier migration to
55  * multiple databases. One or more pools can map to the same actual database. A
56  * connection considered part of the pool, even if its allocated to a thread.
57  * These objects are all publicly accessed via the Database Manager, not
58  * directly.
59  * <P>
60  * If an error occurs in a connection, it is dropped from the pool. The process
61  * using the connection has already received an error which aborts the work in
62  * progress. By dropping the connection, waiting threads are restarted. If
63  * something is wrong with the database (e.g. server is down), they will recieve
64  * errors and also be aborted. A generation number is used to close down all
65  * connections that were open when the error occured, allowing new connections
66  * to be allocated.
67  * <P>
68  * The configuration data is specified in the section: <B><CODE>
69  * DatabaseManager.DB. <I>dbName </I>.Connection</CODE> </B>
70  * <P>
71  * <I>Configuration sub fields are: </I>
72  * <UL>
73  * <LI><B><CODE>Url</CODE> </B>- The JDBC URLof the database. Manditary.
74  * E.g. "jdbc:sequelink://dbHost:4000/[Informix];Database=dummy"
75  * <LI><B><CODE>User</CODE> </B>- The database users used to access the
76  * database. Manditary.
77  * <LI><B><CODE>Password</CODE> </B>- The database user's password.
78  * Manditary.
79  * <LI><B><CODE>MaxPoolSize</CODE> </B>- The maximum number of open
80  * connections to the database. Optional, if not specified, then it default to
81  * 0. A value of 0 means that connections are allocated indefinitely or until
82  * the database (JDBC) refuses any new connections.
83  * <LI><B><CODE>Logging</CODE> </B>- Specify true to enable SQL logging,
84  * false to disable it. Optional, false if not specified.
85  * <LI><B><CODE>AllocationTimeout</CODE> </B>- The Maximum amount of time
86  * that a thread will wait for a connection from the connection allocator before
87  * an exception is thrown. This will prevent possible dead locks. The time out
88  * is in milliseconds. If the time out is <= 0, the allocation of connections
89  * will wait indefinitely. Optional, if not specified, then it defaults to 1000
90  * (ms).
91  * <LI><B><CODE>QueryTimeout</CODE> </B>- The amount of time (in seconds)
92  * that a query will block before throwing an exception. If <= 0 then the query
93  * will not block. Optional, if not specified, then the value defaults to 0.
94  * This is not implemented by all logical databases.
95  * <LI><B><CODE>TransactionTimeout</CODE> </B>- The amount of time (in
96  * seconds) that a transaction will block before throwing an exception. If <= 0
97  * then the transaction will not block. Optional, if not specified, then the
98  * value defaults to 0. This is not implemented by all logical databases.
99  * <LI><B><CODE>MaxPreparedStatements</CODE> </B>- If specified, overrides
100  * the JDBC <CODE>Connection.getMetaData().getMaxStatements()</CODE> value. If
101  * less than zero, use the meta data value. Optional, default is to use the meta
102  * data.
103  * </UL>
104  * It would be nice to add a config parameter that would disable caching of
105  * PreparedStatements.
106  *
107  * @author Mark Diekhans
108  * @author Kyle Clark
109  * @author Paul Morgan
110  * @since LBS1.8
111  * @version $Revision: 1.3 $
112  */

113 // Excelsior, LLC. Memory leak patch begin
114
/**
115  * Brief description of the patch: Since each long-time used connection holds
116  * too much memory (about 15Mb after several hours of work) it was decided to
117  * close and recreate connections that were allocated more than the
118  * MaxConnectionUsages value set in the proper config file. We also changed the
119  * stack-like structure of the connection pool to queue-like. This guarantees
120  * that no connections become stagnant. 4.07.2003
121  */

122 // Excelsior, LLC. Memory leak patch end
123
public class SimpleDataSourceConnectionAllocator implements ExtendedConnectionAllocator {
124
125     /**
126      * Reference to the logical database for easy access to the connection pool.
127      */

128     protected LogicalDatabase logicalDatabase = null;
129
130     /**
131      * JDBC URL of database.
132      */

133     protected DataSource JavaDoc dataSource;
134
135     /**
136      * JDBC URL of database.
137      */

138     protected String JavaDoc url;
139
140     /**
141      * SQL user name.
142      */

143     protected String JavaDoc user;
144
145     /**
146      * SQL password..
147      */

148     protected String JavaDoc password;
149
150     /**
151      * database "ShutDown" string
152      */

153     protected String JavaDoc shutDownStr;
154
155     /**
156      * Maximum number of connections in the pool. If this value is <= zero, then
157      * create as many connections as possible.
158      */

159     private int maxPoolSize;
160
161     /**
162      * Current size of the pool; includes allocated connections.
163      */

164     private int currentPoolSize;
165
166     /**
167      * Maximum time that connection will wait in connection pool before they
168      * will be closed;
169      */

170     private long connectionIdileTimeout = -1;
171
172     /**
173      * Maximum size the pool ever got to, regardless of generation.
174      */

175     private int biggestPoolSize;
176
177     /**
178      * Date at which the biggest pool size occured.
179      */

180     private Date JavaDoc biggestPoolDate;
181
182     /**
183      * Number of queries or transactions on this logical database.
184      */

185     protected long numRequests;
186
187     /**
188      * The actual pool of DBConnection objects.
189      */

190     // Excelsior, LLC. Memory leak patch begin
191
/*
192      * original code private Stack pool;
193      */

194     private LinkedList JavaDoc pool;
195
196     /**
197      * This hashtable holds the number of times a particular DBConnection was
198      * allocated. The key is the DBConnection object and the value is an Integer
199      * object. If the connectionUsageCounter is null, then the number of
200      * connection usages is unlimited. Maybe, it would be better to have the
201      * respective instance field in the DBConnection but it worsens locality of
202      * changes made...
203      */

204     private Hashtable JavaDoc connectionUsageCounter;
205
206     /**
207      * JP Patch Maximum number of DBConnections that will be waiting in the pool
208      */

209     protected int maxWaitingConnections;
210
211     /**
212      * Maximum number of times a particular connection is allowed to be
213      * allocated before it is closed and replaced with a new one. If this value
214      * is <= zero, then the number of allocations is unlimited.
215      */

216     private int maxConnectionUsages = -1;
217
218     // Excelsior, LLC. Memory leak patch end
219
/**
220      * Indicates if logging is enabled.
221      */

222     protected boolean sqlLogging;
223
224     /**
225      * Indicates dods not to use connection pool.
226      */

227     protected boolean disableConnectionPool = false;
228
229     /**
230      * Maximum amount of time in milliseconds to wait for a connection.
231      */

232     private int timeOut;
233
234     /**
235      * Maximum amount of time in seconds to block on a query. The DBQuery object
236      * will retrieve this value from the connection.
237      */

238     protected int queryTimeOut;
239
240     /**
241      * Maximum amount of time in seconds to block on a transaction. The
242      * DBTransaction object will retrieve this value from the connection.
243      */

244     protected int transactionTimeOut;
245
246     /**
247      * Maximum number of prepared statements to use; if less-than zero, then
248      * JDBC is queried for this value.
249      */

250     protected int maxPreparedStatements;
251
252     /**
253      * Generation number. When an SQL error occurs, all objects of the same
254      * generation or earlier are dropped.
255      */

256     protected int generation = 1;
257
258     /**
259      * Create a new connection in the pool.
260      *
261      * @exception java.sql.SQLException
262      * If a SQL error occures.
263      */

264     protected DBConnection createConnection() throws java.sql.SQLException JavaDoc {
265         DBConnection dbConnection;
266         if (dataSource != null)
267             // dbConnection =
268
// dbConnectionFactory.createConnection((ConnectionAllocator)this,
269
// dataSource, maxPreparedStatements, sqlLogging, generation);
270
dbConnection = new SimpleDataSourceDBConnection(this, dataSource, maxPreparedStatements, sqlLogging,
271                             generation);
272         else
273             // dbConnection =
274
// dbConnectionFactory.createConnection((ConnectionAllocator)this,
275
// url, user,
276
dbConnection = new SimpleDataSourceDBConnection((ConnectionAllocator) this, url, user, password,
277                             maxPreparedStatements, sqlLogging, generation);
278
279         return dbConnection;
280     }
281
282     private AbstractDBConnectionFactory dbConnectionFactory = null;
283
284     private String JavaDoc dbConnectionFactoryName = null;
285
286     private AbstractDBConnectionFactory createDBConnectionFactory(String JavaDoc factoryName) {
287         Class JavaDoc connectionFactoryClass = null;
288         Constructor JavaDoc connectionFactoryConstructor = null;
289         Class JavaDoc[] methodTypes = {};
290         Object JavaDoc[] methodArgs = {};
291         AbstractDBConnectionFactory factory = null;
292         if (factoryName != null) {
293             try {
294                 connectionFactoryClass = Class.forName(factoryName);
295                 factory = (AbstractDBConnectionFactory) connectionFactoryClass.newInstance();
296             } catch (Exception JavaDoc e) {
297                 DODS.getLogChannel().write(
298                                 Logger.INFO,
299                                 "Faild to make Connection Factory :" + factoryName
300                                                 + " creating StandardDBConnectionFactory insted");
301                 factory = null;
302             }
303         }
304         if (factoryName == null || factory == null) {
305             try {
306                 connectionFactoryClass = Class
307                                 .forName("com.lutris.appserver.server.sql.standard.StandardDBConnectionFactory");
308                 factory = (AbstractDBConnectionFactory) connectionFactoryClass.newInstance();
309             } catch (Exception JavaDoc e) {
310                 DODS
311                                 .getLogChannel()
312                                 .write(Logger.INFO,
313                                                 "Faild to make Standard Connection Factory : com.lutris.appserver.server.sql.standard.StandardDBConnectionFactory");
314                 factory = null;
315             }
316             //factory = new StandardDBConnectionFactory();
317
}
318         return factory;
319
320     }
321
322     /**
323      * Initialize the connection allocator object. Connections are opened on
324      * demand and stored in a pool.
325      *
326      * @param logicalDatabase
327      * LogicalDatabase.
328      * @param conConfig
329      * LogicalDatabase Config object
330      * @exception ConfigException
331      * if bad configuration information is given in the config
332      * file.
333      */

334     public SimpleDataSourceConnectionAllocator(LogicalDatabase logicalDatabase, Config conConfig)
335                     throws ConfigException {
336         this.logicalDatabase = logicalDatabase;
337
338         //sinisa 21.04.2004. add DataSource
339
try {
340             String JavaDoc stringValue = "";
341             try {
342                 if (conConfig.getDataSource("DataSourceName") != null) {
343
344                     if (conConfig.getDataSource("DataSourceName") instanceof DataSource JavaDoc)
345                         dataSource = (DataSource JavaDoc) conConfig.getDataSource("DataSourceName");
346                     else if (conConfig.getDataSource("DataSourceName") instanceof String JavaDoc) {
347                         String JavaDoc jndiName = (String JavaDoc) conConfig.getDataSource("DataSourceName");
348                         if (jndiName.startsWith("jndi:")) {
349                             stringValue = jndiName.substring(5);
350                         } else
351                             stringValue = jndiName;
352
353                         InitialContext JavaDoc context = null;
354                         Context JavaDoc envCtx = null;
355
356                         try {
357                             context = new InitialContext JavaDoc();
358                             envCtx = (Context JavaDoc) context.lookup("java:comp/env");
359
360                         } catch (NamingException JavaDoc ex) {
361                             envCtx = null;
362                         }
363                         try {
364                             dataSource = (DataSource JavaDoc) envCtx.lookup(stringValue);
365                         } catch (Exception JavaDoc ex) {
366                             dataSource = null;
367                         }
368                         if (dataSource == null) {
369                             try {
370                                 dataSource = (DataSource JavaDoc) context.lookup(stringValue);
371                             } catch (Exception JavaDoc ex) {
372                                 dataSource = null;
373                             }
374                         }
375                     } else
376                         dataSource = null;
377                 }
378             } catch (Exception JavaDoc ex) {
379                 dataSource = null;
380             }
381             if (dataSource == null) {
382                 url = conConfig.getString("Url");
383                 user = conConfig.getString("User");
384                 password = conConfig.getString("Password");
385             }
386             timeOut = conConfig.getInt("AllocationTimeout", 1000);
387             maxPoolSize = conConfig.getInt("MaxPoolSize", 0);
388             sqlLogging = conConfig.getBoolean("Logging", false);
389             disableConnectionPool = conConfig.getBoolean("DisableConnectionPool", false);
390             queryTimeOut = conConfig.getInt("QueryTimeout", 0);
391             transactionTimeOut = conConfig.getInt("TransactionTimeout", 0);
392             connectionIdileTimeout = conConfig.getLong("ConnectionIdleTimeout", -1);
393             maxPreparedStatements = conConfig.getInt("MaxPreparedStatements", -1);
394             maxConnectionUsages = conConfig.getInt("MaxConnectionUsages", -1);
395             maxWaitingConnections = conConfig.getInt("MaxWaitingConnections", Integer.MAX_VALUE);
396             shutDownStr = conConfig.getString("ShutDownString", null);
397
398             dbConnectionFactoryName = conConfig.getString(CommonConstants.CONNECTION_FACTORY, null);
399             dbConnectionFactory = createDBConnectionFactory(dbConnectionFactoryName);
400             
401         } catch (KeywordValueException except) {
402             throw new ConfigException("Bad DatabaseManager.DB." + logicalDatabase.getName()
403                             + ".Connection section defined in config file.");
404         }
405         currentPoolSize = 0;
406         // Excelsior, LLC. Memory leak patch begin
407
/*
408          * original code pool = new Stack ();
409          */

410         pool = new LinkedList JavaDoc();
411         if (maxConnectionUsages > 0) {
412             connectionUsageCounter = new Hashtable JavaDoc();
413         }
414         // Excelsior, LLC. Memory leak patch end
415
biggestPoolSize = 0;
416         biggestPoolDate = new Date JavaDoc();
417         numRequests = 0;
418     }
419
420     /**
421      * If pool is used:
422      *
423      * Allocate a connection to a thread. If none are available, grow the pool.
424      * If the pool is alredy its maximum size, then the thread waits.
425      *
426      * If pool is not used (disableConnectionPool=true) then only create new
427      * transaction.
428      *
429      * @return The allocated connection object.
430      * @exception SQLException
431      * If a SQL error occures.
432      */

433     public synchronized DBConnection allocate() throws SQLException JavaDoc {
434         //
435
// It isn't always possible to determine the maximum
436
// number of connections allowed to the database because
437
// of JDBC driver differences. We assume connections are
438
// available until we fail to allocate one or we reach
439
// the maximum configured.
440
//
441
boolean createNewConn = true;
442         // Excelsior, LLC. Memory leak patch begin
443
/*
444          * original code while (pool.empty()) {
445          */

446         DBConnection conn = null;
447         if (disableConnectionPool) {
448             try {
449                 conn = createConnection();
450             } catch (SQLException JavaDoc e) {
451                 DODS.getLogChannel().write(
452                                             Logger.EMERGENCY,
453                                             "ConnectionAllocator: "
454                                                 + "failed to allocate a new connection"
455                                                 + "\n (connection pool is not used!) \n");
456                 throw e;
457             }
458         } else {
459             while (conn == null) {
460                 while (pool.isEmpty()) {
461                     // Excelsior, LLC. Memory leak patch end
462
if (createNewConn && ((currentPoolSize < maxPoolSize) || (maxPoolSize <= 0))) {
463                         try {
464                             // Excelsior, LLC. Memory leak patch begin
465
/*
466                              * original code pool.push(createConnection());
467                              */

468                             DBConnection newConnection = createConnection();
469
470                             if (connectionUsageCounter != null) {
471                                 connectionUsageCounter.put(newConnection, new Integer JavaDoc(maxConnectionUsages));
472                             }
473                             pool.addLast(newConnection);
474                             // Excelsior, LLC. Memory leak patch end
475
currentPoolSize++;
476                             if (currentPoolSize > biggestPoolSize) {
477                                 biggestPoolSize = currentPoolSize;
478                                 biggestPoolDate = new Date JavaDoc();
479                             }
480                         } catch (SQLException JavaDoc e) {
481                             if (currentPoolSize > 0) {
482                                 DODS.getLogChannel().write(
483                                                             Logger.INFO,
484                                                             "ConnectionAllocator: " + "failed to allocate a new connection due to"
485                                                                 + e.toString() + "Error code: " + e.getErrorCode()
486                                                                 + "\n" + "SQLState: " + e.getSQLState() + "\n"
487                                                                 + "\nCurrent pool size is: " + currentPoolSize
488                                                                 + "\nMaximum configured pool size is now "
489                                                                 + maxPoolSize + "\nContinuing...\n");
490                                 createNewConn = false;
491                             } else {
492                                 DODS.getLogChannel().write(
493                                                             Logger.EMERGENCY,
494                                                             "ConnectionAllocator: " + "failed to allocate a new connection"
495                                                                 + "\nThe connection pool is empty!\n");
496                                 throw e;
497                             }
498                         }
499                     } else {
500                         try {
501                             if (timeOut > 0) {
502                                 wait(timeOut);
503                                 // Excelsior, LLC. Memory leak patch begin
504
/*
505                                  * original code if (pool.empty()) {
506                                  */

507                                 if (pool.isEmpty()) {
508                                     // Excelsior, LLC. Memory leak patch begin
509
DODS.getLogChannel().write(
510                                                                 Logger.EMERGENCY,
511                                                                 "ConnectionAllocator: "
512                                                                     + "allocation of a new connection timed out."
513                                                                     + "Possible dead lock avoided.");
514                                     String JavaDoc msg = "Connections are currently unavailable.\n"
515                                                     + "Possible dead lock avoided.";
516
517                                     throw new SQLException JavaDoc(msg);
518                                 }
519                             } else {
520                                 wait();
521                             }
522                         } catch (InterruptedException JavaDoc intEx) {
523                         }
524                     }
525                 }
526                 //
527
// A connection is available.
528
//
529
// Excelsior, LLC. Memory leak patch begin
530
/*
531                  * original code conn = (DBConnection)pool.pop();
532                  */

533                 // check
534
try {
535                     conn = (DBConnection) pool.removeFirst();
536                 } catch (NoSuchElementException JavaDoc e) {
537                 }
538                 if (connectionUsageCounter != null) {
539                     Integer JavaDoc connUsages = (Integer JavaDoc) connectionUsageCounter.get(conn);
540
541                     if (connUsages != null && connUsages.intValue() > 0) {
542                         // decrease connection usage counter
543
connectionUsageCounter.put(conn, new Integer JavaDoc(connUsages.intValue() - 1));
544                     } else { // the usages limit is over, close the connection
545
conn.close();
546                         currentPoolSize--;
547                         connectionUsageCounter.remove(conn);
548                         DODS.getLogChannel().write(
549                                                     Logger.DEBUG,
550                                                     "ConnectionAllocator: connection closed due to usage counter. currentPoolSize="
551                                                                     + currentPoolSize + "\n");
552                         conn = null;
553                     }
554                 }
555                 if ((conn != null) && (conn.getConnection().isClosed())) {
556                     conn.close();
557                     currentPoolSize--;
558                     if (connectionUsageCounter != null && connectionUsageCounter.contains(conn)) {
559                         connectionUsageCounter.remove(conn);
560                     }
561                     DODS.getLogChannel().write(
562                                                     Logger.DEBUG,
563                                                     "ConnectionAllocator: Inactiv connection closed due allocate() operation. Geting new one. currentPoolSize="
564                                                     + currentPoolSize + "\n");
565                     conn = null;
566                 }
567                 if ((conn != null) && (connectionIdileTimeout > 0)) {
568                     if ((System.currentTimeMillis() - ((ExtendedDBConnection) conn).getConnectionEnterPoolTime()) > connectionIdileTimeout) {
569                         conn.close();
570                         currentPoolSize--;
571                         DODS.getLogChannel().write(
572                                             Logger.DEBUG,
573                                             "ConnectionAllocator: Connection closed due allocate() operation - long connection idile time. Geting new one. currentPoolSize="
574                                                     + currentPoolSize + "\n");
575                         conn = null;
576                     }
577                 }
578             }
579         }
580         conn.allocate();
581         return conn;
582     }
583
584     /**
585      * Return a connection to the pool (if used else only close connection).
586      *
587      * @param dbConnection
588      * The connection object to return.
589      */

590     public synchronized void release(DBConnection dbConnection) {
591         try {
592             if (disableConnectionPool) {
593                 dbConnection.close();
594                 dbConnection = null;
595             } else {
596                 if ((dbConnection.getGeneration() < generation) || (dbConnection.isMarkedForDrop())
597                                 || (dbConnection.getConnection().isClosed()) || (pool.size() >= maxWaitingConnections)) {
598                     dbConnection.close();
599                     dbConnection = null;
600                     currentPoolSize--;
601                 } else {
602                     // Excelsior, LLC. Memory leak patch begin
603
/*
604                      * original code pool.push (dbConnection);
605                      */

606                     if (connectionIdileTimeout > 0) {
607                         ((ExtendedDBConnection) dbConnection).setConnectionEnterPoolTime(System.currentTimeMillis());
608                     }
609                     pool.addLast(dbConnection);
610                     // Excelsior, LLC. Memory leak patch end
611
}
612             }
613         } catch (SQLException JavaDoc ex) {
614             DODS.getLogChannel().write(Logger.DEBUG, "Eror relasing connection");
615         }
616         notify();
617     }
618
619     /**
620      * Called when a connection in this pool has an SQL error. All unallocated
621      * connections in the pool are dropped if they have a generation number less
622      * than or equal to the error connection. If the current generation number
623      * is the same as this generation number, increment it. This way so that all
624      * outstanding connections (including the one passed in) of the same
625      * generation are dropped when returned.
626      *
627      * @param dbConnection
628      * The connection object to drop. The connection should be
629      * returned to the pool after this function returns.
630      */

631     public synchronized void drop(DBConnection dbConnection) {
632         if (generation <= dbConnection.getGeneration()) {
633             generation++; // new generation
634
}
635         // Delete all entries of the last generation.
636
// Excelsior, LLC. Memory leak patch begin
637
/*
638          * original code Stack holdPool = new Stack (); while (!pool.empty ()) {
639          * DBConnection connect = (DBConnection) pool.pop (); if
640          * (connect.getGeneration () < generation) { connect.close ();
641          * currentPoolSize--; } else { holdPool.push (connect); } } // Put all
642          * current generation entries back in the pool. while (!holdPool.empty
643          * ()) { pool.push (holdPool.pop ()); }
644          */

645         LinkedList JavaDoc newPool = new LinkedList JavaDoc();
646
647         try {
648             while (!pool.isEmpty()) {
649                 DBConnection connect = (DBConnection) pool.removeFirst();
650
651                 if (connect.getGeneration() < generation) {
652                     connect.close();
653                     currentPoolSize--;
654                 } else {
655                     newPool.addLast(connect);
656                 }
657             }
658         } catch (NoSuchElementException JavaDoc e) {
659         }
660         // replace the original pool with the one that contains
661
// only current generation entries
662
pool = newPool;
663         // Excelsior, LLC. Memory leak patch end
664
notify();
665     }
666
667     /**
668      * Called when the database manager is shutting down: Close all connections
669      * immediately.
670      */

671     public synchronized void dropAllNow() {
672         // Excelsior, LLC. Memory leak patch begin
673
/*
674          * original code while (!pool.empty ()) { DBConnection connect =
675          * (DBConnection) pool.pop (); connect.close (); currentPoolSize--; }
676          */

677
678         if (shutDownStr != null) {
679             try {
680                 DBConnection tmpConn = allocate();
681                 tmpConn.execute(shutDownStr);
682                 tmpConn.release();
683             } catch (SQLException JavaDoc e1) {
684             }
685         }
686
687         try {
688             while (!pool.isEmpty()) {
689                 DBConnection connect = (DBConnection) pool.removeFirst();
690
691                 connect.close();
692                 currentPoolSize--;
693             }
694         } catch (NoSuchElementException JavaDoc e) {
695         }
696         // Excelsior, LLC. Memory leak patch begin
697
}
698
699     /**
700      * Return the number of currently active connections.
701      *
702      * @return The number of connections.
703      */

704     public int getActiveCount() {
705         return currentPoolSize;
706     }
707
708     /**
709      * Return the maximum number of connections active at one time.
710      *
711      * @return The number of connections.
712      */

713     public int getMaxCount() {
714         return biggestPoolSize;
715     }
716
717     /**
718      * Return the time when the maximum connection count occured.
719      *
720      * @return The <CODE>Date</CODE> when the maximum connection count
721      * occured.
722      */

723     public Date JavaDoc getMaxCountDate() {
724         return biggestPoolDate;
725     }
726
727     /**
728      * Reset the maximum connection count and date.
729      */

730     public void resetMaxCount() {
731         biggestPoolSize = currentPoolSize;
732         biggestPoolDate = new Date JavaDoc();
733     }
734
735     /**
736      * Return the number of database requests.
737      *
738      * @return The number of database requests (queries or transactions).
739      */

740     public long getRequestCount() {
741         return numRequests;
742     }
743
744     /**
745      * Finalizer. If any connections allocated by this object have not been
746      * closed, this method ensures that garbage collection does so.
747      */

748     protected void finalize() {
749         dropAllNow();
750     }
751
752     /**
753      * @return database name of current connection
754      *
755      */

756     public String JavaDoc getDatabaseName() {
757         return logicalDatabase.getName();
758     }
759
760     public void IncrementRequesteCount() {
761         numRequests++;
762     }
763 }
Popular Tags