KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jmeter > threads > JMeterThread


1 // $Header: /home/cvs/jakarta-jmeter/src/core/org/apache/jmeter/threads/JMeterThread.java,v 1.48.2.7 2005/03/14 00:54:43 sebb Exp $
2
/*
3  * Copyright 2001-2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17 */

18
19 package org.apache.jmeter.threads;
20 import java.util.Collection JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.ListIterator JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import org.apache.jmeter.assertions.Assertion;
28 import org.apache.jmeter.assertions.AssertionResult;
29 import org.apache.jmeter.control.Controller;
30 import org.apache.jmeter.engine.StandardJMeterEngine;
31 import org.apache.jmeter.engine.event.LoopIterationEvent;
32 import org.apache.jmeter.engine.event.LoopIterationListener;
33 import org.apache.jmeter.processor.PostProcessor;
34 import org.apache.jmeter.samplers.SampleEvent;
35 import org.apache.jmeter.samplers.SampleResult;
36 import org.apache.jmeter.samplers.Sampler;
37 import org.apache.jmeter.testbeans.TestBean;
38 import org.apache.jmeter.testelement.TestElement;
39 import org.apache.jmeter.testelement.TestListener;
40 import org.apache.jmeter.timers.Timer;
41 import org.apache.jorphan.collections.HashTree;
42 import org.apache.jorphan.collections.HashTreeTraverser;
43 import org.apache.jorphan.collections.SearchByClass;
44 import org.apache.jorphan.logging.LoggingManager;
45 import org.apache.jorphan.util.JMeterStopTestException;
46 import org.apache.jorphan.util.JMeterStopThreadException;
47 import org.apache.jorphan.util.JOrphanUtils;
48 import org.apache.log.Logger;
49
50 /**
51  * The JMeter interface to the sampling process, allowing JMeter to see the
52  * timing, add listeners for sampling events and to stop the sampling process.
53  *
54  * @author unattributed
55  * @version $Revision: 1.48.2.7 $ Last updated: $Date: 2005/03/14 00:54:43 $
56  */

