Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class represent a DBConnection pool. Another user can use the
4
 *    object to initial a connection pool, get db connection or return it. 
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Jing Tao
8
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2010-04-19 16:51:13 -0700 (Mon, 19 Apr 2010) $'
11
 * '$Revision: 5319 $'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27

    
28
package edu.ucsb.nceas.metacat.database;
29

    
30
import java.util.Vector;
31
import java.sql.*;
32

    
33
import org.apache.log4j.Logger;
34

    
35
import edu.ucsb.nceas.metacat.properties.PropertyService;
36
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
37

    
38
/** 
39
 * A class represent a DBConnection pool. Another user can use the
40
 * object to initial a connection pool, get db connection or return it.
41
 * This a singleton class, this means only one instance of this class could
42
 * be in the program at one time. 
43
 */
44
public class DBConnectionPool implements Runnable
45
{
46

    
47
  //static attributes
48
  private static DBConnectionPool instance;
49
  private static Vector<DBConnection> connectionPool;
50
  private static Thread runner;
51
  private static int _countOfReachMaximum = 0;
52
  private static Logger logMetacat = Logger.getLogger(DBConnectionPool.class);
53

    
54
  private static int _maxConnNum;
55
  private static int _initConnNum;
56
  private static int _incrConnNum;
57
  private static long _maxAge;
58
  private static long _maxConnTime;
59
  private static int _maxUsageNum;
60
  private static int _connCountWarnLimit;
61
  private static String _dbConnRecyclThrd;
62
  private static long _cyclTimeDbConn;
63
  
64
  final static int MAXIMUMCONNECTIONNUMBER;
65
  final static int INITIALCONNECTIONNUMBER;
66
  final static int INCREASECONNECTIONNUMBER;
67
  final static long MAXIMUMAGE;
68
  final static long MAXIMUMCONNECTIONTIME;
69
  final static int MAXIMUMUSAGENUMBER;
70
  final static String DBCONNECTIONRECYCLETHREAD ;
71
  final static long CYCLETIMEOFDBCONNECTION;
72
  
73
  static {
74
//		int maxConnNum = 0;
75
//		int initConnNum = 0;
76
//		int incrConnNum = 0;
77
//		long maxAge = 0;
78
//		long maxConnTime = 0;
79
//		int maxUsageNum = 0;
80
//		int connCountWarnLevel = 0;
81
//		String dbConnRecyclThrd = null;
82
//		long cyclTimeDbConn = 0;
83
		
84
		try {
85
			// maximum connection number in the connection pool
86
			_maxConnNum = Integer.parseInt(PropertyService
87
					.getProperty("database.maximumConnections"));
88
			_initConnNum = Integer.parseInt(PropertyService
89
					.getProperty("database.initialConnections"));
90
			_incrConnNum = Integer.parseInt(PropertyService
91
					.getProperty("database.incrementConnections"));
92
			_maxAge = Integer.parseInt(PropertyService
93
					.getProperty("database.maximumConnectionAge"));
94
			_maxConnTime = Long.parseLong(PropertyService
95
					.getProperty("database.maximumConnectionTime"));
96
			_maxUsageNum = Integer.parseInt(PropertyService
97
					.getProperty("database.maximumUsageNumber"));
98
			_connCountWarnLimit = Integer.parseInt(PropertyService
99
					.getProperty("database.connectionCountWarnLimit"));
100
			_dbConnRecyclThrd = PropertyService
101
					.getProperty("database.runDBConnectionRecycleThread");
102
			_cyclTimeDbConn = Long.parseLong(PropertyService
103
					.getProperty("database.cycleTimeOfDBConnection"));
104
		} catch (PropertyNotFoundException pnfe) {
105
			System.err.println("Could not get property in static block: "
106
					+ pnfe.getMessage());
107
		}
108
		
109
		MAXIMUMCONNECTIONNUMBER = _maxConnNum;
110
		INITIALCONNECTIONNUMBER = _initConnNum;
111
		INCREASECONNECTIONNUMBER = _incrConnNum;
112
		MAXIMUMAGE = _maxAge;
113
		MAXIMUMCONNECTIONTIME = _maxConnTime;
114
		MAXIMUMUSAGENUMBER = _maxUsageNum;
115
		DBCONNECTIONRECYCLETHREAD  = _dbConnRecyclThrd;
116
		CYCLETIMEOFDBCONNECTION = _cyclTimeDbConn;
117
	}
118
  
119
  // the number for trying to check out a connection in the pool in
120
  // getDBConnection method
121
  final static int LIMIT = 2;
122
  
123
  final static int FREE = 0; //status of a connection
124
  final static int BUSY = 1; //status of a connection
125
  /**
126
   * Returns the single instance, creating one if it's the
127
   * first time this method is called.
128
   */
129
  public static synchronized DBConnectionPool getInstance()
130
                                 throws SQLException 
131
  {
132
    if (instance == null) {
133
      instance = new DBConnectionPool();
134
      Logger log = Logger.getLogger(DBConnectionPool.class);
135
      log.debug("DBConnectionPool.getInstance - MaximumConnectionNumber: " + MAXIMUMCONNECTIONNUMBER);
136
      log.debug("DBConnectionPool.getInstance - Intial connection number: " + INITIALCONNECTIONNUMBER);
137
      log.debug("DBConnectionPool.getInstance - Increated connection Number: " + INCREASECONNECTIONNUMBER);
138
      log.debug("DBConnectionPool.getInstance - Maximum connection age: " + MAXIMUMAGE);
139
      log.debug("DBConnectionPool.getInstance - Maximum connection time: " + MAXIMUMCONNECTIONTIME);
140
      log.debug("DBConnectionPool.getInstance - Maximum usage count: " + MAXIMUMUSAGENUMBER);
141
      log.debug("DBConnectionPool.getInstance - Running recycle thread or not: " + DBCONNECTIONRECYCLETHREAD);
142
      log.debug("DBConnectionPool.getInstance - Cycle time of recycle: " + CYCLETIMEOFDBCONNECTION); 
143
    }
144
    return instance;
145
  }
146

    
147

    
148
  /**
149
   * This is a private constructor since it is singleton
150
   */
151
   
152
  private DBConnectionPool()  throws SQLException 
153
  {
154
    connectionPool = new Vector<DBConnection>();
155
    initialDBConnectionPool();
156
    //running the thread to recycle DBConnection
157
    if (DBCONNECTIONRECYCLETHREAD.equals("on"))
158
    {
159
      runner = new Thread(this);
160
      runner.start();
161
    }
162
  }//DBConnection
163

    
164
  /**
165
   * Method to get the size of DBConnectionPool
166
   */
167
  public int getSizeOfDBConnectionPool()
168
  {
169
    return connectionPool.size();
170
  }
171
  
172
  
173
  /**
174
   * Method to initial a pool of DBConnection objects 
175
   */
176
  private void initialDBConnectionPool() throws SQLException 
177
  {
178

    
179
    DBConnection dbConn = null;
180
    
181
    for ( int i = 0; i < INITIALCONNECTIONNUMBER; i++ ) 
182
    {
183
      //create a new object of DBConnection
184
      //this DBConnection object has a new connection in it
185
      //it automatically generate the createtime and tag
186
      dbConn = new DBConnection();
187
      //put DBConnection into vetor
188
      connectionPool.add(dbConn);
189
    }    
190
    
191
  
192
  }//initialDBConnectionPool
193
  
194
  /**
195
   * Method to get Connection object (Not DBConnection)
196
   */
197
  /*public static Connection getConnection() throws SQLException
198
  {
199
    DBConnection dbConn = null;
200
    //get a DBConnection
201
    dbConn = getDBConnection();
202
    //get connection object in DBConnection object
203
    //The following getConnections method is in DBConnection class
204
    return dbConn.getConnections();
205
  }*/
206
  
207
 
208
  /**
209
   * Method to get a DBConnection in connection pool
210
   * 1) try to get a DBConnection from DBConnection pool
211
   * 2) if 1) failed, then check the size of pool. If the size reach the
212
   *    maximum number of connection, throw a exception: couldn't get one
213
   * 3) If the size is less than the maximum number of connectio, create some
214
   *    new connections and recursive get one
215
   * @param methodName, the name of method which will check connection out
216
   */
217
  public static synchronized DBConnection getDBConnection(String methodName) 
218
                                                throws SQLException
219
  {
220
    if (instance == null) {
221
      instance = DBConnectionPool.getInstance();
222
    }
223
    DBConnection db = null;
224
    int random = 0; //random number
225
    int index = 0; //index
226
    int size = 0; //size of connection pool
227
//    logMetacat.debug("DBConnectionPool.getDBConnection - Trying to check out connection...");
228
    size = connectionPool.size();
229
//    logMetacat.debug("DBConnectionPool.getDBConnection - size of connection pool: " + size);
230
    
231
     //try every DBConnection in the pool
232
    //every DBConnection will be try LIMITE times
233
    for (int j=0 ; j<LIMIT; j++)
234
    {
235
       //create a random number as the started index for connection pool
236
      //So that the connection ofindex of 0 wouldn't be a the heaviest user
237
      random = (new Double (Math.random()*100)).intValue();
238
      for (int i=0; i<size; i++)
239
      {
240
        index =(i+random)%size;
241
        db = (DBConnection) connectionPool.elementAt(index);
242
//        logMetacat.debug("DBConnectionPool.getDBConnection - Index: " + index);
243
//        logMetacat.debug("DBConnectionPool.getDBConnection - Tag: " + db.getTag());
244
//        logMetacat.debug("DBConnectionPool.getDBConnection - Status: " + db.getStatus());
245
        //check if the connection is free
246
        if (db.getStatus()==FREE)
247
        {
248
          //If this connection is good, return this DBConnection
249
          if (validateDBConnection(db))
250
          {
251
            
252
            //set this DBConnection status
253
            db.setStatus(BUSY);
254
            //increase checkout serial number
255
            db.increaseCheckOutSerialNumber(1);
256
            //increase one usageCount
257
            db.increaseUsageCount(1);
258
            //set method name to DBConnection
259
            db.setCheckOutMethodName(methodName);
260
            db.setAutoCommit(true);
261
            //debug message
262
//            logMetacat.debug("DBConnectionPool.getDBConnection - The connection is checked out: " + db.getTag());
263
//            logMetacat.debug("DBConnectionPool.getDBConnection - The method for checking is: " + db.getCheckOutMethodName());
264
//            logMetacat.debug("DBConnectionPool.getDBConnection - The age is " + db.getAge());
265
//            logMetacat.debug("DBConnectionPool.getDBConnection - The usage is " + db.getUsageCount());
266
//            logMetacat.debug("DBConnectionPool.getDBConnection - The connection time is: " + db.getConnectionTime());
267
            //set check out time
268
            db.setCheckOutTime(System.currentTimeMillis());
269
            // set count of reach maximum 0 because it can check out
270
            _countOfReachMaximum = 0;
271
            return db;
272
          }//if
273
          else//The DBConnection has some problem
274
          {
275
            //close this DBConnection
276
            db.close();
277
            //remove it form connection pool
278
            connectionPool.remove(index);
279
            //insert a new DBConnection to same palace
280
            db = new DBConnection();
281
            connectionPool.insertElementAt(db, index);
282
          }//else
283
        }//if
284
      }//for
285
    }//for
286
    
287
    //if couldn't get a connection, we should increase DBConnection pool
288
    //if the connection pool size is less than maximum connection number
289
   
290
    if ( size < MAXIMUMCONNECTIONNUMBER )
291
    {
292
       if ((size + INCREASECONNECTIONNUMBER) < MAXIMUMCONNECTIONNUMBER)
293
       { 
294
         //if we can create INCREASECONNECTIONNUMBER of new DBConnection
295
         //add to connection pool
296
         for ( int i = 0; i < INCREASECONNECTIONNUMBER; i++)
297
         {
298
           DBConnection dbConn = new DBConnection();
299
           connectionPool.add(dbConn);
300
         }//for
301
       }//if
302
       else
303
       {
304
         //There is no enough room to increase INCREASECONNECTIONNUMBER 
305
         //we create new DBCoonection to Maximum connection number
306
         for (int i= size+1; i<= MAXIMUMCONNECTIONNUMBER; i++)
307
         {
308
           DBConnection dbConn = new DBConnection();
309
           connectionPool.add(dbConn);
310
         }//for
311
       }//else
312
   
313
    }//if
314
    else
315
    {
316
      /*throw new SQLException("The maximum of " +MAXIMUMCONNECTIONNUMBER + 
317
                            " open db connections is reached." +
318
                            " New db connection to MetaCat" +
319
                            " cannot be established.");*/
320
       logMetacat.fatal("DBConnectionPool.getDBConnection - The maximum of " + MAXIMUMCONNECTIONNUMBER + 
321
    		" open db connections is reached. New db connection to MetaCat" +
322
       		" cannot be established.");
323
       _countOfReachMaximum ++;
324
       if (_countOfReachMaximum >= 10)
325
       {
326
         _countOfReachMaximum =0;
327
         logMetacat.fatal("finally could not get dbconnection");
328
         return null;
329
       }
330
       else
331
       {
332
         //if couldn't get a connection, sleep 20 seconds and try again.
333
         try
334
         {
335
           logMetacat.debug("DBConnectionPool.getDBConnection - sleep 5000ms, could not get dbconnection");
336
           Thread.sleep(5000);
337
         }
338
         catch (Exception e)
339
        {
340
           logMetacat.error("DBConnectionPool.getDBConnection - General exception: " + e.getMessage());
341
        }
342
      }
343
         
344
      
345
    }//else
346
    
347
    //recursive to get new connection    
348
    return getDBConnection(methodName); 
349
  }//getDBConnection
350
 
351
  /** 
352
   * Method to check if a db connection works fine or not
353
   * Check points include:
354
   * 1. check the usageCount if it is too many
355
   * 2. check the dbconne age if it is too old
356
   * 3. check the connection time if it is too long
357
   * 4. run simple sql query
358
   *
359
   * @param dbConn, the DBConnection object need to check
360
   */
361
  private static boolean validateDBConnection (DBConnection dbConn)
362
  {    
363
    //Check if the DBConnection usageCount if it is too many
364
    if (dbConn.getUsageCount() >= MAXIMUMUSAGENUMBER )
365
    {
366
      logMetacat.debug("DBConnectionPool.validateDBConnection - Connection usageCount is too high: "+
367
      dbConn.getUsageCount());
368
      return false;
369
    }
370
    
371
    //Check if the DBConnection has too much connection time
372
    if (dbConn.getConnectionTime() >= MAXIMUMCONNECTIONTIME)
373
    {
374
      logMetacat.debug("DBConnectionPool.validateDBConnection - Connection has too much connection time: " +
375
    		  dbConn.getConnectionTime());
376
      return false;
377
    }
378
    
379
    //Check if the DBConnection is too old
380
    if (dbConn.getAge() >=MAXIMUMAGE)
381
    {
382
      logMetacat.debug("DBConnectionPool.validateDBConnection - Connection is too old: " + dbConn.getAge());
383
      return false;
384
    }
385
    
386
    //Try to run a simple query
387
    try
388
    {
389
      long startTime=System.currentTimeMillis();
390
      DatabaseMetaData metaData = dbConn.getMetaData();
391
      long stopTime=System.currentTimeMillis();
392
      //increase one usagecount
393
      dbConn.increaseUsageCount(1);
394
      //increase connection time
395
      dbConn.setConnectionTime(stopTime-startTime);
396
  
397
    }
398
    catch (Exception e)
399
    {
400
      logMetacat.error("DBConnectionPool.validateDBConnection - General error:" + e.getMessage());
401
      return false;
402
    }
403
    
404
    return true;
405
    
406
  }//validateDBConnection()
407
  
408
  /**
409
   * Method to return a connection to DBConnection pool.
410
   * @param conn, the Connection object need to check in
411
   */
412
  public static synchronized void returnDBConnection(DBConnection conn, 
413
                                                              int serialNumber)
414
  {
415
    int index = -1;
416
    DBConnection dbConn = null;
417
  
418
    index = getIndexOfPoolForConnection(conn);
419
    if ( index ==-1 )
420
    {
421
//      logMetacat.info("DBConnectionPool.returnDBConnection - Couldn't find a DBConnection in the pool" + 
422
//    		  " which have same tag to the returned DBConnetion object");
423
      return;
424
                                  
425
    }//if
426
    else
427
    {
428
      //check the parameter - serialNumber which will be keep in calling method
429
      //if it is as same as the object's checkout serial number.
430
      //if it is same return it. If it is not same, maybe the connection already
431
      // was returned earlier.
432
//      logMetacat.debug("DBConnectionPool.returnDBConnection - serial number in Connection: " +
433
//              conn.getCheckOutSerialNumber());
434
//      logMetacat.debug("DBConnectionPool.returnDBConnection - serial number in local: " + serialNumber);
435
      if (conn.getCheckOutSerialNumber() == serialNumber)
436
      {
437
        dbConn = (DBConnection) connectionPool.elementAt(index);
438
        //set status to free
439
        dbConn.setStatus(FREE);
440
        //count connection time
441
        dbConn.setConnectionTime
442
                          (System.currentTimeMillis()-dbConn.getCheckOutTime());
443
                          
444
        //set check out time to 0
445
        dbConn.setCheckOutTime(0);
446
        
447
//        logMetacat.debug("DBConnectionPool.returnDBConnection - Connection: " + 
448
//        		dbConn.getTag() + " checked in.");
449
//        logMetacat.debug("DBConnectionPool.returnDBConnection - Connection: " +
450
//        		dbConn.getTag() + "'s status: " + dbConn.getStatus());
451
                                                                       
452
      }//if
453
      else
454
      {
455
//        logMetacat.info("DBConnectionPool.returnDBConnection - This DBConnection couldn't return" +
456
//        		dbConn.getTag());
457
      }//else
458
    }//else
459
   
460
 
461
  }//returnConnection
462
  
463
  /**
464
   * Given a returned DBConnection, try to find the index of DBConnection object
465
   * in dbConnection pool by comparing DBConnection' tag and conn.toString.
466
   * If couldn't find , -1 will be returned.
467
   * @param conn, the connection need to be found
468
   */
469
  private static synchronized int getIndexOfPoolForConnection(DBConnection conn)
470
  {
471
    int index = -1;
472
    String info = null;
473
    //if conn is null return -1 too
474
    if (conn==null)
475
    {
476
      return -1;
477
    }
478
    //get tag of this returned DBConnection
479
    info = conn.getTag();
480
    //if the tag is null or empty, -1 will be returned
481
    if (info==null || info.equals(""))
482
    {
483
      return index;
484
    }
485
    //compare this info to the tag of every DBConnection in the pool
486
    for ( int i=0; i< connectionPool.size(); i++)
487
    {
488
      DBConnection dbConn = (DBConnection) connectionPool.elementAt(i);
489
      if (info.equals(dbConn.getTag()))
490
      {
491
        index = i;
492
        break;
493
      }//if
494
    }//for
495
    
496
    return index;
497
  }//getIndexOfPoolForConnection  
498
  
499
  /**
500
   * Method to shut down all connections
501
   */
502
  public static void release()
503
  {
504
    
505
    //shut down the background recycle thread
506
    if (DBCONNECTIONRECYCLETHREAD.equals("on"))
507
    {
508
      runner.interrupt();
509
    }
510
    //close every dbconnection in the pool
511
    synchronized(connectionPool)
512
    {
513
      for (int i=0;i<connectionPool.size();i++)
514
      {
515
        try
516
        {
517
          DBConnection dbConn= (DBConnection) connectionPool.elementAt(i);
518
          dbConn.close();
519
        }//try
520
        catch (SQLException e)
521
        {
522
          logMetacat.error("DBConnectionPool.release - Error in release connection: "
523
                                            +e.getMessage());
524
        }//catch
525
      }//for
526
    }//synchronized
527
  }//release()
528
  
529
  /**
530
   * periodically to recycle the connection
531
   */
532
  public void run()
533
  {
534
    DBConnection dbConn = null;
535
    //keep the thread running
536
    while (true)
537
    {
538
      //check every dbconnection in the pool
539
      synchronized(connectionPool)
540
      {
541
        for (int i=0; i<connectionPool.size(); i++)
542
        {
543
          dbConn = (DBConnection) connectionPool.elementAt(i);
544
          
545
          //if a DBConnection conncectioning time for one check out is greater 
546
          //than 30000 milliseconds print it out
547
          if (dbConn.getStatus()==BUSY && 
548
            (System.currentTimeMillis()-dbConn.getCheckOutTime())>=30000)
549
          {
550
            logMetacat.fatal("DBConnectionPool.run - This DBConnection is checked out for: " +
551
            		(System.currentTimeMillis()-dbConn.getCheckOutTime())/1000 + " secs");
552
            logMetacat.fatal("DBConnectionPool.run - " + dbConn.getTag());
553
            logMetacat.error("DBConnectionPool.run - method: " + dbConn.getCheckOutMethodName());
554
            
555
          }
556
          
557
          //check the validation of free connection in the pool
558
          if (dbConn.getStatus() == FREE)
559
          {
560
            try
561
            {
562
              //try to print out the warning message for every connection
563
              if (dbConn.getWarningMessage()!=null)
564
              {
565
                logMetacat.warn("DBConnectionPool.run - Warning for connection " +
566
                		dbConn.getTag() + " : " + dbConn.getWarningMessage());
567
              }
568
              //check if it is valiate, if not create new one and replace old one
569
              if (!validateDBConnection(dbConn))
570
              {
571
                logMetacat.debug("DBConnectionPool.run - Recyle: " + dbConn.getTag());
572
                //close this DBConnection
573
                dbConn.close();
574
                //remove it form connection pool
575
                connectionPool.remove(i);
576
                //insert a new DBConnection to same palace
577
                dbConn = new DBConnection();
578
                connectionPool.insertElementAt(dbConn, i);
579
               }//if
580
            }//try
581
            catch (SQLException e)
582
            {
583
              logMetacat.error("DBConnectionPool.run - SQL error: " + e.getMessage());
584
            }//catch
585
          }//if
586
        }//for
587
      }//synchronize   
588
      //Thread sleep 
589
      try
590
      {
591
        Thread.sleep(CYCLETIMEOFDBCONNECTION);
592
      }
593
      catch (Exception e)
594
      {
595
        logMetacat.error("DBConnectionPool.run - General error: " + e.getMessage());
596
      }
597
    }//while
598
  }//run
599
  
600
  /**
601
   * Method to get the number of free DBConnection in DBConnection pool
602
   */
603
  private static synchronized int getFreeDBConnectionNumber()
604
  {
605
    int numberOfFreeDBConnetion = 0; //return number
606
    DBConnection db = null; //single DBconnection
607
    int poolSize = 0; //size of connection pool
608
    //get the size of DBConnection pool
609
    poolSize = connectionPool.size();
610
    //Check every DBConnection in the pool
611
    for ( int i=0; i<poolSize; i++)
612
    {
613
      
614
      db = (DBConnection) connectionPool.elementAt(i);
615
      //check the status of db. If it is free, count it
616
      if (db.getStatus() == FREE)
617
      {
618
        numberOfFreeDBConnetion++;
619
      }//if
620
    }//for
621
    //return the count result
622
    return numberOfFreeDBConnetion;
623
  }//getFreeDBConnectionNumber
624
      
625
  	/**
626
	 * Print a list of busy connections. This method should be called when the
627
	 * used connection count exceeds the _connCountWarnLimit set in
628
	 * metacat.properties.
629
	 * 
630
	 * @param usedConnectionCount
631
	 *            the current count of busy connections
632
	 */
633
	private static void printBusyDBConnections(int usedConnectionCount) {
634
		boolean showCountWarning = usedConnectionCount > _connCountWarnLimit;
635
		
636
		String warnMessage = ""; 
637

    
638
		// Check every DBConnection in the pool
639
		for (DBConnection dbConnection : connectionPool) {
640
			// check the status of db. If it is busy, add it to the message
641
			if (dbConnection.getStatus() == BUSY) {
642
				if (showCountWarning) {
643
					warnMessage += "\n   --- Method: " + dbConnection.getCheckOutMethodName() + 
644
						" is using: " + dbConnection.getTag() + " for " + dbConnection.getAge() + " ms ";
645
				}
646
				
647
				if (dbConnection.getConnectionTime() > _maxConnTime) {
648
					logMetacat.warn("DBConnectionPool.printBusyDBConnections - Excessive connection time, method: " + 
649
							dbConnection.getCheckOutMethodName() + " is using: " + dbConnection.getTag() + 
650
							" for " + dbConnection.getConnectionTime() + " ms ");
651
				}
652
			}// if
653
		}// for
654
		
655
		if (showCountWarning) {
656
			logMetacat.warn("DBConnectionPool.printBusyDBConnections - " + usedConnectionCount + 
657
					" DB connections currently busy because: " + warnMessage);
658
		}
659
	}
660
  
661
  /**
662
	 * Method to decrease dbconnection pool size when all dbconnections are idle
663
	 * If all connections are free and connection pool size greater than initial
664
	 * value, shrink connection pool size to initial value
665
	 */
666
  public static synchronized boolean shrinkConnectionPoolSize() 
667
  {
668
     int connectionPoolSize = 0; //store the number of dbconnection pool size
669
     int freeConnectionSize = 0; //store the number of free dbconnection in pool
670
     int difference = 0; // store the difference number between connection size
671
                         // and free connection
672
     boolean hasException = false; //to check if has a exception happened
673
     boolean result = false; //result
674
     DBConnection conn = null; // the dbconnection
675
     connectionPoolSize = connectionPool.size();
676
     freeConnectionSize = getFreeDBConnectionNumber();
677
     difference = connectionPoolSize - freeConnectionSize;
678

    
679
     if(freeConnectionSize < connectionPoolSize){
680
    	 logMetacat.info("DBConnectionPool.shrinkConnectionPoolSize - " + difference + " connection(s) " +
681
                        "being used and connection pool size is " + connectionPoolSize);
682
     } else {
683
    	 logMetacat.info("DBConnectionPool.shrinkConnectionPoolSize - Connection pool size: " + connectionPoolSize);
684
    	 logMetacat.info("DBConnectionPool.shrinkConnectionPoolSize - Free Connection number: " + freeConnectionSize);
685
     }
686
     
687
     //If all connections are free and connection pool size greater than 
688
     //initial value, shrink connection pool size to intital value
689
     if (difference == 0 && connectionPoolSize > INITIALCONNECTIONNUMBER)
690
     {
691
       //db connection having index from  to connectionpoolsize -1
692
       //intialConnectionnumber should be close and remove from pool
693
       for ( int i=connectionPoolSize-1; i >= INITIALCONNECTIONNUMBER ; i--)
694
       {
695
        
696
         //get the dbconnection from pool
697
         conn = (DBConnection) connectionPool.elementAt(i);
698
         
699
         try
700
         {
701
           //close conn
702
           conn.close();
703
         }//try
704
         catch (SQLException e)
705
         { 
706
           // set hadException true
707
           hasException = true;
708
           logMetacat.error("DBConnectionPool.shrinkConnectionPoolSize - SQL Exception: " + e.getMessage());
709
         }//catch
710
                                        
711
        //remove it from pool
712
        connectionPool.remove(i);
713
        // because enter the loop, set result true
714
        result = true;
715
       }//for
716
     }//if
717
     
718
     //if hasException is true ( there at least once exception happend)
719
     // the result should be false
720
     if (hasException)
721
     {
722
       result =false;
723
     }//if
724
     // return result
725
     return result;
726
  }//shrinkDBConnectionPoolSize
727
   
728
    /**
729
   * Method to decrease dbconnection pool size when all dbconnections are idle
730
   * If all connections are free and connection pool size greater than 
731
   * initial value, shrink connection pool size to intital value
732
   */
733
  public static synchronized void shrinkDBConnectionPoolSize() 
734
  {
735
     int connectionPoolSize = 0; //store the number of dbconnection pool size
736
     int freeConnectionSize = 0; //store the number of free dbconnection in pool
737
     int usedConnectionCount = 0; // store the difference number between connection size
738
                         // and free connection
739
    
740
     DBConnection conn = null; // the dbconnection
741
     connectionPoolSize = connectionPool.size();
742
     freeConnectionSize = getFreeDBConnectionNumber();
743
     usedConnectionCount = connectionPoolSize - freeConnectionSize;
744

    
745
     printBusyDBConnections(usedConnectionCount);
746
     
747
     if(freeConnectionSize < connectionPoolSize){
748
         logMetacat.info("DBConnectionPool.shrinkDBConnectionPoolSize - " + usedConnectionCount + " connection(s) " +
749
        		 "being used and connection pool size is " + connectionPoolSize);
750
     } else {
751
         logMetacat.debug("DBConnectionPool.shrinkDBConnectionPoolSize - " + 
752
        		 "Connection pool size: " + connectionPoolSize);
753
         logMetacat.debug("DBConnectionPool.shrinkDBConnectionPoolSize - " + 
754
        		 "Free Connection number: " + freeConnectionSize);
755
     }
756
     
757
     //If all connections are free and connection pool size greater than 
758
     //initial value, shrink connection pool size to intital value
759
     if (usedConnectionCount == 0 && connectionPoolSize > INITIALCONNECTIONNUMBER)
760
     {
761
       //db connection having index from  to connectionpoolsize -1
762
       //intialConnectionnumber should be close and remove from pool
763
       for ( int i=connectionPoolSize-1; i >= INITIALCONNECTIONNUMBER ; i--)
764
       {
765
        
766
         //get the dbconnection from pool
767
         conn = (DBConnection) connectionPool.elementAt(i);
768
         //make sure again the DBConnection status is free
769
         if (conn.getStatus()==FREE)
770
         {
771
           try
772
           {
773
             //close conn
774
             conn.close();
775
           }//try
776
           catch (SQLException e)
777
           { 
778
          
779
             logMetacat.error("DBConnectionPool.shrinkDBConnectionPoolSize - SQL error: " + e.getMessage());
780
           }//catch
781
        
782
           //remove it from pool
783
           connectionPool.remove(i);
784
         }//if
785
       
786
       }//for
787
     }//if
788
     
789
    
790
  }//shrinkDBConnectionPoolSize
791
   
792
  
793
}//DBConnectionPool
(2-2/4)