001: /**
002: * Copyright (C) 2003 Manfred Andres
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU General Public License
006: * as published by the Free Software Foundation; either version 2
007: * of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: */package freecs.auth.sqlConnectionPool;
018:
019: import java.sql.*;
020: import freecs.Server;
021: import freecs.auth.SQLAuthenticator;
022: import freecs.core.CanceledRequestException;
023: import freecs.core.ConnectionBuffer;
024:
025: public class ConnectionPool {
026:
027: final SQLAuthenticator authenticator;
028: final DbProperties dbProps;
029: final PoolElement pool[];
030: volatile int p = 0, idCnt = 0;
031:
032: /**
033: * Construct a new ConnectionPool for the given authenticator
034: * and the given dbProperties
035: * @param authenticator the authenticator this ConnectionPool will used by.
036: * @param dbProps the dbProperties describing the datastructure
037: */
038: public ConnectionPool(SQLAuthenticator authenticator,
039: DbProperties dbProps) {
040: this .authenticator = authenticator;
041: this .dbProps = dbProps;
042: pool = new PoolElement[dbProps.poolsize];
043: if (Server.TRACE_CREATE_AND_FINALIZE) {
044: Server.log(this ,
045: "++++++++++++++++++++++++++++++++++++++++CREATE",
046: Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
047: }
048: }
049:
050: /**
051: * close every connection to the jdbc-source and remove the PooleElements
052: */
053: public void shutdown() {
054: synchronized (this .pool) {
055: for (int i = 0; i < pool.length; i++) {
056: if (pool[i] == null) {
057: continue;
058: }
059: pool[i].cleanup();
060: pool[i] = null;
061: }
062: }
063: }
064:
065: /**
066: * creates an connectionpool-element
067: * @return the PoolElement connected to the jdbc-datasource
068: * @throws Exception
069: */
070: private PoolElement createPoolElement() throws Exception {
071: idCnt++;
072: if (idCnt == Integer.MAX_VALUE) {
073: idCnt = 0;
074: }
075: Connection con = DriverManager.getConnection(dbProps.url,
076: dbProps.conProps);
077: return new PoolElement(this , con, dbProps, idCnt);
078: }
079:
080: public PoolElement getPoolElement(int retrys, ConnectionBuffer cb)
081: throws Exception {
082: // try [retrys] times to retrieve PoolElement
083: for (int i = 0; i < retrys; i++) {
084: if ((cb != null && !cb.isValid())
085: || Thread.currentThread().isInterrupted())
086: throw new CanceledRequestException(
087: "ConnectionBuffer has been invalidated");
088:
089: PoolElement el = null;
090: try {
091: el = this .getPoolElement(cb);
092: if (el != null) // if el isn't null, return it (it was checked for validity)
093: return el;
094: } catch (CanceledRequestException cre) {
095: throw cre;
096: } catch (Exception e) {
097: Server.debug(Thread.currentThread(), this .toString()
098: + "getPoolElement: ", e, Server.MSG_AUTH,
099: Server.LVL_MAJOR);
100: el = null;
101: }
102: }
103: throw new Exception("Unable to get available PoolElement");
104: }
105:
106: /**
107: * Gets the next available and valid poolelement or tryes to create a new one
108: * @return the valid and available PoolElement
109: * @throws Exception If creation of PoolElement failes
110: */
111: private PoolElement getPoolElement(ConnectionBuffer cb)
112: throws Exception {
113: for (int i = 0; i < dbProps.poolsize; i++) {
114: if ((cb != null && !cb.isValid())
115: || Thread.currentThread().isInterrupted())
116: throw new CanceledRequestException(
117: "ConnectionBuffer has been invalidated");
118: p++;
119: if (p > dbProps.poolsize - 1)
120: p = 0;
121: synchronized (this .pool) {
122: if (pool[p] == null) {
123: pool[p] = createPoolElement();
124: }
125: switch (pool[p].grab()) {
126: case PoolElement.INVALID:
127: pool[p].cleanup();
128: pool[p] = createPoolElement();
129: case PoolElement.IDLE:
130: return pool[p];
131: case PoolElement.ACTIVE:
132: continue;
133: }
134: }
135: }
136: return null;
137: }
138:
139: public int size() {
140: return pool.length;
141: }
142:
143: public void finalize() {
144: if (Server.TRACE_CREATE_AND_FINALIZE)
145: Server
146: .log(
147: this ,
148: "----------------------------------------FINALIZED",
149: Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
150: }
151:
152: private ConnectionPool() throws Exception {
153: throw new Exception("not instatiable without arguments");
154: }
155: }
|