KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > protomatter > jdbc > pool > PoolTest


1 package com.protomatter.jdbc.pool;
2
3 /**
4  * {{{ The Protomatter Software License, Version 1.0
5  * derived from The Apache Software License, Version 1.1
6  *
7  * Copyright (c) 1998-2002 Nate Sammons. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed for the
24  * Protomatter Software Project
25  * (http://protomatter.sourceforge.net/)."
26  * Alternately, this acknowledgment may appear in the software itself,
27  * if and wherever such third-party acknowledgments normally appear.
28  *
29  * 4. The names "Protomatter" and "Protomatter Software Project" must
30  * not be used to endorse or promote products derived from this
31  * software without prior written permission. For written
32  * permission, please contact support@protomatter.com.
33  *
34  * 5. Products derived from this software may not be called "Protomatter",
35  * nor may "Protomatter" appear in their name, without prior written
36  * permission of the Protomatter Software Project
37  * (support@protomatter.com).
38  *
39  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED. IN NO EVENT SHALL THE PROTOMATTER SOFTWARE PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE. }}}
51  */

52
53 import java.io.*;
54 import java.sql.*;
55 import java.util.*;
56
57 import com.protomatter.syslog.*;
58 import com.protomatter.syslog.xml.SyslogXML;
59
60 /**
61  * A standalone connection pool testing application. Here is an
62  * example config file that will hammer a MySQL database:<P>
63  *
64  * <blockquote><pre>
65  * #####################################################
66  * ##
67  * ## Protomatter JDBC Connection Pool test
68  * ## harness config file.
69  * ##
70  *
71  * ##
72  * ## The classname of the underlying JDBC driver that the
73  * ## pool driver will use.
74  * ##
75  * jdbc.driver = org.gjt.mm.mysql.Driver
76  *
77  * ##
78  * ## The URL used to connect the underlying driver to
79  * ## the database.
80  * ##
81  * jdbc.URL = jdbc:mysql://hostname:3306/mysql
82  *
83  * ##
84  * ## Properties for the underlying driver and it's
85  * ## connection. The format is "name=val,name=val,..."
86  * ##
87  * jdbc.properties = user=root,password=secret
88  *
89  * ##
90  * ## A statement to execute. It doesn't matter what it
91  * ## is, it should just not throw an error when executed
92  * ## with Statement.executeQuery(...)
93  * ##
94  * jdbc.statement = select * from user
95  *
96  * ##
97  * ## A statement that is guaranteed to return at least 1
98  * ## row from the database. (for Oracle, this is
99  * ## "select 1 from dual", for Sybase and MySQL it's
100  * ## "select 1")
101  * ##
102  * jdbc.validityCheckStatement = select 1
103  *
104  * ##
105  * ## Number of seconds between pool refreshes by the
106  * ## low priority pool refresh thread.
107  * ##
108  * pool.refreshThreadCheckInterval = 10
109  *
110  * ##
111  * ## Should the refresh operation be verbose?
112  * ##
113  * pool.verboseRefresh = true
114  *
115  * ##
116  * ## Should the pre-checkout validate operation be verbose?
117  * ##
118  * pool.verboseValidate = true
119  *
120  * ##
121  * ## The initial size of the pool
122  * ##
123  * pool.initialSize = 1
124  *
125  * ##
126  * ## The maximum size that the pool should grow to.
127  * ##
128  * pool.maxSize = 5
129  *
130  * ##
131  * ## The time (in milliseconds) to sleep between tries
132  * ## to create multiple connections to the database
133  * ## (some databases can be overwhelmed by trying to
134  * ## open a group of connections too fast)
135  * ##
136  * pool.createWaitTime = 2000
137  *
138  * ##
139  * ## If the pool needs to be grown, this is the number of
140  * ## connections to allocate at a time.
141  * ##
142  * pool.growBlock = 2
143  *
144  * ##
145  * ## Should the pool validate connectione before handing them out?
146  * ##
147  * pool.validateOnCheckout = true
148  *
149  * ##
150  * ## For the test, the min and max times (in milliseconds)
151  * ## to sleep between tries to access the database. A random
152  * ## interval between these times is picked by each thread.
153  * ##
154  * test.minSleepTime = 1000
155  * test.maxSleepTime = 2000
156  *
157  * ##
158  * ## The number of test threads to spawn.
159  * ##
160  * test.numThreads = 10
161  *
162  * ##
163  * ## Number of times each thread should checkout a
164  * ## connection and use it. If this number is -1, the
165  * ## test will run forever. If this is set to something
166  * ## other than -1, when the run is complete, each thread
167  * ## will display statistics about how long it had to
168  * ## wait for connections from the pool.
169  * ##
170  * test.numRuns = -1
171  *
172  * ##
173  * ## If this property is present, Syslog is initialized using
174  * ## the given XML file. If not, a logger is created that writes
175  * ## to standard out.
176  * ##
177  * Syslog.xml = syslog.xml
178  * </pre></blockquote><P>
179  *
180  * Modify this config file or write your own, and then pass it to
181  * <tt>PoolTest</tt> as it's first commandline argument, like this:
182  *
183  * <blockquote><pre>
184  * java com.protomatter.jdbc.pool.PoolTest <i>config.properties</i>
185  * </pre></blockquote>
186  *
187  */

