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
 *    Release: @release@
9
 *
10
 *   '$Author: sgarg $'
11
 *     '$Date: 2005-11-02 11:07:07 -0800 (Wed, 02 Nov 2005) $'
12
 * '$Revision: 2716 $'
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
 */
28

    
29
package edu.ucsb.nceas.metacat;
30

    
31
import java.io.*;
32
import java.util.Vector;
33
import java.lang.*;
34
import java.sql.*;
35
import java.util.Stack;
36
import java.util.Hashtable;
37
import java.util.Enumeration;
38

    
39
import org.apache.log4j.Logger;
40

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

    
50
  //static attributes
51
  private static DBConnectionPool instance;
52
  private static Vector connectionPool;
53
  private static Thread runner;
54
  private static int countOfReachMaximum = 0;
55
  private static Logger logMetacat = Logger.getLogger(DBConnectionPool.class);
56

    
57
  //maximum connection number in the connection pool
58
  final static int MAXIMUMCONNECTIONNUMBER=
59
                  Integer.parseInt(MetaCatUtil.getOption("maximumConnections"));
60
  
61
  //inintila connection number int the connection pool
62
  final static int INITIALCONNECTIONNUMBER=
63
                  Integer.parseInt(MetaCatUtil.getOption("initialConnections"));
64
 
65
  //the number to increase connection pool size
66
  final static int INCREASECONNECTIONNUMBER=
67
                Integer.parseInt(MetaCatUtil.getOption("incrementConnections"));
68
                
69
  //maximum age for a connection (in milli seconds)
70
  final static long MAXIMUMAGE =
71
                  Long.parseLong(MetaCatUtil.getOption("maximumConnectionAge"));
72
  //maximum connection time for a connection ( in milli second)
73
  final static long MAXIMUMCONNECTIONTIME =
74
                 Long.parseLong(MetaCatUtil.getOption("maximumConnectionTime"));
75
  //maximum number for using a connection.
76
  final static int MAXIMUMUSAGENUMBER =
77
                  Integer.parseInt(MetaCatUtil.getOption("maximumUsageNumber"));
78
  //the parameter if run dbconncestionrecyclethread or not
79
  final static String DBCONNECTIONRECYCLETHREAD =
80
                          MetaCatUtil.getOption("runDBConnectionRecycleThread");
81
  //the cycle time of connection recycle action
82
  final static long CYCLETIMEOFDBCONNECTION = 
83
               Long.parseLong(MetaCatUtil.getOption("cycleTimeOfDBConnection"));
84
               
85
  //the number for trying to check out a connection in the pool in 
86
  //getDBConnection method
87
  final static int LIMIT = 2;
88
  
89
  final static int FREE = 0; //status of a connection
90
  final static int BUSY = 1; //statis of a connection
91
  /**
92
   * Returns the single instance, creating one if it's the
93
   * first time this method is called.
94
   */
95
  public static synchronized DBConnectionPool getInstance()
96
                                 throws SQLException 
97
  {
98
    MetaCatUtil.printMessage
99
                      ("MaximumConnectionNumber: "+MAXIMUMCONNECTIONNUMBER);
100
    MetaCatUtil.printMessage
101
                     ("Intial connection number: "+INITIALCONNECTIONNUMBER);
102
    MetaCatUtil.printMessage
103
                 ("Increated connection Number: "+INCREASECONNECTIONNUMBER);
104
    MetaCatUtil.printMessage
105
                  ("Maximum connection age: "+MAXIMUMAGE);
106
    MetaCatUtil.printMessage
107
                  ("Maximum connection time: "+MAXIMUMCONNECTIONTIME);
108
    MetaCatUtil.printMessage
109
                  ("Maximum usage count: "+MAXIMUMUSAGENUMBER);
110
    MetaCatUtil.printMessage
111
             ("Running recycle thread or not: "+DBCONNECTIONRECYCLETHREAD);
112
    MetaCatUtil.printMessage
113
             ("Cycle time of recycle: "+CYCLETIMEOFDBCONNECTION); 
114
    if (instance == null) {
115
      instance = new DBConnectionPool();
116
    }
117
    return instance;
118
  }//getInstance
