Java tutorial
/* * ConnectionPool.java * * Created on Mar 19, 2009 6:56:40 PM * * Copyright (C) 2009 Jayson Yu * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package com.flexoodb.pool; import java.sql.Connection; import java.sql.SQLException; import java.util.Date; import java.util.Enumeration; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.pool.impl.GenericObjectPool; /** * implemenation for ODBCB connection pooling. * * @author Jayson Yu * @since 1.0 */ public class ConnectionPool implements ConnectionPoolInterface { private GenericObjectPool connections; private int maxconnections, initconnections; private String dbURL, driverClassName, user, password, CTXT; private int timeout; int COLUMN_TYPE = 0; int COLUMN_SIZE = 1; int PRECISION = 2; int SCALE = 3; private boolean _connected = false; private boolean _reconnecting = false; private boolean _autoreturn = false; private ConcurrentHashMap<Connection, Date> _borrowed = null; private Checker _checker = null; public boolean set(String dbURL, String user, String password, String driverClassName, int initialConnections, int maxConnections, String s) throws Exception { return set(dbURL, user, password, driverClassName, initialConnections, maxConnections, s, false); } public boolean set(String dbURL, String user, String password, String driverClassName, int initialConnections, int maxConnections, String s, boolean autoreturn) throws Exception { boolean success = false; try { if (_connected) disconnect(); this.CTXT = s; //Class.forName(driverClassName).newInstance(); this.dbURL = dbURL; this.user = user; this.password = password; this.driverClassName = driverClassName; this.initconnections = initialConnections; this.maxconnections = maxConnections; //connections = new HashedMap(this.initconnections); if (autoreturn) { _borrowed = new ConcurrentHashMap<Connection, Date>(); _autoreturn = true; _checker = new Checker(); (new Thread(_checker)).start(); } // set timeout for 10 seconds. this.timeout = 300000; _connected = true; if (reconnect()) { success = true; } else { throw new Exception( "Error: ConnectionPool could not be started, please check ODBC parameter settings or if the DB is accessible."); } } catch (Exception e) { e.printStackTrace(); } return success; } public boolean attemptset(String dbURL, String user, String password, String driverClassName, int initialConnections, int maxConnections, String name) throws Exception { return attemptset(dbURL, user, password, driverClassName, initialConnections, maxConnections, name, 2, 2); } public boolean attemptset(String dbURL, String user, String password, String driverClassName, int initialConnections, int maxConnections, String name, int tries, int sleep) throws Exception { return attemptset(dbURL, user, password, driverClassName, initialConnections, maxConnections, name, tries, sleep, false); } public boolean attemptset(String dbURL, String user, String password, String driverClassName, int initialConnections, int maxConnections, String name, int tries, int sleep, boolean autoreturn) throws Exception { int i = 0; boolean ok = false; while (!ok && i < tries) { try { ok = set(dbURL, user, password, driverClassName, initialConnections, maxConnections, name, autoreturn); if (!ok) { Thread.sleep(sleep * 1000); } } catch (Exception e) { Thread.sleep(sleep * 1000); } i++; } return ok; } public void disconnect() { try { _connected = false; if (_autoreturn) { _checker.halt(); _borrowed.clear(); } emptyConnections(); connections.close(); connections = null; } catch (Exception e) { e.printStackTrace(); } } public boolean reconnect() { boolean result = false; Connection conn = null; try { if (!_reconnecting) { if (_autoreturn) { _borrowed.clear(); } _reconnecting = true; if (connections != null) { disconnect(); } connections = new GenericObjectPool(new ConnectionPoolFactory(driverClassName.trim(), dbURL.trim(), user.trim(), password.trim())); connections.setTestWhileIdle(true); connections.setTimeBetweenEvictionRunsMillis(600000); // 30 seconds before it checks for evictable objects. connections.setMinEvictableIdleTimeMillis(600000); // connection pool can be idle for 2 minutes connections.setMinIdle(this.initconnections); connections.setMaxActive(this.maxconnections); connections.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL); _connected = true; conn = (Connection) getConnection(); _connected = (conn != null); _reconnecting = false; } else { //_log.warn("Database re-connection already on-going, re-connection ignored."); } } catch (Exception e) { result = false; _reconnecting = false; //_log.error(e); e.printStackTrace(); } finally { if (_connected) { result = true; releaseConnection(conn); } } return result; } private Object getConnection(int counter) throws Exception { Connection con = null; try { con = (Connection) connections.borrowObject(); if ((con == null || con.isClosed()) && counter <= 5) { reconnect(); Thread.sleep(500); con = (Connection) getConnection(++counter); } if (_autoreturn && con != null) { _borrowed.put(con, new Date()); } } catch (Exception e) { if (con == null && counter <= 5) { if (!_autoreturn) { Thread.sleep(500); } else { Thread.sleep(1000); } con = (Connection) getConnection(++counter); } if (counter > 5) { //_log.warn("ran out of DB connections. Maximum active:"+connections.getMaxActive() +", Currently active:"+connections.getNumActive()+", Idle:"+connections.getNumIdle()); } } return con; } public synchronized Object getConnection() throws SQLException { Connection con = null; try { if (_connected) { con = (Connection) getConnection(0); } } catch (Exception e) { e.printStackTrace(); } return con; } public void releaseConnection(Object r) { try { connections.returnObject(r); } catch (Exception e) { e.printStackTrace(); } } private synchronized void emptyConnections() { // finally we clear the connection pool hashtable. if (connections != null) { connections.clear(); } } private class Checker implements Runnable { boolean _ok = true; public Checker() { } public void halt() { _ok = false; } private void check() { try { //System.out.println(con+" "+_autoreturn+" "+_borrowed); if (_borrowed.size() > 0) { Date now = new Date(); Enumeration en = _borrowed.keys(); while (_ok && en.hasMoreElements()) { Connection c = (Connection) en.nextElement(); Date d = _borrowed.get(c); long seconds = (now.getTime() - d.getTime()) / 1000; //System.out.println(c+" "+d+" "+d+" "+seconds); if (seconds > (30 * 1)) // return connections after 30 seconds { _borrowed.remove(c); releaseConnection(c); } } } } catch (Exception f) { } } public void run() { while (_ok) { try { Thread.sleep(5000); check(); } catch (Exception f) { } } } } }