57 public class JMeterThread implements Runnable JavaDoc, java.io.Serializable JavaDoc
58 {
59     transient private static Logger log = LoggingManager.getLoggerForClass();
60     static Map JavaDoc samplers = new HashMap JavaDoc();
61     int initialDelay = 0;
62     Controller controller;
63     private boolean running;
64     HashTree testTree;
65     TestCompiler compiler;
66     JMeterThreadMonitor monitor;
67     String JavaDoc threadName;
68     JMeterContext threadContext; // current working thread context
69
JMeterVariables threadVars;// Initial thread variables
70
Collection JavaDoc testListeners;
71     ListenerNotifier notifier;
72     int threadNum = 0;
73     long startTime = 0;
74     long endTime = 0;
75     private boolean scheduler = false;
76     //based on this scheduler is enabled or disabled
77

78     
79     private StandardJMeterEngine engine = null; // For access to stop methods.
80
private boolean onErrorStopTest;
81     private boolean onErrorStopThread;
82     
83     public static final String JavaDoc PACKAGE_OBJECT = "JMeterThread.pack"; // $NON-NLS-1$
84
public static final String JavaDoc LAST_SAMPLE_OK = "JMeterThread.last_sample_ok"; // $NON-NLS-1$
85

86     public JMeterThread()
87     {
88     }
89
90     public JMeterThread(
91         HashTree test,
92         JMeterThreadMonitor monitor,
93         ListenerNotifier note)
94     {
95         this.monitor = monitor;
96         threadVars = new JMeterVariables();
97         testTree = test;
98         compiler = new TestCompiler(testTree, threadVars);
99         controller = (Controller) testTree.getArray()[0];
100         SearchByClass threadListenerSearcher =
101             new SearchByClass(TestListener.class);
102         test.traverse(threadListenerSearcher);
103         testListeners = threadListenerSearcher.getSearchResults();
104         notifier = note;
105     }
106
107     public void setInitialContext(JMeterContext context)
108     {
109         threadVars.putAll(context.getVariables());
110     }
111
112
113     /**
114      * Checks whether the JMeterThread is Scheduled.
115      * author T.Elanjchezhiyan(chezhiyan@siptech.co.in)
116      */

117     public boolean isScheduled()
118     {
119         return this.scheduler;
120     }
121
122     /**
123      * Enable the scheduler for this JMeterThread.
124      * author T.Elanjchezhiyan(chezhiyan@siptech.co.in)
125      */

126     public void setScheduled(boolean sche)
127     {
128         this.scheduler = sche;
129     }
130
131
132     /**
133      * Set the StartTime for this Thread.
134      *
135      * @param stime the StartTime value.
136      * author T.Elanjchezhiyan(chezhiyan@siptech.co.in)
137      */

138     public void setStartTime(long stime)
139     {
140         startTime = stime;
141     }
142
143     /**
144      * Get the start time value.
145      *
146      * @return the start time value.
147      * author T.Elanjchezhiyan(chezhiyan@siptech.co.in)
148      */

149     public long getStartTime()
150     {
151         return startTime;
152     }
153
154     /**
155      * Set the EndTime for this Thread.
156      *
157      * @param etime the EndTime value.
158      * author T.Elanjchezhiyan(chezhiyan@siptech.co.in)
159      */

160     public void setEndTime(long etime)
161     {
162         endTime = etime;
163     }
164     
165     /**
166      * Get the end time value.
167      *
168      * @return the end time value.
169      * author T.Elanjchezhiyan(chezhiyan@siptech.co.in)
170      */

171     public long getEndTime()
172     {
173         return endTime;
174     }
175
176
177     /**
178      * Check the scheduled time is completed.
179      *
180      * author T.Elanjchezhiyan(chezhiyan@siptech.co.in)
181      */

182     private void stopScheduler()
183     {
184         long delay = System.currentTimeMillis() - endTime;
185         if ((delay >= 0))
186         {
187             running = false;
188         }
189     }
190
191     /**
192      * Wait until the scheduled start time if necessary
193      *
194      * Author T.Elanjchezhiyan(chezhiyan@siptech.co.in)
195      */

196     private void startScheduler()
197     {
198         long delay = (startTime - System.currentTimeMillis());
199         if (delay > 0)
200         {
201             try
202             {
203                 Thread.sleep(delay);
204             }
205             catch (Exception JavaDoc e)
206             {
207             }
208         }
209     }
210
211     public void setThreadName(String JavaDoc threadName)
212     {
213         this.threadName = threadName;
214     }
215
216     /*
217      * See below for reason for this change.
218      * Just in case this causes problems, allow the change to be backed out
219     */

220     private static final boolean startEarlier =
221         org.apache.jmeter.util.JMeterUtils.getPropDefault("jmeterthread.startearlier",true);
222     
223     static{
224         if (startEarlier){
225             log.warn("jmeterthread.startearlier=true (see jmeter.properties)");
226         } else {
227             log.info("jmeterthread.startearlier=false (see jmeter.properties)");
228         }
229     }
230     
231     public void run()
232     {
233         try
234         {
235             threadContext = JMeterContextService.getContext();
236             threadContext.setVariables(threadVars);
237             threadContext.setThreadNum(getThreadNum());
238             // initialise
239
threadContext.getVariables().put(LAST_SAMPLE_OK,"true"); // $NON-NLS-1$
240
testTree.traverse(compiler);
241             running = true;
242             //listeners = controller.getListeners();
243

244             if (scheduler)
245             {
246                 //set the scheduler to start
247
startScheduler();
248             }
249
250             rampUpDelay();
251             
252             log.info("Thread " + Thread.currentThread().getName() + " started");
253             /*
254              * Setting SamplingStarted before the contollers are initialised
255              * allows them to access the running values of functions and variables
256              * (however it does not seem to help with the listeners)
257              */

258             if (startEarlier) threadContext.setSamplingStarted(true);
259             controller.initialize();
260             controller.addIterationListener(new IterationListener());
261             if (!startEarlier) threadContext.setSamplingStarted(true);
262             threadStarted();
263             while (running)
264             {
265                 Sampler sam;
266                 while (running && (sam=controller.next())!=null)
267                 {
268                     try
269                     {
270                         threadContext.setCurrentSampler(sam);
271                         SamplePackage pack = compiler.configureSampler(sam);
272                         
273                         //Hack: save the package for any transaction controllers
274
threadContext.getVariables().putObject(PACKAGE_OBJECT,pack);
275                         
276                         delay(pack.getTimers());
277                         Sampler sampler= pack.getSampler();
278                         sampler.setThreadContext(threadContext);
279                         sampler.setThreadName(threadName);
280                         if (sampler instanceof TestBean) ((TestBean)sampler).prepare();
281                         SampleResult result = sampler.sample(null); // TODO: remove this useless Entry parameter
282
result.setThreadName(threadName);
283                         threadContext.setPreviousResult(result);
284                         runPostProcessors(pack.getPostProcessors());
285                         checkAssertions(pack.getAssertions(), result);
286                         notifyListeners(pack.getSampleListeners(), result);
287                         compiler.done(pack);
288                         if (result.isStopThread() || (!result.isSuccessful() && onErrorStopThread)){
289                             stopThread();
290                         }
291                         if (result.isStopTest() || (!result.isSuccessful() && onErrorStopTest)){
292                             stopTest();
293                         }
294                         if (scheduler)
295                         {
296                             //checks the scheduler to stop the iteration
297
stopScheduler();
298                         }
299
300                     }
301                     catch (JMeterStopTestException e)
302                     {
303                         log.info("Stopping Test: "+e.toString());
304                         stopTest();
305                     }
306                     catch (JMeterStopThreadException e)
307                     {
308                         log.info("Stopping Thread: "+e.toString());
309                         stopThread();
310                     }
311                     catch (Exception JavaDoc e)
312                     {
313                         log.error("", e);
314                     }
315                 }
316                 if (controller.isDone())
317                 {
318                     running = false;
319                 }
320             }
321         }
322         // Might be found by contoller.next()
323
catch (JMeterStopTestException e)
324         {
325             log.info("Stopping Test: "+e.toString());
326             stopTest();
327         }
328         catch (JMeterStopThreadException e)
329         {
330             log.info("Stop Thread seen: "+e.toString());
331         }
332         catch (Exception JavaDoc e)
333         {
334             log.error("Test failed!", e);
335         }
336         catch (ThreadDeath JavaDoc e){
337             throw e; // Must not ignore this one
338
}
339         catch (Error JavaDoc e){// Make sure errors are output to the log file
340
log.error("Test failed!", e);
341         }
342         finally
343         {
344             threadContext.clear();
345             log.info("Thread " + threadName + " is done");
346             monitor.threadFinished(this);
347             threadFinished();
348         }
349     }
350
351     /**
352      *
353      */

354     private void threadStarted() {
355         Traverser startup = new Traverser(true);
356         testTree.traverse(startup);
357     }
358
359     /**
360      *
361      */

362     private void threadFinished() {
363         Traverser shut = new Traverser(false);
364         testTree.traverse(shut);
365     }
366
367     private class Traverser implements HashTreeTraverser
368     {
369     private boolean isStart = false;
370     private Traverser(boolean start)
371     {
372     isStart = start;
373     }
374         public void addNode(Object JavaDoc node, HashTree subTree) {
375             if (node instanceof TestElement) {
376                 TestElement te = (TestElement) node;
377                 if (isStart)
378                 {
379                     te.threadStarted();
380                 }
381                 else
382                 {
383                     te.threadFinished();
384                 }
385             }
386         }
387
388         public void subtractNode()
389         {
390         }
391
392         public void processPath()
393         {
394         }
395     }
396
397     public String JavaDoc getThreadName()
398     {
399         return threadName;
400     }
401
402     public void stop()
403     {
404         running = false;
405         log.info("Stopping " + threadName);
406     }
407     private void stopTest()
408     {
409         running = false;
410         log.info("Stop Test detected by thread " + threadName);
411         //engine.stopTest();
412
if (engine != null ) engine.askThreadsToStop();
413     }
414     private void stopThread()
415     {
416         running = false;
417         log.info("Stop Thread detected by thread " + threadName);
418     }
419
420
421     private void checkAssertions(List JavaDoc assertions, SampleResult result)
422     {
423         Iterator JavaDoc iter = assertions.iterator();
424         while (iter.hasNext())
425         {
426             Assertion assertion= (Assertion)iter.next();
427             if (assertion instanceof TestBean) ((TestBean)assertion).prepare();
428             AssertionResult assertionResult = assertion.getResult(result);
429             result.setSuccessful(
430                 result.isSuccessful()
431                     && !(assertionResult.isError() || assertionResult.isFailure()));
432             result.addAssertionResult(assertionResult);
433         }
434         threadContext.getVariables().put(LAST_SAMPLE_OK,
435                 JOrphanUtils.booleanToString(result.isSuccessful()));
436     }
437
438     private void runPostProcessors(List JavaDoc extractors)
439     {
440         ListIterator JavaDoc iter = extractors.listIterator(extractors.size());
441         while (iter.hasPrevious())
442         {
443             PostProcessor ex = (PostProcessor) iter.previous();
444             if (ex instanceof TestBean) ((TestBean)ex).prepare();
445             ex.process();
446         }
447     }
448
449     private void delay(List JavaDoc timers)
450     {
451         int sum = 0;
452         Iterator JavaDoc iter = timers.iterator();
453         while (iter.hasNext())
454         {
455             Timer timer= (Timer) iter.next();
456             if (timer instanceof TestBean) ((TestBean)timer).prepare();
457             sum += timer.delay();
458         }
459         if (sum > 0)
460         {
461             try
462             {
463                 Thread.sleep(sum);
464             }
465             catch (InterruptedException JavaDoc e)
466             {
467                 log.error("", e);
468             }
469         }
470     }
471
472     private void notifyTestListeners()
473     {
474         threadVars.incIteration();
475         Iterator JavaDoc iter = testListeners.iterator();
476         while (iter.hasNext())
477         {
478             TestListener listener = (TestListener)iter.next();
479             if(listener instanceof TestElement)
480             {
481                 listener.testIterationStart(
482                     new LoopIterationEvent(
483                         controller,
484                         threadVars.getIteration()));
485                 ((TestElement)listener).recoverRunningVersion();
486             }
487             else
488             {
489                 listener.testIterationStart(
490                     new LoopIterationEvent(
491                         controller,
492                         threadVars.getIteration()));
493             }
494         }
495     }
496
497     private void notifyListeners(List JavaDoc listeners, SampleResult result)
498     {
499         SampleEvent event =
500             new SampleEvent(
501                 result,
502                 controller.getPropertyAsString(TestElement.NAME));
503         compiler.sampleOccurred(event);
504         notifier.notifyListeners(event, listeners);
505
506     }
507     public void setInitialDelay(int delay)
508     {
509         initialDelay = delay;
510     }
511
512     /**
513      * Initial delay if ramp-up period is active for this group.
514      */

515     private void rampUpDelay()
516     {
517         if (initialDelay > 0)
518         {
519             try
520             {
521                 Thread.sleep(initialDelay);
522             }
523             catch (InterruptedException JavaDoc e)
524             {}
525         }
526     }
527     
528     /**
529      * Returns the threadNum.
530      */

531     public int getThreadNum()
532     {
533         return threadNum;
534     }
535
536     /**
537      * Sets the threadNum.
538      * @param threadNum the threadNum to set
539      */

540     public void setThreadNum(int threadNum)
541     {
542         this.threadNum = threadNum;
543     }
544     
545     private class IterationListener implements LoopIterationListener
546     {
547         /* (non-Javadoc)
548          * @see LoopIterationListener#iterationStart(LoopIterationEvent)
549          */

550         public void iterationStart(LoopIterationEvent iterEvent)
551         {
552             notifyTestListeners();
553         }
554     }
555     /**
556      * Save the engine instance for access to the stop methods
557      *
558      * @param engine
559      */

560     public void setEngine(StandardJMeterEngine engine)
561     {
562         this.engine = engine;
563     }
564
565     /**
566      * Should Test stop on sampler error?
567      *
568      * @param b - true or false
569      */

570     public void setOnErrorStopTest(boolean b)
571     {
572         onErrorStopTest = b;
573     }
574
575     /**
576      * Should Thread stop on Sampler error?
577      *
578      * @param b - true or false
579      */

580     public void setOnErrorStopThread(boolean b)
581     {
582         onErrorStopThread = b;
583     }
584
585 }
Popular Tags