📄 connectionpoolimpl.java
字号:
package com.sure.dataabstraction;
import java.sql.*;
import java.util.*;
import java.io.PrintWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
/**
* aggregate JDBC Connection objects implement JDBC Connections pool,it's a
* thread that manager all connection ,client can use getConnection to get a
* database connection and use free or close method to free connection (not
* close connection).
*
*@author Mengzy
*@date 2002-8-16
*/
public class ConnectionPoolImpl extends ConnectionPool implements Runnable {
private Thread runner;
//like a daemon thread to check connection
private boolean runFlag;
//thread run flag
private Connection[] pool;
//aggregate Connections
private int[] connStatus;
//Connection status
private long[] connLockTime;
//Connection locked datetime
private long[] connCreateDate;
//Connection create datetime in ms
private String dbDriver;
private String dbURL;
private String dbUser;
private String dbPassword;
private int currConnCount;
//current Connections count
private int maxConns;
//max Connections in this Pool
private int initConns;
//init Connections size in this Pool
private int maxIdleMSec;
//max Connections idle time in ms
private boolean available;
//flag this Pool is ready
private PrintWriter log;
//log some Exception ro error
private SQLWarning currSQLWarning;
//a Connection's SQLWarning
private boolean debug;
//output debug information
private boolean initFlag;
//init correctly flag
private final static int CN_STATUS_INVALID = 0;
//default value
private final static int CN_STATUS_CLOSED = 1;
//not create
private final static int CN_STATUS_FREE = 2;
//not used
private final static int CN_STATUS_USED = 3;
//used
/**
* Description of the Field
*/
public final static int MAX_USED_TIME = 1000 * 60000;
//max connection used time 60 second
/**
*@param aDatabaseInfo
*@exception DBPoolException Description of the Exception
*/
public ConnectionPoolImpl(DatabaseInfo aDatabaseInfo) throws DBPoolException {
super(aDatabaseInfo);
//get all database infomation for create connection pool
dbDriver = databaseInfo.getDriverName();
dbURL = databaseInfo.getURL();
dbUser = databaseInfo.getUserName();
dbPassword = databaseInfo.getPasswd();
maxConns = databaseInfo.getPoolSize();
initConns = databaseInfo.getInitSize();
maxIdleMSec = (int) databaseInfo.getLifecycle() * 60000;
//a minute in ms
if (maxIdleMSec < 30000) {
maxIdleMSec = 30000;
}
pool = new Connection[maxConns];
//create Connection pool array
connCreateDate = new long[maxConns];
//record a connection created datetime
connLockTime = new long[maxConns];
//record a connection locked datetime
connStatus = new int[maxConns];
//default value is CN_STATUS_CLOSED
currConnCount = 0;
try {
File file = new File(databaseInfo.getLogName());
if (!file.exists()) {
//not exists create it
String path = file.getPath();
path = path.substring(0, path.lastIndexOf(file.getName()));
//get path
new File(path).mkdirs();
file.createNewFile();
}
log = new PrintWriter(new FileWriter(databaseInfo.getLogName(), true), true);
log.println("------------------ " + new java.util.Date() + " -----------------");
} catch (IOException e) {
System.err.println(e.getMessage());
}
//now create init Connection
boolean flag = false;
initFlag = false;
if (initConns > maxConns) {
initConns = maxConns;
}
for (int i = 0; i < initConns; i++) {
//try to 3 times to create connection ,if failed ,throw DBException
for (byte retry = 1; retry <= 3; retry++) {
try {
pool[i] = createConn(i);
flag = true;
currConnCount++;
break;
} catch (SQLException e) {
log.println("Attempt (" + retry + " times of 3 of " + i + ") failed to create new database connections :");
log.println("-------Exception:" + e.getMessage());
try {
Thread.sleep(5 * 1000);
//try again in 5 seconds
} catch (InterruptedException _ie) {}
}
//end of try create connection
}
//end of retry 3 times
}
//end For of create init connection
if (!flag) {
initFlag = false;
log.println(new java.util.Date() + "create init connection faild");
throw new DBPoolException("can not create connection");
} else {
initFlag = true;
}
available = true;
runFlag = true;
runner = new Thread(this);
runner.setDaemon(true);
runner.start();
}
/**
* Description of the Method
*
*@param msg Description of the Parameter
*/
private void debug(String msg) {
if (debug) {
System.out.println(msg);
}
}
/**
* Description of the Method
*
*@param index Description of the Parameter
*@return Description of the Return Value
*@exception SQLException Description of the Exception
*/
private Connection createConn(int index) throws SQLException {
Connection cn = null;
if (index < 0) {
return null;
}
//create connections and put them to pool
try {
java.util.Date date = new java.util.Date();
Class.forName(dbDriver);
cn = DriverManager.getConnection(dbURL, dbUser, dbPassword);
//get Connection
connCreateDate[index] = date.getTime();
//get create datetime stamp
connStatus[index] = CN_STATUS_FREE;
//set connection status is FALSE(not use)
log.println(date.toString() + " : create database connection for index " + index + " successful");
} catch (Exception ce) {
throw new SQLException(ce.getMessage());
}
return cn;
}
//create next Connection return the index of connection pool
/**
* Description of the Method
*
*@return Description of the Return Value
*/
private int createNextConn() {
Connection cn = null;
if (currConnCount > maxConns) {
return -1;
}
try {
//daemon thread close connection ,so we can reuse it
for (int i = 0; i < currConnCount; i++) {
if ((connStatus[i] == CN_STATUS_CLOSED) || (connStatus[i] == CN_STATUS_INVALID)) {
debug("create next of " + i);
cn = createConn(i);
pool[i] = cn;
return i;
}
}
//no closed or invalid connection must create a next conntcion
cn = createConn(currConnCount);
pool[currConnCount] = cn;
currConnCount++;
return currConnCount - 1;
} catch (SQLException e) {
log.println("can not create connection Exception:" + e.getMessage());
return -1;
}
}
/**
* Sets the debug attribute of the MWConnectionPoolImpl object
*
*@param de The new debug value
*/
public void setDebug(boolean de) {
debug = de;
}
/**
*/
public void run() {
//System.out.println("Thread is Run");
while (runFlag) {
for (int i = 0; i < currConnCount; i++) {
//check closed
if ((connStatus[i] == CN_STATUS_CLOSED) || (connStatus[i] == CN_STATUS_INVALID)) {
continue;
}
// if closed next connection
//check null
if (pool[i] == null) {
try {
synchronized (this) {
debug("null create");
pool[i] = createConn(i);
}
} catch (SQLException e1) {}
continue;
//next connection
}
//clear SQLWarning
try {
currSQLWarning = pool[i].getWarnings();
if (currSQLWarning != null) {
log.println("SQLWarnings ( " + i + " ) : " + currSQLWarning);
pool[i].clearWarnings();
}
} catch (SQLException e2) {}
//check connection open status
try {
if ((connStatus[i] == CN_STATUS_FREE) && (pool[i].isClosed())) {
//connection close ,so recreate it
synchronized (this) {
debug("close create");
log.println(new java.util.Date() + " : connection of " + i + " was recreated");
pool[i] = createConn(i);
}
}
} catch (SQLException e3) {}
//check use time
try {
if ((connStatus[i] == CN_STATUS_USED) &&
(System.currentTimeMillis() - connLockTime[i] > MAX_USED_TIME)) {
debug("use time create");
pool[i].close();
synchronized (this) {
pool[i] = createConn(i);
}
}
} catch (SQLException e4) {}
//check connection idle time
try {
if ((connStatus[i] == CN_STATUS_FREE) &&
(getAvailableCount() > initConns) &&
((System.currentTimeMillis() - connLockTime[i]) > maxIdleMSec)) {
//close connection and set null
synchronized (connStatus) {
pool[i].close();
pool[i] = null;
connStatus[i] = CN_STATUS_CLOSED;
log.println("Recycle connection ( " + i + " )");
}
}
} catch (SQLException e5) {}
}
// end of for
try {
Thread.sleep(500);
}
//sleep 500 ms
catch (InterruptedException ee) {}
}
// end of while
}
/**
*@return Connection
*@exception DBPoolException
*@roseuid 3BF1CE1E0268
*/
public Connection getConnection() throws DBPoolException {
if (!initFlag) {
throw new DBPoolException("Connection pool do not init correctly, please check Connection Pool error log");
}
Connection cn = null;
boolean flag = false;
if (!available) {
throw new DBPoolException("can not getConnection while destory()");
}
//check opened connection
synchronized (connStatus) {
if (getUsedCount() < getAvailableCount()) {
for (int i = 0; i < currConnCount; i++) {
if (connStatus[i] == CN_STATUS_FREE) {
cn = pool[i];
debug("get connection of " + i);
try {
if (cn.isClosed()) {
//this Connection was closed ,so must create a new instance
debug("UsedCount < AvailableCount Close : Create");
pool[i] = createConn(i);
cn = pool[i];
}
} catch (SQLException e) {
System.out.println("getConnectino Exception:" + e.getMessage());
}
//get connection so must set flag
connStatus[i] = CN_STATUS_USED;
connLockTime[i] = System.currentTimeMillis();
flag = true;
break;
//now get it ( a Connection so break )
}
}
}
}
//end of synchronized (connStatus)
if (flag) {
return new ConnectionWrapper(cn, this);
}
//no free connection
if (getAvailableCount() < maxConns) {
// all exists connection was used so must create new connection (not exceed maxConn)
synchronized (this) {
System.out.println("Create next connection");
int index = createNextConn();
if (index != -1) {
cn = pool[index];
connStatus[index] = CN_STATUS_USED;
connLockTime[index] = System.currentTimeMillis();
flag = true;
} else {
//create faild set flag = close
connStatus[index] = CN_STATUS_CLOSED;
}
}
//end of synchronized(this)
} else {
//currConnCount >= maxConns
//because all connection was used ,so must wait client free connection
int retry = 0;
while (getUsedCount() >= getAvailableCount()) {
//just wait 200 ms
try {
Thread.sleep(200);
retry++;
} catch (InterruptedException _ex) {}
if (retry >= 50) {
//10 seconds
throw new DBPoolException("all connection is busy, please try again");
}
}
//end of while
//now one connection was freed ,so can get it from pool
//lock connStatus
synchronized (connStatus) {
for (int i = 0; i < currConnCount; i++) {
if (connStatus[i] == CN_STATUS_FREE) {
cn = pool[i];
try {
if (cn.isClosed()) {
//this Connection was closed ,so must create a new instance
pool[i] = createConn(i);
cn = pool[i];
}
} catch (SQLException e) {}
connLockTime[i] = System.currentTimeMillis();
connStatus[i] = CN_STATUS_USED;
flag = true;
break;
//get a connection so break
}
}
//end of for
}
//end of synchronized (connStatus)
}
//end of else currConnCount >= maxConns
if (flag) {
return new ConnectionWrapper(cn, this);
}
throw new DBPoolException("can not get a connection ,please check your database's status");
}
/**
*/
public void destroy() {
available = false;
runFlag = false;
runner.interrupt();
try {
runner.join(1000 * 10);
//wait 10 seconds thread will die
} catch (InterruptedException _ex) {}
//just wait all connection pull back to pool
for (long l = System.currentTimeMillis();
(getUsedCount() > 0) && (System.currentTimeMillis() - l <= 1000 * 10); ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -