1 18 19 package org.apache.jmeter.engine; 20 21 import java.io.PrintWriter ; 22 import java.io.Serializable ; 23 import java.io.StringWriter ; 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.HashMap ; 27 import java.util.HashSet ; 28 import java.util.Iterator ; 29 import java.util.LinkedList ; 30 import java.util.List ; 31 import java.util.Map ; 32 33 import org.apache.jmeter.reporters.ResultCollector; 34 import org.apache.jmeter.testelement.TestElement; 35 import org.apache.jmeter.testelement.TestListener; 36 import org.apache.jmeter.testelement.TestPlan; 37 import org.apache.jmeter.threads.JMeterContextService; 38 import org.apache.jmeter.threads.JMeterThread; 39 import org.apache.jmeter.threads.JMeterThreadMonitor; 40 import org.apache.jmeter.threads.ListenerNotifier; 41 import org.apache.jmeter.threads.TestCompiler; 42 import org.apache.jmeter.threads.ThreadGroup; 43 import org.apache.jorphan.collections.HashTree; 44 import org.apache.jorphan.collections.ListedHashTree; 45 import org.apache.jorphan.collections.SearchByClass; 46 import org.apache.jorphan.logging.LoggingManager; 47 import org.apache.log.Logger; 48 49 52 public class StandardJMeterEngine 53 implements JMeterEngine, JMeterThreadMonitor, Runnable , Serializable 54 { 55 transient private static Logger log = LoggingManager.getLoggerForClass(); 56 private transient Thread runningThread; 57 private static long WAIT_TO_DIE = 5 * 1000; private transient Map allThreads; 59 private boolean running = false; 60 private boolean serialized = false; 61 private volatile boolean schcdule_run = false; 62 private HashTree test; 63 private transient SearchByClass testListeners; 64 private String host = null; 65 private transient ListenerNotifier notifier; 66 67 private static transient Map allThreadNames; 72 private static StandardJMeterEngine engine; 73 private static Map allThreadsSave; 74 public static void stopEngineNow() 75 { 76 if (engine != null) engine.stopTest(true); 78 } 79 public static void stopEngine() 80 { 81 if (engine != null) engine.stopTest(false); 83 } 84 public static boolean stopThread(String threadName) 85 { 86 return stopThread(threadName,false); 87 } 88 public static boolean stopThreadNow(String threadName) 89 { 90 return stopThread(threadName,true); 91 } 92 private static boolean stopThread(String threadName, boolean now) 93 { 94 if (allThreadNames == null) return false; JMeterThread thrd; 96 try { 97 thrd = (JMeterThread)allThreadNames.get(threadName); 98 } catch (Exception e) { 99 log.warn("stopThread: "+e); 100 return false; 101 } 102 if (thrd!= null) 103 { 104 thrd.stop(); 105 if (now) 106 { 107 Thread t = (Thread ) allThreadsSave.get(thrd); 108 if (t != null) 109 { 110 t.interrupt(); 111 } 112 113 } 114 return true; 115 } 116 else 117 { 118 return false; 119 } 120 } 121 123 126 private static List testList = null; 127 public static synchronized void register(TestListener tl) 128 { 129 testList.add(tl); 130 } 131 132 public StandardJMeterEngine() 133 { 134 allThreads = new HashMap (); 135 engine=this; 136 allThreadNames = new HashMap (); 137 allThreadsSave = allThreads; 138 } 139 140 public StandardJMeterEngine(String host) 141 { 142 this(); 143 this.host = host; 144 } 145 146 public void configure(HashTree testTree) 147 { 148 test = testTree; 149 } 150 151 public void setHost(String host) 152 { 153 this.host = host; 154 } 155 156 protected HashTree getTestTree() 157 { 158 return test; 159 } 160 161 protected void compileTree() 162 { 163 PreCompiler compiler = new PreCompiler(); 164 getTestTree().traverse(compiler); 165 } 166 167 public void runTest() throws JMeterEngineException 168 { 169 try 170 { 171 runningThread = new Thread (this); 172 runningThread.start(); 173 } 174 catch (Exception err) 175 { 176 stopTest(); 177 StringWriter string = new StringWriter (); 178 PrintWriter writer = new PrintWriter (string); 179 err.printStackTrace(writer); 180 throw new JMeterEngineException(string.toString()); 181 } 182 } 183 184 private void removeThreadGroups(List elements) 185 { 186 Iterator iter = elements.iterator(); 187 while (iter.hasNext()) 188 { 189 Object item = iter.next(); 190 if (item instanceof ThreadGroup ) 191 { 192 iter.remove(); 193 } 194 else if (!(item instanceof TestElement)) 195 { 196 iter.remove(); 197 } 198 } 199 } 200 201 protected void setMode() 202 { 203 SearchByClass testPlan = new SearchByClass(TestPlan.class); 204 getTestTree().traverse(testPlan); 205 Object [] plan = testPlan.getSearchResults().toArray(); 206 ResultCollector.enableFunctionalMode( 207 ((TestPlan) plan[0]).isFunctionalMode()); 208 } 209 210 protected void notifyTestListenersOfStart() 211 { 212 Iterator iter = testListeners.getSearchResults().iterator(); 213 while (iter.hasNext()) 214 { 215 TestListener it = (TestListener)iter.next(); 216 log.info("Notifying test listener: " + it.getClass().getName()); 217 if (host == null) 218 { 219 it.testStarted(); 220 } 221 else 222 { 223 it.testStarted(host); 224 } 225 } 226 } 227 228 protected void notifyTestListenersOfEnd() 229 { 230 log.info("Notifying listeners of end of test"); 231 232 Iterator iter = testListeners.getSearchResults().iterator(); 233 while (iter.hasNext()) 234 { 235 TestListener it = (TestListener)iter.next(); 236 log.info("Notifying test listener: " + it.getClass().getName()); 237 if (host == null) 238 { 239 it.testEnded(); 240 } 241 else 242 { 243 it.testEnded(host); 244 } 245 } 246 log.info("Test has ended"); 247 } 248 249 private ListedHashTree cloneTree(ListedHashTree tree) 250 { 251 TreeCloner cloner = new TreeCloner(true); 252 tree.traverse(cloner); 253 return cloner.getClonedTree(); 254 } 255 256 public void reset() 257 { 258 if (running) 259 { 260 stopTest(); 261 } 262 } 263 264 public synchronized void threadFinished(JMeterThread thread) 265 { 266 allThreads.remove(thread); 267 if (!serialized && allThreads.size() == 0 && !schcdule_run ) 268 { 269 stopTest(); 270 } 271 } 272 273 public synchronized void stopTest() 274 { 275 Thread stopThread = new Thread (new StopTest()); 276 stopThread.start(); 277 } 278 279 public synchronized void stopTest(boolean b) 280 { 281 Thread stopThread = new Thread (new StopTest(b)); 282 stopThread.start(); 283 } 284 285 public void askThreadsToStop() 286 { 287 engine.stopTest(false); 288 } 289 290 private class StopTest implements Runnable 291 { 292 boolean now; 293 private StopTest(){ 294 now=true; 295 } 296 private StopTest(boolean b){ 297 now=b; 298 } 299 public void run() 300 { 301 if (running) 302 { 303 running = false; 304 if (now){ 305 tellThreadsToStop(); 306 } else { 307 stopAllThreads(); 308 } 309 try 310 { 311 Thread.sleep(10 * allThreads.size()); 312 } 313 catch (InterruptedException e) 314 {} 315 boolean stopped=verifyThreadsStopped(); 316 if (stopped || now){ 317 notifyTestListenersOfEnd(); 318 } 319 } 320 } 321 } 322 323 public void run() 324 { 325 log.info("Running the test!"); 326 running = true; 327 testList = new ArrayList (); 328 329 SearchByClass testPlan = new SearchByClass(TestPlan.class); 330 getTestTree().traverse(testPlan); 331 Object [] plan = testPlan.getSearchResults().toArray(); 332 if (plan.length == 0){ 333 System.err.println("Could not find the TestPlan!"); 334 log.error("Could not find the TestPlan!"); 335 System.exit(1); 336 } 337 if (((TestPlan) plan[0]).isSerialized()) 338 { 339 serialized = true; 340 } 341 compileTree(); 342 343 347 testListeners = new SearchByClass(TestListener.class); 348 getTestTree().traverse(testListeners); 349 log.info("About to call test listeners"); 350 Collection col = testListeners.getSearchResults(); 351 col.addAll(testList); 352 testList=null; 353 notifyTestListenersOfStart(); 354 355 getTestTree().traverse(new TurnElementsOn()); 356 357 List testLevelElements = 358 new LinkedList (getTestTree().list(getTestTree().getArray()[0])); 359 removeThreadGroups(testLevelElements); 360 SearchByClass searcher = new SearchByClass(ThreadGroup .class); 361 362 setMode(); 363 getTestTree().traverse(searcher); 364 TestCompiler.initialize(); 365 JMeterThread[] threads; 369 Iterator iter = searcher.getSearchResults().iterator(); 370 371 377 System.gc(); 378 379 380 notifier = new ListenerNotifier(); 381 382 schcdule_run = true; 383 JMeterContextService.getContext().setSamplingStarted(true); 384 int groupCount = 0; 385 while (iter.hasNext()) 386 { 387 groupCount++; 388 ThreadGroup group = (ThreadGroup ) iter.next(); 389 int numThreads = group.getNumThreads(); 390 boolean onErrorStopTest = group.getOnErrorStopTest(); 391 boolean onErrorStopThread = group.getOnErrorStopThread(); 392 String groupName = group.getName(); 393 int rampUp = group.getRampUp(); 394 float perThreadDelay = ((float) (rampUp * 1000) / (float) numThreads); 395 threads = new JMeterThread[numThreads]; 396 397 log.info("Starting " + numThreads + " threads for group "+ groupName 398 + ". Ramp up = "+ rampUp + "."); 399 400 if (onErrorStopTest) { 401 log.info("Test will stop on error"); 402 } else if (onErrorStopThread) { 403 log.info("Thread will stop on error"); 404 } else { 405 log.info("Continue on error"); 406 } 407 408 for (int i = 0; running && i < threads.length; i++) 409 { 410 ListedHashTree threadGroupTree = 411 (ListedHashTree) searcher.getSubTree(group); 412 threadGroupTree.add(group, testLevelElements); 413 threads[i] = 414 new JMeterThread( 415 cloneTree(threadGroupTree), 416 this, 417 notifier); 418 threads[i].setThreadNum(i); 419 threads[i].setInitialContext(JMeterContextService.getContext()); 420 threads[i].setInitialDelay((int) (perThreadDelay * (float) i)); 421 String threadName = groupName + " " + groupCount + "-" + (i + 1); 422 threads[i].setThreadName(threadName); 423 424 scheduleThread(threads[i], group); 425 426 threads[i].setEngine(this); 428 threads[i].setOnErrorStopTest(onErrorStopTest); 429 threads[i].setOnErrorStopThread(onErrorStopThread); 430 431 Thread newThread = new Thread (threads[i]); 432 newThread.setName(threadName); 433 allThreads.put(threads[i], newThread); 434 allThreadNames.put(threadName,threads[i]); 435 if (serialized 436 && !iter.hasNext() 437 && i == threads.length - 1) { 439 serialized = false; 440 } 441 newThread.start(); 442 } 443 schcdule_run = false; 444 if (serialized) 445 { 446 while (running && allThreads.size() > 0) 447 { 448 try 449 { 450 Thread.sleep(1000); 451 } 452 catch (InterruptedException e) 453 {} 454 } 455 } 456 } 457 } 458 459 465 private void scheduleThread(JMeterThread thread, ThreadGroup group) 466 { 467 if (group.getScheduler()) 469 { 470 long now = System.currentTimeMillis(); 471 if (group.getDelay() > 0 ){ thread.setStartTime(group.getDelay()*1000+now); 474 } else { 475 long start = group.getStartTime(); 476 if (start < now) start = now; thread.setStartTime(start); 478 } 479 480 if (group.getDuration() > 0){ thread.setEndTime(group.getDuration()*1000+(thread.getStartTime())); 483 } else { 484 thread.setEndTime(group.getEndTime()); 485 } 486 487 thread.setScheduled(true); 489 } 490 } 491 492 private boolean verifyThreadsStopped() 493 { 494 boolean stoppedAll=true; 495 Iterator iter = new HashSet (allThreads.keySet()).iterator(); 496 while (iter.hasNext()) 497 { 498 Thread t = (Thread ) allThreads.get(iter.next()); 499 if (t != null && t.isAlive()) 500 { 501 try 502 { 503 t.join(WAIT_TO_DIE); 504 } 505 catch (InterruptedException e) 506 {} 507 if (t.isAlive()) 508 { 509 stoppedAll=false; 510 log.info("Thread won't die: " + t.getName()); 511 } 512 } 513 } 514 return stoppedAll; 515 } 516 517 private void tellThreadsToStop() 518 { 519 Iterator iter = new HashSet (allThreads.keySet()).iterator(); 520 while (iter.hasNext()) 521 { 522 JMeterThread item = (JMeterThread) iter.next(); 523 item.stop(); 524 Thread t = (Thread ) allThreads.get(item); 525 if (t != null) 526 { 527 t.interrupt(); 528 } 529 else 530 { 531 log.warn("Lost thread: " + item.getThreadName()); 532 allThreads.remove(item); 533 } 534 } 535 } 536 537 private void stopAllThreads() 538 { 539 Iterator iter = new HashSet (allThreads.keySet()).iterator(); 540 while (iter.hasNext()) 541 { 542 JMeterThread item = (JMeterThread) iter.next(); 543 item.stop(); 544 } 545 } 546 547 public void exit() 549 { 550 Thread t = new Thread (){ 552 public void run(){ 553 try 555 { 556 Thread.sleep(1000); 557 } 558 catch (InterruptedException e) 559 { 560 } 561 log.info("Bye"); 562 System.exit(0); 563 }; 564 }; 565 log.info("Starting Closedown"); 566 t.start(); 567 } 568 } 569 | Popular Tags |