1 18 19 package org.apache.jmeter.threads; 20 import java.util.Collection ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.ListIterator ; 25 import java.util.Map ; 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 57 public class JMeterThread implements Runnable , java.io.Serializable 58 { 59 transient private static Logger log = LoggingManager.getLoggerForClass(); 60 static Map samplers = new HashMap (); 61 int initialDelay = 0; 62 Controller controller; 63 private boolean running; 64 HashTree testTree; 65 TestCompiler compiler; 66 JMeterThreadMonitor monitor; 67 String threadName; 68 JMeterContext threadContext; JMeterVariables threadVars; Collection testListeners; 71 ListenerNotifier notifier; 72 int threadNum = 0; 73 long startTime = 0; 74 long endTime = 0; 75 private boolean scheduler = false; 76 78 79 private StandardJMeterEngine engine = null; private boolean onErrorStopTest; 81 private boolean onErrorStopThread; 82 83 public static final String PACKAGE_OBJECT = "JMeterThread.pack"; public static final String LAST_SAMPLE_OK = "JMeterThread.last_sample_ok"; 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 117 public boolean isScheduled() 118 { 119 return this.scheduler; 120 } 121 122 126 public void setScheduled(boolean sche) 127 { 128 this.scheduler = sche; 129 } 130 131 132 138 public void setStartTime(long stime) 139 { 140 startTime = stime; 141 } 142 143 149 public long getStartTime() 150 { 151 return startTime; 152 } 153 154 160 public void setEndTime(long etime) 161 { 162 endTime = etime; 163 } 164 165 171 public long getEndTime() 172 { 173 return endTime; 174 } 175 176 177 182 private void stopScheduler() 183 { 184 long delay = System.currentTimeMillis() - endTime; 185 if ((delay >= 0)) 186 { 187 running = false; 188 } 189 } 190 191 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 e) 206 { 207 } 208 } 209 } 210 211 public void setThreadName(String threadName) 212 { 213 this.threadName = threadName; 214 } 215 216 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 threadContext.getVariables().put(LAST_SAMPLE_OK,"true"); testTree.traverse(compiler); 241 running = true; 242 244 if (scheduler) 245 { 246 startScheduler(); 248 } 249 250 rampUpDelay(); 251 252 log.info("Thread " + Thread.currentThread().getName() + " started"); 253 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 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); 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 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 e) 312 { 313 log.error("", e); 314 } 315 } 316 if (controller.isDone()) 317 { 318 running = false; 319 } 320 } 321 } 322 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 e) 333 { 334 log.error("Test failed!", e); 335 } 336 catch (ThreadDeath e){ 337 throw e; } 339 catch (Error e){ 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 354 private void threadStarted() { 355 Traverser startup = new Traverser(true); 356 testTree.traverse(startup); 357 } 358 359 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 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 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 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 assertions, SampleResult result) 422 { 423 Iterator 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 extractors) 439 { 440 ListIterator 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 timers) 450 { 451 int sum = 0; 452 Iterator 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 e) 466 { 467 log.error("", e); 468 } 469 } 470 } 471 472 private void notifyTestListeners() 473 { 474 threadVars.incIteration(); 475 Iterator 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 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 515 private void rampUpDelay() 516 { 517 if (initialDelay > 0) 518 { 519 try 520 { 521 Thread.sleep(initialDelay); 522 } 523 catch (InterruptedException e) 524 {} 525 } 526 } 527 528 531 public int getThreadNum() 532 { 533 return threadNum; 534 } 535 536 540 public void setThreadNum(int threadNum) 541 { 542 this.threadNum = threadNum; 543 } 544 545 private class IterationListener implements LoopIterationListener 546 { 547 550 public void iterationStart(LoopIterationEvent iterEvent) 551 { 552 notifyTestListeners(); 553 } 554 } 555 560 public void setEngine(StandardJMeterEngine engine) 561 { 562 this.engine = engine; 563 } 564 565 570 public void setOnErrorStopTest(boolean b) 571 { 572 onErrorStopTest = b; 573 } 574 575 580 public void setOnErrorStopThread(boolean b) 581 { 582 onErrorStopThread = b; 583 } 584 585 } | Popular Tags |