119

    
120

    
121
  /**
122
   * This is a private constructor since it is singleton
123
   */
124
   
125
  private DBConnectionPool()  throws SQLException 
126
  {
127
    connectionPool = new Vector();
128
    initialDBConnectionPool();
129
    //running the thread to recycle DBConnection
130
    if (DBCONNECTIONRECYCLETHREAD.equals("on"))
131
    {
132
      runner = new Thread(this);
133
      runner.start();
134
    }
135
  }//DBConnection
136

    
137
  /**
138
   * Method to get the size of DBConnectionPool
139
   */
140
  public int getSizeOfDBConnectionPool()
141
  {
142
    return connectionPool.size();
143
  }
144
  
145
  
146
  /**
147
   * Method to initial a pool of DBConnection objects 
148
   */
149
  private void initialDBConnectionPool() throws SQLException 
150
  {
151

    
152
    DBConnection dbConn = null;
153
    
154
    for ( int i = 0; i < INITIALCONNECTIONNUMBER; i++ ) 
155
    {
156
      //create a new object of DBConnection
157
      //this DBConnection object has a new connection in it
158
      //it automatically generate the createtime and tag
159
      dbConn = new DBConnection();
160
      //put DBConnection into vetor
161
      connectionPool.add(dbConn);
162
    }    
163
    
164
  
165
  }//initialDBConnectionPool
166
  
167
  /**
168
   * Method to get Connection object (Not DBConnection)
169
   */
170
  /*public static Connection getConnection() throws SQLException
171
  {
172
    DBConnection dbConn = null;
173
    //get a DBConnection
174
    dbConn = getDBConnection();
175
    //get connection object in DBConnection object
176
    //The following getConnections method is in DBConnection class
177
    return dbConn.getConnections();
178
  }*/
179
  
180
 
181
  /**
182
   * Method to get a DBConnection in connection pool
183
   * 1) try to get a DBConnection from DBConnection pool
184
   * 2) if 1) failed, then check the size of pool. If the size reach the
185
   *    maximum number of connection, throw a exception: couldn't get one
186
   * 3) If the size is less than the maximum number of connectio, create some
187
   *    new connections and recursive get one
188
   * @param methodName, the name of method which will check connection out
189
   */
190
  public static synchronized DBConnection getDBConnection(String methodName) 
191
                                                throws SQLException
