001: /*
002: * @(#) PoolManagerImpl 1.0 02/08/01
003: */
004:
005: package org.smartlib.pool.core;
006:
007: import org.xml.sax.SAXNotRecognizedException;
008: import org.xml.sax.SAXException;
009: import org.apache.log4j.Logger;
010:
011: import java.io.*;
012: import java.util.*;
013: import java.sql.*;
014:
015: /**
016: * This class implements the PoolManager interface.The basic responsibility of
017: * this class is to load the configuration file , and initialise the pools and
018: * priovide a single point access to the pools.
019: *
020: * @author Sachin Shekar Shetty
021: * @version 1.0, 02/08/01
022: *
023: */
024:
025: public class PoolManagerImpl implements PoolManager {
026:
027: private Map poolMap = new HashMap();
028: private String defaultPool;
029: private boolean shutDown = false;
030: private static Logger logger = Logger
031: .getLogger(PoolManagerImpl.class);
032:
033: private void loadConfig(File file) throws ConnectionPoolException {
034:
035: PoolConfig[] config = null;
036: try {
037: config = new ConfigFileProcessor().getPoolConfig(file
038: .getAbsolutePath());
039: } catch (Exception e) {
040: throw new ConnectionPoolException(
041: "Error occurred during loading config file: "
042: + file.getAbsolutePath(), e);
043: }
044:
045: for (int i = 0; i < config.length; i++) {
046: PoolConfig pc = config[i];
047: String poolName = pc.getMultiPoolName();
048: if (logger.isDebugEnabled()) {
049: logger.debug("" + pc);
050: }
051: if (pc.isDefaultPool()) {
052: if (defaultPool != null)
053: throw new ConnectionPoolException(
054: "More than one Connection Pools cannot have default set to 'true'");
055: defaultPool = poolName;
056: }
057: poolMap.put(poolName, new MultiPoolImpl(pc));
058: }
059:
060: }
061:
062: /**
063: * This constructor intialises the SmartPoolClass , reads the
064: * configuration from <code>fileName</code> and loads the PoolManger.
065: *
066: * @param file The absolute configuration file path.
067: * @exception ConnectionPoolException if there is any problem
068: * initialising the pools
069: */
070: public PoolManagerImpl(String fileName)
071: throws ConnectionPoolException {
072:
073: if (fileName == null || fileName.trim().equals(""))
074: throw new IllegalArgumentException(
075: "File Name cannot be null/empty");
076: File f1 = new File(fileName);
077: loadConfig(f1);
078:
079: }
080:
081: /**
082: * This constructor intialises the SmartPoolClass , reads the
083: * configuration from <code>file</code> and loads the PoolManger.
084: *
085: * @param file The configuration file.
086: * @exception ConnectionPoolException if there is any problem
087: * initialising the pools
088: */
089: public PoolManagerImpl(File file) throws ConnectionPoolException {
090:
091: loadConfig(file);
092:
093: }
094:
095: /**
096: * This method returns a Connection from the default connection pool.
097: * The owner of this pool is marked as N/A indicating unknown.
098: *
099: * <b>Note: This method blocks if the pool size has reached it's
100: * maximum size and no free connections are available
101: * until a free connection is available.</b> The time period for which this
102: * method blocks depends on the connection-wait-time-out specified in
103: * the configuration file.
104: *
105: *
106: * @return Connection from the default pool
107: * @exception ConnectionPoolException if there is any problem
108: * getting connection.
109: */
110:
111: public Connection getConnection() throws ConnectionPoolException {
112:
113: if (defaultPool == null)
114: throw new ConnectionPoolException(
115: "No default pool specified");
116: return (getConnection(defaultPool));
117:
118: }
119:
120: /**
121: * This method returns a Connection from the pool <code>poolName</code>.
122: * The owner of this pool is marked as N/A indicating unknown.
123: *
124: * <b>Note: This method blocks if the pool size has reached it's
125: * maximum size and no free connections are available
126: * until a free connection is available.</b> The time period for which this
127: * method blocks depends on the connection-wait-time-out specified in
128: * the configuration file.
129: *
130: *
131: * @param poolName Name of the pool.
132: * @return Connection from the pool
133: * @exception ConnectionPoolException if there is any problem
134: * getting connection.
135: */
136: public Connection getConnection(String poolName)
137: throws ConnectionPoolException {
138:
139: MultiPool p = (MultiPool) poolMap.get(poolName);
140: if (p == null)
141: throw new ConnectionPoolException("No such pool:"
142: + poolName);
143: return p.getConnection();
144:
145: }
146:
147: /**
148: * This method returns a Connection from the pool <code>poolName</code>.
149: * The owner of this connection is identified by <code>owner</code> .
150: *
151: * <b>Note: This method blocks if the pool size has reached it's
152: * maximum size and no free connections are available
153: * until a free connection is available</b>. The time period for which this
154: * method blocks depends on the connection-wait-time-out specified in
155: * the configuration file.
156: *
157: * @param poolName Name of the pool.
158: * @param owner String identifying the owner.
159: * @return Connection from the pool
160: *
161: * @exception ConnectionPoolException if there is any problem
162: * getting connection.
163: */
164: public Connection getConnection(String poolName, String owner)
165: throws ConnectionPoolException {
166:
167: MultiPool p = (MultiPool) poolMap.get(poolName);
168: if (p == null)
169: throw new ConnectionPoolException("No such pool:"
170: + poolName);
171: return p.getConnection(owner);
172:
173: }
174:
175: /**
176: * This method adds a connection leak listener.The methods of
177: * <code>cle</code> will be called when a leak is detected as per the
178: * pool configuration.
179: *
180: * @param poolName Name of the pool.
181: * @param cle Class implementing ConnectionLeakListener interface.
182: * @exception ConnectionPoolException if there is any problem
183: * adding ConnectionLeakListener.
184: */
185: public void addConnectionLeakListener(String poolName,
186: ConnectionLeakListener cle) throws ConnectionPoolException {
187:
188: MultiPool p = (MultiPool) poolMap.get(poolName);
189: if (p == null)
190: throw new ConnectionPoolException("No such pool:"
191: + poolName);
192: p.addConnectionLeakListener(cle);
193:
194: }
195:
196: /**
197: * This method removes a connection leak listener.<code>cle</code> will
198: * not get any further notifications.
199: *
200: * @param poolName Name of the pool.
201: * @param cle Class implementing ConnectionLeakListener interface.
202: * @exception ConnectionPoolException if there is any problem
203: * removing ConnectionLeakListener.
204: */
205: public void removeConnectionLeakListener(String poolName,
206: ConnectionLeakListener cle) throws ConnectionPoolException {
207:
208: MultiPool p = (MultiPool) poolMap.get(poolName);
209: if (p == null)
210: throw new ConnectionPoolException("No such pool:"
211: + poolName);
212: p.removeConnectionLeakListener(cle);
213:
214: }
215:
216: /**
217: * This method returns the instance of PoolMonitor for the pool
218: * <code>poolName</code>
219: *
220: * @param poolName Name of the pool.
221: * @return PoolMonitor interface to monitor the state of the pool
222: * @exception ConnectionPoolException
223: *
224: */
225: public MultiPoolMonitor getMultiPoolMonitor(String poolName)
226: throws ConnectionPoolException {
227:
228: MultiPoolMonitor p = (MultiPoolMonitor) poolMap.get(poolName);
229: if (p == null)
230: throw new ConnectionPoolException("No such pool:"
231: + poolName);
232: return p;
233:
234: }
235:
236: /**
237: * This method shuts down the pool, that is closes all connections to the database,
238: * the pool can no longer be used unless reinitialised using a new SmartPoolFactory instance.
239: */
240: public void shutDown() {
241: shutDown = true;
242: Set set = poolMap.entrySet();
243: for (Iterator it = set.iterator(); it.hasNext();) {
244: Map.Entry entry = (Map.Entry) it.next();
245: if (logger.isDebugEnabled()) {
246: logger.debug("Shutting down: " + entry.getKey());
247: }
248: ((MultiPool) entry.getValue()).shutDown();
249: }
250:
251: }
252:
253: // Main method , once upon a time this used to be the only method in
254: // my java programs. That is how you do procedural programming in java.
255: public static void main(String args[]) throws Exception {
256:
257: int k = 0;
258: Thread arr[] = new Thread[40];
259: try {
260: PoolManagerImpl p1 = new PoolManagerImpl(
261: "c:\\windows\\desktop\\org.smartlib.pool.test.xml");
262: System.exit(0);
263: for (int i = 0; i < 20; i++) {
264:
265: Thread r = new Thread(new ThreadRunner(p1, "Sachin", ""
266: + i, i * 800));
267: arr[k] = r;
268: k++;
269: r.start();
270: r = new Thread(new ThreadRunner(p1, "Shetty", "" + i,
271: i * 800));
272: r.start();
273: arr[k] = r;
274: k++;
275: }
276:
277: } catch (Exception e) {
278: if (logger.isDebugEnabled()) {
279: logger.debug(e, e);
280: }
281: }
282: for (int z = 0; z < k; z++) {
283: System.out.println("Wating ------> for " + z);
284: arr[z].join();
285: }
286: System.out.println("Child threads Finished -->Exiting");
287: }
288:
289: public static class ThreadRunner implements Runnable {
290:
291: PoolManager p1;
292: String poolName;
293: String owner;
294: int sleepTime;
295:
296: public ThreadRunner(PoolManager p1, String poolName,
297: String owner, int sleepTime) {
298:
299: this .p1 = p1;
300: this .poolName = poolName;
301: this .owner = owner;
302: this .sleepTime = sleepTime;
303:
304: }
305:
306: public void run() {
307:
308: try {
309: for (int i = 0; i <= 10; i++) {
310: System.out.println("Thread " + owner + " running");
311: Connection conn = p1.getConnection(poolName);
312: try {
313: Thread.sleep(sleepTime);
314: } catch (InterruptedException ie) {
315: }
316: conn.close();
317: }
318: } catch (Exception e) {
319: e.printStackTrace();
320: }
321:
322: }
323:
324: }
325:
326: }
|