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: jones $'
11
 *     '$Date: 2004-08-23 14:21:45 -0700 (Mon, 23 Aug 2004) $'
12
 * '$Revision: 2250 $'
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
/** 
40
 * A class represent a DBConnection pool. Another user can use the
41
 * object to initial a connection pool, get db connection or return it.
42
 * This a singleton class, this means only one instance of this class could
43
 * be in the program at one time. 
44
 */
45
public class DBConnectionPool implements Runnable
46
{
47

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

    
117

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

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

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

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