Author: sebb
Date: Sat Oct 11 17:30:16 2008
New Revision: 703753

URL: http://svn.apache.org/viewvc?rev=703753&view=rev
Log:
Simplify code by using NoThreadClone
Make class Remoteable so output appears in client, not server logs

Modified:
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/reporters/Summariser.java

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/reporters/Summariser.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/reporters/Summariser.java?rev=703753&r1=703752&r2=703753&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/reporters/Summariser.java 
(original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/reporters/Summariser.java 
Sat Oct 11 17:30:16 2008
@@ -24,12 +24,13 @@
 import java.util.Map;
 
 import org.apache.jmeter.engine.event.LoopIterationEvent;
+import org.apache.jmeter.engine.util.NoThreadClone;
+import org.apache.jmeter.samplers.Remoteable;
 import org.apache.jmeter.samplers.SampleEvent;
 import org.apache.jmeter.samplers.SampleListener;
 import org.apache.jmeter.samplers.SampleResult;
 import org.apache.jmeter.testelement.AbstractTestElement;
 import org.apache.jmeter.testelement.TestListener;
-import org.apache.jmeter.testelement.ThreadListener;
 import org.apache.jmeter.util.JMeterUtils;
 import org.apache.jmeter.visualizers.RunningSample;
 import org.apache.jorphan.logging.LoggingManager;
@@ -51,9 +52,19 @@
  * this means that the delta interval is likely to be longer than the 
reporting interval.
  *
  * Also, the sum of the delta intervals will be larger than the overall 
elapsed time.
+ * 
+ * Data is accumulated according to the test element name.
  *
  */
-public class Summariser extends AbstractTestElement implements Serializable, 
SampleListener, TestListener, ThreadListener {
+public class Summariser extends AbstractTestElement 
+    implements Serializable, SampleListener, TestListener, NoThreadClone, 
Remoteable {
+
+    /*
+     * N.B. NoThreadClone is used to ensure that the testStarted() methods 
will share the same
+     * instance as the sampleOccured() methods, so the testStarted() method 
can fetch the
+     * Totals accumulator object for the samples to be stored in. 
+     */
+
     private static final long serialVersionUID = 233L;
 
     private static final Logger log = LoggingManager.getLoggerForClass();
@@ -73,14 +84,14 @@
      */
     private static final int INTERVAL_WINDOW = 5; // in seconds
 
-    /**
-     * Summariser elements are cloned for each thread in each group; this Map 
is
-     * used to allow them to share the same statistics. The key is the
-     * Summariser name, so all Summarisers with the same name will use the same
-     * accumulators.
+    /*
+     * This map allows summarisers with the same name to contribute to the 
same totals.
      */
     //@GuardedBy("accumulators")
     private static final Hashtable accumulators = new Hashtable();
+    
+    //@GuardedBy("accumulators")
+    private static int instanceCount; // number of active tests
 
     /*
      * Cached copy of Totals for this instance.
@@ -91,6 +102,7 @@
     //@GuardedBy("myTotals")
     private transient Totals myTotals = null;
 
+    // Name of the accumulator. Set up by testStarted().
     private transient String myName;
 
     /*
@@ -102,6 +114,10 @@
      */
     public Summariser() {
         super();
+        synchronized (accumulators) {
+            accumulators.clear();
+            instanceCount=0;
+        }
     }
 
     /**
@@ -266,6 +282,17 @@
     }
 
     /*
+     * The testStarted/testEnded methods are called at the start and end of a 
test.
+     * 
+     * However, when a test is run on multiple nodes, there is no guarantee 
that all the
+     * testStarted() methods will be called before all the threadStart() or 
sampleOccurred()
+     * methods for other threads - nor that testEnded() will only be called 
after all
+     * sampleOccurred() calls. The ordering is only guaranteed within a single 
test.
+     * 
+     */
+    
+    
+    /*
      * (non-Javadoc)
      *
      * @see org.apache.jmeter.testelement.TestListener#testStarted()
@@ -288,16 +315,23 @@
      *
      * Called once for each Summariser in the test plan.
      * There may be more than one summariser with the same name,
-     * however they will all be called before the test proper starts,
-     * so it does not matter if the totals are reset again.
+     * however they will all be called before the test proper starts.
+     * 
+     * However, note that this applies to a single test only.
+     * When running in client-server mode, testStarted() may be 
+     * invoked after sampleOccurred().
      *
      * @see 
org.apache.jmeter.testelement.TestListener#testStarted(java.lang.String)
      */
     public void testStarted(String host) {
-        // testStarted and testFinished are called from different threads,
-        // so need to synch for visibility.
         synchronized (accumulators) {
-            accumulators.clear(); // Should not be needed, but just in case 
previous run does not clear up.
+            myName = getName();
+            myTotals = (Totals) accumulators.get(myName);
+            if (myTotals == null){
+                myTotals = new Totals();
+                accumulators.put(myName, myTotals);
+            }
+            instanceCount++;
         }
     }
 
@@ -308,17 +342,24 @@
      * @see 
org.apache.jmeter.testelement.TestListener#testEnded(java.lang.String)
      */
     public void testEnded(String host) {
-        Object[] totals;
+        Object[] totals = null;
         synchronized (accumulators) {
-            totals = accumulators.entrySet().toArray();
-            accumulators.clear(); // Instance is not needed anymore
+            instanceCount--;
+            if (instanceCount <= 0){
+                totals = accumulators.entrySet().toArray();                
+            }
+        }
+        if (totals == null) {// We're not done yet
+            return;
         }
         for (int i=0; i<totals.length; i++) {
             Map.Entry me = (Map.Entry)totals[i];
             String str;
             String name = (String) me.getKey();
             Totals total = (Totals) me.getValue();
-            if (total.total.getNumSamples() != 0) {// Only print delta if 
different from total
+            // Only print final delta if there were some samples in the delta
+            // and there has been at least one sample reported previously
+            if (total.delta.getNumSamples() > 0 && total.total.getNumSamples() 
>  0) {
                 str = format(name, total.delta, "+");
                 if (TOLOG) {
                     log.info(str);
@@ -346,20 +387,4 @@
     public void testIterationStart(LoopIterationEvent event) {
         // not used
     }
-
-    public void threadFinished() {
-        // not used
-    }
-
-    public void threadStarted() {
-        myName = getName();
-        synchronized (accumulators) {
-            myTotals = (Totals) accumulators.get(myName);
-            if (myTotals == null){
-                myTotals = new Totals();
-                accumulators.put(myName, myTotals);
-            }
-        }
-    }
-
 }
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to