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 2006/03/25 23:05:35 UTC

svn commit: r388841 - in /jakarta/jmeter/branches/rel-2-1: src/functions/org/apache/jmeter/functions/IterationCounter.java xdocs/changes.xml xdocs/usermanual/functions.xml

Author: sebb
Date: Sat Mar 25 14:05:33 2006
New Revision: 388841

URL: http://svn.apache.org/viewcvs?rev=388841&view=rev
Log:
Fix counter function to use independent per-user counters

Modified:
    jakarta/jmeter/branches/rel-2-1/src/functions/org/apache/jmeter/functions/IterationCounter.java
    jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml
    jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/functions.xml

Modified: jakarta/jmeter/branches/rel-2-1/src/functions/org/apache/jmeter/functions/IterationCounter.java
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/src/functions/org/apache/jmeter/functions/IterationCounter.java?rev=388841&r1=388840&r2=388841&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/src/functions/org/apache/jmeter/functions/IterationCounter.java (original)
+++ jakarta/jmeter/branches/rel-2-1/src/functions/org/apache/jmeter/functions/IterationCounter.java Sat Mar 25 14:05:33 2006
@@ -1,6 +1,5 @@
-// $Header$
 /*
- * Copyright 2001-2004 The Apache Software Foundation.
+ * Copyright 2001-2004, 2006 The Apache Software Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,8 +34,12 @@
 
 	private static final String KEY = "__counter";
 
-	private static final String perThreadCounter = "perThreadCounter";
-
+    private transient ThreadLocal perThreadInt = new ThreadLocal(){
+        protected synchronized Object initialValue() {
+            return new Integer(0);
+        }
+    };
+    
 	static {
 		desc.add(JMeterUtils.getResString("iteration_counter_arg_1"));
 		desc.add(JMeterUtils.getResString("function_name_param"));
@@ -44,20 +47,15 @@
 
 	transient private Object[] variables;
 
-	transient private int[] counter;
-
-	transient private String key; // Used to keep track of counter
+	transient private int globalCounter;//MAXINT = 2,147,483,647
 
 	public IterationCounter() {
-		counter = new int[1];
-		// TODO use better key if poss. Can't use varName - it may not be
-		// present
-		key = KEY + System.identityHashCode(this);
-	}
+        globalCounter=0;
+    }
 
 	public Object clone() {
 		IterationCounter newCounter = new IterationCounter();
-		newCounter.counter = counter;
+		newCounter.globalCounter = globalCounter;
 		return newCounter;
 	}
 
@@ -68,29 +66,28 @@
 	 */
 	public synchronized String execute(SampleResult previousResult, Sampler currentSampler)
 			throws InvalidVariableException {
-		counter[0]++;
+
+        new Integer(1);
+        globalCounter++;
 
 		JMeterVariables vars = getVariables();
 
 		boolean perThread = Boolean.valueOf(((CompoundVariable) variables[0]).execute()).booleanValue();
 
-		String varName = ((CompoundVariable) variables[variables.length - 1]).execute();
-		String counterString = "";
+		String varName = "";
+        if (variables.length >=2) {// Ensure variable has been provided
+            varName = ((CompoundVariable) variables[1]).execute();
+        }
+		
+        String counterString = "";
 
 		if (perThread) {
-			// counterString = Integer.toString(vars.getIteration());
-			int counterInt;
-			try {
-				counterInt = ((Integer) vars.getObject(perThreadCounter)).intValue() + 1;
-
-			} catch (NullPointerException e) {
-				// First Time! Initialize
-				counterInt = 1;
-			}
-			vars.putObject(perThreadCounter, new Integer(counterInt));
-			counterString = Integer.toString(counterInt);
+			int threadCounter;
+            threadCounter = ((Integer) perThreadInt.get()).intValue() + 1;                
+            perThreadInt.set(new Integer(threadCounter));
+			counterString = String.valueOf(threadCounter);
 		} else {
-			counterString = String.valueOf(counter[0]);
+			counterString = String.valueOf(globalCounter);
 		}
 
 		if (varName.length() > 0)
@@ -107,8 +104,8 @@
 
 		variables = parameters.toArray();
 
-		if (variables.length < 2) {
-			throw new InvalidVariableException("Fewer than 2 parameters");
+		if (variables.length < 1) {
+			throw new InvalidVariableException("Need at least 1 parameter");
 		}
 	}
 

Modified: jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml?rev=388841&r1=388840&r2=388841&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml (original)
+++ jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml Sat Mar 25 14:05:33 2006
@@ -105,6 +105,7 @@
 <li>Add write(OS,IS) implementation to TCPClientImpl</li>
 <li>Sample Result converter saves response code as "rc". Previously it saved as "rs" but read with "rc"; it will now also read with "rc".
 The XSL stylesheets also now accept either "rc" or "rs"</li>
+<li>Fix counter function so each counter instance is independent (previously the per-user counters were shared between instances of the function)</li>
 </ul>	
 	
 <h4>Other changes</h4>

Modified: jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/functions.xml
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/functions.xml?rev=388841&r1=388840&r2=388841&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/functions.xml (original)
+++ jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/functions.xml Sat Mar 25 14:05:33 2006
@@ -84,6 +84,8 @@
 With built-in functions users can compute new values at run-time based on previous response data, which
 thread the function is in, the time, and many other sources.  These values are generated fresh for every
 request throughout the course of the test. </p>
+<note>Functions are shared between threads. 
+Each occurrence of a function call in a test plan is handled by a separate function instance.</note>
 </subsection>
 
 <subsection name="&sect-num;.2 Where can functions be used?" anchor="where">
@@ -182,17 +184,24 @@
 <component index="&sect-num;.5.2" name="__counter">
 <description><p>The counter generates a new number each time it is called, starting with 1
 and incrementing by +1 each time.  The counter can be configured to keep each simulated user's values
-separate, or to use the same counter for all user.  If each user's values is incremented separately,
+separate, or to use the same counter for all users.  If each user's values is incremented separately,
 that is like counting the number of iterations through the test plan.  A global counter is like
-counting how many times that request was run.</p></description>
-
+counting how many times that request was run.
+</p>
+<p>The counter uses an integer variable to hold the count, which therefore has a maximum of 2,147,483,647.</p>
+<p>The counter function instances are now completely independent. 
+[JMeter 2.1.1 and earlier used a fixed thread variable to keep track of the per-user count, 
+so multiple counter functions operated on the same value.] 
+The global counter - "FALSE" - is separately maintained by each counter instance.
+</p>
+</description>
 <properties>
         <property name="First argument" required="Yes">TRUE if you wish each simulated user's counter
         to be kept independent and separate from the other users.  FALSE for a global counter.</property>
 
-<property name="Second argument" required="Yes">A reference name for reusing the value created by this function.<br></br>
+<property name="Second argument" required="No">A reference name for reusing the value created by this function.<br></br>
                 Stored values are of the form ${refName}.  This allows you to keep one counter and refer to its value in
-                multiple places.</property>
+                multiple places. [For JMeter 2.1.1 and earlier this parameter was required.]</property>
 </properties>
 </component>
 



---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org