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 2007/05/26 12:16:21 UTC

svn commit: r541883 - in /jakarta/jmeter/branches/rel-2-2: src/core/org/apache/jmeter/control/ src/core/org/apache/jmeter/threads/ xdocs/ xdocs/usermanual/

Author: sebb
Date: Sat May 26 03:16:18 2007
New Revision: 541883

URL: http://svn.apache.org/viewvc?view=rev&rev=541883
Log:
Bug 41913 - TransactionController now creates samples as sub-samples of the transaction

Added:
    jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionSampler.java   (with props)
Modified:
    jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionController.java
    jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/JMeterThread.java
    jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/TestCompiler.java
    jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml
    jakarta/jmeter/branches/rel-2-2/xdocs/usermanual/component_reference.xml

Modified: jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionController.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionController.java?view=diff&rev=541883&r1=541882&r2=541883
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionController.java (original)
+++ jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionController.java Sat May 26 03:16:18 2007
@@ -20,15 +20,7 @@
 
 import java.io.Serializable;
 
-import org.apache.jmeter.samplers.SampleEvent;
-import org.apache.jmeter.samplers.SampleListener;
-import org.apache.jmeter.samplers.SampleResult;
 import org.apache.jmeter.samplers.Sampler;
-import org.apache.jmeter.threads.JMeterContext;
-import org.apache.jmeter.threads.JMeterThread;
-import org.apache.jmeter.threads.JMeterVariables;
-import org.apache.jmeter.threads.ListenerNotifier;
-import org.apache.jmeter.threads.SamplePackage;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.log.Logger;
 
@@ -36,108 +28,37 @@
  * Transaction Controller to measure transaction times
  * 
  */
