📄 connectionpool.java
字号:
/** * $RCSfile$ * $Revision: 3189 $ * $Date: 2005-12-11 19:38:08 -0800 (Sun, 11 Dec 2005) $ * * Copyright (C) 2004 Jive Software. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution. */package org.jivesoftware.database;import org.jivesoftware.util.ClassUtils;import org.jivesoftware.util.Log;import org.jivesoftware.util.JiveGlobals;import java.io.IOException;import java.sql.*;import java.util.*;/** * Database connection pool. * * @author Jive Software */public class ConnectionPool implements Runnable { private String driver; private String serverURL; private String username; private String password; private int minCon; private int maxCon; private int conTimeout; private boolean mysqlUseUnicode; private Thread houseKeeper; private boolean shutdownStarted = false; private int conCount = 0; private int waitingForCon = 0; private Connection[] cons; private ConnectionWrapper[] wrappers; private Object waitLock = new Object(); private Object conCountLock = new Object(); public ConnectionPool(String driver, String serverURL, String username, String password, int minCon, int maxCon, double conTimeout, boolean mysqlUseUnicode) throws IOException { this.driver = driver; this.serverURL = serverURL; this.username = username; this.password = password; this.minCon = minCon; this.maxCon = maxCon; // Setting the timeout to 3 hours this.conTimeout = (int)(conTimeout * 1000 * 60 * 60 * 3); // convert to milliseconds this.mysqlUseUnicode = mysqlUseUnicode; if (driver == null) { Log.error("JDBC driver value is null."); } try { ClassUtils.forName(driver); DriverManager.getDriver(serverURL); } catch (ClassNotFoundException e) { Log.error("Could not load JDBC driver class: " + driver); } catch (SQLException e) { Log.error("Error starting connection pool.", e); } // Setup pool, open minimum number of connections wrappers = new ConnectionWrapper[maxCon]; cons = new Connection[maxCon]; boolean success = false; int maxTry = 3; for (int i = 0; i < maxTry; i++) { try { for (int j = 0; j < minCon; j++) { createCon(j); conCount++; } success = true; break; } catch (SQLException e) { // close any open connections for (int j = 0; j < minCon; j++) { if (cons[j] != null) { try { cons[j].close(); cons[j] = null; wrappers[j] = null; conCount--; } catch (SQLException e1) { /* ignore */ } } } // let admin know that there was a problem Log.error("Failed to create new connections on startup. " + "Attempt " + i + " of " + maxTry, e); try { Thread.sleep(10000); } catch (InterruptedException e1) { /* ignore */ } } } if (!success) { throw new IOException(); } // Start the background housekeeping thread houseKeeper = new Thread(this); houseKeeper.setDaemon(true); houseKeeper.start(); } public Connection getConnection() throws SQLException { // if we're shutting down, don't create any connections if (shutdownStarted) { return null; } // Check to see if there are any connections available. If not, then enter wait-based // retry loop ConnectionWrapper con = getCon(); if (con != null) { synchronized (con) { con.checkedout = true; con.lockTime = System.currentTimeMillis(); } return con; } else { synchronized (waitLock) { try { waitingForCon++; while (true) { con = getCon(); if (con != null) { --waitingForCon; synchronized (con) { con.checkedout = true; con.lockTime = System.currentTimeMillis(); } return con; } else { waitLock.wait(); } } } catch (InterruptedException ex) { --waitingForCon; waitLock.notifyAll(); throw new SQLException("Interrupted while waiting for connection to " + "become available."); } } } } public void freeConnection() { synchronized (waitLock) { if (waitingForCon > 0) { waitLock.notifyAll(); } } } public void destroy() throws SQLException { // set shutdown flag shutdownStarted = true; // shut down the background housekeeping thread houseKeeper.interrupt(); // wait 1/2 second for housekeeper to die try { houseKeeper.join(500); } catch (InterruptedException e) { /* ignore */ } // check to see if there's any currently open connections to close for (int i = 0; i < conCount; i++) { ConnectionWrapper wrapper = wrappers[i]; // null means that the connection hasn't been initialized, which will only occur // if the current index is greater than the current connection count if (wrapper == null) { break; } // if it's currently checked out, wait 1/2 second then close it anyways if (wrapper.checkedout) { try { Thread.sleep(500); } catch (InterruptedException e) {/* ignore */ } if (wrapper.checkedout) { Log.info("Forcefully closing connection " + i); } } cons[i].close(); cons[i] = null; wrappers[i] = null; } } public int getSize() { return conCount; } /** * Housekeeping thread. This thread runs every 30 seconds and checks connections for the * following conditions:<BR> * <p/> * <ul> * <li>Connection has been open too long - it'll be closed and another connection created. * <li>Connection hasn't been used for 30 seconds and the number of open connections is * greater than the minimum number of connections. The connection will be closed. This * is done so that the pool can shrink back to the minimum number of connections if the * pool isn't being used extensively. * <li>Unable to create a statement with the connection - it'll be reset. * </ul>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -