KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > slamd > example > SQLSearchRateJobClass


1 /*
2  * Sun Public License
3  *
4  * The contents of this file are subject to the Sun Public License Version
5  * 1.0 (the "License"). You may not use this file except in compliance with
6  * the License. A copy of the License is available at http://www.sun.com/
7  *
8  * The Original Code is the SLAMD Distributed Load Generation Engine.
9  * The Initial Developer of the Original Code is Neil A. Wilson.
10  * Portions created by Neil A. Wilson are Copyright (C) 2004.
11  * Some preexisting portions Copyright (C) 2002-2004 Sun Microsystems, Inc.
12  * All Rights Reserved.
13  *
14  * Contributor(s): Neil A. Wilson
15  */

16 package com.sun.slamd.example;
17
18
19
20 import java.sql.*;
21 import java.util.*;
22 import com.sun.slamd.job.*;
23 import com.sun.slamd.parameter.*;
24 import com.sun.slamd.stat.*;
25
26
27
28
29 /**
30  * This class implements a SLAMD job that can be used to measure the search
31  * performance of an SQL database. It should work with any database for which a
32  * JDBC driver exists.
33  *
34  *
35  * @author Neil A. Wilson
36  */

37 public class SQLSearchRateJobClass
38        extends JobClass
39 {
40   /**
41    * The display name of the stat tracker that counts exceptions caught while
42    * processing queries.
43    */

44   public static final String JavaDoc STAT_TRACKER_EXCEPTIONS_CAUGHT =
45        "Exceptions Caught";
46
47
48
49   /**
50    * The display name of the stat tracker that tracks the rate at which queries
51    * are able to be processed.
52    */

53   public static final String JavaDoc STAT_TRACKER_QUERIES_COMPLETED =
54        "Queries Completed";
55
56
57
58   /**
59    * The display name of the stat tracker that tracks the average length of time
60    * required to process a query.
61    */

62   public static final String JavaDoc STAT_TRACKER_QUERY_DURATION =
63        "Query Duration (ms)";
64
65
66
67   /**
68    * The display name of the stat tracker that tracks the average number of
69    * rows returned from each query.
70    */

71   public static final String JavaDoc STAT_TRACKER_ROWS_RETURNED = "Rows Returned";
72
73
74
75   // The parameter that indicates whether to always disconnect from the DB.
76
BooleanParameter disconnectParameter =
77        new BooleanParameter("disconnect", "Always Disconnect",
78                             "Indicates whether the connection to the " +
79                             "database should be dropped after each query.",
80                             false);
81
82   // The parameter that specifies the cool down time.
83
IntegerParameter coolDownParameter =
84        new IntegerParameter("cool_down", "Cool Down Time (s)",
85                             "Specifies the length of time in seconds before " +
86                             "the job ends that it should stop collecting " +
87                             "statistics.", true, 0, true, 0, false, 0);
88
89   // The parameter that specifies the number of iterations to perform.
90
IntegerParameter iterationsParameter =
91        new IntegerParameter("iterations", "Number of Iterations",
92                             "The number of queries to issue before ending " +
93                             "the job.", false, -1, true, -1, false, 0);
94
95   // The parameter that specifies the time between queries.
96
IntegerParameter timeBetweenQueriesParameter =
97        new IntegerParameter("time_between_queries", "Time Between Queries (ms)",
98                             "Specifies the length of time in milliseconds " +
99                             "that should be allowed between queries. Note " +
100                             "that this time is measured between the " +
101                             "beginning of one query and the beginning of the " +
102                             "next rather than the end of one and the " +
103                             "beginning of the next.", true, 0, true, 0, false,
104                             0);
105
106   // The parameter that specifies the warm up time.
107
IntegerParameter warmUpParameter =
108        new IntegerParameter("warm_up", "Warm Up Time (s)",
109                             "Specifies the length of time in seconds after " +
110                             "the job starts that it should begin collecting " +
111                             "statistics.", true, 0, true, 0, false, 0);
112
113   // The parameter that specifies the password to use to connect to the DB.
114
PasswordParameter passwordParameter =
115        new PasswordParameter("password", "User Password",
116                              "The password for the user account to use to " +
117                              "connect to the database.", false, "");
118
119   // A placeholder used for spacing in the admin interface.
120
PlaceholderParameter placeholder = new PlaceholderParameter();
121
122   // The parameter that specifies the Java class that provides the JDBC driver.
123
StringParameter driverClassParameter =
124        new StringParameter("driver_class", "JDBC Driver Class",
125                            "The fully-qualified Java class that provides " +
126                            "the JDBC interface to the SQL database.", true, "");
127
128   // The parameter that specifies the JDBC URL to connect to the database.
129
StringParameter jdbcURLParameter =
130        new StringParameter("jdbc_url", "JDBC URL",
131                            "The URL that specifies the information to use to " +
132                            "connect to the SQL database.", true, "");
133
134   // The parameter that specifies the SQL query to issue to the database.
135
StringParameter sqlQueryParameter =
136        new StringParameter("sql_query", "SQL Query",
137                            "The SQL statement to use to query the database. " +
138                            "It may optionally include a bracketed pair of " +
139                            "integers separated by a dash (for random access) " +
140                            "or a colon (for sequential access) to alter the " +
141                            "query each time it is issued.", true, "");
142
143   // The parameter that specifies the username to use to connect to the DB.
144
StringParameter userNameParameter =
145        new StringParameter("username", "User Name",
146                            "The username for the account to use to connect " +
147                            "to the database.", false, "");
148
149
150
151   // Variables that correspond to parameter values.
152
static boolean alwaysDisconnect;
153   static boolean useRange;
154   static boolean useSequential;
155   static int coolDownTime;
156   static int iterations;
157   static int rangeMin;
158   static int rangeMax;
159   static int rangeSpan;
160   static int sequentialCounter;
161   static int timeBetweenQueries;
162   static int warmUpTime;
163   static String JavaDoc driverClass;
164   static String JavaDoc jdbcURL;
165   static String JavaDoc sqlQuery;
166   static String JavaDoc userName;
167   static String JavaDoc userPassword;
168   static String JavaDoc variableInitial;
169   static String JavaDoc variableFinal;
170
171
172   // Variables used in generating random numbers.
173
static Random parentRandom;
174   Random random;
175
176
177   // A variable representing the connection to the database.
178
Connection connection;
179
180
181   // Variables used for tracking statistics.
182
IncrementalTracker exceptionsCaught;
183   IncrementalTracker queriesCompleted;
184   IntegerValueTracker rowsReturned;
185   TimeTracker queryTimer;
186
187
188
189   /**
190    * Creates a new instance of this SQL SearchRate job.
191    */

192   public SQLSearchRateJobClass()
193   {
194     super();
195   }
196
197
198
199   /**
200    * Retrieves the display name for this job.
201    *
202    * @return The display name for this job.
203    */

204   public String JavaDoc getJobName()
205   {
206     return "SQL SearchRate";
207   }
208
209
210
211   /**
212    * Retrieves a description for this job.
213    *
214    * @return A description for this job.
215    */

216   public String JavaDoc getJobDescription()
217   {
218     return "This job can be used to repeatedly query an SQL database to " +
219            "generate load and measure performance.";
220   }
221
222
223
224   /**
225    * Retrieves the name of the category in which this job class should be
226    * classified. This is used to arrange the job classes in the administrative
227    * interface.
228    *
229    * @return The name of the category in which this job class should be
230    * classified.
231    */

232   public String JavaDoc getJobCategoryName()
233   {
234     return "SQL";
235   }
236
237
238
239   /**
240    * Retrieves a parameter list that can be used to determine all the
241    * customizeable options that are available for this job.
242    *
243    * @return A parameter list that can be used to determine all the
244    * customizable options that are available for this job.
245    */

246   public ParameterList getParameterStubs()
247   {
248     Parameter[] parameters = new Parameter[]
249     {
250       placeholder,
251       driverClassParameter,
252       jdbcURLParameter,
253       userNameParameter,
254       passwordParameter,
255       sqlQueryParameter,
256       placeholder,
257       warmUpParameter,
258       coolDownParameter,
259       timeBetweenQueriesParameter,
260       iterationsParameter,
261       disconnectParameter
262     };
263
264     return new ParameterList(parameters);
265   }
266
267
268
269   /**
270    * Retrieves the set of stat trackers that will be maintained by this job
271    * class.
272    *
273    * @param clientID The client ID that should be used for the
274    * returned stat trackers.
275    * @param threadID The thread ID that should be used for the
276    * returned stat trackers.
277    * @param collectionInterval The collection interval that should be used for
278    * the returned stat trackers.
279    *
280    * @return The set of stat trackers that will be maintained by this job
281    * class.
282    */

283   public StatTracker[] getStatTrackerStubs(String JavaDoc clientID, String JavaDoc threadID,
284                                            int collectionInterval)
285   {
286     return new StatTracker[]
287     {
288       new IncrementalTracker(clientID, threadID, STAT_TRACKER_QUERIES_COMPLETED,
289                              collectionInterval),
290       new IntegerValueTracker(clientID, threadID, STAT_TRACKER_ROWS_RETURNED,
291                               collectionInterval),
292       new TimeTracker(clientID, threadID, STAT_TRACKER_QUERY_DURATION,
293                       collectionInterval),
294       new IncrementalTracker(clientID, threadID, STAT_TRACKER_EXCEPTIONS_CAUGHT,
295                              collectionInterval)
296     };
297   }
298
299
300
301   /**
302    * Retrieves the set of stat trackers that have been maintained by this job.
303    *
304    * @return The set of stat trackers that have been maintained by this job.
305    */

306   public StatTracker[] getStatTrackers()
307   {
308     return new StatTracker[]
309     {
310       queriesCompleted,
311       queryTimer,
312       rowsReturned,
313       exceptionsCaught
314     };
315   }
316
317
318
319   /**
320    * Indicates whether this job class implements logic that makes it possible to
321    * test the validity of job parameters before scheduling the job for execution
322    * (e.g., to see if the server is reachable using the information provided).
323    *
324    * @return <CODE>true</CODE> if this job provides a means of testing the job
325    * parameters, or <CODE>false</CODE> if not.
326    */

327   public boolean providesParameterTest()
328   {
329     return true;
330   }
331
332
333
334   /**
335    * Provides a means of testing the provided job parameters to determine
336    * whether they are valid (e.g., to see if the server is reachable) before
337    * scheduling the job for execution. This method will be executed by the
338    * SLAMD server system itself and not by any of the clients.
339    *
340    * @param parameters The job parameters to be tested.
341    * @param outputMessages The lines of output that were generated as part of
342    * the testing process. Each line of output should
343    * be added to this list as a separate string, and
344    * empty strings (but not <CODE>null</CODE> values)
345    * are allowed to provide separation between
346    * different messages. No formatting should be
347    * provided for these messages, however, since they
348    * may be displayed in either an HTML or plain text
349    * interface.
350    *
351    * @return <CODE>true</CODE> if the test completed successfully, or
352    * <CODE>false</CODE> if not. Note that even if the test did not
353    * complete successfully, the user will be presented with a warning
354    * but will still be allowed to schedule the job using the provided
355    * parameters. This is necessary because the parameters may still be
356    * valid even if the server couldn't validate them at the time the
357    * job was scheduled (e.g., if the server wasn't running or could not
358    * be reached by the SLAMD server even though it could be by the
359    * clients).
360    */

361   public boolean testJobParameters(ParameterList parameters,
362                                    ArrayList outputMessages)
363   {
364     // Get the necessary parameter values.
365
StringParameter driverParam =
366          parameters.getStringParameter(driverClassParameter.getName());
367     if ((driverParam == null) || (! driverParam.hasValue()))
368     {
369       outputMessages.add("ERROR: No JDBC driver class provided.");
370       return false;
371     }
372     String JavaDoc driverClass = driverParam.getStringValue();
373
374
375     StringParameter urlParam =
376          parameters.getStringParameter(jdbcURLParameter.getName());
377     if ((urlParam == null) || (! urlParam.hasValue()))
378     {
379       outputMessages.add("ERROR: No JDBC URL provided.");
380       return false;
381     }
382     String JavaDoc jdbcURL = urlParam.getStringValue();
383
384
385     String JavaDoc userName = "";
386     StringParameter usernameParam =
387          parameters.getStringParameter(userNameParameter.getName());
388     if ((usernameParam != null) && usernameParam.hasValue())
389     {
390       userName = usernameParam.getStringValue();
391     }
392
393
394     String JavaDoc userPW = "";
395     PasswordParameter pwParam =
396          parameters.getPasswordParameter(passwordParameter.getName());
397     if ((pwParam != null) && pwParam.hasValue())
398     {
399       userPW = pwParam.getStringValue();
400     }
401
402
403     // Try to load the JDBC driver.
404
try
405     {
406       outputMessages.add("Trying to load JDBC driver class '" + driverClass +
407                          "'....");
408       Class.forName(driverClass);
409       outputMessages.add("Driver class loaded successfully.");
410       outputMessages.add("");
411     }
412     catch (Exception JavaDoc e)
413     {
414       outputMessages.add("ERROR: Unable to load driver class: " +
415                          stackTraceToString(e));
416       return false;
417     }
418
419
420     // Try to establish a connection to the database using the JDBC URL,
421
// username, and password.
422
try
423     {
424       outputMessages.add("Trying to connect to database using JDBC URL '" +
425                          jdbcURL + "' as user '" + userName + "'....");
426
427       Connection connection = DriverManager.getConnection(jdbcURL, userName,
428                                                           userPW);
429
430       outputMessages.add("Connected successfully.");
431       outputMessages.add("");
432
433       try
434       {
435         connection.close();
436       } catch (Exception JavaDoc e) {}
437
438       outputMessages.add("Connection closed.");
439       outputMessages.add("");
440     }
441     catch (Exception JavaDoc e)
442     {
443       outputMessages.add("ERROR: Unable to connect: " +
444                          stackTraceToString(e));
445       return false;
446     }
447
448     outputMessages.add("All tests completed.");
449     return true;
450   }
451
452
453
454   /**
455    * Performs one-time client initialization for this job, including assinging
456    * the values of the parameters to instance variables.
457    *
458    * @param clientID The client ID for the current client.
459    * @param parameters The set of parameters that have been defined for this
460    * job.
461    */

462   public void initializeClient(String JavaDoc clientID, ParameterList parameters)
463   {
464     // Get the database driver class.
465
driverClass = null;
466     driverClassParameter =
467          parameters.getStringParameter(driverClassParameter.getName());
468     if (driverClassParameter != null)
469     {
470       driverClass = driverClassParameter.getStringValue();
471     }
472
473     // Get the JDBC URL to use to connect to the database.
474
jdbcURL = null;
475     jdbcURLParameter =
476          parameters.getStringParameter(jdbcURLParameter.getName());
477     if (jdbcURLParameter != null)
478     {
479       jdbcURL = jdbcURLParameter.getStringValue();
480     }
481
482     // Get the username to use to connect to the database.
483
userName = "";
484     userNameParameter =
485          parameters.getStringParameter(userNameParameter.getName());
486     if ((userNameParameter != null) && userNameParameter.hasValue())
487     {
488       userName = userNameParameter.getStringValue();
489     }
490
491     // Get the password to use to connect to the database.
492
userPassword = "";
493     passwordParameter =
494          parameters.getPasswordParameter(passwordParameter.getName());
495     if ((passwordParameter != null) && passwordParameter.hasValue())
496     {
497       userPassword = passwordParameter.getStringValue();
498     }
499
500     // Get the SQL query to issue to the database.
501
sqlQueryParameter =
502          parameters.getStringParameter(sqlQueryParameter.getName());
503     if (sqlQueryParameter != null)
504     {
505       sqlQuery = sqlQueryParameter.getStringValue();
506       useRange = false;
507       useSequential = false;
508
509       int openBracketPos = sqlQuery.indexOf('[');
510       int dashPos = sqlQuery.indexOf('-', openBracketPos);
511       if (dashPos < 0)
512       {
513         dashPos = sqlQuery.indexOf(':', openBracketPos);
514         useSequential = true;
515       }
516
517       int closeBracketPos;
518       if ((openBracketPos >= 0) && (dashPos > 0) &&
519           ((closeBracketPos = sqlQuery.indexOf(']', dashPos)) > 0))
520       {
521         try
522         {
523           rangeMin = Integer.parseInt(sqlQuery.substring(openBracketPos+1,
524                                                          dashPos));
525           rangeMax = Integer.parseInt(sqlQuery.substring(dashPos+1,
526                                                          closeBracketPos));
527           rangeSpan = rangeMax - rangeMin + 1;
528
529           variableInitial = "";
530           int openSpacePos = sqlQuery.lastIndexOf(' ', openBracketPos);
531           if (openSpacePos > 0)
532           {
533             variableInitial = sqlQuery.substring(openSpacePos+1,
534                                                  openBracketPos);
535             if (variableInitial.startsWith("\"") ||
536                 variableInitial.startsWith("'"))
537             {
538               variableInitial = variableInitial.substring(1);
539             }
540           }
541           else
542           {
543             openSpacePos = openBracketPos-1;
544           }
545
546           variableFinal = "";
547           int closeSpacePos = sqlQuery.indexOf(' ', closeBracketPos);
548           int closeParenPos = sqlQuery.indexOf(')', closeBracketPos);
549           if ((closeSpacePos < 0) ||
550               ((closeParenPos > 0) && (closeParenPos < closeSpacePos)))
551           {
552             closeSpacePos = closeParenPos;
553           }
554           if (closeSpacePos > 0)
555           {
556             variableFinal = sqlQuery.substring(closeBracketPos+1,
557                                                closeSpacePos);
558           }
559           else
560           {
561             closeSpacePos = sqlQuery.indexOf(';', closeBracketPos);
562             if (closeSpacePos > 0)
563             {
564               variableFinal = sqlQuery.substring(closeBracketPos+1,
565                                                  closeSpacePos);
566             }
567             else
568             {
569               closeSpacePos = closeBracketPos + 1;
570             }
571           }
572           if (variableFinal.endsWith("\"") || variableFinal.endsWith("'"))
573           {
574             variableFinal = variableFinal.substring(0,
575                                                     variableFinal.length()-1);
576           }
577
578           sqlQuery = sqlQuery.substring(0, openSpacePos+1) + "?" +
579                       sqlQuery.substring(closeSpacePos);
580           useRange = true;
581           sequentialCounter = rangeMin;
582         }
583         catch (Exception JavaDoc e)
584         {
585           useRange = false;
586         }
587       }
588       else
589       {
590         useRange = false;
591       }
592     }
593
594     // Get the warm up time.
595
warmUpTime = 0;
596     warmUpParameter = parameters.getIntegerParameter(warmUpParameter.getName());
597     if (warmUpParameter != null)
598     {
599       warmUpTime = warmUpParameter.getIntValue();
600     }
601
602     // Get the cool down time.
603
coolDownTime = 0;
604     coolDownParameter =
605          parameters.getIntegerParameter(coolDownParameter.getName());
606     if (coolDownParameter != null)
607     {
608       coolDownTime = coolDownParameter.getIntValue();
609     }
610
611     // Get the time between queries.
612
timeBetweenQueries = 0;
613     timeBetweenQueriesParameter =
614          parameters.getIntegerParameter(timeBetweenQueriesParameter.getName());
615     if (timeBetweenQueriesParameter != null)
616     {
617       timeBetweenQueries = timeBetweenQueriesParameter.getIntValue();
618     }
619
620     // Get the number of iterations to perform.
621
iterations = -1;
622     iterationsParameter =
623          parameters.getIntegerParameter(iterationsParameter.getName());
624     if ((iterationsParameter != null) && iterationsParameter.hasValue())
625     {
626       iterations = iterationsParameter.getIntValue();
627     }
628
629     // Determine whether to disconnect after each query.
630
alwaysDisconnect = false;
631     disconnectParameter =
632          parameters.getBooleanParameter(disconnectParameter.getName());
633     if (disconnectParameter != null)
634     {
635       alwaysDisconnect = disconnectParameter.getBooleanValue();
636     }
637
638
639     // Initialize the parent random number generator.
640
parentRandom = new Random();
641   }
642
643
644
645   /**
646    * Performs one-time client initialization for this job, including assinging
647    * the values of the parameters to instance variables.
648    *
649    * @param clientID The client ID for the current client.
650    * @param threadID The thread ID for the current thread.
651    * @param collectionInterval The length of time in seconds to use as the
652    * statistics collection interval.
653    * @param parameters The set of parameters that have been defined
654    * for this job.
655    */

656   public void initializeThread(String JavaDoc clientID, String JavaDoc threadID,
657                                int collectionInterval, ParameterList parameters)
658   {
659     // Initialize the stat trackers.
660
queriesCompleted = new IncrementalTracker(clientID, threadID,
661                                               STAT_TRACKER_QUERIES_COMPLETED,
662                                               collectionInterval);
663     queryTimer = new TimeTracker(clientID, threadID,
664                                  STAT_TRACKER_QUERY_DURATION,
665                                  collectionInterval);
666     rowsReturned = new IntegerValueTracker(clientID, threadID,
667                                            STAT_TRACKER_ROWS_RETURNED,
668                                            collectionInterval);
669     exceptionsCaught = new IncrementalTracker(clientID, threadID,
670                                               STAT_TRACKER_EXCEPTIONS_CAUGHT,
671                                               collectionInterval);
672
673
674     // Enable real-time reporting of the data for these stat trackers.
675
RealTimeStatReporter statReporter = getStatReporter();
676     if (statReporter != null)
677     {
678       String JavaDoc jobID = getJobID();
679       queriesCompleted.enableRealTimeStats(statReporter, jobID);
680       queryTimer.enableRealTimeStats(statReporter, jobID);
681       rowsReturned.enableRealTimeStats(statReporter, jobID);
682       exceptionsCaught.enableRealTimeStats(statReporter, jobID);
683     }
684
685
686     // Initialize the thread-specific random number generator.
687
random = new Random(parentRandom.nextLong());
688   }
689
690
691
692   /**
693    * Perform the work of actually querying the database.
694    */

695   public void runJob()
696   {
697     // First, load the driver class. It will automatically be registered with
698
// the JDBC driver manager.
699
try
700     {
701       Class.forName(driverClass);
702     }
703     catch (Exception JavaDoc e)
704     {
705       logMessage("Unable to load the driver class \"" + driverClass + "\" -- " +
706                  e);
707       indicateStoppedDueToError();
708       return;
709     }
710
711
712     // Determine the range of time for which we should collect statistics.
713
long currentTime = System.currentTimeMillis();
714     boolean collectingStats = false;
715     long startCollectingTime = currentTime + (1000 * warmUpTime);
716     long stopCollectingTime = Long.MAX_VALUE;
717     if ((coolDownTime > 0) && (getShouldStopTime() > 0))
718     {
719       stopCollectingTime = getShouldStopTime() - (1000 * coolDownTime);
720     }
721
722
723     // Set up variables that will be used throughout the job.
724
boolean connected = false;
725     boolean infinite = (iterations <= 0);
726     long queryStartTime = 0;
727     PreparedStatement statement = null;
728     connection = null;
729
730
731     // Loop until it is determined we should stop.
732
for (int i=0; ((! shouldStop()) && ((infinite || (i < iterations)))); i++)
733     {
734       currentTime = System.currentTimeMillis();
735       if ((! collectingStats) && (currentTime >= startCollectingTime) &&
736           (currentTime < stopCollectingTime))
737       {
738         // Tell the stat trackers that they should start tracking now.
739
queriesCompleted.startTracker();
740         queryTimer.startTracker();
741         rowsReturned.startTracker();
742         exceptionsCaught.startTracker();
743         collectingStats = true;
744       }
745       else if (collectingStats && (currentTime >= stopCollectingTime))
746       {
747         // Tell the stat trackers that tehy should stop tracking now.
748
queriesCompleted.stopTracker();
749         queryTimer.stopTracker();
750         rowsReturned.stopTracker();
751         exceptionsCaught.stopTracker();
752         collectingStats = false;
753       }
754
755
756       // If the connection is not currently established, then connect it.
757
if (! connected)
758       {
759         try
760         {
761           connection = DriverManager.getConnection(jdbcURL, userName,
762                                                    userPassword);
763           connected = true;
764         }
765         catch (SQLException se)
766         {
767           logMessage("Unable to connect to the database: " + se);
768           indicateStoppedDueToError();
769           break;
770         }
771
772         try
773         {
774           statement = connection.prepareStatement(sqlQuery);
775         }
776         catch (SQLException se)
777         {
778           logMessage("Unable to parse SQL query \"" + sqlQuery + "\".");
779           indicateStoppedDueToError();
780           break;
781         }
782       }
783
784
785       // Create a counter that will be used to count the number of matching
786
// rows.
787
int matchingRows = 0;
788
789
790       // Execute the query and process through the results.
791
if (timeBetweenQueries > 0)
792       {
793         queryStartTime = System.currentTimeMillis();
794       }
795       if (collectingStats)
796       {
797         queryTimer.startTimer();
798       }
799       try
800       {
801         if (useRange)
802         {
803           statement.setString(1, getQueryVariableComponent());
804         }
805         ResultSet resultSet = statement.executeQuery();
806         while (resultSet.next())
807         {
808           matchingRows++;
809         }
810
811         if (collectingStats)
812         {
813           queryTimer.stopTimer();
814           queriesCompleted.increment();
815           rowsReturned.addValue(matchingRows);
816         }
817       }
818       catch (SQLException se)
819       {
820         writeVerbose("Caught SQL Exception: " + se);
821         if (collectingStats)
822         {
823           exceptionsCaught.increment();
824         }
825       }
826
827
828       // If we should disconnect from the database, then do so.
829
if (alwaysDisconnect)
830       {
831         try
832         {
833           statement.close();
834         } catch (Exception JavaDoc e) {}
835
836         try
837         {
838           connection.close();
839         } catch (Exception JavaDoc e) {}
840         connected = false;
841       }
842
843
844       // If we should sleep before the next query, then do so.
845
if (timeBetweenQueries > 0)
846       {
847         if (! shouldStop())
848         {
849           long now = System.currentTimeMillis();
850           long sleepTime = timeBetweenQueries - (now - queryStartTime);
851           if (sleepTime > 0)
852           {
853             try
854             {
855               Thread.sleep(sleepTime);
856             } catch (InterruptedException JavaDoc ie) {}
857           }
858         }
859       }
860     }
861
862
863     // If the connection is still established, then close it.
864
if (connected)
865     {
866       try
867       {
868         statement.close();
869       } catch (Exception JavaDoc e) {}
870
871       try
872       {
873         connection.close();
874       } catch (Exception JavaDoc e) {}
875     }
876
877     if (collectingStats)
878     {
879       queriesCompleted.stopTracker();
880       queryTimer.stopTracker();
881       rowsReturned.stopTracker();
882       exceptionsCaught.stopTracker();
883     }
884   }
885
886
887
888   /**
889    * Try to force the thread to exit by closing the connection to the database
890    * and setting it to <CODE>null</CODE>.
891    */

892   public void destroy()
893   {
894     if (connection != null)
895     {
896       try
897       {
898         connection.close();
899       } catch (Exception JavaDoc e) {}
900
901       connection = null;
902     }
903   }
904
905
906
907   /**
908    * Retrieves the next value that should be used for the variable portion of
909    * the query.
910    *
911    * @return The next value that should be used for the variable portion of the
912    * query.
913    */

914   public String JavaDoc getQueryVariableComponent()
915   {
916     int value;
917     if (useSequential)
918     {
919       value = sequentialCounter++;
920       if (sequentialCounter > rangeMax)
921       {
922         sequentialCounter = rangeMin;
923       }
924     }
925     else
926     {
927       value = ((random.nextInt() & 0x7FFFFFFF) % rangeSpan) + rangeMin;
928     }
929
930     return variableInitial + value + variableFinal;
931   }
932 }
933
934
Popular Tags