-public class TransactionController extends GenericController implements SampleListener, Controller, Serializable {
-	protected static final Logger log = LoggingManager.getLoggerForClass();
+public class TransactionController extends GenericController implements Controller, Serializable {
+	private static final Logger log = LoggingManager.getLoggerForClass();
 
-	transient private String threadName;
+    transient private TransactionSampler transactionSampler;
 
-	transient private ListenerNotifier lnf;
-
-	transient private SampleResult res;
-    
-    transient private int calls;
-
-    transient private int noFailingSamples;
-
-	/**
-	 * Creates a Transaction Controller
-	 */
-	public TransactionController() {
-		threadName = Thread.currentThread().getName();
-		lnf = new ListenerNotifier();
-	}
-
-    private Object readResolve(){
-        threadName = Thread.currentThread().getName();
-        lnf = new ListenerNotifier();
-        return this;
-    }
-
-    private void log_debug(String s) {
-		String n = this.getName();
-		log.debug(threadName + " " + n + " " + s);
-	}
-    
 	/**
 	 * @see org.apache.jmeter.control.Controller#next()
 	 */
 	public Sampler next() {
+        // Check if transaction is done
+        if(transactionSampler != null && transactionSampler.isTransactionDone()) {
+            log.debug("End of transaction");
+            // This transaction is done
+            transactionSampler = null;
+            return null;
+        }
+        
+        // Check if it is the start of a new transaction
 		if (isFirst()) // must be the start of the subtree
 		{
-			log_debug("+++++++++++++++++++++++++++++");
-			calls = 0;
-            noFailingSamples = 0;
-			res = new SampleResult();
-            res.setSampleLabel(getName());
-            // Assume success
-            res.setSuccessful(true);
-			res.sampleStart();
+		    log.debug("Start of transaction");
+		    transactionSampler = new TransactionSampler(this, getName());
 		}
 
-        Sampler returnValue = super.next();
-        
-		if (returnValue == null) // Must be the end of the controller
-		{
-			log_debug("-----------------------------" + calls);
-			if (res == null) {
-				log_debug("already called");
-			} else {
-				res.sampleEnd();
-                res.setResponseMessage("Number of samples in transaction : " + calls + ", number of failing samples : " + noFailingSamples);
-                if(res.isSuccessful()) {
-                    res.setResponseCodeOK();
-                }
-
-				// TODO could these be done earlier (or just once?)
-                JMeterContext threadContext = getThreadContext();
-                JMeterVariables threadVars = threadContext.getVariables();
-
-				SamplePackage pack = (SamplePackage) threadVars.getObject(JMeterThread.PACKAGE_OBJECT);
-				if (pack == null) {
-					log.warn("Could not fetch SamplePackage");
-				} else {
-                    SampleEvent event = new SampleEvent(res, getName());
-                    // We must set res to null now, before sending the event for the transaction,
-                    // so that we can ignore that event in our sampleOccured method 
-                    res = null;
-					lnf.notifyListeners(event, pack.getSampleListeners());
-				}
-			}
-		}
-        else {
-            // We have sampled one of our children
-            calls++;            
+        // Sample the children of the transaction
+		Sampler subSampler = super.next();
+        transactionSampler.setSubSampler(subSampler);
+        // If we do not get any sub samplers, the transaction is done
+        if (subSampler == null) {
+            transactionSampler.setTransactionDone();
         }
-
-		return returnValue;
+        return transactionSampler;
 	}
-    
-    public void sampleOccurred(SampleEvent se) {
-        // Check if we have are still sampling our children
-        if(res != null) {
-            SampleResult sampleResult = se.getResult(); 
-            res.setThreadName(sampleResult.getThreadName());
-            res.setBytes(res.getBytes() + sampleResult.getBytes());
-            if(!sampleResult.isSuccessful()) {
-                res.setSuccessful(false);
-                noFailingSamples++;
-            }
-       }
-    }
-
-    public void sampleStarted(SampleEvent e) {
-    }
-
-    public void sampleStopped(SampleEvent e) {
-    }
 }

Added: jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionSampler.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionSampler.java?view=auto&rev=541883
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionSampler.java (added)
+++ jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionSampler.java Sat May 26 03:16:18 2007
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+/*
+ *  N.B. Although this is a type of sampler, it is only used by the transaction controller,
+ *  and so is in the control package
+*/
+package org.apache.jmeter.control;
+
+
+import org.apache.jmeter.samplers.AbstractSampler;
+import org.apache.jmeter.samplers.Entry;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.samplers.Sampler;
+
+/**
+ * Transaction Controller to measure transaction times
+ * 
+ */
+public class TransactionSampler extends AbstractSampler {
+  private boolean transactionDone = false;
+
+    private TransactionController transactionController; 
+    
+	private Sampler subSampler;
+
+	private SampleResult transactionSampleResult;
+
+	private int calls = 0;
+
+	private int noFailingSamples = 0;
+
+	public TransactionSampler(){
+		//log.warn("Constructor only intended for use in testing");
+	}
+
+	public TransactionSampler(TransactionController controller, String name) {
+        transactionController = controller;
+		transactionSampleResult = new SampleResult();
+		transactionSampleResult.setSampleLabel(name);
+		// Assume success
+		transactionSampleResult.setSuccessful(true);
+		transactionSampleResult.sampleStart();
+	}
+
+    /**
+     * One cannot sample the TransactionSample directly.
+     */
+	public SampleResult sample(Entry e) {
+        // It is the JMeterThread which knows how to sample a
+        // real sampler
+        return null;
+	}
+    
+    public Sampler getSubSampler() {
+        return subSampler;
+    }
+    
+    public SampleResult getTransactionResult() {
+        return transactionSampleResult;
+    }
+    
+    public TransactionController getTransactionController() {
+        return transactionController;
+    }
+
+    public boolean isTransactionDone() {
+        return transactionDone;
+    }
+    
+    public void addSubSamplerResult(SampleResult res) {
+        // Another subsample for the transaction
+        calls++;
+        // The transaction fails if any sub sample fails
+        if (!res.isSuccessful()) {
+            transactionSampleResult.setSuccessful(false);
+            noFailingSamples++;
+        }
+        // Add the sub result to the transaction result
+        transactionSampleResult.addSubResult(res);
+    }
+
+	protected void setTransactionDone() {
+		this.transactionDone = true;
+		// Set the overall status for the transaction sample
+		// TODO: improve, e.g. by adding counts to the SampleResult class
+		transactionSampleResult.setResponseMessage("Number of samples in transaction : "
+						+ calls + ", number of failing samples : "
+						+ noFailingSamples);
+		if (transactionSampleResult.isSuccessful()) {
+			transactionSampleResult.setResponseCodeOK();
+		}
+	}
+
+	protected void setSubSampler(Sampler subSampler) {
+		this.subSampler = subSampler;
+	}
+}

Propchange: jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionSampler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/control/TransactionSampler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/JMeterThread.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/JMeterThread.java?view=diff&rev=541883&r1=541882&r2=541883
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/JMeterThread.java (original)
+++ jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/JMeterThread.java Sat May 26 03:16:18 2007
@@ -19,6 +19,7 @@
 package org.apache.jmeter.threads;
 
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -27,12 +28,14 @@
 import org.apache.jmeter.assertions.Assertion;
 import org.apache.jmeter.assertions.AssertionResult;
 import org.apache.jmeter.control.Controller;
+import org.apache.jmeter.control.TransactionSampler;
 import org.apache.jmeter.engine.StandardJMeterEngine;
 import org.apache.jmeter.engine.event.LoopIterationEvent;
 import org.apache.jmeter.engine.event.LoopIterationListener;
 import org.apache.jmeter.gui.GuiPackage;
 import org.apache.jmeter.processor.PostProcessor;
 import org.apache.jmeter.samplers.SampleEvent;
+import org.apache.jmeter.samplers.SampleListener;
 import org.apache.jmeter.samplers.SampleResult;
 import org.apache.jmeter.samplers.Sampler;
 import org.apache.jmeter.testbeans.TestBeanHelper;
@@ -56,7 +59,7 @@
 public class JMeterThread implements Runnable, Serializable {
 	private static final Logger log = LoggingManager.getLoggerForClass();
 
-	private static final long serialVersionUID = 221L; // Remember to change this when the class changes ...
+	private static final long serialVersionUID = 23L; // Remember to change this when the class changes ...
 	
 	// NOT USED private static Map samplers = new HashMap();
 	private int initialDelay = 0;
@@ -100,8 +103,6 @@
 
 	private boolean onErrorStopThread;
 
-	public static final String PACKAGE_OBJECT = "JMeterThread.pack"; // $NON-NLS-1$
-
 	public static final String LAST_SAMPLE_OK = "JMeterThread.last_sample_ok"; // $NON-NLS-1$
 
 	public JMeterThread() {
@@ -244,41 +245,82 @@
 				while (running && (sam = controller.next()) != null) {
 					try {
 						threadContext.setCurrentSampler(sam);
-						SamplePackage pack = compiler.configureSampler(sam);
-
-						// Hack: save the package for any transaction
-						// controllers
-						threadContext.getVariables().putObject(PACKAGE_OBJECT, pack);
-
-						delay(pack.getTimers());
-						Sampler sampler = pack.getSampler();
-						sampler.setThreadContext(threadContext);
-						sampler.setThreadName(threadName);
-						TestBeanHelper.prepare(sampler);
-						SampleResult result = sampler.sample(null); 
-                        // TODO: remove this useless Entry parameter
                         
-						if (result != null) {
-							result.setThreadName(threadName);
-							threadContext.setPreviousResult(result);
-							runPostProcessors(pack.getPostProcessors());
-							checkAssertions(pack.getAssertions(), result);
-							notifyListeners(pack.getSampleListeners(), result);
-							compiler.done(pack);
-							if (result.isStopThread() || (!result.isSuccessful() && onErrorStopThread)) {
-								stopThread();
-							}
-							if (result.isStopTest() || (!result.isSuccessful() && onErrorStopTest)) {
-								stopTest();
-							}
-						} else {
-                            compiler.done(pack); // Finish up
+                        // Check if we are running a transaction
+                        TransactionSampler transactionSampler = null;
+                        if(sam instanceof TransactionSampler) {
+                            transactionSampler = (TransactionSampler) sam;
+                        }
+                        // Find the package for the transaction
+                        SamplePackage transactionPack = null;
+                        if(transactionSampler != null) {
+                            transactionPack = compiler.configureTransactionSampler(transactionSampler);
+                            
+                            // Check if the transaction is done
+                            if(transactionSampler.isTransactionDone()) {
+                                // Get the transaction sample result
+                                SampleResult transactionResult = transactionSampler.getTransactionResult();
+
+                                // Check assertions for the transaction sample
+                                transactionResult.setThreadName(threadName);
+                                checkAssertions(transactionPack.getAssertions(), transactionResult);
+                                // Notify listeners with the transaction sample result
+                                notifyListeners(transactionPack.getSampleListeners(), transactionResult);
+                                compiler.done(transactionPack);
+                                // Transaction is done, we do not have a sampler to sample
+                                sam = null;
+                            }
+                            else {
+                                // It is the sub sampler of the transaction that will be sampled
+                                sam = transactionSampler.getSubSampler();
+                            }
+                        }
+                        
+                        // Check if we have a sampler to sample
+                        if(sam != null) {
+                            // Get the sampler ready to sample
+                            SamplePackage pack = compiler.configureSampler(sam);
+
+                            delay(pack.getTimers());
+                            Sampler sampler = pack.getSampler();
+                            sampler.setThreadContext(threadContext);
+                            sampler.setThreadName(threadName);
+                            TestBeanHelper.prepare(sampler);
+                        
+                            // Perform the actual sample
+                            SampleResult result = sampler.sample(null); 
+                            // TODO: remove this useless Entry parameter
+                        
+                            // If we got any results, then perform processing on the result
+                            if (result != null) {
+                                result.setThreadName(threadName);
+                                threadContext.setPreviousResult(result);
+                                runPostProcessors(pack.getPostProcessors());
+                                checkAssertions(pack.getAssertions(), result);
+                                // Do not send subsamples to listeners which receive the transaction sample
+                                List sampleListeners = getSampleListeners(pack, transactionPack, transactionSampler);
+                                notifyListeners(sampleListeners, result);
+                                compiler.done(pack);
+                                // Add the result as subsample of transaction if we are in a transaction
+                                if(transactionSampler != null) {
+                                    transactionSampler.addSubSamplerResult(result);
+                                }
+
+                                // Check if thread or test should be stopped
+                                if (result.isStopThread() || (!result.isSuccessful() && onErrorStopThread)) {
+                                    stopThread();
+                                }
+                                if (result.isStopTest() || (!result.isSuccessful() && onErrorStopTest)) {
+                                    stopTest();
+                                }
+                            } else {
+                                compiler.done(pack); // Finish up
+                            }
                         }
 						if (scheduler) {
 							// checks the scheduler to stop the iteration
 							stopScheduler();
 						}
-
 					} catch (JMeterStopTestException e) {
 						log.info("Stopping Test: " + e.toString());
 						stopTest();
@@ -313,6 +355,41 @@
 			threadFinished();
 		}
 	}
+    
+    /**
+     * Get the SampleListeners for the sampler. Listeners who receive transaction sample
+     * will not be in this list.
+     * 
+     * @param samplePack
+     * @param transactionPack
+     * @param transactionSampler
+     * @return the listeners who should receive the sample result
+     */
+    private List getSampleListeners(SamplePackage samplePack, SamplePackage transactionPack, TransactionSampler transactionSampler) {
+        List sampleListeners = samplePack.getSampleListeners();
+        // Do not send subsamples to listeners which receive the transaction sample
+        if(transactionSampler != null) {
+            ArrayList onlySubSamplerListeners = new ArrayList();
+            List transListeners = transactionPack.getSampleListeners();
+            for(Iterator i = sampleListeners.iterator(); i.hasNext();) {
+                SampleListener listener = (SampleListener)i.next();
+                // Check if this instance is present in transaction listener list
+                boolean found = false;
+                for(Iterator j = transListeners.iterator(); j.hasNext();) {
+                    // Check for the same instance
+                    if(j.next() == listener) {
+                        found = true;
+                        break;
+                    }
+                }
+                if(!found) {
+                    onlySubSamplerListeners.add(listener);
+                }
+            }
+            sampleListeners = onlySubSamplerListeners;
+        }
+        return sampleListeners;
+    }
 
 	/**
 	 * 
@@ -485,7 +562,6 @@
 
 	private void notifyListeners(List listeners, SampleResult result) {
 		SampleEvent event = new SampleEvent(result, controller.getPropertyAsString(TestElement.NAME));
-		compiler.sampleOccurred(event);
 		notifier.notifyListeners(event, listeners);
 
 	}

Modified: jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/TestCompiler.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/TestCompiler.java?view=diff&rev=541883&r1=541882&r2=541883
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/TestCompiler.java (original)
+++ jakarta/jmeter/branches/rel-2-2/src/core/org/apache/jmeter/threads/TestCompiler.java Sat May 26 03:16:18 2007
@@ -18,7 +18,6 @@
 
 package org.apache.jmeter.threads;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -31,10 +30,11 @@
 import org.apache.jmeter.assertions.Assertion;
 import org.apache.jmeter.config.ConfigTestElement;
 import org.apache.jmeter.control.Controller;
+import org.apache.jmeter.control.TransactionController;
+import org.apache.jmeter.control.TransactionSampler;
 import org.apache.jmeter.engine.event.LoopIterationListener;
 import org.apache.jmeter.processor.PostProcessor;
 import org.apache.jmeter.processor.PreProcessor;
-import org.apache.jmeter.samplers.SampleEvent;
 import org.apache.jmeter.samplers.SampleListener;
 import org.apache.jmeter.samplers.Sampler;
 import org.apache.jmeter.testbeans.TestBeanHelper;
@@ -46,17 +46,15 @@
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.log.Logger;
 
-/**
- * @author unascribed
- * @version $Revision$
- */
-public class TestCompiler implements HashTreeTraverser, SampleListener {
+public class TestCompiler implements HashTreeTraverser {
 	private static final Logger log = LoggingManager.getLoggerForClass();
 
 	private LinkedList stack = new LinkedList();
 
 	private Map samplerConfigMap = new HashMap();
 
+	private Map transactionControllerConfigMap = new HashMap();
+	
 	private HashTree testTree;
 
 	/*
@@ -65,7 +63,7 @@
 	 */
 	private static Set pairing = new HashSet();
 
-	List loopIterListeners = new ArrayList();
+	//List loopIterListeners = new ArrayList();
 
 	public TestCompiler(HashTree testTree, JMeterVariables vars) {
 		this.testTree = testTree;
@@ -82,16 +80,6 @@
 		}
 	}
 
-	public void sampleOccurred(SampleEvent e) {
-		// NOTREAD previousResult = e.getResult();
-	}
-
-	public void sampleStarted(SampleEvent e) {
-	}
-
-	public void sampleStopped(SampleEvent e) {
-	}
-
 	public SamplePackage configureSampler(Sampler sampler) {
 		SamplePackage pack = (SamplePackage) samplerConfigMap.get(sampler);
 		pack.setSampler(sampler);
@@ -99,6 +87,13 @@
 		runPreProcessors(pack.getPreProcessors());
 		return pack;
 	}
+    
+    public SamplePackage configureTransactionSampler(TransactionSampler transactionSampler) {
+        TransactionController controller = transactionSampler.getTransactionController();
+        SamplePackage pack = (SamplePackage) transactionControllerConfigMap.get(controller);
+        pack.setSampler(transactionSampler);
+        return pack;
+    }
 
 	private void runPreProcessors(List preProcessors) {
 		Iterator iter = preProcessors.iterator();
@@ -127,6 +122,9 @@
 		if (child instanceof Sampler) {
 			saveSamplerConfigs((Sampler) child);
 		}
+        else if(child instanceof TransactionController) {
+            saveTransactionControllerConfigs((TransactionController) child);
+        }
 		stack.removeLast();
 		if (stack.size() > 0) {
 			ObjectPair pair = new ObjectPair(child, (TestElement) stack.getLast());
@@ -206,6 +204,37 @@
 		pack.setRunningVersion(true);
 		samplerConfigMap.put(sam, pack);
 	}
+    
+    private void saveTransactionControllerConfigs(TransactionController tc) {
+        List configs = new LinkedList();
+        List modifiers = new LinkedList();
+        List controllers = new LinkedList();
+        List responseModifiers = new LinkedList();
+        List listeners = new LinkedList();
+        List timers = new LinkedList();
+        List assertions = new LinkedList();
+        LinkedList posts = new LinkedList();
+        LinkedList pres = new LinkedList();
+        for (int i = stack.size(); i > 0; i--) {
+            addDirectParentControllers(controllers, (TestElement) stack.get(i - 1));
+            Iterator iter = testTree.list(stack.subList(0, i)).iterator();
+            while (iter.hasNext()) {
+                TestElement item = (TestElement) iter.next();
+                if (item instanceof SampleListener) {
+                    listeners.add(item);
+                }
+                if (item instanceof Assertion) {
+                    assertions.add(item);
+                }
+            }
+        }
+
+        SamplePackage pack = new SamplePackage(configs, modifiers, responseModifiers, listeners, timers, assertions,
+                posts, pres, controllers);
+        pack.setSampler(new TransactionSampler(tc, tc.getName()));
+        pack.setRunningVersion(true);
+        transactionControllerConfigMap.put(tc, pack);
+    }
 
 	/**
 	 * @param controllers

Modified: jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml?view=diff&rev=541883&r1=541882&r2=541883
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml (original)
+++ jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml Sat May 26 03:16:18 2007
@@ -42,6 +42,7 @@
 <li>__V() function allows support of nested variable references</li>
 <li>LDAP Ext sampler optionally parses result sets and supports secure mode</li>
 <li>FTP Sampler supports Ascii/Binary mode and upload</li>
+<li>Transaction Controller now generates Sample with subresults</li>
 </ul>
 <p>
 The main bug fixes are:
@@ -88,6 +89,7 @@
 so the temporary work-round of using '\' and '@' in the username to delimit the domain and realm
 has been removed.
 </p>
+<p>The Transaction Controller no longer appears as a separate sample; it now includes its nested samples as subsamples</p>
 <h4>Incompatible changes (development):</h4>
 <p>
 Calulator and SamplingStatCalculator classes no longer provide any formatting of their data.
@@ -143,6 +145,7 @@
 <li>Allow user to cancel out of Close dialogue</li>
 <li>Use ISO date-time format for Tree View Listener (previously the year was not shown)</li>
 <li>Improve loading of CSV files: if possible, use header to determine format; guess timestamp format if not milliseconds</li>
+<li>Bug 41913 - TransactionController now creates samples as sub-samples of the transaction</li>
 </ul>
 
 <h4>Non-functional improvements:</h4>

Modified: jakarta/jmeter/branches/rel-2-2/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/xdocs/usermanual/component_reference.xml?view=diff&rev=541883&r1=541882&r2=541883
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/branches/rel-2-2/xdocs/usermanual/component_reference.xml Sat May 26 03:16:18 2007
@@ -1426,6 +1426,12 @@
 		The clock might tick after the controller recorded the start time but before the first sample starts.
 		Similarly at the end.
 		</p>
+		<p>For JMeter versions after 2.2, the controlled samples no longer appear as separate samples, but as subsamples.
+		Also the Transaction Sample is only regarded as successful if all its sub-samples are successful.
+		This is similar to the way the HTTP Samplers work when retrieving embedded objects (images etc).
+		The individual samples can still be seen in the Tree View Listener,
+		but no longer appear as separate entries in other Listeners.
+		</p>
 	</description>
 <properties>
 	<property name="Name" required="Yes">Descriptive name for this controller that is shown in the tree, and used to name the transaction.</property>



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