KickJava   Java API By Example, From Geeks To Geeks.

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


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: DataSourceConnectionAllocator.java,v 1.9 2005/07/01 14:35:07 predrag Exp $
26  */

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

105 public class DataSourceConnectionAllocator implements
106         ExtendedConnectionAllocator {
107
108     /**
109      * Reference to the logical database for easy access to the connection pool.
110      */

111     protected LogicalDatabase logicalDatabase = null;
112
113     /**
114      * JDBC DataSource of database.
115      */

116     protected DataSource JavaDoc dataSource;
117
118     /**
119      * database "ShutDown" string
120      */

121     protected String JavaDoc shutDownStr;
122
123     /**
124      * JDBC URL of database.
125      */

126     protected String JavaDoc url;
127
128     /**
129      * SQL user name.
130      */

131     protected String JavaDoc user;
132
133     /**
134      * SQL password..
135      */

136     protected String JavaDoc password;
137
138     /**
139      * Maximum number of connections in the pool. If this value is <= zero, then
140      * create as many connections as possible.
141      */

142     private int maxPoolSize;
143
144     /**
145      * Current size of the pool; includes allocated connections.
146      */

147     private int currentPoolSize;
148
149     /**
150      * Maximum size the pool ever got to, regardless of generation.
151      */

152     private int biggestPoolSize;
153
154     /**
155      * Date at which the biggest pool size occured.
156      */

157     private Date JavaDoc biggestPoolDate;
158
159     /**
160      * Number of queries or transactions on this logical database.
161      */

162     protected long numRequests;
163
164     /**
165      * The actual pool of DBConnection objects ready for allocate.
166      */

167     private ConnectionPool allocatePool;
168
169     /**
170      * Maximum time that connection will wait in connection pool before they
171      * will be closed;
172      */

173     private long connectionIdileTimeout = -1;
174
175     /**
176      * The dealloate pool.
177      */

178     private ConnectionPool releasePool;
179
180     private int requestCounter = 0;
181
182     private int waitCounter = 0;
183
184     private CountMonitor waitConnectionMonitor;
185
186     private Object JavaDoc allocateMonitor;
187
188     private Object JavaDoc releaseMonitor;
189
190     /**
191      * JP Patch Maximum number of DBConnections that will be waiting in the pool
192      */

193     protected int maxWaitingConnections;
194
195     protected int initWaitingConnections;
196
197     /**
198      * Maximum number of times a particular connection is allowed to be
199      * allocated before it is closed and replaced with a new one. If this value
200      * is <= zero, then the number of allocations is unlimited.
201      */

202     private int maxConnectionUsages = -1;
203
204     // Excelsior, LLC. Memory leak patch end
205
/**
206      * Indicates if logging is enabled.
207      */

208     protected boolean sqlLogging;
209
210     /**
211      * Indicates dods not to use connection pool.
212      */

213     protected boolean disableConnectionPool = false;
214
215     /**
216      * Maximum amount of time in milliseconds to wait for a connection.
217      */

218     private int timeOut;
219
220     /**
221      * Maximum amount of time in seconds to block on a query. The DBQuery object
222      * will retrieve this value from the connection.
223      */

224     protected int queryTimeOut;
225
226     /**
227      * Maximum amount of time in seconds to block on a transaction. The
228      * DBTransaction object will retrieve this value from the connection.
229      */

230     protected int transactionTimeOut;
231
232     /**
233      * Maximum number of prepared statements to use; if less-than zero, then
234      * JDBC is queried for this value.
235      */

236     protected int maxPreparedStatements;
237
238     /**
239      * Generation number. When an SQL error occurs, all objects of the same
240      * generation or earlier are dropped.
241      */

242     protected int generation = 1;
243
244     
245     /**
246      * Internal ConnectionPool class, encapsulate LinkedList with addition of
247      * drop counter.
248      */

249     class ConnectionPool {
250
251         int dropCount = 0;
252
253         LinkedList JavaDoc pool;
254
255         /**
256          *
257          */

258         public ConnectionPool() {
259             pool = new LinkedList JavaDoc();
260
261         }
262
263     }
264
265     
266     /**
267      * Internal CountMonitor class, implements Monitor synchronization
268      * mechanism.
269      */

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

384     private DataSourceDBConnectionFactory dbConnectionFactory = null;
385
386     
387     /**
388      * Internal ConnectionFactory class name.
389      */

390     private String JavaDoc dbConnectionFactoryName = null;
391
392     /**
393      * Creates Internal ConnectionFactory object as instance of factoryName
394      * class
395      *
396      * @param factoryName
397      * ConnectionFactory class name.
398      * @return ConnectionFactory object.
399      */

400     private DataSourceDBConnectionFactory createDBConnectionFactory(
401             String JavaDoc factoryName) {
402         Class JavaDoc connectionFactoryClass = null;
403         Constructor JavaDoc connectionFactoryConstructor = null;
404         Class JavaDoc[] methodTypes = {};
405         Object JavaDoc[] methodArgs = {};
406         DataSourceDBConnectionFactory factory = null;
407         if (factoryName != null) {
408             try {
409                 connectionFactoryClass = Class.forName(factoryName);
410                 factory = (DataSourceDBConnectionFactory) connectionFactoryClass
411                         .newInstance();
412             } catch (Exception JavaDoc e) {
413                 DODS
414                         .getLogChannel()
415                         .write(
416                                 Logger.INFO,
417                                 "Faild to make Connection Factory :"
418                                         + factoryName
419                                         + " creating DataSourceDBConnectionFactory insted");
420                 factory = null;
421             }
422         }
423         if (factoryName == null || factory == null) {
424             factory = new DataSourceDBConnectionFactory();
425         }
426         return factory;
427     }
428
429     /**
430      * Create a new connection in the pool.
431      *
432      * @exception java.sql.SQLException
433      * If a SQL error occures.
434      */

435     protected DBConnection createConnection() throws java.sql.SQLException JavaDoc {
436         DBConnection dbConnection;
437         if (dataSource != null)
438             dbConnection = dbConnectionFactory.createConnection(
439                     (ConnectionAllocator) this, dataSource,
440                     maxPreparedStatements, sqlLogging, generation);
441         else
442             dbConnection = dbConnectionFactory.createConnection(
443                     (ConnectionAllocator) this, url, user, password,
444                     maxPreparedStatements, sqlLogging, generation);
445         return dbConnection;
446     }
447
448     /**
449      * /** Creates instance of StandardConnectionAllocator object.
450      *
451      * @param logicalDatabase
452      * LogicalDatabase that is owner of this ConnectionAllocator
453      * object.
454      * @param conConfig
455      * Connection allocator configuration object.
456      * @throws ConfigException
457      */

458     public DataSourceConnectionAllocator(LogicalDatabase logicalDatabase, Config conConfig) throws ConfigException {
459         this.logicalDatabase = logicalDatabase;
460         try {
461             String JavaDoc stringValue = "";
462             try {
463                 if (conConfig.getDataSource("DataSourceName") != null) {
464
465                     if (conConfig.getDataSource("DataSourceName") instanceof DataSource JavaDoc)
466                         dataSource = (DataSource JavaDoc) conConfig.getDataSource("DataSourceName");
467                     else if (conConfig.getDataSource("DataSourceName") instanceof String JavaDoc) {
468                         String JavaDoc jndiName = (String JavaDoc) conConfig.getDataSource("DataSourceName");
469                         if (jndiName.startsWith("jndi:")) {
470                             stringValue = jndiName.substring(5);
471                         } else
472                             stringValue = jndiName;
473
474                         InitialContext JavaDoc context = null;
475                         Context JavaDoc envCtx = null;
476
477                         try {
478                             context = new InitialContext JavaDoc();
479                             envCtx = (Context JavaDoc) context.lookup("java:comp/env");
480
481                         } catch (NamingException JavaDoc ex) {
482                             envCtx = null;
483                         }
484                         try {
485                             dataSource = (DataSource JavaDoc) envCtx.lookup(stringValue);
486                         } catch (Exception JavaDoc ex) {
487                             dataSource = null;
488                         }
489                         if (dataSource == null) {
490                             try {
491                                 dataSource = (DataSource JavaDoc) context.lookup(stringValue);
492                             } catch (Exception JavaDoc ex) {
493                                 dataSource = null;
494                             }
495                         }
496                     } else
497                         dataSource = null;
498                 }
499             } catch (Exception JavaDoc ex) {
500                 dataSource = null;
501             }
502             if (dataSource == null) {
503                 url = conConfig.getString("Url");
504                 user = conConfig.getString("User");
505                 password = conConfig.getString("Password");
506             }
507             timeOut = conConfig.getInt("AllocationTimeout", 1000);
508             maxPoolSize = conConfig.getInt("MaxPoolSize", 0);
509             sqlLogging = conConfig.getBoolean("Logging", false);
510             disableConnectionPool = conConfig.getBoolean("DisableConnectionPool", false);
511             shutDownStr = conConfig.getString("ShutDownString", null);
512             queryTimeOut = conConfig.getInt("QueryTimeout", 0);
513             transactionTimeOut = conConfig.getInt("TransactionTimeout", 0);
514             maxPreparedStatements = conConfig.getInt("MaxPreparedStatements", -1);
515             maxConnectionUsages = conConfig.getInt("MaxConnectionUsages", -1);
516             maxWaitingConnections = conConfig.getInt("MaxWaitingConnections", Integer.MAX_VALUE);
517             initWaitingConnections = conConfig.getInt("InitConnectionsPoolSize", -1);
518             connectionIdileTimeout = conConfig.getLong("ConnectionIdleTimeout", -1);
519
520             dbConnectionFactoryName = conConfig.getString(CommonConstants.CONNECTION_FACTORY, null);
521             dbConnectionFactory = createDBConnectionFactory(dbConnectionFactoryName);
522
523         } catch (KeywordValueException except) {
524             throw new ConfigException("Bad DatabaseManager.DB." + logicalDatabase.getName()
525                             + ".Connection section defined in config file.");
526         }
527         currentPoolSize = 0;
528
529         allocatePool = new ConnectionPool();
530         releasePool = new ConnectionPool();
531
532         waitConnectionMonitor = new CountMonitor(maxPoolSize);
533         allocateMonitor = new Object JavaDoc();
534         releaseMonitor = new Object JavaDoc();
535
536         // Excelsior, LLC. Memory leak patch end
537
biggestPoolSize = 0;
538         biggestPoolDate = new Date JavaDoc();
539         numRequests = 0;
540         try {
541             initConnectionPool(initWaitingConnections);
542         } catch (SQLException JavaDoc e) {
543         }
544     }
545
546     /**
547      * Initially fills connection allocator pool with initWaitingConnections
548      * number of connections.
549      *
550      * @param initWaitingConnections
551      * Number of connections that will be initially added to pool.
552      */

553     private void initConnectionPool(int initWaitingConnections)
554             throws SQLException JavaDoc {
555         if (initWaitingConnections > maxPoolSize) {
556             initWaitingConnections = maxPoolSize;
557         }
558         if (initWaitingConnections > 0) {
559             DBConnection newConnection;
560             for (int i = 1; i <= initWaitingConnections; i++) {
561                 newConnection = createConnection();
562                 if (!newConnection.getConnection().isClosed()) {
563                     if (maxConnectionUsages > 0) {
564                         ((ExtendedDBConnection) newConnection)
565                                 .setConnectionUsageCounter(maxConnectionUsages);
566                     } else {
567                         ((ExtendedDBConnection) newConnection)
568                                 .setConnectionUsageCounter(Integer.MAX_VALUE);
569                     }
570                     allocatePool.pool.addLast(newConnection);
571                     currentPoolSize++;
572                     waitConnectionMonitor.countNotify(initWaitingConnections);
573                     if (currentPoolSize > biggestPoolSize) {
574                         biggestPoolSize = currentPoolSize;
575                         biggestPoolDate = new Date JavaDoc();
576                     }
577                 }
578             }
579         }
580     }
581
582     
583     /**
584      * Allocate new connection from pool.
585      * @see com.lutris.appserver.server.sql.ConnectionAllocator#allocate()
586      */

587     public DBConnection allocate() throws SQLException JavaDoc {
588         boolean createNewConn = true;
589         boolean connected = false;
590         DBConnection conn = null;
591         long enterWaitTime = 0;
592         long timeToWait = -1;
593         boolean newConn = false;
594         if (timeOut > 0)
595             timeToWait = timeOut;
596         if (disableConnectionPool) {
597             try {
598                 conn = createConnection();
599             } catch (SQLException JavaDoc e) {
600                 DODS.getLogChannel().write(
601                                         Logger.EMERGENCY,
602                                         "ConnectionAllocator: "
603                                                 + "failed to allocate a new connection"
604                                                 + "\n (connection pool is not used!) \n");
605                 throw e;
606             }
607         } else {
608             while (conn == null) {
609                 connected = false;
610                 newConn = false;
611                 synchronized (allocateMonitor) {
612                     if (allocatePool.pool.isEmpty()) {
613                         switchPools();
614                     }
615                     if (allocatePool.pool.isEmpty()) {
616                         if (createNewConn
617                                 && ((currentPoolSize < maxPoolSize) || (maxPoolSize <= 0))) {
618                             try {
619
620                                 conn = createConnection();
621                                 if (maxConnectionUsages > 0) {
622                                     ((ExtendedDBConnection) conn)
623                                             .setConnectionUsageCounter(maxConnectionUsages);
624                                 } else {
625                                     ((ExtendedDBConnection) conn)
626                                             .setConnectionUsageCounter(Integer.MAX_VALUE);
627                                 }
628                                 currentPoolSize++;
629                                 newConn = true;
630                                 if (currentPoolSize > biggestPoolSize) {
631                                     biggestPoolSize = currentPoolSize;
632                                     biggestPoolDate = new Date JavaDoc();
633                                 }
634                             } catch (SQLException JavaDoc e) {
635                                 conn = null;
636                                 if (currentPoolSize > 0) {
637                                 DODS.getLogChannel().write(
638                                                     Logger.INFO,
639                                                     "ConnectionAllocator: "
640                                                             + "failed to allocate a new connection due to"
641                                                             + e.toString()
642                                                             + "Error code: "
643                                                             + e.getErrorCode()
644                                                             + "\n"
645                                                             + "SQLState: "
646                                                             + e.getSQLState()
647                                                             + "\n"
648                                                             + "\nCurrent pool size is: "
649                                                             + currentPoolSize
650                                                             + "\nMaximum configured pool size is now "
651                                                             + maxPoolSize
652                                                             + "\nContinuing...\n");
653                                     createNewConn = false;
654                                 } else {
655                                     DODS.getLogChannel().write(
656                                                     Logger.EMERGENCY,
657                                                     "ConnectionAllocator: "
658                                                             + "failed to allocate a new connection"
659                                                             + "\nThe connection pool is empty!\n"
660                                                             + e.toString()
661                                                             + "Error code: "
662                                                             + e.getErrorCode()
663                                                             + "\n"
664                                                             + "SQLState: "
665                                                             + e.getSQLState()
666                                                             + "\n"
667                                                             + "\nCurrent pool size is: "
668                                                             + currentPoolSize
669                                                             + "\nMaximum configured pool size is now "
670                                                             + maxPoolSize
671                                                             + "\nContinuing...\n");
672                                     throw e;
673                                 }
674                             }
675                         }
676                     }
677                     try {
678                         if (conn == null) {
679                             conn = (ExtendedDBConnection) allocatePool.pool
680                                     .removeFirst();
681                         }
682                     } catch (NoSuchElementException JavaDoc e) {
683                     }
684
685                     if (conn != null) {
686                         connected = true;
687                         if (maxConnectionUsages > 0) {
688                             int connUsages = ((ExtendedDBConnection) conn)
689                                     .getConnectionUsageCounter();
690                             if (connUsages > 0) {
691                                 ((ExtendedDBConnection) conn)
692                                         .setConnectionUsageCounter(--connUsages);
693                             } else {
694                                 // the usages limit is over, close the
695
// connection
696
conn.close();
697                                 currentPoolSize--;
698                                 DODS.getLogChannel().write(
699                                         Logger.DEBUG,
700                                         "ConnectionAllocator: connection closed due to usage counter. currentPoolSize="
701                                                 + currentPoolSize + "\n");
702                                 conn = null;
703                             }
704                         }
705                         if (conn != null) {
706                             if (((ExtendedDBConnection) conn).isDroped()
707                                     || conn.getConnection().isClosed()
708                                     || (conn.getGeneration() < generation)
709                                     || conn.isMarkedForDrop()) {
710                                 conn.close();
711                                 currentPoolSize--;
712                                 DODS.getLogChannel().write(
713                                                 Logger.DEBUG,
714                                                 "ConnectionAllocator: Inactiv connection closed due allocate() operation. Geting new one. currentPoolSize="
715                                                         + currentPoolSize
716                                                         + "\n");
717                                 conn = null;
718                             }
719                         }
720                         if ((conn != null) && (connectionIdileTimeout > 0)) {
721                             if ((System.currentTimeMillis() - ((ExtendedDBConnection) conn)
722                                     .getConnectionEnterPoolTime()) > connectionIdileTimeout) {
723                                 conn.close();
724                                 currentPoolSize--;
725                                 DODS.getLogChannel().write(
726                                                 Logger.DEBUG,
727                                                 "ConnectionAllocator: Connection closed due allocate() operation - long connection idile time. Geting new one. currentPoolSize="
728                                                         + currentPoolSize
729                                                         + "\n");
730                                 conn = null;
731                             }
732                         }
733                     }
734                 }
735                 if (conn == null) {
736                     try {
737                         if (timeToWait == 0) {
738                         DODS.getLogChannel().write(
739                                             Logger.EMERGENCY,
740                                             "ConnectionAllocator:"
741                                                     + "allocation of a new connection timed out."
742                                                     + "Possible dead lock avoided.");
743                             String JavaDoc msg = "Connections are currently unavailable.\n"
744                                     + "Possible dead lock avoided.";
745                             throw new SQLException JavaDoc(msg);
746
747                         } else if (timeToWait > 0) {
748                             timeToWait = waitConnectionMonitor
749                                     .countWait(timeToWait);
750                         } else {
751                             waitConnectionMonitor.countWait();
752                         }
753
754                     } catch (InterruptedException JavaDoc intEx) {
755                     }
756                 }
757             }
758         }
759         conn.allocate();
760         return conn;
761     }
762
763     /**
764      *
765      */

766     private void switchPools() {
767         synchronized (releaseMonitor) {
768             if (releasePool.pool.size() > allocatePool.pool.size()) {
769                 LinkedList JavaDoc tmp = allocatePool.pool;
770                 allocatePool.pool = releasePool.pool;
771                 releasePool.pool = tmp;
772             }
773         }
774     }
775
776     /*
777      * (non-Javadoc)
778      *
779      * @see com.lutris.appserver.server.sql.ConnectionAllocator#release(com.lutris.appserver.server.sql.DBConnection)
780      */

781     public void release(DBConnection dbConnection) {
782         if (dbConnection != null) {
783             if (disableConnectionPool) {
784                 dbConnection.close();
785                 dbConnection = null;
786             } else {
787                 int releaseSize = 0;
788                 synchronized (releaseMonitor) {
789                     if (connectionIdileTimeout > 0) {
790                         ((ExtendedDBConnection) dbConnection)
791                                 .setConnectionEnterPoolTime(System
792                                         .currentTimeMillis());
793                     }
794                     releasePool.pool.addLast(dbConnection);
795                     releaseSize = releasePool.pool.size();
796                 }
797                 waitConnectionMonitor.countNotify(releaseSize);
798             }
799         }
800     }
801
802     /**
803      * Called when a connection in this pool has an SQL error. All unallocated
804      * connections in the pool are dropped if they have a generation number less
805      * than or equal to the error connection. If the current generation number
806      * is the same as this generation number, increment it. This way so that all
807      * outstanding connections (including the one passed in) of the same
808      * generation are dropped when returned.
809      *
810      * @param dbConnection
811      * The connection object to drop. The connection should be
812      * returned to the pool after this function returns.
813      */

814     public void drop(DBConnection dbConnection) {
815         int releasedCounter = 1;
816         LinkedList JavaDoc newAllocatePool = new LinkedList JavaDoc();
817         LinkedList JavaDoc newReleasePool = new LinkedList JavaDoc();
818         LinkedList JavaDoc tmpPool;
819         synchronized (allocateMonitor) {
820             if (generation <= dbConnection.getGeneration()) {
821                 generation++; // new generation
822
}
823             synchronized (releaseMonitor) {
824                 tmpPool = releasePool.pool;
825                 releasePool.pool = newReleasePool;
826             }
827             try {
828                 while (!tmpPool.isEmpty()) {
829                     DBConnection connect = (DBConnection) tmpPool.removeFirst();
830                     if (connect.getGeneration() < generation) {
831                         connect.close();
832                         releasedCounter++;
833                         currentPoolSize--;
834                     } else {
835                         newAllocatePool.addLast(connect);
836                     }
837                 }
838             } catch (NoSuchElementException JavaDoc e) {
839             }
840             try {
841                 while (!allocatePool.pool.isEmpty()) {
842                     DBConnection connect = (DBConnection) allocatePool.pool
843                             .removeFirst();
844                     if (connect.getGeneration() < generation) {
845                         connect.close();
846                         releasedCounter++;
847                         currentPoolSize--;
848                     } else {
849                         newAllocatePool.addLast(connect);
850                     }
851                 }
852             } catch (NoSuchElementException JavaDoc e) {
853             }
854             allocatePool.pool = newAllocatePool;
855             dbConnection.close();
856             currentPoolSize--;
857         }
858         for (int i = 0; i < releasedCounter; i++) {
859             waitConnectionMonitor.countNotify(releasedCounter);
860         }
861     }
862
863     /**
864      * Called when the database manager is shutting down: Close all connections
865      * immediately.
866      */

867     public void dropAllNow() {
868         if (shutDownStr != null) {
869             try {
870                 DBConnection tmpConn = allocate();
871                 tmpConn.execute(shutDownStr);
872                 tmpConn.release();
873             } catch (SQLException JavaDoc e1) {
874             }
875         }
876         synchronized (releaseMonitor) {
877             synchronized (allocateMonitor) {
878                 try {
879                     while (!allocatePool.pool.isEmpty()) {
880                         DBConnection connect = (DBConnection) allocatePool.pool
881                                 .removeFirst();
882                         connect.close();
883                         currentPoolSize--;
884                     }
885                 } catch (NoSuchElementException JavaDoc e) {}
886             }
887             try {
888                 while (!releasePool.pool.isEmpty()) {
889                     DBConnection connect = (DBConnection) releasePool.pool
890                             .removeFirst();
891                     connect.close();
892                     currentPoolSize--;
893                 }
894             } catch (NoSuchElementException JavaDoc e) {
895             }
896         }
897     }
898
899     /**
900      * Return the number of currently active connections.
901      *
902      * @return The number of connections.
903      */

904     public int getActiveCount() {
905         return currentPoolSize;
906     }
907
908     /**
909      * Return the maximum number of connections active at one time.
910      *
911      * @return The number of connections.
912      */

913     public int getMaxCount() {
914         return biggestPoolSize;
915     }
916
917     /**
918      * Return the time when the maximum connection count occured.
919      *
920      * @return The <CODE>Date</CODE> when the maximum connection count
921      * occured.
922      */

923     public Date JavaDoc getMaxCountDate() {
924         return biggestPoolDate;
925     }
926
927     /**
928      * Reset the maximum connection count and date.
929      */

930     public void resetMaxCount() {
931         biggestPoolSize = currentPoolSize;
932         biggestPoolDate = new Date JavaDoc();
933     }
934
935     /**
936      * Return the number of database requests.
937      *
938      * @return The number of database requests (queries or transactions).
939      */

940     public long getRequestCount() {
941         return numRequests;
942     }
943
944     /**
945      * Finalizer.
946      * If any connections allocated by this object have not been closed,
947      * this method ensures that garbage collection does so.
948      */

949     protected void finalize() {
950         dropAllNow();
951     }
952
953     /**
954      * @return database name of current connection
955      *
956      */

957     public String JavaDoc getDatabaseName() {
958         return logicalDatabase.getName();
959     }
960
961     
962     /*
963      * Increments, numRequests, request counter
964      */

965     public void IncrementRequesteCount() {
966         numRequests++;
967     }
968 }
Popular Tags