188 public class PoolTest
189 {
190   private Properties props = null;
191
192   public static void main(String JavaDoc args[])
193   {
194     if (args.length != 1)
195     {
196       System.out.println("Usage: com.protomatter.jdbc.pool.PoolTest props");
197       System.exit(0);
198     }
199     try
200     {
201       Properties props = new Properties();
202       props.load(new FileInputStream(new File(args[0])));
203
204       if (props.getProperty("Syslog.xml") != null)
205       {
206           File file = new File(props.getProperty("Syslog.xml"));
207           SyslogXML.configure(file);
208       }
209       else
210       {
211           Syslog.removeAllLoggers();
212           Syslog.setLogMask("DEBUG");
213     
214           BasicLogger l = new PrintWriterLog(new PrintWriter(System.out));
215           SimpleSyslogTextFormatter f = new SimpleSyslogTextFormatter();
216           f.setShowThreadName(true);
217           l.setTextFormatter(f);
218           Syslog.addLogger(l);
219       }
220
221       PoolTest test = new PoolTest(props);
222       test.run();
223     }
224     catch (Throwable JavaDoc x)
225     {
226       x.printStackTrace();
227     }
228   }
229
230   private PoolTest(Properties props)
231   {
232     this.props = props;
233   }
234
235   private void run()
236   {
237     Syslog.info(this, "Test starting");
238
239     Syslog.info(this, "Loading connection pool driver");
240     try
241     {
242       Class.forName("com.protomatter.jdbc.pool.JdbcConnectionPoolDriver")
243         .newInstance();
244     }
245     catch (Exception JavaDoc x)
246     {
247       Syslog.log(this, x);
248       return;
249     }
250
251     Map args = new HashMap();
252
253     String JavaDoc sql = props.getProperty("jdbc.statement");
254
255     args.put("jdbc.driver", props.getProperty("jdbc.driver"));
256     args.put("jdbc.URL", props.getProperty("jdbc.URL"));
257     args.put("jdbc.validityCheckStatement", props.getProperty("jdbc.validityCheckStatement"));
258
259     Properties p = new Properties();
260     StringTokenizer st
261       = new StringTokenizer(props.getProperty("jdbc.properties"), ",");
262     while (st.hasMoreTokens())
263     {
264       StringTokenizer st2 = new StringTokenizer(st.nextToken(), "=");
265       p.put(st2.nextToken(), st2.nextToken());
266     }
267     args.put("jdbc.properties", p);
268
269     args.put("pool.growBlock",
270       new Integer JavaDoc(Integer.parseInt(props.getProperty("pool.growBlock"))));
271     args.put("pool.initialSize",
272       new Integer JavaDoc(Integer.parseInt(props.getProperty("pool.initialSize"))));
273     args.put("pool.maxSize",
274       new Integer JavaDoc(Integer.parseInt(props.getProperty("pool.maxSize"))));
275     args.put("pool.createWaitTime",
276       new Integer JavaDoc(Integer.parseInt(props.getProperty("pool.createWaitTime"))));
277     args.put("pool.refreshThreadCheckInterval",
278       new Integer JavaDoc(Integer.parseInt(props.getProperty("pool.refreshThreadCheckInterval"))));
279     args.put("pool.validateOnCheckout",
280       new Boolean JavaDoc(props.getProperty("pool.validateOnCheckout")));
281
282     if (props.get("pool.verboseRefresh") != null)
283     {
284       args.put("pool.verboseRefresh",
285         new Boolean JavaDoc(props.getProperty("pool.verboseRefresh")));
286     }
287
288     if (props.get("pool.verboseValidate") != null)
289     {
290       args.put("pool.verboseValidate",
291         new Boolean JavaDoc(props.getProperty("pool.verboseValidate")));
292     }
293
294     boolean useMaidThread = false;
295     if (props.get("pool.maxConnectionIdleTime") != null)
296     {
297       args.put("pool.maxConnectionIdleTime",
298         new Integer JavaDoc(Integer.parseInt(
299           props.getProperty("pool.maxConnectionIdleTime"))));
300       useMaidThread = true;
301     }
302     if (props.get("pool.maidThreadCheckInterval") != null)
303     {
304       args.put("pool.maidThreadCheckInterval",
305         new Integer JavaDoc(Integer.parseInt(
306           props.getProperty("pool.maidThreadCheckInterval"))));
307       useMaidThread = true;
308     }
309
310
311     int minSleepTime = Integer.parseInt(props.getProperty("test.minSleepTime"));
312     int maxSleepTime = Integer.parseInt(props.getProperty("test.maxSleepTime"));
313     int numThreads = Integer.parseInt(props.getProperty("test.numThreads"));
314
315     int numRuns = Integer.parseInt(props.getProperty("test.numRuns"));
316
317     JdbcConnectionPool pool = null;
318
319     Syslog.info(this, "Connection pool properties:");
320     Syslog.info(this, " driver = " + props.getProperty("jdbc.driver"));
321     Syslog.info(this, " URL = " + props.getProperty("jdbc.URL"));
322     Syslog.info(this, " properties = " + args.get("jdbc.properties"));
323     Syslog.info(this, " Query = " + sql);
324     Syslog.info(this, " initialSize = " + args.get("pool.initialSize"));
325     Syslog.info(this, " maxSize = " + args.get("pool.maxSize"));
326     Syslog.info(this, " growBlock = " + args.get("pool.growBlock"));
327     Syslog.info(this, " createWaitTime = " + args.get("pool.createWaitTime"));
328     Syslog.info(this, " validateOnCheckout = " + args.get("pool.validateOnCheckout"));
329     Syslog.info(this, " validity stmt = " + args.get("jdbc.validityCheckStatement"));
330     Syslog.info(this, " check interval = " + args.get("pool.refreshThreadCheckInterval"));
331
332     if (useMaidThread)
333     {
334       Syslog.info(this, " Will use the maid thread.");
335       Syslog.info(this, " Will NOT be closing connections ourself.");
336       Syslog.info(this, " Maid thread check interval = " + args.get("pool.maidThreadCheckInterval") + " seconds");
337       Syslog.info(this, " Max connection idle time = " + args.get("pool.maxConnectionIdleTime") + " seconds");
338     }
339     else
340     {
341       Syslog.info(this, " Will NOT use the maid thread.");
342     }
343
344     try
345     {
346       Syslog.info(this, "Creating connection pool");
347       pool = new JdbcConnectionPool("testPool", args);
348     }
349     catch (Exception JavaDoc x)
350     {
351       Syslog.log(this, x);
352       return;
353     }
354
355     PoolMonitorThread pmt = new PoolMonitorThread(pool);
356     pmt.start();
357
358     Syslog.info(this, "Starting " + numThreads + " worker threads");
359     for (int i=0; i<numThreads; i++)
360     {
361       PoolTestThread t = new PoolTestThread(i, sql, minSleepTime, maxSleepTime, numRuns, useMaidThread);
362       t.start();
363     }
364   }
365 }
366
367 /**
368  * A slave thread for the PoolTest application.
369  */

