You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2009/04/23 04:55:57 UTC
svn commit: r767769 - in /jakarta/jmeter/trunk:
src/core/org/apache/jmeter/engine/StandardJMeterEngine.java
src/core/org/apache/jmeter/resources/messages.properties xdocs/changes.xml
Author: sebb
Date: Thu Apr 23 02:55:56 2009
New Revision: 767769
URL: http://svn.apache.org/viewvc?rev=767769&view=rev
Log:
Improvements to Stop and Shutdown processing
Modified:
jakarta/jmeter/trunk/src/core/org/apache/jmeter/engine/StandardJMeterEngine.java
jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
jakarta/jmeter/trunk/xdocs/changes.xml
Modified: jakarta/jmeter/trunk/src/core/org/apache/jmeter/engine/StandardJMeterEngine.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/engine/StandardJMeterEngine.java?rev=767769&r1=767768&r2=767769&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/engine/StandardJMeterEngine.java (original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/engine/StandardJMeterEngine.java Thu Apr 23 02:55:56 2009
@@ -31,6 +31,7 @@
import java.util.Map;
import java.util.Properties;
+import org.apache.jmeter.JMeter;
import org.apache.jmeter.testbeans.TestBean;
import org.apache.jmeter.testbeans.TestBeanHelper;
import org.apache.jmeter.testelement.TestElement;
@@ -93,13 +94,8 @@
// e.g. from beanshell server
// Assumes that there is only one instance of the engine
// at any one time so it is not guaranteed to work ...
- private static Map/*<String, JMeterThread>*/ allThreadNames; //TODO does not appear to be populated yet
-
private volatile static StandardJMeterEngine engine;
- /** Unmodifiable static version of {@link allThreads} JMeterThread => JVM Thread */
- private static Map/*<JMeterThread, Thread>*/ allThreadsSave;
-
public static void stopEngineNow() {
if (engine != null) {// May be null if called from Unit test
engine.stopTest(true);
@@ -132,20 +128,24 @@
}
private static boolean stopThread(String threadName, boolean now) {
- if (allThreadNames == null) {
+ if (engine == null) {
return false;// e.g. not yet started
}
- JMeterThread thrd;
- try {
- thrd = (JMeterThread) allThreadNames.get(threadName);
- } catch (Exception e) {
- log.warn("stopThread: " + e);
- return false;
+ JMeterThread thrd=null;
+ synchronized (engine.allThreads) { // Protect iterator
+ Iterator iter = engine.allThreads.keySet().iterator();
+ while(iter.hasNext()){
+ thrd = (JMeterThread) iter.next();
+ if (thrd.getThreadName().equals(threadName)){
+ break; // Found matching thread
+ }
+ }
}
if (thrd != null) {
thrd.stop();
+ thrd.interrupt();
if (now) {
- Thread t = (Thread) allThreadsSave.get(thrd);
+ Thread t = (Thread) engine.allThreads.get(thrd);
if (t != null) {
t.interrupt();
}
@@ -163,11 +163,9 @@
public StandardJMeterEngine(String host) {
this.host = host;
- this.allThreads = new HashMap();
- // Hacks to allow external control
+ this.allThreads = Collections.synchronizedMap(new HashMap());
+ // Hack to allow external control
engine = this;
- allThreadNames = new HashMap();
- allThreadsSave = Collections.unmodifiableMap(allThreads);
}
public void configure(HashTree testTree) {
@@ -267,15 +265,15 @@
// Called by JMeter thread when it finishes
public synchronized void threadFinished(JMeterThread thread) {
- try {
- allThreads.remove(thread);
- log.info("Ending thread " + thread.getThreadName());
- if (!startingGroups && allThreads.size() == 0 ) {
- log.info("Stopping test");
- stopTest();
- }
- } catch (Throwable e) {
- log.fatalError("Call to threadFinished should never throw an exception - this can deadlock JMeter",e);
+ log.info("Ending thread " + thread.getThreadName());
+ allThreads.remove(thread);
+ if (!startingGroups && allThreads.size() == 0 ) {// All threads have exitted
+ new Thread(){// Ensure that the current sampler thread can exit cleanly
+ public void run() {
+ log.info("Stopping test");
+ notifyTestListenersOfEnd(testListenersSave);
+ }
+ }.start();
}
}
@@ -296,21 +294,25 @@
}
public void run() {
- if (running) {
- running = false;
- if (now) {
- tellThreadsToStop();
- } else {
- stopAllThreads();
- }
- try {
- Thread.sleep(10 * allThreads.size());
- } catch (InterruptedException e) {
- }
+ running = false;
+ engine = null;
+ if (now) {
+ tellThreadsToStop();
+ pause(10 * allThreads.size());
boolean stopped = verifyThreadsStopped();
- if (stopped || now) {
+ if (!stopped) {
notifyTestListenersOfEnd(testListenersSave);
- }
+ if (JMeter.isNonGUI()) {
+ exit();
+ } else {
+ JMeterUtils.reportErrorToUser(
+ JMeterUtils.getResString("stopping_test_failed"),
+ JMeterUtils.getResString("stopping_test_title"));
+ // TODO - perhaps allow option to stop them?
+ }
+ } // else will be done by threadFinished()
+ } else {
+ stopAllThreads();
}
}
}
@@ -426,10 +428,7 @@
if (serialized && iter.hasNext()) {
log.info("Waiting for thread group: "+groupName+" to finish before starting next group");
while (running && allThreads.size() > 0) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
+ pause(1000);
}
}
} // end of thread groups
@@ -476,17 +475,26 @@
private boolean verifyThreadsStopped() {
boolean stoppedAll = true;
- Iterator iter = new HashSet(allThreads.keySet()).iterator();
- while (iter.hasNext()) {
- Thread t = (Thread) allThreads.get(iter.next());
- if (t != null && t.isAlive()) {
+ List/*<Thread>*/ threadsToCheck = new ArrayList/*<Thread>*/(allThreads.size());
+ synchronized (allThreads) { // Protect iterator
+ Iterator/*<Thread>*/ iter = allThreads.keySet().iterator();
+ while (iter.hasNext()) {
+ Thread t = (Thread) allThreads.get(iter.next());
+ if (t != null) {
+ threadsToCheck.add(t); // Do work later to reduce time in synch block.
+ }
+ }
+ }
+ for(int i=0; i < threadsToCheck.size(); i++) {
+ Thread t = (Thread) threadsToCheck.get(i);
+ if (t.isAlive()) {
try {
t.join(WAIT_TO_DIE);
} catch (InterruptedException e) {
}
if (t.isAlive()) {
stoppedAll = false;
- log.warn("Thread won't die: " + t.getName());
+ log.warn("Thread won't exit: " + t.getName());
}
}
}
@@ -494,17 +502,14 @@
}
private void tellThreadsToStop() {
- Iterator iter = new HashSet(allThreads.keySet()).iterator();
- while (iter.hasNext()) {
- JMeterThread item = (JMeterThread) iter.next();
- item.stop(); // set stop flag
- item.interrupt(); // interrupt sampler if possible
- Thread t = (Thread) allThreads.get(item);
- if (t != null) {
+ synchronized (allThreads) { // Protect iterator
+ Iterator iter = new HashSet(allThreads.keySet()).iterator();
+ while (iter.hasNext()) {
+ JMeterThread item = (JMeterThread) iter.next();
+ item.stop(); // set stop flag
+ item.interrupt(); // interrupt sampler if possible
+ Thread t = (Thread) allThreads.get(item);
t.interrupt(); // also interrupt JVM thread
- } else {
- log.warn("Lost thread: " + item.getThreadName());
- allThreads.remove(item);
}
}
}
@@ -513,15 +518,13 @@
engine.stopTest(false);
}
- public void askThreadsToStopNow() {
- engine.stopTest(true);
- }
-
private void stopAllThreads() {
- Iterator iter = new HashSet(allThreads.keySet()).iterator();
- while (iter.hasNext()) {
- JMeterThread item = (JMeterThread) iter.next();
- item.stop();
+ synchronized (allThreads) {// Protect iterator
+ Iterator iter = new HashSet(allThreads.keySet()).iterator();
+ while (iter.hasNext()) {
+ JMeterThread item = (JMeterThread) iter.next();
+ item.stop(); // This is quick
+ }
}
}
@@ -531,10 +534,7 @@
Thread t = new Thread() {
public void run() {
// log.info("Pausing");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
+ pause(1000); // Allow RMI to complete
log.info("Bye");
System.exit(0);
}
@@ -543,6 +543,13 @@
t.start();
}
+ private void pause(long ms){
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ }
+ }
+
public void setProperties(Properties p) {
log.info("Applying properties "+p);
JMeterUtils.getJMeterProperties().putAll(p);
Modified: jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=767769&r1=767768&r2=767769&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Thu Apr 23 02:55:56 2009
@@ -769,6 +769,7 @@
starttime=Start Time
stop=Stop
stopping_test=Shutting down all test threads. Please be patient.
+stopping_test_failed=One or more test threads won't exit; see log file.
stopping_test_title=Stopping Test
string_from_file_file_name=Enter full path to file
string_from_file_seq_final=Final file sequence number (opt)
Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=767769&r1=767768&r2=767769&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Thu Apr 23 02:55:56 2009
@@ -241,6 +241,9 @@
<li>Mirror server now supports "X-Sleep" header - if this is set, the responding thread will wait for the specified number of milliseconds</li>
<li>Make some samplers interruptible: HTTP (both), SoapSampler, FTPSampler</li>
<li>Test Action now supports "Stop Now" action</li>
+<li>The Menu items Stop and Shutdown now behave better. Shutdown will now wait until all threads exit.
+In GUI mode it can be cancelled and Stop run instead.
+Stop now reports if some threads will not exit, and exits if running in non-GUI mode</li>
</ul>
<h3>Non-functional changes</h3>
---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org