KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.*;
21 import java.security.*;
22 import java.util.*;
23 import netscape.ldap.*;
24 import netscape.ldap.factory.*;
25 import com.sun.slamd.job.*;
26 import com.sun.slamd.parameter.*;
27 import com.sun.slamd.stat.*;
28
29
30
31 /**
32  * This class implements a SLAMD job class that is intended for use in priming
33  * an LDAP directory server. It is very similar to the SearchRate job, but it
34  * is designed specifically for priming, which reads all or a significant part
35  * of the database. Unfortunately, it is necessary to specify the number of
36  * clients to use twice (once for the scheduling info and once as a job
37  * parameter) because otherwise each client does not have any knowledge of the
38  * total number of clients. Note that this job expects the directory entries to
39  * have a sequentially-incrementing counter as a value for one of the attributes
40  * in it (it does not have to be the RDN attribute, but it should be indexed),
41  * so it is unfortunately only feasible to use for contrived data sets.
42  *
43  *
44  * @author Neil A. Wilson
45  */

46 public class LDAPPrimeJobClass
47        extends JobClass
48 {
49   /**
50    * The display name for the stat tracker that will be used to track the time
51    * required to run each search.
52    */

53   public static final String JavaDoc STAT_TRACKER_SEARCH_TIME = "Search Time (ms)";
54
55
56
57   /**
58    * The display name for the stat tracker that will be used to track the number
59    * of entries returned from each search.
60    */

61   public static final String JavaDoc STAT_TRACKER_ENTRY_COUNT = "Entries Returned";
62
63
64
65   /**
66    * The display name for the stat tracker that will be used to track the number
67    * of successful searches.
68    */

69   public static final String JavaDoc STAT_TRACKER_SEARCHES_COMPLETED =
70        "Searches Completed";
71
72
73
74   /**
75    * The display name for the stat tracker that will be used to accumulate the
76    * total number of successful searches.
77    */

78   public static final String JavaDoc STAT_TRACKER_TOTAL_SEARCHES_COMPLETED =
79        "Total Searches Completed";
80
81
82
83   /**
84    * The display name for the stat tracker that will be used to track the number
85    * of exceptions caught.
86    */

87   public static final String JavaDoc STAT_TRACKER_EXCEPTIONS_CAUGHT =
88        "Exceptions Caught";
89
90
91
92   // The parameter that indicates the number of clients to use for the job.
93
IntegerParameter clientsParameter =
94        new IntegerParameter("num_clients", "Number of Clients",
95                             "The number of clients over which the priming " +
96                             "should be distributed", true, 0, true, 1, false,
97                             0);
98
99   // The parameter that indicates the port number for the directory server
100
IntegerParameter portParameter =
101        new IntegerParameter("ldapport", "Directory Server Port",
102                             "The port number for the LDAP directory server",
103                             true, 389, true, 1, true, 65535);
104
105   // The parameter that specifies the starting value for the attribute.
106
IntegerParameter rangeStartParameter =
107        new IntegerParameter("rangestart", "Value Range Start",
108                             "The value that should be used as the start of " +
109                             "the range when priming the job.", true, 0, false,
110                             0, false, 0);
111
112   // The parameter that specifies the ending value for the attribute.
113
IntegerParameter rangeStopParameter =
114        new IntegerParameter("rangestop", "Value Range End",
115                             "The value that should be used as the end of " +
116                             "the range when priming the job.", true, 0, false,
117                             0, false, 0);
118
119   // The parameter that indicates the maximum length of time to wait for results
120
// to a search.
121
IntegerParameter timeLimitParameter =
122        new IntegerParameter("timelimit", "Search Time Limit",
123                             "The maximum length of time to wait for the " +
124                             "result of a search operation (0 to wait forever)",
125                             true, 0, true, 0, false, 0);
126
127   // The placeholder parameter used as a spacer in the admin interface.
128
PlaceholderParameter placeholder = new PlaceholderParameter();
129
130   // The parameter that indicates the search base
131
StringParameter searchBaseParameter =
132        new StringParameter("searchbase", "Search Base",
133                            "The DN of the entry to use as the search base",
134                            false, "");
135
136   // The parameter that specifies the attribute name.
137
StringParameter attributeNameParameter =
138        new StringParameter("attrname", "Attribute Name",
139                            "The name of the LDAP attribute that contains the " +
140                            "sequentially-incrementing value used to prime " +
141                            "the directory", true, "");
142
143   // The parameter that indicates the DN to use when binding to the server
144
StringParameter bindDNParameter =
145        new StringParameter("binddn", "Bind DN",
146                            "The DN to use to bind to the server", false, "");
147
148   // The parameter that indicates the address of the directory server
149
StringParameter hostParameter =
150        new StringParameter("ldaphost", "Directory Server Host",
151                            "The DNS hostname or IP address of the LDAP " +
152                            "directory server", true, "");
153
154   // The parameter that indicates the bind password
155
PasswordParameter bindPWParameter =
156        new PasswordParameter("bindpw", "Bind Password",
157                              "The password for the bind DN", false, "");
158
159
160   // Instance variables that correspond to the parameter values
161
static int ldapPort;
162   static int numClients;
163   static int rangeStart;
164   static int rangeStop;
165   static int timeLimit;
166   static String JavaDoc attributeName;
167   static String JavaDoc searchBase;
168   static String JavaDoc bindDN;
169   static String JavaDoc bindPassword;
170   static String JavaDoc ldapHost;
171
172
173   // The range that will be used for this client.
174
static int clientMax;
175   static int clientMin;
176
177
178   // The range that will be used for this thread.
179
int threadMax;
180   int threadMin;
181
182
183   // The LDAP connection that will be used to issue the searches.
184
LDAPConnection conn;
185
186
187   // Variables used for status counters
188
AccumulatingTracker totalSearches;
189   IncrementalTracker exceptionsCaught;
190   IncrementalTracker successfulSearches;
191   IntegerValueTracker entryCount;
192   TimeTracker searchTime;
193
194
195
196
197   /**
198    * The default constructor used to create a new instance of the search thread.
199    * The only thing it should do is to invoke the superclass constructor. All
200    * other initialization should be performed in the <CODE>initialize</CODE>
201    * method.
202    */

203   public LDAPPrimeJobClass()
204   {
205     super();
206   }
207
208
209
210   /**
211    * Retrieves the name of the job performed by this job thread.
212    *
213    * @return The name of the job performed by this job thread.
214    */

215   public String JavaDoc getJobName()
216   {
217     return "LDAP Prime Job";
218   }
219
220
221
222   /**
223    * Retrieves a description of the job performed by this job thread.
224    *
225    * @return A description of the job performed by this job thread.
226    */

227   public String JavaDoc getJobDescription()
228   {
229     return "This job can be used to prime the caches of an LDAP directory " +
230            "server that contains a contrived data set with an attribute " +
231            "whose value is a sequentially incrementing number";
232   }
233
234
235
236   /**
237    * Retrieves the name of the category in which this job class exists. This is
238    * used to help arrange the job classes in the administrative interface.
239    *
240    * @return The name of the category in which this job class exists.
241    */

242   public String JavaDoc getJobCategoryName()
243   {
244     return "LDAP";
245   }
246
247
248
249   /**
250    * Retrieve a parameter list that can be used to determine all of the
251    * customizeable options that are available for this job.
252    *
253    * @return A parameter list that can be used to determine all of the
254    * customizeable options that are available for this job.
255    */

256   public ParameterList getParameterStubs()
257   {
258     Parameter[] parameters = new Parameter[]
259     {
260       placeholder,
261       hostParameter,
262       portParameter,
263       bindDNParameter,
264       bindPWParameter,
265       placeholder,
266       searchBaseParameter,
267       attributeNameParameter,
268       rangeStartParameter,
269       rangeStopParameter,
270       timeLimitParameter
271     };
272
273     return new ParameterList(parameters);
274   }
275
276
277
278   /**
279    * Retrieves a list of parameter "stubs" that specify all the parameters that
280    * should be available to clients. In this case, this list is different from
281    * the set of parameter stubs exposed to the end user because we have a
282    * dynamically-generated "num_clients" parameter used to specify the number of
283    * clients used to run the job.
284    *
285    * @return A list of parameter "stubs" that specify all the parameters that
286    * should be available to clients.
287    */

288   public ParameterList getClientSideParameterStubs()
289   {
290     Parameter[] parameters = new Parameter[]
291     {
292       placeholder,
293       hostParameter,
294       portParameter,
295       bindDNParameter,
296       bindPWParameter,
297       placeholder,
298       searchBaseParameter,
299       attributeNameParameter,
300       rangeStartParameter,
301       rangeStopParameter,
302       timeLimitParameter,
303       clientsParameter
304     };
305
306     return new ParameterList(parameters);
307   }
308
309
310
311   /**
312    * Retrieves the set of stat trackers that will be maintained by this job
313    * class. The stat trackers returned by this method do not have to actually
314    * contain any statistics -- the display name and stat tracker class should
315    * be the only information that callers of this method should rely upon. Note
316    * that this list can be different from the list of statistics actually
317    * collected by the job in some cases (e.g., if the job may not return all the
318    * stat trackers it advertises in all cases, or if the job may return stat
319    * trackers that it did not advertise), but it is a possibility that only the
320    * stat trackers returned by this method will be accessible for some features
321    * in the SLAMD server.
322    *
323    * @param clientID The client ID that should be used for the
324    * returned stat trackers.
325    * @param threadID The thread ID that should be used for the
326    * returned stat trackers.
327    * @param collectionInterval The collection interval that should be used for
328    * the returned stat trackers.
329    *
330    * @return The set of stat trackers that will be maintained by this job
331    * class.
332    */

333   public StatTracker[] getStatTrackerStubs(String JavaDoc clientID, String JavaDoc threadID,
334                                            int collectionInterval)
335   {
336     return new StatTracker[]
337     {
338       new IncrementalTracker(clientID, threadID,
339                              STAT_TRACKER_SEARCHES_COMPLETED,
340                              collectionInterval),
341       new IncrementalTracker(clientID, threadID, STAT_TRACKER_EXCEPTIONS_CAUGHT,
342                              collectionInterval),
343       new IntegerValueTracker(clientID, threadID, STAT_TRACKER_ENTRY_COUNT,
344                               collectionInterval),
345       new TimeTracker(clientID, threadID, STAT_TRACKER_SEARCH_TIME,
346                       collectionInterval)
347     };
348   }
349
350
351
352   /**
353    * Retrieves the stat trackers that are maintained for this job thread.
354    *
355    * @return The stat trackers that are maintained for this job thread.
356    */

357   public StatTracker[] getStatTrackers()
358   {
359     return new StatTracker[]
360     {
361       successfulSearches,
362       totalSearches,
363       exceptionsCaught,
364       entryCount,
365       searchTime
366     };
367   }
368
369
370
371   /**
372    * Provides a means of validating the information used to schedule the job,
373    * including the scheduling information and list of parameters.
374    *
375    * @param numClients The number of clients that should be used to
376    * run the job.
377    * @param threadsPerClient The number of threads that should be created on
378    * each client to run the job.
379    * @param threadStartupDelay The delay in milliseconds that should be used
380    * when starting the client threads.
381    * @param startTime The time that the job should start running.
382    * @param stopTime The time that the job should stop running.
383    * @param duration The maximum length of time in seconds that the
384    * job should be allowed to run.
385    * @param collectionInterval The collection interval that should be used
386    * when gathering statistics for the job.
387    * @param parameters The set of parameters provided to this job that
388    * can be used to customize its behavior.
389    *
390    * @throws InvalidValueException If the provided information is not
391    * appropriate for running this job.
392    */

393   public void validateJobInfo(int numClients, int threadsPerClient,
394                               int threadStartupDelay, Date startTime,
395                               Date stopTime, int duration,
396                               int collectionInterval, ParameterList parameters)
397          throws InvalidValueException
398   {
399     // This is sneaky. We're going to pass the number of clients to the job as
400
// a job parameter. Otherwise, the job would have no idea how many clients
401
// there are, and therefore would have no idea how to break up the work for
402
// each client.
403
IntegerParameter clientsParameter =
404          new IntegerParameter("num_clients", numClients);
405     parameters.addParameter(clientsParameter);
406   }
407
408
409
410   /**
411    * Indicates whether this job class implements logic that makes it possible to
412    * test the validity of job parameters before scheduling the job for execution
413    * (e.g., to see if the server is reachable using the information provided).
414    *
415    * @return <CODE>true</CODE> if this job provides a means of testing the job
416    * parameters, or <CODE>false</CODE> if not.
417    */

418   public boolean providesParameterTest()
419   {
420     return true;
421   }
422
423
424
425   /**
426    * Provides a means of testing the provided job parameters to determine
427    * whether they are valid (e.g., to see if the server is reachable) before
428    * scheduling the job for execution. This method will be executed by the
429    * SLAMD server system itself and not by any of the clients.
430    *
431    * @param parameters The job parameters to be tested.
432    * @param outputMessages The lines of output that were generated as part of
433    * the testing process. Each line of output should
434    * be added to this list as a separate string, and
435    * empty strings (but not <CODE>null</CODE> values)
436    * are allowed to provide separation between
437    * different messages. No formatting should be
438    * provided for these messages, however, since they
439    * may be displayed in either an HTML or plain text
440    * interface.
441    *
442    * @return <CODE>true</CODE> if the test completed successfully, or
443    * <CODE>false</CODE> if not. Note that even if the test did not
444    * complete successfully, the user will be presented with a warning
445    * but will still be allowed to schedule the job using the provided
446    * parameters. This is necessary because the parameters may still be
447    * valid even if the server couldn't validate them at the time the
448    * job was scheduled (e.g., if the server wasn't running or could not
449    * be reached by the SLAMD server even though it could be by the
450    * clients).
451    */

452   public boolean testJobParameters(ParameterList parameters,
453                                    ArrayList outputMessages)
454   {
455     // Get all the parameters that we might need to perform the test.
456
StringParameter hostParam =
457          parameters.getStringParameter(hostParameter.getName());
458     if ((hostParam == null) || (! hostParam.hasValue()))
459     {
460       outputMessages.add("ERROR: No directory server address was provided.");
461       return false;
462     }
463     String JavaDoc host = hostParam.getStringValue();
464
465
466     IntegerParameter portParam =
467          parameters.getIntegerParameter(portParameter.getName());
468     if ((portParam == null) || (! hostParam.hasValue()))
469     {
470       outputMessages.add("ERROR: No directory server port was provided.");
471       return false;
472     }
473     int port = portParam.getIntValue();
474
475
476     String JavaDoc bindDN = "";
477     StringParameter bindDNParam =
478          parameters.getStringParameter(bindDNParameter.getName());
479     if ((bindDNParam != null) && bindDNParam.hasValue())
480     {
481       bindDN = bindDNParam.getStringValue();
482     }
483
484
485     String JavaDoc bindPassword = "";
486     PasswordParameter bindPWParam =
487          parameters.getPasswordParameter(bindPWParameter.getName());
488     if ((bindPWParam != null) && bindPWParam.hasValue())
489     {
490       bindPassword = bindPWParam.getStringValue();
491     }
492
493
494     StringParameter baseDNParam =
495          parameters.getStringParameter(searchBaseParameter.getName());
496     if ((baseDNParam == null) || (! baseDNParam.hasValue()))
497     {
498       outputMessages.add("ERROR: No base DN was provided.");
499       return false;
500     }
501     String JavaDoc baseDN = baseDNParam.getStringValue();
502
503
504     // Create the LDAPConnection object that we will use to communicate with the
505
// directory server.
506
LDAPConnection conn = new LDAPConnection();
507
508
509     // Attempt to establish a connection to the directory server.
510
try
511     {
512       outputMessages.add("Attempting to establish a connection to " + host +
513                          ":" + port + "....");
514       conn.connect(host, port);
515       outputMessages.add("Connected successfully.");
516       outputMessages.add("");
517     }
518     catch (Exception JavaDoc e)
519     {
520       outputMessages.add("ERROR: Unable to connect to the directory " +
521                          "server: " + stackTraceToString(e));
522       return false;
523     }
524
525
526     // Attempt to bind to the directory server using the bind DN and password.
527
try
528     {
529       outputMessages.add("Attempting to perform an LDAPv3 bind to the " +
530                          "directory server with a DN of '" + bindDN + "'....");
531       conn.bind(3, bindDN, bindPassword);
532       outputMessages.add("Bound successfully.");
533       outputMessages.add("");
534     }
535     catch (Exception JavaDoc e)
536     {
537       try
538       {
539         conn.disconnect();
540       } catch (Exception JavaDoc e2) {}
541
542       outputMessages.add("ERROR: Unable to bind to the directory server: " +
543                          stackTraceToString(e));
544       return false;
545     }
546
547
548     // Make sure that the entry specified as the base DN exists.
549
try
550     {
551       outputMessages.add("Checking to make sure that the base DN entry '" +
552                          baseDN + "' exists in the directory....");
553       LDAPEntry baseDNEntry = conn.read(baseDN, new String JavaDoc[] { "1.1" });
554       if (baseDNEntry == null)
555       {
556         try
557         {
558           conn.disconnect();
559         } catch (Exception JavaDoc e2) {}
560
561         outputMessages.add("ERROR: Unable to retrieve the base DN entry.");
562         return false;
563       }
564       else
565       {
566         outputMessages.add("Successfully read the base DN entry.");
567         outputMessages.add("");
568       }
569     }
570     catch (Exception JavaDoc e)
571     {
572       try
573       {
574         conn.disconnect();
575       } catch (Exception JavaDoc e2) {}
576
577       outputMessages.add("ERROR: Unable to retrieve the base DN entry: " +
578                          stackTraceToString(e));
579       return false;
580     }
581
582
583     // At this point, all tests have passed. Close the connection and return
584
// true.
585
try
586     {
587       conn.disconnect();
588     } catch (Exception JavaDoc e) {}
589
590     outputMessages.add("All tests completed successfully.");
591     return true;
592   }
593
594
595
596   /**
597    * Performs client-level initialization for this job, including retrieving
598    * the values of all the parameters and reading the filter file (if one has
599    * been specified).
600    *
601    * @param clientID The ID assigned to the client that will be running the
602    * job.
603    * @param parameters The list of parameters defined for this job.
604    *
605    * @throws UnableToRunException If the initialization fails for some reason.
606    */

607   public void initializeClient(String JavaDoc clientID, ParameterList parameters)
608          throws UnableToRunException
609   {
610     // Get the address of the target directory server
611
ldapHost = null;
612     hostParameter = parameters.getStringParameter(hostParameter.getName());
613     if (hostParameter != null)
614     {
615       ldapHost = hostParameter.getStringValue();
616     }
617
618     // Get the port for the target directory server
619
ldapPort = 389;
620     portParameter = parameters.getIntegerParameter(portParameter.getName());
621     if (portParameter != null)
622     {
623       ldapPort = portParameter.getIntValue();
624     }
625
626     // Get the bind DN for the target directory server
627
bindDN = "";
628     bindDNParameter = parameters.getStringParameter(bindDNParameter.getName());
629     if (bindDNParameter != null)
630     {
631       bindDN = bindDNParameter.getStringValue();
632     }
633
634     // Get the bind password for the target directory server
635
bindPassword = "";
636     bindPWParameter =
637          parameters.getPasswordParameter(bindPWParameter.getName());
638     if (bindPWParameter != null)
639     {
640       bindPassword = bindPWParameter.getStringValue();
641     }
642
643     // Get the search base
644
searchBase = "";
645     searchBaseParameter =
646          parameters.getStringParameter(searchBaseParameter.getName());
647     if (searchBaseParameter != null)
648     {
649       searchBase = searchBaseParameter.getStringValue();
650     }
651
652     // Get the attribute name
653
attributeName = null;
654     attributeNameParameter =
655          parameters.getStringParameter(attributeNameParameter.getName());
656     if (attributeNameParameter != null)
657     {
658       attributeName = attributeNameParameter.getStringValue();
659     }
660
661     // Get the range start value.
662
rangeStart = 0;
663     rangeStartParameter =
664          parameters.getIntegerParameter(rangeStartParameter.getName());
665     if (rangeStartParameter != null)
666     {
667       rangeStart = rangeStartParameter.getIntValue();
668     }
669
670     // Get the range end value.
671
rangeStop = Integer.MAX_VALUE;
672     rangeStopParameter =
673          parameters.getIntegerParameter(rangeStopParameter.getName());
674     if (rangeStopParameter != null)
675     {
676       rangeStop = rangeStopParameter.getIntValue();
677     }
678
679
680     // Get the time limit per search.
681
timeLimit = 0;
682     timeLimitParameter =
683          parameters.getIntegerParameter(timeLimitParameter.getName());
684     if (timeLimitParameter != null)
685     {
686       timeLimit = timeLimitParameter.getIntValue();
687     }
688
689     // Get the total number of clients.
690
numClients = 0;
691     clientsParameter =
692          parameters.getIntegerParameter(clientsParameter.getName());
693     if (clientsParameter != null)
694     {
695       numClients = clientsParameter.getIntValue();
696     }
697
698
699     // Calculate the range of values that will be used by this client.
700
int totalSpan = rangeStop - rangeStart + 1;
701     int spanPerClient = totalSpan / numClients;
702     if ((totalSpan % numClients) != 0)
703     {
704       spanPerClient++;
705     }
706
707     int clientNumber = getClientNumber();
708     if (clientNumber >= numClients)
709     {
710       throw new UnableToRunException("Detected that this client is client " +
711                                      "number " + clientNumber +
712                                      ", but the reported number of clients " +
713                                      "was " + numClients +
714                                      " -- skipping this client");
715     }
716     else if (clientNumber == (numClients - 1))
717     {
718       clientMin = (clientNumber * spanPerClient) + rangeStart;
719       clientMax = rangeStop;
720     }
721     else
722     {
723       clientMin = (clientNumber * spanPerClient) + rangeStart;
724       clientMax = clientMin + spanPerClient - 1;
725     }
726   }
727
728
729   /**
730    * Initializes this job thread to be used to actually run the job on the
731    * client. The provided parameter list should be processed to customize the
732    * behavior of this job thread, and any other initialization that needs to be
733    * done in order for the job to run should be performed here as well.
734    *
735    * @param clientID The client ID for this job thread.
736    * @param threadID The thread ID for this job thread.
737    * @param collectionInterval The length of time in seconds to use as the
738    * statistics collection interval.
739    * @param parameters The set of parameters provided to this job that
740    * can be used to customize its behavior.
741    *
742    * @throws UnableToRunException If a problem occurs that prevents the thread
743    * from being able to run properly.
744    */

745   public void initializeThread(String JavaDoc clientID, String JavaDoc threadID,
746                                int collectionInterval, ParameterList parameters)
747          throws UnableToRunException
748   {
749     // Set up the status counters
750
entryCount = new IntegerValueTracker(clientID, threadID,
751                                          STAT_TRACKER_ENTRY_COUNT,
752                                          collectionInterval);
753     exceptionsCaught = new IncrementalTracker(clientID, threadID,
754                                               STAT_TRACKER_EXCEPTIONS_CAUGHT,
755                                               collectionInterval);
756     searchTime = new TimeTracker(clientID, threadID, STAT_TRACKER_SEARCH_TIME,
757                                  collectionInterval);
758     successfulSearches = new IncrementalTracker(clientID, threadID,
759                                                 STAT_TRACKER_SEARCHES_COMPLETED,
760                                                 collectionInterval);
761     totalSearches =
762          new AccumulatingTracker(clientID, threadID,
763                                  STAT_TRACKER_TOTAL_SEARCHES_COMPLETED,
764                                  collectionInterval);
765
766
767     // Enable real-time reporting of the data for these stat trackers.
768
RealTimeStatReporter statReporter = getStatReporter();
769     if (statReporter != null)
770     {
771       String JavaDoc jobID = getJobID();
772       successfulSearches.enableRealTimeStats(statReporter, jobID);
773       totalSearches.enableRealTimeStats(statReporter, jobID);
774       exceptionsCaught.enableRealTimeStats(statReporter, jobID);
775       entryCount.enableRealTimeStats(statReporter, jobID);
776       searchTime.enableRealTimeStats(statReporter, jobID);
777     }
778
779
780     // Figure out the span to use for this particular thread.
781
int numThreads = getClientSideJob().getThreadsPerClient();
782     int clientSpan = clientMax - clientMin + 1;
783     int spanPerThread = clientSpan / numThreads;
784     if ((clientSpan % numThreads) != 0)
785     {
786       spanPerThread++;
787     }
788
789     int threadNumber = getThreadNumber();
790     if (threadNumber == (numThreads - 1))
791     {
792       threadMin = (threadNumber * spanPerThread) + clientMin;
793       threadMax = clientMax;
794     }
795     else
796     {
797       threadMin = (threadNumber * spanPerThread) + clientMin;
798       threadMax = threadMin + spanPerThread - 1;
799     }
800   }
801
802
803
804   /**
805    * Perform the work of this job thread by establishing the connection(s) to
806    * the directory server and issuing all the appropriate queries. The job will
807    * continue until the specified number of iterations have been performed, the
808    * stop time has been reached, the maximum duration has been reached, or the
809    * SLAMD server indicates that a stop has been requested.
810    */

811   public void runJob()
812   {
813     // Establish the connection to the directory server.
814
conn = new LDAPConnection();
815     try
816     {
817       conn.connect(3, ldapHost, ldapPort, bindDN, bindPassword);
818     }
819     catch (LDAPException le)
820     {
821       logMessage("Unable to connect to directory server " + ldapHost + ":" +
822                  ldapPort + ": " + le);
823       indicateCompletedWithErrors();
824       return;
825     }
826
827     // Create the search constraints to use and set the time limit.
828
LDAPSearchConstraints searchConstraints = conn.getSearchConstraints();
829     searchConstraints.setTimeLimit(1000 * timeLimit);
830     searchConstraints.setServerTimeLimit(timeLimit);
831
832
833     // Tell the stat trackers that they should start tracking now
834
successfulSearches.startTracker();
835     totalSearches.startTracker();
836     exceptionsCaught.startTracker();
837     entryCount.startTracker();
838     searchTime.startTracker();
839
840     // Create a loop that will run until it needs to stop
841
for (int i=threadMin; ((! shouldStop()) && (i <= threadMax)); i++)
842     {
843       // Create a flag that will be used to determine if the search was
844
// successful or not
845
boolean successfulSearch = false;
846
847
848       // Create a counter that will be used to record the number of matching
849
// entries
850
int matchingEntries = 0;
851
852       // Perform the search and iterate through all matching entries
853
searchTime.startTimer();
854       try
855       {
856         String JavaDoc filter = "(" + attributeName + "=" + i + ")";
857         LDAPSearchResults results = conn.search(searchBase,
858                                                 LDAPConnection.SCOPE_SUB,
859                                                 filter, null, false,
860                                                 searchConstraints);
861         while (results.hasMoreElements())
862         {
863           if (results.nextElement() instanceof LDAPEntry)
864           {
865             matchingEntries++;
866           }
867         }
868
869         successfulSearch = true;
870       }
871       catch (Exception JavaDoc e)
872       {
873         exceptionsCaught.increment();
874         indicateCompletedWithErrors();
875       }
876
877       // Record the current time as the end of the search
878
searchTime.stopTimer();
879
880
881       // Update the appropriate status counters
882
if (successfulSearch)
883       {
884         entryCount.addValue(matchingEntries);
885         successfulSearches.increment();
886         totalSearches.increment();
887       }
888     }
889
890
891     // If the connection is still established, then close it
892
try
893     {
894       conn.disconnect();
895     } catch (LDAPException le) {}
896
897     // Tell the stat trackers that they should stop tracking
898
successfulSearches.stopTracker();
899     totalSearches.stopTracker();
900     exceptionsCaught.stopTracker();
901     entryCount.stopTracker();
902     searchTime.stopTracker();
903   }
904
905
906
907   /**
908    * Attempts to force this thread to exit by closing the connection to the
909    * directory server and setting it to <CODE>null</CODE>.
910    */

911   public void destroy()
912   {
913     if (conn != null)
914     {
915       try
916       {
917         conn.disconnect();
918       } catch (Exception JavaDoc e) {}
919
920       conn = null;
921     }
922   }
923 }
924
925
Popular Tags