com.flexoodb.pool.ConnectionPool.java Source code

Java tutorial

Introduction

Here is the source code for com.flexoodb.pool.ConnectionPool.java

Source

/*
 * 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) {
                }
            }
        }
    }

}