192
  {
193
    if (instance == null) {
194
      instance = DBConnectionPool.getInstance();
195
    }
196
    DBConnection db = null;
197
    int random = 0; //random number
198
    int index = 0; //index
199
    int size = 0; //size of connection pool
200
    logMetacat.debug("Try to checking out connection...");
201
    size = connectionPool.size();
202
    logMetacat.debug("size of connection pool: "+size);
203
    
204
     //try every DBConnection in the pool
205
    //every DBConnection will be try LIMITE times
206
    for (int j=0 ; j<LIMIT; j++)
207
    {
208
       //create a random number as the started index for connection pool
209
      //So that the connection ofindex of 0 wouldn't be a the heaviest user
210
      random = (new Double (Math.random()*100)).intValue();
211
      for (int i=0; i<size; i++)
212
      {
213
        index =(i+random)%size;
214
        db = (DBConnection) connectionPool.elementAt(index);
215
        logMetacat.debug("Index: "+index);
216
        logMetacat.debug("Tag: "+db.getTag());
217
        logMetacat.debug("Status: "+db.getStatus());
218
        //check if the connection is free
219
        if (db.getStatus()==FREE)
220
        {
221
          //If this connection is good, return this DBConnection
222
          if (validateDBConnection(db))
223
          {
224
            
225
            //set this DBConnection status
226
            db.setStatus(BUSY);
227
            //increase checkout serial number
228
            db.increaseCheckOutSerialNumber(1);
229
            //increase one usageCount
230
            db.increaseUsageCount(1);
231
            //set method name to DBConnection
232
            db.setCheckOutMethodName(methodName);
233
            db.setAutoCommit(true);
234
            //debug message
235
            logMetacat.debug("The connection is checked out: "
236
                                       +db.getTag());
237
            logMetacat.debug("The method for checking is: " 
238
                                              +db.getCheckOutMethodName());
239
            logMetacat.debug("The age is "+db.getAge());
240
            logMetacat.debug("The usage is "+db.getUsageCount());
241
            logMetacat.debug("The conection time it has: "
242
                                                +db.getConnectionTime());
243
            //set check out time
244
            db.setCheckOutTime(System.currentTimeMillis());
245
            // set count of reach maximum 0 because it can check out
246
            countOfReachMaximum =0;
247
            return db;
248
          }//if
249
          else//The DBConnection has some problem
250
          {
251
            //close this DBConnection
252
            db.close();
253
            //remove it form connection pool
254
            connectionPool.remove(index);
255
            //insert a new DBConnection to same palace
256
            db = new DBConnection();
257
            connectionPool.insertElementAt(db, index);
258
          }//else
259
        }//if
260
      }//for
261
    }//for
262
    
263
    //if couldn't get a connection, we should increase DBConnection pool
264
    //if the connection pool size is less than maximum connection number
265
   
266
    if ( size < MAXIMUMCONNECTIONNUMBER )
267
    {
268
       if ((size+INCREASECONNECTIONNUMBER) < MAXIMUMCONNECTIONNUMBER)
269
       { 
270
         //if we can create INCREASECONNECTIONNUMBER of new DBConnection
271
         //add to connection pool
272
         for ( int i=0; i<INCREASECONNECTIONNUMBER; i++)
273
         {
274
           DBConnection dbConn = new DBConnection();
275
           connectionPool.add(dbConn);
276
         }//for
277
       }//if
278
       else
279
       {
280
         //There is no enough room to increase INCREASECONNECTIONNUMBER 
281
         //we create new DBCoonection to Maximum connection number
282
         for (int i= size+1; i<= MAXIMUMCONNECTIONNUMBER; i++)
283
         {
284
           DBConnection dbConn = new DBConnection();
285
           connectionPool.add(dbConn);
286
         }//for
287
       }//else
288
   
289
    }//if
290
    else
291
    {
292
      /*throw new SQLException("The maximum of " +MAXIMUMCONNECTIONNUMBER + 
293
                            " open db connections is reached." +
294
                            " New db connection to MetaCat" +
295
                            " cannot be established.");*/
296
       logMetacat.fatal("The maximum of " +MAXIMUMCONNECTIONNUMBER + 
297
                            " open db connections is reached." +
298
                            " New db connection to MetaCat" +
299
                            " cannot be established.");
300
       countOfReachMaximum ++;
301
       if (countOfReachMaximum >= 10)
302
       {
303
         countOfReachMaximum =0;
304
         logMetacat.fatal("finally could not get dbconnection");
305
         return null;
306
       }
307
       else
308
       {
309
         //if couldn't get a connection, sleep 20 seconds and try again.
310
         try
311
         {
312
           logMetacat.info("sleep for could not get dbconnection");
313
           Thread.sleep(5000);
314
         }
315
         catch (Exception e)
316
        {
317
           logMetacat.error("Exception in getDBConnection" + e.getMessage());
318
        }
319
      }
320
         
321
      
322
    }//else
323
    
324
    //recursive to get new connection    
325
    return getDBConnection(methodName); 
326
  }//getDBConnection
327

    
328
 
329
  
330
  
