Annotation of java/classes/org/w3c/tools/jdbc/ConnectionManager.java, revision 1.5
1.1 bmahe 1: // ConnectionManager.java
1.5 ! ylafon 2: // $Id: ConnectionManager.java,v 1.4 2000/06/16 11:58:45 bmahe Exp $
1.1 bmahe 3: // (c) COPYRIGHT MIT, INRIA and Keio, 2000.
4: // Please first read the full copyright statement in file COPYRIGHT.html
5: package org.w3c.tools.jdbc;
6:
7: import java.sql.SQLException;
8: import java.util.Hashtable;
1.3 bmahe 9: import java.util.Properties;
1.1 bmahe 10:
11: import org.w3c.util.LRUList;
12: import org.w3c.util.SyncLRUList;
1.3 bmahe 13: import org.w3c.util.PropertyMonitoring;
14: import org.w3c.util.ObservableProperties;
1.1 bmahe 15:
16: /**
1.5 ! ylafon 17: * @version $Revision: 1.4 $
1.1 bmahe 18: * @author Beno�t Mah� (bmahe@w3.org)
19: */
1.3 bmahe 20:
21: class ManagerDescription {
22: ConnectionManager manager = null;
23: Properties properties = null;
24:
25: final ConnectionManager getManager() {
26: return manager;
27: }
28:
29: final boolean sameProperties(Properties props) {
30: return props == properties;
31: }
32:
33: ManagerDescription(ConnectionManager manager, Properties props) {
34: this.manager = manager;
35: this.properties = props;
36: }
37: }
38:
39: public class ConnectionManager implements PropertyMonitoring {
1.1 bmahe 40:
1.5 ! ylafon 41: public final static boolean debug = false;
1.1 bmahe 42:
1.4 bmahe 43: protected int conn_count = 0;
44: protected int conn_max = 10;
1.3 bmahe 45:
1.4 bmahe 46: Properties props = null;
1.3 bmahe 47:
48: /**
49: * To keep track of existing managers
50: */
51: private static ManagerDescription managers[] = null;
1.1 bmahe 52:
53: /**
54: * The LRU list of connections.
55: */
56: protected LRUList connectionsLru = null;
57:
58: /**
59: * The cached servers, index is the jdbc URL
60: */
61: protected Hashtable servers = null;
62:
63: /**
1.3 bmahe 64: * PropertyMonitoring implementation.
65: */
1.4 bmahe 66: public boolean propertyChanged(String name) {
67: if (name.equals(Jdbc.MAX_CONNECTIONS_P)) {
68: conn_max = Jdbc.getMaxConn(props);
69: return true;
70: }
71: return false;
1.3 bmahe 72: }
73:
74: /**
1.1 bmahe 75: * Get a connection to the given server.
76: * @param server the jdbc server.
77: * @return a JdbcConnection or null if there is no connection available.
78: */
79: protected JdbcConnection getConnection(JdbcServer server) {
1.4 bmahe 80: JdbcServerState ss = server.getState();
81: JdbcConnection conn = null;
82:
1.1 bmahe 83: while ( true ) {
1.4 bmahe 84: synchronized (this) {
85: while ( true ) {
86: conn = ss.getConnection();
87: if ( conn == null )
88: break;
89: if (debug) {
90: System.out.println("Reusing connection. ");
91: }
92: if (conn.markUsed())
93: return conn;
94: }
95: if (negotiateConnection(server)) {
96: conn = allocateConnection(server);
97: if ( conn.markUsed() ) {
98: return conn;
99: } else {
100: // Failed to establish a fresh connection !
101: return null;
102: }
1.1 bmahe 103: }
104: }
105: // Wait for a connection to become available:
106: try {
1.2 bmahe 107: waitForConnection(server);
1.1 bmahe 108: } catch (InterruptedException ex) {
109: }
110: }
111: }
112:
113: /**
114: * Connections management - Allocate a new connection for this server.
115: * @param server the JdbcServer
116: * @return a newly created connection or null
117: */
118: protected JdbcConnection allocateConnection(JdbcServer server) {
1.4 bmahe 119: if (debug) {
120: System.out.println("Allocating new connection to "+server);
121: }
1.2 bmahe 122: JdbcConnection conn = new JdbcConnection(server);
1.1 bmahe 123: notifyConnection(conn);
124: return conn;
125: }
126:
127: protected boolean negotiateConnection(JdbcServer server) {
1.4 bmahe 128: if (conn_count >= conn_max) {
129: // remove the oldest idle Connection
130: JdbcConnection conn = (JdbcConnection) connectionsLru.removeTail();
131: if (conn == null) { // no idle connection
132: return false;
133: } else {
134: if (debug) {
135: System.out.println("DELETING IDLE CONNECTION!!!");
136: }
137: conn.delete();
138: }
139: }
140: return true;
1.1 bmahe 141: }
142:
143: protected void deleteConnection(JdbcConnection conn) {
144: JdbcServerState ss = conn.getServer().getState();
145: ss.deleteConnection(conn);
146: synchronized(this) {
147: --conn_count;
148: if (debug)
149: System.out.println("+++ delete conn_count: " + conn_count);
150: notify();
151: }
152: }
153:
154: /**
155: * A new connection has just been created.
156: * @param conn the new connection
157: */
158: protected synchronized void notifyConnection(JdbcConnection conn) {
159: ++conn_count;
160: }
161:
162: /**
163: * The given connection is about to be used.
164: * Update our list of available servers.
165: * @param conn The idle connection.
166: */
167: public void notifyUse(JdbcConnection conn) {
168: if (debug)
169: System.out.println("+++ JdbcConnection used");
170: connectionsLru.remove(conn);
171: }
172:
173: /**
174: * The given connection can be reused, but is now idle.
175: * @param conn The connection that is now idle.
176: */
177: public synchronized void notifyIdle(JdbcConnection conn) {
178: if (debug)
179: System.out.println("+++ JdbcConnection idle");
180: connectionsLru.toHead(conn);
181: JdbcServerState ss = conn.getServer().getState();
182: ss.registerConnection(conn);
183: notify();
184: }
185:
186: /**
187: * Wait for a connection to come up.
188: * @param server, the target server.
189: * @exception InterruptedException If interrupted..
190: */
191:
192: protected synchronized void waitForConnection(JdbcServer server)
193: throws InterruptedException
194: {
195: wait();
196: }
197:
1.3 bmahe 198: /**
199: * Get an instance of the Jdbc manager.
200: * This method returns an actual instance of the Jdbc manager. It may
201: * return different managers, if it decides to distribute the load on
202: * different managers (avoid the ConnectionManager being a bottleneck).
203: * @return An application wide instance of the Jdbc manager.
204: */
205:
206: public static synchronized ConnectionManager getManager(Properties p) {
207: if (managers != null) {
208: for (int i = 0 ; i < managers.length ; i++) {
209: if ( managers[i] == null )
210: continue;
211: if ( managers[i].sameProperties(p) ) {
212: return managers[i].getManager();
213: }
214: }
215: }
216: ConnectionManager manager = new ConnectionManager(p);
217: if (managers != null) {
218: ManagerDescription nm[]= new ManagerDescription[managers.length+1];
219: System.arraycopy(managers, 0, nm, 0, managers.length);
220: nm[managers.length] = new ManagerDescription(manager, p);
221: } else {
222: managers = new ManagerDescription[1];
223: managers[0] = new ManagerDescription(manager, p);
224: }
225: return manager;
226: }
227:
228: public static ConnectionManager getManager() {
229: return getManager(System.getProperties());
1.1 bmahe 230: }
231:
1.3 bmahe 232: private ConnectionManager(Properties p) {
1.4 bmahe 233: this.props = p;
1.3 bmahe 234: this.connectionsLru = new SyncLRUList();
235: this.servers = new Hashtable();
1.4 bmahe 236: if (props instanceof ObservableProperties) {
237: ((ObservableProperties) props).registerObserver(this);
1.3 bmahe 238: }
1.4 bmahe 239: int max = Jdbc.getMaxConn(props);
240: this.conn_max = ( max != -1 ? max : this.conn_max);
1.1 bmahe 241: }
242:
243: }
Webmaster