Project

General

Profile

« Previous | Next » 

Revision 5015

Added by daigle over 15 years ago

Create database and shared directories for database management code and shared code respectively.

View differences:

src/edu/ucsb/nceas/shared/AccessException.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: An Exception thrown when an error occurs because an 
4
 *             AccessionNumber was invalid or used incorrectly
5
 *  Copyright: 2008 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Michael Daigle
8
 *
9
 *   '$Author: daigle $'
10
 *     '$Date: 2008-07-06 21:25:34 -0700 (Sun, 06 Jul 2008) $'
11
 * '$Revision: 4080 $'
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.shared;
29

  
30
/**
31
 * Exception thrown when an error occurs in a configuration administrative
32
 * class
33
 */
34
public class AccessException extends BaseException {
35
	
36
	private static final long serialVersionUID = -8436697355629175917L;
37

  
38
	/**
39
	 * Create a new AccessException.
40
	 *
41
	 * @param message The error or warning message.
42
	 */
43
	public AccessException(String message) {
44
		super(message);
45
	}
46
	
47
	public AccessException(String message, BaseException deeperException) {
48
		super(message, deeperException);
49
	}
50
}
51 0

  
src/edu/ucsb/nceas/shared/BaseDAO.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that holds the data from the scheduled_task 
4
 *             table in the database. 
5
 *  Copyright: 2009 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Michael Daigle
8
 * 
9
 *   '$Author: daigle $'
10
 *     '$Date: 2009-03-23 13:56:56 -0800 (Mon, 23 Mar 2009) $'
11
 * '$Revision: 4854 $'
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
package edu.ucsb.nceas.shared;
28

  
29
import java.sql.Timestamp;
30

  
31
public class BaseDAO {
32
	
33
	private Long _id;
34
	private Timestamp _createTime;
35
	private Timestamp _modTime;
36
	private String _status;
37
	
38
	public Long getId() {
39
		return _id;
40
	}
41
	
42
	public void setId(Long id) {
43
		_id = id;
44
	}
45
	
46
	public Timestamp getCreateTime() {
47
		return _createTime;
48
	}
49
	
50
	public void setCreateTime(Timestamp createTime) {
51
		_createTime = createTime;
52
	}
53
	
54
	public Timestamp getModTime() {
55
		return _modTime;
56
	}
57
	
58
	public void setModTime(Timestamp modTime) {
59
		_modTime = modTime;
60
	}
61
	
62
	public String getStatus() {
63
		return _status;
64
	}
65
	
66
	public void setStatus(String status) {
67
		_status = status;
68
	}
69
	
70
}
src/edu/ucsb/nceas/shared/BaseAccess.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that manages database access 
4
 *             information.
5
 *  Copyright: 2009 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Michael Daigle
8
 * 
9
 *   '$Author: daigle $'
10
 *     '$Date: 2009-03-23 13:56:56 -0800 (Mon, 23 Mar 2009) $'
11
 * '$Revision: 4854 $'
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.shared;
29

  
30
import java.sql.ResultSet;
31
import java.sql.SQLException;
32

  
33
import edu.ucsb.nceas.metacat.DBConnection;
34
import edu.ucsb.nceas.metacat.DBConnectionPool;
35

  
36
public abstract class BaseAccess {
37
	
38
	protected DBConnection conn = null;
39
    protected int serialNumber = -1;
40
    protected ResultSet rs = null;
41
	
42
    protected BaseAccess(String methodName) throws AccessException {
43
        //check out DBConnection
44
    	try {
45
    		conn = DBConnectionPool.
46
                	getDBConnection("methodName");
47
    		serialNumber = conn.getCheckOutSerialNumber();
48
    	} catch (SQLException sqle) {
49
    		throw new AccessException("Could not get connection from DB connection pool: " 
50
    				+ sqle.getMessage());
51
    	}
52
    }
53
    
54
    protected abstract BaseDAO populateDAO(ResultSet resultSet) throws SQLException ;
55
}
src/edu/ucsb/nceas/shared/BaseException.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: An Exception thrown when an error occurs because an 
4
 *             AccessionNumber was invalid or used incorrectly
5
 *  Copyright: 2008 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Michael Daigle
8
 *
9
 *   '$Author: daigle $'
10
 *     '$Date: 2008-07-06 21:25:34 -0700 (Sun, 06 Jul 2008) $'
11
 * '$Revision: 4080 $'
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.shared;
29

  
30
/**
31
 * Exception thrown when an error occurs in a configuration administrative
32
 * class
33
 */
34
public class BaseException extends Exception {
35

  
36

  
37
	private static final long serialVersionUID = 1331212806605660813L;
38
	
39
	private static String _coreMessage;
40
	
41
	/**
42
	 * Create a new AccessException.
43
	 *
44
	 * @param message The error or warning message.
45
	 */
46
	public BaseException(String message) {
47
		super(message);
48
		_coreMessage = message;
49
	}
50
	
51
	/**
52
	 * Create a new BaseException.
53
	 *
54
	 * @param message The error or warning message.
55
	 */
56
	public BaseException(String message, BaseException deeperException) {
57
		super(message + " --> " + deeperException.getMessage());
58
		_coreMessage = deeperException.getCoreMessage();
59
	}
60
	
61
	public String getCoreMessage() {
62
		return _coreMessage;
63
	}
64
	
65
	public void setCoreMessage(String coreMessage) {
66
		_coreMessage = coreMessage;
67
	}
68
	
69

  
70

  
71
}
72 0

  
src/edu/ucsb/nceas/metacat/DBConnectionPool.java
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$'
10
 *     '$Date$'