331
  /** 
332
   * Method to check if a db connection works fine or not
333
   * Check points include:
334
   * 1. check the usageCount if it is too many
335
   * 2. check the dbconne age if it is too old
336
   * 3. check the connection time if it is too long
337
   * 4. run simple sql query
338
   *
339
   * @param dbConn, the DBConnection object need to check
340
   */
341
  private static boolean validateDBConnection (DBConnection dbConn)
342
  {
343
    
344
    
345
    //Check if the DBConnection usageCount if it is too many
346
    if (dbConn.getUsageCount() >= MAXIMUMUSAGENUMBER )
347
    {
348
      logMetacat.debug("Connection usageCount is too many: "+
349
      dbConn.getUsageCount());
350
      return false;
351
    }
352
    
353
    //Check if the DBConnection has too much connection time
354
    if (dbConn.getConnectionTime() >= MAXIMUMCONNECTIONTIME)
355
    {
356
      logMetacat.debug("Connection has too much connection time: "+
357
      dbConn.getConnectionTime());
358
      return false;
359
    }
360
    
361
    //Check if the DBConnection is too old
362
    if (dbConn.getAge() >=MAXIMUMAGE)
363
    {
364
      logMetacat.debug("Connection is too old: "+dbConn.getAge());
365
      return false;
366
    }
367
    
368
    //Try to run a simple query
369
    try
370
    {
371
      long startTime=System.currentTimeMillis();
372
      DatabaseMetaData metaData = dbConn.getMetaData();
373
      long stopTime=System.currentTimeMillis();
374
      //increase one usagecount
375
      dbConn.increaseUsageCount(1);
376
      //increase connection time
377
      dbConn.setConnectionTime(stopTime-startTime);
378
  
379
    }
380
    catch (Exception e)
381
    {
382
      logMetacat.error("Error in validateDBConnection: "
383
                                +e.getMessage());
384
      return false;
385
    }
386
    
387
    return true;
388
    
389
  }//validateDBConnection()
390
  
391
  /**
392
   * Method to return a connection to DBConnection pool.
393
   * @param conn, the Connection object need to check in
394
   */
395
  public static synchronized void returnDBConnection(DBConnection conn, 
396
                                                              int serialNumber)
397
  {
398
    int index = -1;
399
    DBConnection dbConn = null;
400
  
401
    index = getIndexOfPoolForConnection(conn);
402
    if ( index ==-1 )
403
    {
404
      logMetacat.info("Couldn't find a DBConnection in the pool"
405
                                  +" which have same tag to the returned"
406
                                  +" DBConnetion object");
407
      return;
408
                                  
409
    }//if
410
    else
411
    {
412
      //check the paramter - serialNumber which will be keep in calling method
413
      //if it is as same as the object's checkoutserial number.
414
      //if it is same return it. If it is not same, maybe the connection already
415
      // was returned ealier.
416
      logMetacat.debug("serial number in Connection: "
417
                                      +conn.getCheckOutSerialNumber());
418
      logMetacat.debug("serial number in local: "+serialNumber);
419
      if (conn.getCheckOutSerialNumber() == serialNumber)
420
      {
421
        dbConn = (DBConnection) connectionPool.elementAt(index);
422
        //set status to free
423
        dbConn.setStatus(FREE);
424
        //count connection time
425
        dbConn.setConnectionTime
426
                          (System.currentTimeMillis()-dbConn.getCheckOutTime());
427
                          
428
        //set check out time to 0
429
        dbConn.setCheckOutTime(0);
430
        
431
        logMetacat.debug("Connection: "+dbConn.getTag()+" checked in.");
432
        logMetacat.debug("Connection: "+dbConn.getTag()+"'s status: "
433
                                                    +dbConn.getStatus());
434
                                                                       
435
      }//if
436
      else
437
      {
438
        logMetacat.info("This DBConnection couldn't return");
439
      }//else
440
    }//else
441
   
442
 
443
  }//returnConnection
