Revision 1092
Added by Jing Tao over 22 years ago
src/edu/ucsb/nceas/metacat/DBConnectionPool.java | ||
---|---|---|
42 | 42 |
* This a singleton class, this means only one instance of this class could |
43 | 43 |
* be in the program at one time. |
44 | 44 |
*/ |
45 |
public class DBConnectionPool |
|
45 |
public class DBConnectionPool implements Runnable
|
|
46 | 46 |
{ |
47 | 47 |
|
48 | 48 |
//static attributes |
49 | 49 |
private static DBConnectionPool instance; |
50 | 50 |
private static Vector connectionPool; |
51 |
private static Thread runner; |
|
51 | 52 |
|
52 | 53 |
//maximum connection number in the connection pool |
53 | 54 |
final static int MAXIMUMCONNECTIONNUMBER= |
54 | 55 |
Integer.parseInt(MetaCatUtil.getOption("maximumConnections")); |
56 |
|
|
55 | 57 |
//inintila connection number int the connection pool |
56 | 58 |
final static int INITIALCONNECTIONNUMBER= |
57 | 59 |
Integer.parseInt(MetaCatUtil.getOption("initialConnections")); |
60 |
|
|
58 | 61 |
//the number to increase connection pool size |
59 | 62 |
final static int INCREASECONNECTIONNUMBER= |
60 | 63 |
Integer.parseInt(MetaCatUtil.getOption("incrementConnections")); |
64 |
|
|
61 | 65 |
//maximum age for a connection (in milli seconds) |
62 | 66 |
final static long MAXIMUMAGE = |
63 | 67 |
Long.parseLong(MetaCatUtil.getOption("maximumConnectionAge")); |
... | ... | |
75 | 79 |
* Returns the single instance, creating one if it's the |
76 | 80 |
* first time this method is called. |
77 | 81 |
*/ |
78 |
static synchronized public DBConnectionPool getInstance()
|
|
82 |
public static synchronized DBConnectionPool getInstance()
|
|
79 | 83 |
throws SQLException |
80 | 84 |
{ |
85 |
MetaCatUtil.debugMessage |
|
86 |
("MaximumConnectionNumber: "+MAXIMUMCONNECTIONNUMBER, 49); |
|
87 |
MetaCatUtil.debugMessage |
|
88 |
("Intial connection number: "+INITIALCONNECTIONNUMBER, 49); |
|
89 |
MetaCatUtil.debugMessage |
|
90 |
("Increated connection Number: "+INCREASECONNECTIONNUMBER, 49); |
|
91 |
MetaCatUtil.debugMessage |
|
92 |
("Maximum connection age: "+MAXIMUMAGE, 49); |
|
93 |
MetaCatUtil.debugMessage |
|
94 |
("Maximum connection time: "+MAXIMUMCONNECTIONTIME, 49); |
|
95 |
MetaCatUtil.debugMessage |
|
96 |
("Maximum usage count: "+MAXIMUMUSAGENUMBER, 49); |
|
81 | 97 |
if (instance == null) |
82 | 98 |
{ |
83 | 99 |
instance = new DBConnectionPool(); |
... | ... | |
85 | 101 |
return instance; |
86 | 102 |
}//getInstance |
87 | 103 |
|
104 |
|
|
88 | 105 |
/** |
89 |
* Method to get the size of DBConnectionPool |
|
90 |
*/ |
|
91 |
public int getSizeOfDBConnectionPool() |
|
92 |
{ |
|
93 |
return connectionPool.size(); |
|
94 |
} |
|
95 |
|
|
96 |
/** |
|
97 | 106 |
* This is a private constructor since it is singleton |
98 | 107 |
*/ |
99 | 108 |
|
100 | 109 |
private DBConnectionPool() throws SQLException |
101 | 110 |
{ |
102 |
|
|
111 |
connectionPool = new Vector(); |
|
103 | 112 |
initialDBConnectionPool(); |
113 |
//running the thread to recycle DBConnection |
|
114 |
runner = new Thread(this); |
|
115 |
runner.start(); |
|
104 | 116 |
}//DBConnection |
117 |
|
|
118 |
/** |
|
119 |
* Method to get the size of DBConnectionPool |
|
120 |
*/ |
|
121 |
public int getSizeOfDBConnectionPool() |
|
122 |
{ |
|
123 |
return connectionPool.size(); |
|
124 |
} |
|
105 | 125 |
|
126 |
|
|
106 | 127 |
/** |
107 | 128 |
* Method to initial a pool of DBConnection objects |
108 | 129 |
*/ |
109 |
private Vector initialDBConnectionPool() throws SQLException
|
|
110 |
{ |
|
130 |
private void initialDBConnectionPool() throws SQLException
|
|
131 |
{
|
|
111 | 132 |
|
112 | 133 |
DBConnection dbConn = null; |
113 | 134 |
|
... | ... | |
121 | 142 |
connectionPool.add(dbConn); |
122 | 143 |
} |
123 | 144 |
|
124 |
return connectionPool; |
|
125 |
} |
|
126 | 145 |
|
146 |
}//initialDBConnectionPool |
|
147 |
|
|
148 |
/** |
|
149 |
* Method to get Connection object (Not DBConnection) |
|
150 |
*/ |
|
151 |
/*public static Connection getConnection() throws SQLException |
|
152 |
{ |
|
153 |
DBConnection dbConn = null; |
|
154 |
//get a DBConnection |
|
155 |
dbConn = getDBConnection(); |
|
156 |
//get connection object in DBConnection object |
|
157 |
//The following getConnections method is in DBConnection class |
|
158 |
return dbConn.getConnections(); |
|
159 |
}*/ |
|
160 |
|
|
127 | 161 |
|
128 | 162 |
|
129 | 163 |
|
130 | 164 |
/** |
131 | 165 |
* Method to get a DBConnection in connection pool |
166 |
* 1) try to get a DBConnection from DBConnection pool |
|
167 |
* 2) if 1) failed, then check the size of pool. If the size reach the |
|
168 |
* maximum number of connection, throw a exception: couldn't get one |
|
169 |
* 3) If the size is less than the maximum number of connectio, create some |
|
170 |
* new connections and recursive get one |
|
132 | 171 |
*/ |
133 |
public static DBConnection getDBConnection() throws SQLException |
|
172 |
public static synchronized DBConnection getDBConnection() throws SQLException
|
|
134 | 173 |
{ |
135 |
DBConnection db = null; |
|
174 |
DBConnection db = null; |
|
175 |
MetaCatUtil.debugMessage("Try to checking out connection...", 10); |
|
136 | 176 |
//try every DBConnection in the pool |
137 |
synchronized(connectionPool) |
|
138 |
{ |
|
177 |
|
|
139 | 178 |
for (int i=0; i<connectionPool.size(); i++) |
140 | 179 |
{ |
141 | 180 |
db = (DBConnection) connectionPool.elementAt(i); |
... | ... | |
145 | 184 |
//If this connection is good, return this DBConnection |
146 | 185 |
if (validateDBConnection(db)) |
147 | 186 |
{ |
187 |
|
|
148 | 188 |
//set this DBConnection status |
149 | 189 |
db.setStatus(BUSY); |
190 |
//increase one usageCount |
|
191 |
db.increaseUsageCount(1); |
|
192 |
//debug message |
|
193 |
MetaCatUtil.debugMessage("The connection is checked out: " |
|
194 |
+db.getTag(), 5); |
|
195 |
MetaCatUtil.debugMessage("The age is "+db.getAge(), 5); |
|
196 |
MetaCatUtil.debugMessage("The usage is "+db.getUsageCount(), 5); |
|
197 |
MetaCatUtil.debugMessage("The conection time it has: " |
|
198 |
+db.getConnectionTime(), 5); |
|
150 | 199 |
//set check out time |
151 | 200 |
db.setCheckOutTime(System.currentTimeMillis()); |
152 | 201 |
//check it out |
... | ... | |
164 | 213 |
}//else |
165 | 214 |
}//if |
166 | 215 |
}//for |
167 |
}//sychronize |
|
168 | 216 |
|
217 |
|
|
169 | 218 |
//if couldn't get a connection, we should increase DBConnection pool |
170 | 219 |
//if the connection pool size is less than maximum connection number |
171 | 220 |
int poolSize = connectionPool.size(); |
... | ... | |
245 | 294 |
} |
246 | 295 |
|
247 | 296 |
//Try to run a simple query |
248 |
conn = dbConn.getConnection(); |
|
297 |
conn = dbConn.getConnections();
|
|
249 | 298 |
try |
250 | 299 |
{ |
251 | 300 |
long startTime=System.currentTimeMillis(); |
... | ... | |
268 | 317 |
|
269 | 318 |
}//validateDBConnection() |
270 | 319 |
|
320 |
/** |
|
321 |
* Method to return a connection to DBConnection pool. |
|
322 |
* @param conn, the Connection object need to check in |
|
323 |
*/ |
|
324 |
public static synchronized void returnDBConnection(DBConnection conn) |
|
325 |
{ |
|
326 |
int index = -1; |
|
327 |
DBConnection dbConn = null; |
|
328 |
|
|
329 |
index = getIndexOfPoolForConnection(conn); |
|
330 |
if ( index ==-1 ) |
|
331 |
{ |
|
332 |
MetaCatUtil.debugMessage("Couldn't find a DBConnection in the pool" |
|
333 |
+" which have same tag to the returned" |
|
334 |
+" DBConnetion object"); |
|
335 |
return; |
|
336 |
|
|
337 |
}//if |
|
338 |
else |
|
339 |
{ |
|
340 |
dbConn = (DBConnection) connectionPool.elementAt(index); |
|
341 |
//set status to free |
|
342 |
dbConn.setStatus(FREE); |
|
343 |
//count check out time |
|
344 |
dbConn.setConnectionTime |
|
345 |
(System.currentTimeMillis()-dbConn.getCheckOutTime()); |
|
346 |
MetaCatUtil.debugMessage("Connection: "+dbConn.getTag()+" checked in.", |
|
347 |
5); |
|
348 |
}//else |
|
349 |
|
|
350 |
|
|
351 |
}//returnConnection |
|
352 |
|
|
353 |
/** |
|
354 |
* Given a returned DBConnection, try to find the index of DBConnection object |
|
355 |
* in dbConnection pool by comparing DBConnection' tag and conn.toString. |
|
356 |
* If couldn't find , -1 will be returned. |
|
357 |
* @param conn, the connection need to be found |
|
358 |
*/ |
|
359 |
private static synchronized int getIndexOfPoolForConnection(DBConnection conn) |
|
360 |
{ |
|
361 |
int index = -1; |
|
362 |
String info = null; |
|
363 |
//get tag of this returned DBConnection |
|
364 |
info = conn.getTag(); |
|
365 |
//if the tag is null or empty, -1 will be returned |
|
366 |
if (info==null || info.equals("")) |
|
367 |
{ |
|
368 |
return index; |
|
369 |
} |
|
370 |
//compare this info to the tag of every DBConnection in the pool |
|
371 |
for ( int i=0; i< connectionPool.size(); i++) |
|
372 |
{ |
|
373 |
DBConnection dbConn = (DBConnection) connectionPool.elementAt(i); |
|
374 |
if (info.equals(dbConn.getTag())) |
|
375 |
{ |
|
376 |
index = i; |
|
377 |
break; |
|
378 |
}//if |
|
379 |
}//for |
|
380 |
|
|
381 |
return index; |
|
382 |
}//getIndexOfPoolForConnection |
|
383 |
|
|
384 |
/** |
|
385 |
* Method to shut down all connections |
|
386 |
*/ |
|
387 |
public static void release() |
|
388 |
{ |
|
389 |
|
|
390 |
//shut down the backgroud recycle thread |
|
391 |
runner.interrupt(); |
|
392 |
|
|
393 |
//cose every dbconnection in the pool |
|
394 |
synchronized(connectionPool) |
|
395 |
{ |
|
396 |
for (int i=0;i<connectionPool.size();i++) |
|
397 |
{ |
|
398 |
try |
|
399 |
{ |
|
400 |
DBConnection dbConn= (DBConnection) connectionPool.elementAt(i); |
|
401 |
dbConn.close(); |
|
402 |
}//try |
|
403 |
catch (SQLException e) |
|
404 |
{ |
|
405 |
MetaCatUtil.debugMessage("Error in release connection: " |
|
406 |
+e.getMessage(), 10); |
|
407 |
}//catch |
|
408 |
}//for |
|
409 |
}//synchronized |
|
410 |
}//release() |
|
411 |
|
|
412 |
/** |
|
413 |
* periodically to recycle the connection |
|
414 |
*/ |
|
415 |
public void run() |
|
416 |
{ |
|
417 |
DBConnection dbConn = null; |
|
418 |
//keep the thread running |
|
419 |
while (true) |
|
420 |
{ |
|
421 |
//check every dbconnection in the pool |
|
422 |
synchronized(connectionPool) |
|
423 |
{ |
|
424 |
for (int i=0; i<connectionPool.size(); i++) |
|
425 |
{ |
|
426 |
dbConn = (DBConnection) connectionPool.elementAt(i); |
|
427 |
if (dbConn.getStatus() == FREE) |
|
428 |
{ |
|
429 |
try |
|
430 |
{ |
|
431 |
//try to print out the warning message for every connection |
|
432 |
MetaCatUtil.debugMessage("Warning for connection "+dbConn.getTag() |
|
433 |
+" : "+ dbConn.getWarningMessage(), 5); |
|
434 |
//check if it is valiate, if not create new one and replace old one |
|
435 |
if (!validateDBConnection(dbConn)) |
|
436 |
{ |
|
437 |
//close this DBConnection |
|
438 |
dbConn.close(); |
|
439 |
//remove it form connection pool |
|
440 |
connectionPool.remove(i); |
|
441 |
//insert a new DBConnection to same palace |
|
442 |
dbConn = new DBConnection(); |
|
443 |
connectionPool.insertElementAt(dbConn, i); |
|
444 |
}//if |
|
445 |
}//try |
|
446 |
catch (SQLException e) |
|
447 |
{ |
|
448 |
MetaCatUtil.debugMessage("Error in DBConnectionPool.run: " |
|
449 |
+e.getMessage(), 20); |
|
450 |
}//catch |
|
451 |
}//if |
|
452 |
}//for |
|
453 |
}//synchronize |
|
454 |
//sleep 1200 seconds (20 minutes) |
|
455 |
try |
|
456 |
{ |
|
457 |
Thread.sleep(30000); |
|
458 |
} |
|
459 |
catch (Exception e) |
|
460 |
{ |
|
461 |
MetaCatUtil.debugMessage("Error in DBConnectionPool.run: " |
|
462 |
+e.getMessage(), 20); |
|
463 |
} |
|
464 |
}//while |
|
465 |
}//run |
|
466 |
|
|
271 | 467 |
}//DBConnectionPool |
Also available in: Unified diff
Add some new methods into this class.