370 class PoolTestThread
371 extends Thread JavaDoc
372 {
373   private String JavaDoc sql = null;
374   private int id = 0;
375   private int minSleepTime;
376   private int maxSleepTime;
377   private Random r = new Random();
378   private int numRuns = 0;
379   private int runs;
380   private boolean useMaidThread = false;
381
382   private long totalWaitTime = 0L;
383
384   public PoolTestThread(int id, String JavaDoc sql, int minSleepTime, int maxSleepTime, int numRuns, boolean useMaidThread)
385   {
386     super();
387     this.id = id;
388     this.sql = sql;
389     this.minSleepTime = minSleepTime;
390     this.maxSleepTime = maxSleepTime;
391     this.numRuns = numRuns;
392     this.useMaidThread = useMaidThread;
393   }
394
395   private int getSleepTime()
396   {
397     float rand = r.nextFloat();
398     int span = (maxSleepTime - minSleepTime);
399     int time = minSleepTime + (int)(rand * span);
400     return time;
401   }
402
403   public void run()
404   {
405     boolean done = false;
406     while (!done)
407     {
408       Connection c = null;
409       Statement s = null;
410       ResultSet r = null;
411       try
412       {
413         long time = System.currentTimeMillis();
414         c = DriverManager.getConnection("jdbc:protomatter:pool:testPool");
415         time = System.currentTimeMillis() - time;
416         totalWaitTime += time;
417         Syslog.info(this, id + ": Waited " + time + "ms for a connection");
418         s = c.createStatement();
419         r = s.executeQuery(sql);
420         if (!r.next())
421         {
422           Syslog.info(this, id + ": ResultSet returned < 1 row");
423         }
424         else
425         {
426           Syslog.info(this, id + ": ResultSet returned >= 1 row");
427         }
428       }
429       catch (Exception JavaDoc x)
430       {
431         Syslog.log(this, id + ": " + x, x, Syslog.ERROR);
432       }
433       finally
434       {
435         if (r != null)
436         {
437           try
438           {
439             r.close();
440           }
441           catch (Exception JavaDoc x)
442           {
443             Syslog.log(this, id + ": " + x, x, Syslog.ERROR);
444           }
445         }
446         if (s != null)
447         {
448           try
449           {
450             s.close();
451           }
452           catch (Exception JavaDoc x)
453           {
454             Syslog.log(this, id + ": " + x, x, Syslog.ERROR);
455           }
456         }
457         if (!useMaidThread)
458         {
459           if (c != null)
460           {
461             try
462             {
463               c.close();
464             }
465             catch (Exception JavaDoc x)
466             {
467               Syslog.log(this, id + ": " + x, x, Syslog.ERROR);
468             }
469           }
470         }
471       }
472       try
473       {
474         Thread.sleep(getSleepTime());
475       }
476       catch (InterruptedException JavaDoc x)
477       {
478         Syslog.log(this, id + ": " + x, x, Syslog.ERROR);
479       }
480
481       ++runs;
482       if (runs == numRuns)
483       {
484         done = true;
485         float averageWaitTime = ((float)totalWaitTime/(float)runs);
486         synchronized(Syslog.class)
487         {
488           Syslog.info(this, id + ": Run results:");
489           Syslog.info(this, id + ": total runs = " + runs);
490           Syslog.info(this, id + ": total wait time = " + totalWaitTime + "ms");
491           Syslog.info(this, id + ": average wait time = " + averageWaitTime + "ms");
492         }
493       }
494     }
495   }
496 }
497
498 /**
499  * A slave thread for the PoolTest application.
500  */

501 class PoolMonitorThread
502 extends Thread JavaDoc
503 {
504   private JdbcConnectionPool pool = null;
505   public PoolMonitorThread(JdbcConnectionPool pool)
506   {
507     super();
508     this.setDaemon(true);
509     this.pool = pool;
510   }
511
512   public void run()
513   {
514     while (true)
515     {
516       try
517       {
518         sleep(1000);
519       }
520       catch (InterruptedException JavaDoc x)
521       {
522         ; // ignore
523
}
524       Syslog.info(this, "############ Connection pool size: inUse=" + pool.getObjectsInUse() + " max=" + pool.getMaxObjectPoolSize() + " avail=" + pool.getObjectPoolSize());
525     }
526   }
527 }
528
Popular Tags