444
  
445
  /**
446
   * Given a returned DBConnection, try to find the index of DBConnection object
447
   * in dbConnection pool by comparing DBConnection' tag and conn.toString.
448
   * If couldn't find , -1 will be returned.
449
   * @param conn, the connection need to be found
450
   */
451
  private static synchronized int getIndexOfPoolForConnection(DBConnection conn)
452
  {
453
    int index = -1;
454
    String info = null;
455
    //if conn is null return -1 too
456
    if (conn==null)
457
    {
458
      return -1;
459
    }
460
    //get tag of this returned DBConnection
461
    info = conn.getTag();
462
    //if the tag is null or empty, -1 will be returned
463
    if (info==null || info.equals(""))
464
    {
465
      return index;
466
    }
467
    //compare this info to the tag of every DBConnection in the pool
468
    for ( int i=0; i< connectionPool.size(); i++)
469
    {
470
      DBConnection dbConn = (DBConnection) connectionPool.elementAt(i);
471
      if (info.equals(dbConn.getTag()))
472
      {
473
        index = i;
474
        break;
475
      }//if
476
    }//for
477
    
478
    return index;
479
  }//getIndexOfPoolForConnection  
480
  
481
  /**
482
   * Method to shut down all connections
483
   */
484
  public static void release()
485
  {
486
    
487
    //shut down the backgroud recycle thread
488
    if (DBCONNECTIONRECYCLETHREAD.equals("on"))
489
    {
490
      runner.interrupt();
491
    }
492
    //cose every dbconnection in the pool
493
    synchronized(connectionPool)
494
    {
495
      for (int i=0;i<connectionPool.size();i++)
496
      {
497
        try
498
        {
499
          DBConnection dbConn= (DBConnection) connectionPool.elementAt(i);
500
          dbConn.close();
501
        }//try
502
        catch (SQLException e)
503
        {
504
          logMetacat.error("Error in release connection: "
505
                                            +e.getMessage());
506
        }//catch
507
      }//for
508
    }//synchronized
509
  }//release()
510
  
511
  /**
512
   * periodically to recycle the connection
513
   */
514
  public void run()
515
  {
516
    DBConnection dbConn = null;
517
    //keep the thread running
518
    while (true)
519
    {
520
      //check every dbconnection in the pool
521
      synchronized(connectionPool)
522
      {
523
        for (int i=0; i<connectionPool.size(); i++)
524
        {
525
          dbConn = (DBConnection) connectionPool.elementAt(i);
526
          
527
          //if a DBConnection conncectioning time for one check out is greater 
528
          //than 30000 milliseconds print it out
529
          if (dbConn.getStatus()==BUSY && 
530
            (System.currentTimeMillis()-dbConn.getCheckOutTime())>=30000)
531
          {
532
            logMetacat.fatal("This DBConnection is checked out for: "
533
            +(System.currentTimeMillis()-dbConn.getCheckOutTime())/1000
534
            +" secs");
535
            logMetacat.fatal(dbConn.getTag());
536
            logMetacat.error("method: "
537
                                          +dbConn.getCheckOutMethodName());
538
            
539
          }
540
          
541
          //check the validation of free connection in the pool
542
          if (dbConn.getStatus() == FREE)
543
          {
544
            try
545
            {
546
              //try to print out the warning message for every connection
547
              if (dbConn.getWarningMessage()!=null)
548
              {
549
                logMetacat.warn("Warning for connection "
550
                  +dbConn.getTag()+" : "+ dbConn.getWarningMessage());
551
              }
552
              //check if it is valiate, if not create new one and replace old one
553
              if (!validateDBConnection(dbConn))
554
              {
555
                logMetacat.debug("Recyle it: "+ dbConn.getTag());
556
                //close this DBConnection
557
                dbConn.close();
558
                //remove it form connection pool
559
                connectionPool.remove(i);
560
                //insert a new DBConnection to same palace
561
                dbConn = new DBConnection();
562
                connectionPool.insertElementAt(dbConn, i);
563
               }//if
564
            }//try
565
            catch (SQLException e)
566
            {
567
              logMetacat.error("Error in DBConnectionPool.run: "
568
                                              +e.getMessage());
569
            }//catch
570
          }//if
571
        }//for
572
      }//synchronize   
573
      //Thread sleep 
574
      try
575
      {
576
        Thread.sleep(CYCLETIMEOFDBCONNECTION);
577
      }
578
      catch (Exception e)
579
      {
580
        logMetacat.error("Error in DBConnectionPool.run: "
581
                                              +e.getMessage());
582
      }
583
    }//while
584
  }//run