11
 * '$Revision$'
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;
29

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

  
38
import org.apache.log4j.Logger;
39

  
40
import edu.ucsb.nceas.metacat.service.PropertyService;
41
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
42

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

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

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

  
148

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

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

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

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

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

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

  
src/edu/ucsb/nceas/metacat/HandlerException.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: An Exception thrown when an error occurs because an 
4
 *             AccessionNumber was invalid or used incorrectly
5
 *  Copyright: 2008 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Michael Daigle
8
 *
9
 *   '$Author: daigle $'
10
 *     '$Date: 2008-07-06 21:25:34 -0700 (Sun, 06 Jul 2008) $'
11
 * '$Revision: 4080 $'
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;
29

  
30
/**
31
 * Exception thrown when an error occurs in a configuration administrative
32
 * class
33
 */
34
public class HandlerException extends Exception {
35

  
36
	private static final long serialVersionUID = 7997030775672963304L;
37

  
38
	/**
39
	 * Create a new AdminException.
40
	 *
41
	 * @param message The error or warning message.
42
	 */
43
	public HandlerException(String message) {
44
		super(message);
45
	}
46
}
47 0

  
src/edu/ucsb/nceas/metacat/DBConnection.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class represent a connection object, it includes connction 
4
 *    itself, index, status, age and usageCount.
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$'
10
 *     '$Date$'
11
 * '$Revision$'
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;
29

  
30
import java.io.*;
31
import java.sql.*;
32

  
33
import org.apache.log4j.Logger;
34

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

  
38
/**
39
 * A class represent a connection object, it includes connection itself, 
40
 * index, status, age, createtime, connection time, usageCount, warning message
41
 */
42
 