585
  
586
  /**
587
   * Method to get the number of free DBConnection in DBConnection pool
588
   */
589
  public static synchronized int getFreeDBConnectionNumber()
590
  {
591
    int numberOfFreeDBConnetion = 0; //return number
592
    DBConnection db = null; //single DBconnection
593
    int poolSize = 0; //size of connection pool
594
    //get the size of DBConnection pool
595
    poolSize = connectionPool.size();
596
    //Check every DBConnection in the pool
597
    for ( int i=0; i<poolSize; i++)
598
    {
599
      
600
      db = (DBConnection) connectionPool.elementAt(i);
601
      //check the status of db. If it is free, count it
602
      if (db.getStatus() == FREE)
603
      {
604
        numberOfFreeDBConnetion++;
605
      }//if
606
    }//for
607
    //return the count result
608
    return numberOfFreeDBConnetion;
609
  }//getFreeDBConnectionNumber
610
      
611
   /**
612
   * Method to print out the method name which have busy DBconnection
613
   */
614
  public void printMethodNameHavingBusyDBConnection()
615
  {
616
    
617
    DBConnection db = null; //single DBconnection
618
    int poolSize = 0; //size of connection pool
619
    //get the size of DBConnection pool
620
    poolSize = connectionPool.size();
621
    //Check every DBConnection in the pool
622
    for ( int i=0; i<poolSize; i++)
623
    {
624
      
625
      db = (DBConnection) connectionPool.elementAt(i);
626
      //check the status of db. If it is free, count it
627
      if (db.getStatus() == BUSY)
628
      {
629
        logMetacat.warn("This method having a busy DBConnection: "
630
                                    +db.getCheckOutMethodName());
631
        logMetacat.warn("The busy DBConnection tag is: "
632
                                    +db.getTag());
633
      }//if
634
    }//for
635
  
636
  }//printMethodNameHavingBusyDBConnection
637
  
638
  /**
639
   * Method to decrease dbconnection pool size when all dbconnections are idle
640
   * If all connections are free and connection pool size greater than 
641
   * initial value, shrink connection pool size to intital value
642
   */
643
  public static synchronized boolean shrinkConnectionPoolSize() 
644
  {
645
     int connectionPoolSize = 0; //store the number of dbconnection pool size
646
     int freeConnectionSize = 0; //store the number of free dbconnection in pool
647
     int difference = 0; // store the difference number between connection size
648
                         // and free connection
649
     boolean hasException = false; //to check if has a exception happend
650
     boolean result = false; //result
651
     DBConnection conn = null; // the dbconnection
652
     connectionPoolSize = connectionPool.size();
653
     freeConnectionSize = getFreeDBConnectionNumber();
654
     difference = connectionPoolSize - freeConnectionSize;
655

    
656
     if(freeConnectionSize < connectionPoolSize){
657
    	 logMetacat.warn(difference + " connection(s) " +
658
                        "being used and connection pool size is " +connectionPoolSize);
659
     } else {
660
    	 logMetacat.info("Connection pool size: " +connectionPoolSize);
661
    	 logMetacat.info("Free Connection number: "+freeConnectionSize);
662
     }
663
     
664
     //If all connections are free and connection pool size greater than 
665
     //initial value, shrink connection pool size to intital value
666
     if (difference == 0 && connectionPoolSize > INITIALCONNECTIONNUMBER)
667
     {
668
       //db connection having index from  to connectionpoolsize -1
669
       //intialConnectionnumber should be close and remove from pool
670
       for ( int i=connectionPoolSize-1; i >= INITIALCONNECTIONNUMBER ; i--)
671
       {
672
        
673
         //get the dbconnection from pool
674
         conn = (DBConnection) connectionPool.elementAt(i);
675
         
676
         try
677
         {
678
           //close conn
679
           conn.close();
680
         }//try
681
         catch (SQLException e)
682
         { 
683
           // set hadException ture
684
           hasException = true;
685
           logMetacat.error("Couldn't close a DBConnection in " +
686
                            "DBConnectionPool.shrinkDBConnectionPoolSize: " +
687
                            e.getMessage());
688
         }//catch
689
                                        
690
        //remove it from pool
691
        connectionPool.remove(i);
692
        // becuase enter the loop, set result true
693
        result = true;
694
       }//for
695
     }//if
696
     
697
     //if hasException is true ( there at least once exception happend)
698
     // the result should be false
699
     if (hasException)
700
     {
701
       result =false;
702
     }//if
703
     // return result
704
     return result;
705
  }//shrinkDBConnectionPoolSize
706
   
707
    /**
708
   * Method to decrease dbconnection pool size when all dbconnections are idle
709
   * If all connections are free and connection pool size greater than 
710
   * initial value, shrink connection pool size to intital value
711
   */
712
  public static synchronized void shrinkDBConnectionPoolSize() 
713
  {
714
     int connectionPoolSize = 0; //store the number of dbconnection pool size
715
     int freeConnectionSize = 0; //store the number of free dbconnection in pool
716
     int difference = 0; // store the difference number between connection size
717
                         // and free connection
718
    
719
     DBConnection conn = null; // the dbconnection
720
     connectionPoolSize = connectionPool.size();
721
     freeConnectionSize = getFreeDBConnectionNumber();
722
     difference = connectionPoolSize - freeConnectionSize;
723

    
724
     if(freeConnectionSize < connectionPoolSize){
725
         logMetacat.warn(difference + " connection(s) " +
726
                        "being used and connection pool size is " +connectionPoolSize);
727
     } else {
728
         logMetacat.info("Connection pool size: " +connectionPoolSize);
729
         logMetacat.info("Free Connection number: "+freeConnectionSize);
730
     }
731
     
732
     //If all connections are free and connection pool size greater than 
733
     //initial value, shrink connection pool size to intital value
734
     if (difference == 0 && connectionPoolSize > INITIALCONNECTIONNUMBER)
735
     {
736
       //db connection having index from  to connectionpoolsize -1
737
       //intialConnectionnumber should be close and remove from pool
738
       for ( int i=connectionPoolSize-1; i >= INITIALCONNECTIONNUMBER ; i--)
739
       {
740
        
741
         //get the dbconnection from pool
742
         conn = (DBConnection) connectionPool.elementAt(i);
743
         //make sure again the DBConnection status is free
744
         if (conn.getStatus()==FREE)
745
         {
746
           try
747
           {
748
             //close conn
749
             conn.close();
750
           }//try
751
           catch (SQLException e)
752
           { 
753
          
754
             logMetacat.error("Couldn't close a DBConnection in " +
755
                            "DBConnectionPool.shrinkDBConnectionPoolSize: " +
756
                            e.getMessage());
757
           }//catch
758
        
759
           //remove it from pool
760
           connectionPool.remove(i);
761
         }//if
762
       
763
       }//for
764
     }//if
765
     
766
    
767
  }//shrinkDBConnectionPoolSize
768
   
769
  
770
}//DBConnectionPool
(19-19/65)