43
public class DBConnection 
44
{
45
  private Connection conn;
46
  private String tag;//to idenify this object
47
  private int status;// free or using
48
  private long age;
49
  private long createTime;
50
  private long connectionTime; //how long it use for connections, 
51
                               //it is accumulated
52
  private long checkOutTime; //the time when check it out
53
  private int usageCount;// how many time the connection was used
54
  private int checkOutSerialNumber; // a number to identify same check out.
55
                                     //for a connection
56
  private SQLWarning warningMessage;
57
  private String checkOutMethodName;
58
  
59
  private static String  DBDriver;
60
  private static String  DBConnectedJDBC;
61
  private static String  userName;
62
  private static String  passWord;
63
  
64
  private static Logger logMetacat = Logger.getLogger(DBConnection.class);
65

  
66
  /**
67
   * Default constructor of the DBConnection class 
68
   * 
69
   */
70
  public DBConnection()  throws SQLException
71
  {
72
	try {
73
		DBDriver = PropertyService.getProperty("database.driver");
74
		DBConnectedJDBC = PropertyService.getProperty("database.connectionURI");
75
		userName = PropertyService.getProperty("database.user");
76
		passWord = PropertyService.getProperty("database.password");
77
	} catch (PropertyNotFoundException pnfe) {
78
		System.err.println("Could not get property in static block: "
79
			+ pnfe.getMessage());
80
	}
81
	  
82
    conn = openConnection();
83
    tag = conn.toString();
84
    status = 0;
85
    age = 0;
86
    createTime = System.currentTimeMillis();
87
    connectionTime = 0;
88
    checkOutTime = 0;
89
    usageCount= 0;
90
    checkOutSerialNumber=0;
91
    warningMessage = null;
92
    checkOutMethodName = null;
93
    
94
  }
95
  
96
 
97
  
98
  /**
99
   * get the  connetion from the object
100
   */
101
  public Connection getConnections()
102
  {
103
    return conn;
104
  }
105
  
106
  /**
107
   * Set a connection to this object
108
   * @param myDBConnection, the connection which will be assign to this object
109
   */
110
  public void setConnections( Connection myConnection)
111
  {
112
    this.conn = myConnection;
113
  }
114

  
115
  /**
116
   * get the db connetion tag from the object
117
   */
118
  public String getTag()
119
  {
120
    return tag;
121
  }
122
  
123
  /**
124
   * Set a connection status to this object
125
   * @param myTag, the tag which will be assign to this object
126
   */
127
  public void setTag(String myTag)
128
  {
129
    this.tag = myTag;
130
  }
131
  
132
  /**
133
   * get the db connetion status from the object
134
   */
135
  public int getStatus()
136
  {
137
    return status;
138
  }
139
  
140
  /**
141
   * Set a connection status to this object
142
   * @param myStatus, the status which will be assign to this object
143
   * 0 is free, 1 is using
144
   */
145
  public void setStatus(int myStatus)
146
  {
147
    this.status = myStatus;
148
  }
149
  
150
  /**
151
   * get the db connetion age from the object
152
   */
153
  public long getAge()
154
  {
155
    return (System.currentTimeMillis() - createTime);
156
  }
157
  
158
 
159
  /**
160
   * Set a connection age to this object
161
   * @param myAge, the Age which will be assign to this object
162
   */
163
  public void setAge(long myAge)
164
  {
165
    this.age = myAge;
166
  }  
167
  
168
  /**
169
   * get the db connetion created time from the object
170
   */
171
  public long getCreateTime()
172
  {
173
    return createTime;
174
  }
175
  
176
  /**
177
   * Set a usage number to this object
178
   * @param myCreateTime, the create time which will be assign to this object
179
   */
180
  public void setCreateTime(long myCreateTime)
181
  {
182
    this.createTime = myCreateTime;
183
  }
184
  
185
  /**
186
   * get the how long db connetion used for the object
187
   */
188
  public long getConnectionTime()
189
  {
190
    return connectionTime;
191
  }
192
  
193
 
194
  /**
195
   * Set a connection time to this object
196
   * It is accumulated
197
   * @param myConnectionTime, the connection time which will assign to
198
   * this object
199
   */
200
  public void setConnectionTime(long myConnectionTime)
201
  {
202
    this.connectionTime = this.connectionTime + myConnectionTime;
203
  }
204
  
205
  /**
206
   * get the when a db connetion was checked out
207
   */
208
  public long getCheckOutTime()
209
  {
210
    return checkOutTime;
211
  }
212
  
213
 
214
  /**
215
   * Set check out time to this object
216
  
217
   * @param myCheckOutTime, the check out time which will assign to
218
   * this object
219
   */
220
  public void setCheckOutTime(long myCheckOutTime)
221
  {
222
    this.checkOutTime = myCheckOutTime;
223
  }
224
  
225
  /**
226
   * get the db connetion usage times from the object
227
   */
228
  public int getUsageCount()
229
  {
230
    return usageCount;
231
  }
232
   
233
 
234
  /**
235
   * Set a usage number to this object
236
   * @param myUsageCount, number of usage which will be assign to this object
237
   */
238
  public void setUsageCount(int myUsageCount)
239
  {
240
    this.usageCount = myUsageCount;
241
  }
242
  
243
  /**
244
   * Increase a usage number to this object
245
   * @param myUsageCount, number of usage which will be add to this object
246
   */
247
  public void increaseUsageCount(int myUsageCount)
248
  {
249
    this.usageCount = this.usageCount + myUsageCount;
250
  }  
251
  
252
  /**
253
   * get the check out serial number
254
   */
255
  public int getCheckOutSerialNumber()
256
  {
257
    return checkOutSerialNumber;
258
  }
259
  
260
 
261
  /**
262
   * Set check out serial number to this object
263
  
264
   * @param myCheckOutSerialNumber, the check out serial number which will 
265
   * assign to this object
266
   */
267
  public void setCheckOutSerialNumber(int myCheckOutSerialNumber)
268
  {
269
    this.checkOutSerialNumber = myCheckOutSerialNumber;
270
  }
271
  
272
  /**
273
   * Increase a usage number to this object
274
   * @param myUsageCount, number of usage which will be add to this object
275
   */
276
  public void increaseCheckOutSerialNumber(int myCheckOutSerialNumber)
277
  {
278
    this.checkOutSerialNumber=this.checkOutSerialNumber+myCheckOutSerialNumber;
279
  }  
280
  
281
  
282
  /**
283
   * get the db connetion waring message from the object
284
   */
285
  public SQLWarning getWarningMessage() throws SQLException
286
  {
287
    //should increase 1 UsageCount
288
    increaseUsageCount(1);
289
    return conn.getWarnings();
290
  }
291
  
292
  /**
293
   * Set a warning message to this object
294
   * @param myWarningMessage, the waring which will be assign to this object
295
   */
296
  public void setWarningMessage(SQLWarning myWarningMessage)
297
  {
298
     this.warningMessage = myWarningMessage;
299
  }
300
  
301
  /**
302
   * get the the name of method checked out the connection from the object
303
   */
304
  public String getCheckOutMethodName()
305
  {
306
    return checkOutMethodName;
307
  }
308
  
309
  /**
310
   * Set a method name to the checkOutMethodName 
311
   * @param myCheckOutMethodName, the name of method will assinged to it
312
   */
313
  public void setCheckOutMethodName(String myCheckOutMethodName)
314
  {
315
     this.checkOutMethodName = myCheckOutMethodName;
316
  }
317
  
318
  /**
319
   * Close a DBConnection object
320
   */
321
  public void close() throws SQLException
322
  {
323
    conn.close();
324
    tag = null;
325
    status = 0;
326
    age = 0;
327
    createTime = System.currentTimeMillis();
328
    connectionTime = 0;
329
    checkOutTime = 0;
330
    usageCount= 0;
331
    warningMessage = null;
332
  }
333
  
334
    /** 
335
   * Method to establish DBConnection 
336
   */
337
  public static Connection openConnection()
338
                  throws SQLException 
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff