Index: src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java =================================================================== --- src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java (revision 910417) +++ src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java (working copy) @@ -59,7 +59,7 @@ import org.apache.jmeter.testelement.property.JMeterProperty; import org.apache.jmeter.testelement.property.PropertyIterator; import org.apache.jmeter.testelement.property.StringProperty; -import org.apache.jmeter.threads.ThreadGroup; +import org.apache.jmeter.threads.AbstractThreadGroup; import org.apache.jmeter.timers.Timer; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.logging.LoggingManager; @@ -638,7 +638,7 @@ * * @@ -654,7 +654,7 @@ if (myTarget != null) { return myTarget; } - myTarget = findFirstNodeOfType(ThreadGroup.class); + myTarget = findFirstNodeOfType(AbstractThreadGroup.class); if (myTarget != null) { return myTarget; } Index: src/protocol/tcp/org/apache/jmeter/protocol/tcp/sampler/TCPSampler.java =================================================================== --- src/protocol/tcp/org/apache/jmeter/protocol/tcp/sampler/TCPSampler.java (revision 910417) +++ src/protocol/tcp/org/apache/jmeter/protocol/tcp/sampler/TCPSampler.java (working copy) @@ -332,7 +332,8 @@ } } } - } catch (IOException ex) { + } catch (Exception ex) { + isSuccessful=false; log.debug("", ex); res.setResponseCode("500"); //$NON-NLS-1$ res.setResponseMessage(ex.toString()); Index: src/components/org/apache/jmeter/control/gui/ModuleControllerGui.java =================================================================== --- src/components/org/apache/jmeter/control/gui/ModuleControllerGui.java (revision 910417) +++ src/components/org/apache/jmeter/control/gui/ModuleControllerGui.java (working copy) @@ -38,7 +38,7 @@ import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; import org.apache.jmeter.testelement.WorkBench; -import org.apache.jmeter.threads.ThreadGroup; +import org.apache.jmeter.threads.AbstractThreadGroup; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.layout.VerticalLayout; @@ -205,7 +205,7 @@ StringBuilder name = new StringBuilder(); JMeterTreeNode cur = (JMeterTreeNode) node.getChildAt(i); TestElement te = cur.getTestElement(); - if (te instanceof ThreadGroup) { + if (te instanceof AbstractThreadGroup) { name.append(parent_name); name.append(cur.getName()); name.append(seperator); Index: src/components/org/apache/jmeter/timers/ConstantThroughputTimer.java =================================================================== --- src/components/org/apache/jmeter/timers/ConstantThroughputTimer.java (revision 910417) +++ src/components/org/apache/jmeter/timers/ConstantThroughputTimer.java (working copy) @@ -26,7 +26,7 @@ import org.apache.jmeter.testelement.AbstractTestElement; import org.apache.jmeter.testelement.TestListener; import org.apache.jmeter.threads.JMeterContextService; -import org.apache.jmeter.threads.ThreadGroup; +import org.apache.jmeter.threads.AbstractThreadGroup; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.logging.LoggingManager; import org.apache.log.Logger; @@ -70,9 +70,9 @@ //For calculating throughput across all threads private final static ThroughputInfo allThreadsInfo = new ThroughputInfo(); - //For holding the ThrougputInfo objects for all ThreadGroups. Keyed by ThreadGroup objects - private final static Map threadGroupsInfoMap = - new ConcurrentHashMap(); + //For holding the ThrougputInfo objects for all ThreadGroups. Keyed by AbstractThreadGroup objects + private final static Map threadGroupsInfoMap = + new ConcurrentHashMap(); /** @@ -165,7 +165,7 @@ break; case 4: //All threads in this group - alternate calculation - final org.apache.jmeter.threads.ThreadGroup group = + final org.apache.jmeter.threads.AbstractThreadGroup group = JMeterContextService.getContext().getThreadGroup(); ThroughputInfo groupInfo; synchronized (threadGroupsInfoMap) { Index: src/core/org/apache/jmeter/control/gui/TestPlanGui.java =================================================================== --- src/core/org/apache/jmeter/control/gui/TestPlanGui.java (revision 910417) +++ src/core/org/apache/jmeter/control/gui/TestPlanGui.java (working copy) @@ -36,7 +36,6 @@ import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; import org.apache.jmeter.testelement.property.JMeterProperty; -import org.apache.jmeter.threads.gui.ThreadGroupGui; import org.apache.jmeter.util.JMeterUtils; /** @@ -87,8 +86,7 @@ public JPopupMenu createPopupMenu() { JPopupMenu pop = new JPopupMenu(); JMenu addMenu = new JMenu(JMeterUtils.getResString("add")); // $NON-NLS-1$ - addMenu.add(MenuFactory.makeMenuItem(new ThreadGroupGui().getStaticLabel(), ThreadGroupGui.class.getName(), - ActionNames.ADD)); + addMenu.add(MenuFactory.makeMenu(MenuFactory.THREADS, ActionNames.ADD)); addMenu.add(MenuFactory.makeMenu(MenuFactory.CONFIG_ELEMENTS, ActionNames.ADD)); addMenu.add(MenuFactory.makeMenu(MenuFactory.TIMERS, ActionNames.ADD)); addMenu.add(MenuFactory.makeMenu(MenuFactory.PRE_PROCESSORS, ActionNames.ADD)); Index: src/core/org/apache/jmeter/gui/util/MenuFactory.java =================================================================== --- src/core/org/apache/jmeter/gui/util/MenuFactory.java (revision 910417) +++ src/core/org/apache/jmeter/gui/util/MenuFactory.java (working copy) @@ -64,6 +64,8 @@ * These are used as menu categories in the menuMap Hashmap, * and also for resource lookup in messages.properties */ + public static final String THREADS = "menu_threads"; //$NON-NLS-1$ + public static final String TIMERS = "menu_timer"; //$NON-NLS-1$ public static final String CONTROLLERS = "menu_logic_controller"; //$NON-NLS-1$ @@ -90,6 +92,7 @@ // MENU_ADD_xxx - controls which items are in the ADD menu // MENU_PARENT_xxx - controls which items are in the Insert Parent menu private static final String[] MENU_ADD_CONTROLLER = new String[] { + MenuFactory.THREADS, MenuFactory.CONTROLLERS, MenuFactory.CONFIG_ELEMENTS, MenuFactory.TIMERS, @@ -115,11 +118,12 @@ private static final String[] MENU_PARENT_SAMPLER = new String[] { MenuFactory.CONTROLLERS }; - private static final List timers, controllers, samplers, configElements, - assertions, listeners, nonTestElements, + private static final List timers, controllers, samplers, threads, + configElements, assertions, listeners, nonTestElements, postProcessors, preProcessors; static { + threads = new LinkedList(); timers = new LinkedList(); controllers = new LinkedList(); samplers = new LinkedList(); @@ -129,6 +133,7 @@ postProcessors = new LinkedList(); preProcessors = new LinkedList(); nonTestElements = new LinkedList(); + menuMap.put(THREADS, threads); menuMap.put(TIMERS, timers); menuMap.put(ASSERTIONS, assertions); menuMap.put(CONFIG_ELEMENTS, configElements); @@ -455,6 +460,9 @@ log.debug(name + " participates in no menus."); continue; } + if (categories.contains(THREADS)) { + threads.add(new MenuInfo(item, name)); + } if (categories.contains(TIMERS)) { timers.add(new MenuInfo(item, name)); } @@ -545,14 +553,14 @@ if (parent instanceof TestPlan) { if (foundClass(nodes, new Class[]{Sampler.class, Controller.class}, // Samplers and Controllers need not apply ... - org.apache.jmeter.threads.ThreadGroup.class) // but ThreadGroup (Controller) is OK + org.apache.jmeter.threads.AbstractThreadGroup.class) // but AbstractThreadGroup (Controller) is OK ){ return false; } return true; } - // ThreadGroup is only allowed under a TestPlan - if (foundClass(nodes, new Class[]{org.apache.jmeter.threads.ThreadGroup.class})){ + // AbstractThreadGroup is only allowed under a TestPlan + if (foundClass(nodes, new Class[]{org.apache.jmeter.threads.AbstractThreadGroup.class})){ return false; } if (parent instanceof Controller) {// Includes thread group; anything goes Index: src/core/org/apache/jmeter/testelement/TestPlan.java =================================================================== --- src/core/org/apache/jmeter/testelement/TestPlan.java (revision 910417) +++ src/core/org/apache/jmeter/testelement/TestPlan.java (working copy) @@ -31,7 +31,7 @@ import org.apache.jmeter.testelement.property.BooleanProperty; import org.apache.jmeter.testelement.property.JMeterProperty; import org.apache.jmeter.testelement.property.TestElementProperty; -import org.apache.jmeter.threads.ThreadGroup; +import org.apache.jmeter.threads.AbstractThreadGroup; import org.apache.jorphan.logging.LoggingManager; import org.apache.jorphan.util.JOrphanUtils; import org.apache.log.Logger; @@ -55,7 +55,7 @@ private final static String BASEDIR = "basedir"; - private transient List threadGroups = new LinkedList(); + private transient List threadGroups = new LinkedList(); // Does not appear to be needed // private transient List configs = new LinkedList(); @@ -71,7 +71,7 @@ static { // WARNING! This String value must be identical to the String value - // returned in org.apache.jmeter.threads.ThreadGroup.getClassLabel() + // returned in org.apache.jmeter.threads.AbstractThreadGroup.getClassLabel() // method. If it's not you will not be able to add a Thread Group // element to a Test Plan. @@ -96,7 +96,7 @@ // create transient item private Object readResolve(){ - threadGroups = new LinkedList(); + threadGroups = new LinkedList(); return this; } @@ -228,15 +228,15 @@ @Override public void addTestElement(TestElement tg) { super.addTestElement(tg); - if (tg instanceof ThreadGroup && !isRunningVersion()) { - addThreadGroup((ThreadGroup) tg); + if (tg instanceof AbstractThreadGroup && !isRunningVersion()) { + addThreadGroup((AbstractThreadGroup) tg); } } // // Does not appear to be needed // public void addJMeterComponent(TestElement child) { -// if (child instanceof ThreadGroup) { -// addThreadGroup((ThreadGroup) child); +// if (child instanceof AbstractThreadGroup) { +// addThreadGroup((AbstractThreadGroup) child); // } // } @@ -262,12 +262,12 @@ // } /** - * Adds a feature to the ThreadGroup attribute of the TestPlan object. + * Adds a feature to the AbstractThreadGroup attribute of the TestPlan object. * * @param group - * the feature to be added to the ThreadGroup attribute + * the feature to be added to the AbstractThreadGroup attribute */ - public void addThreadGroup(ThreadGroup group) { + public void addThreadGroup(AbstractThreadGroup group) { threadGroups.add(group); } Index: src/core/org/apache/jmeter/threads/gui/ThreadGroupGui.java =================================================================== --- src/core/org/apache/jmeter/threads/gui/ThreadGroupGui.java (revision 910417) +++ src/core/org/apache/jmeter/threads/gui/ThreadGroupGui.java (working copy) @@ -19,39 +19,28 @@ package org.apache.jmeter.threads.gui; import java.awt.BorderLayout; -import java.awt.Dimension; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; -import java.util.Collection; import java.util.Date; import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JRadioButton; import javax.swing.JTextField; import org.apache.jmeter.control.LoopController; import org.apache.jmeter.control.gui.LoopControlPanel; -import org.apache.jmeter.gui.AbstractJMeterGuiComponent; -import org.apache.jmeter.gui.action.ActionNames; -import org.apache.jmeter.gui.tree.JMeterTreeNode; import org.apache.jmeter.gui.util.FocusRequester; import org.apache.jmeter.gui.util.JDateField; -import org.apache.jmeter.gui.util.MenuFactory; import org.apache.jmeter.gui.util.VerticalPanel; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.property.BooleanProperty; import org.apache.jmeter.testelement.property.LongProperty; -import org.apache.jmeter.testelement.property.StringProperty; import org.apache.jmeter.threads.ThreadGroup; import org.apache.jmeter.util.JMeterUtils; -public class ThreadGroupGui extends AbstractJMeterGuiComponent implements ItemListener { +public class ThreadGroupGui extends AbstractThreadGroupGui implements ItemListener { private static final long serialVersionUID = 240L; private LoopControlPanel loopPanel; @@ -76,25 +65,12 @@ private JTextField delay; // Relative start-up time - // Sampler error action buttons - private JRadioButton continueBox; - - private JRadioButton stopThrdBox; - - private JRadioButton stopTestBox; - - private JRadioButton stopTestNowBox; - public ThreadGroupGui() { super(); init(); initGui(); } - public Collection getMenuCategories() { - return null; - } - public TestElement createTestElement() { ThreadGroup tg = new ThreadGroup(); modifyTestElement(tg); @@ -117,38 +93,10 @@ tg.setProperty(new LongProperty(ThreadGroup.START_TIME, start.getDate().getTime())); tg.setProperty(new LongProperty(ThreadGroup.END_TIME, end.getDate().getTime())); tg.setProperty(new BooleanProperty(ThreadGroup.SCHEDULER, scheduler.isSelected())); - tg.setProperty(new StringProperty(ThreadGroup.ON_SAMPLE_ERROR, onSampleError())); tg.setProperty(ThreadGroup.DURATION, duration.getText()); tg.setProperty(ThreadGroup.DELAY, delay.getText()); } - private void setSampleErrorBoxes(ThreadGroup te) { - if (te.getOnErrorStopTest()) { - stopTestBox.setSelected(true); - } else if (te.getOnErrorStopTestNow()) { - stopTestNowBox.setSelected(true); - } else if (te.getOnErrorStopThread()) { - stopThrdBox.setSelected(true); - } else { - continueBox.setSelected(true); - } - } - - private String onSampleError() { - if (stopTestBox.isSelected()) { - return ThreadGroup.ON_SAMPLE_ERROR_STOPTEST; - } - if (stopTestNowBox.isSelected()) { - return ThreadGroup.ON_SAMPLE_ERROR_STOPTEST_NOW; - } - if (stopThrdBox.isSelected()) { - return ThreadGroup.ON_SAMPLE_ERROR_STOPTHREAD; - } - - // Defaults to continue - return ThreadGroup.ON_SAMPLE_ERROR_CONTINUE; - } - @Override public void configure(TestElement tg) { super.configure(tg); @@ -174,8 +122,6 @@ } duration.setText(tg.getPropertyAsString(ThreadGroup.DURATION)); delay.setText(tg.getPropertyAsString(ThreadGroup.DELAY)); - - setSampleErrorBoxes((ThreadGroup) tg); } public void itemStateChanged(ItemEvent ie) { @@ -188,25 +134,6 @@ } } - public JPopupMenu createPopupMenu() { - JPopupMenu pop = new JPopupMenu(); - pop.add(MenuFactory.makeMenus(new String[] { - MenuFactory.CONTROLLERS, - MenuFactory.CONFIG_ELEMENTS, - MenuFactory.TIMERS, - MenuFactory.PRE_PROCESSORS, - MenuFactory.SAMPLERS, - MenuFactory.POST_PROCESSORS, - MenuFactory.ASSERTIONS, - MenuFactory.LISTENERS, - }, - JMeterUtils.getResString("add"), // $NON-NLS-1$ - ActionNames.ADD)); - MenuFactory.addEditMenu(pop, true); - MenuFactory.addFileMenu(pop); - return pop; - } - private JPanel createControllerPanel() { loopPanel = new LoopControlPanel(false); LoopController looper = (LoopController) loopPanel.createTestElement(); @@ -276,31 +203,6 @@ return "threadgroup"; // $NON-NLS-1$ } - private JPanel createOnErrorPanel() { - JPanel panel = new JPanel(); - panel.setBorder(BorderFactory.createTitledBorder(JMeterUtils.getResString("sampler_on_error_action"))); // $NON-NLS-1$ - - ButtonGroup group = new ButtonGroup(); - - continueBox = new JRadioButton(JMeterUtils.getResString("sampler_on_error_continue")); // $NON-NLS-1$ - group.add(continueBox); - panel.add(continueBox); - - stopThrdBox = new JRadioButton(JMeterUtils.getResString("sampler_on_error_stop_thread")); // $NON-NLS-1$ - group.add(stopThrdBox); - panel.add(stopThrdBox); - - stopTestBox = new JRadioButton(JMeterUtils.getResString("sampler_on_error_stop_test")); // $NON-NLS-1$ - group.add(stopTestBox); - panel.add(stopTestBox); - - stopTestNowBox = new JRadioButton(JMeterUtils.getResString("sampler_on_error_stop_test_now")); // $NON-NLS-1$ - group.add(stopTestNowBox); - panel.add(stopTestNowBox); - - return panel; - } - @Override public void clearGui(){ super.clearGui(); @@ -311,7 +213,6 @@ private void initGui(){ threadInput.setText("1"); // $NON-NLS-1$ rampInput.setText("1"); // $NON-NLS-1$ - continueBox.setSelected(true); loopPanel.clearGui(); scheduler.setSelected(false); Date today = new Date(); @@ -321,17 +222,10 @@ duration.setText(""); // $NON-NLS-1$ } - private void init() { - setLayout(new BorderLayout(0, 5)); - setBorder(makeBorder()); + @Override + protected void init() { + super.init(); - Box box = Box.createVerticalBox(); - box.add(makeTitlePanel()); - box.add(createOnErrorPanel()); - add(box, BorderLayout.NORTH); - - // JPanel mainPanel = new JPanel(new BorderLayout()); - // THREAD PROPERTIES VerticalPanel threadPropsPanel = new VerticalPanel(); threadPropsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), @@ -385,13 +279,4 @@ intgrationPanel.add(mainPanel); add(intgrationPanel, BorderLayout.CENTER); } - - public void setNode(JMeterTreeNode node) { - getNamePanel().setNode(node); - } - - @Override - public Dimension getPreferredSize() { - return getMinimumSize(); - } } Index: src/core/org/apache/jmeter/threads/ThreadGroup.java =================================================================== --- src/core/org/apache/jmeter/threads/ThreadGroup.java (revision 910417) +++ src/core/org/apache/jmeter/threads/ThreadGroup.java (working copy) @@ -18,37 +18,25 @@ package org.apache.jmeter.threads; -import java.io.Serializable; - -import org.apache.jmeter.control.Controller; -import org.apache.jmeter.control.LoopController; -import org.apache.jmeter.engine.event.LoopIterationListener; -import org.apache.jmeter.samplers.Sampler; -import org.apache.jmeter.testelement.AbstractTestElement; -import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.property.BooleanProperty; import org.apache.jmeter.testelement.property.IntegerProperty; -import org.apache.jmeter.testelement.property.JMeterProperty; import org.apache.jmeter.testelement.property.LongProperty; -import org.apache.jmeter.testelement.property.TestElementProperty; +import org.apache.jorphan.logging.LoggingManager; +import org.apache.log.Logger; /** * ThreadGroup holds the settings for a JMeter thread group. * * This class is intended to be ThreadSafe. */ -public class ThreadGroup extends AbstractTestElement implements Serializable, Controller { +public class ThreadGroup extends AbstractThreadGroup { + private static final Logger log = LoggingManager.getLoggerForClass(); private static final long serialVersionUID = 233L; - /** Number of threads in the thread group */ - public final static String NUM_THREADS = "ThreadGroup.num_threads"; - /** Ramp-up time */ public final static String RAMP_TIME = "ThreadGroup.ramp_time"; - public final static String MAIN_CONTROLLER = "ThreadGroup.main_controller"; - /** Whether scheduler is being used */ public final static String SCHEDULER = "ThreadGroup.scheduler"; @@ -64,72 +52,14 @@ /** Scheduler start delay, overrides start time */ public final static String DELAY = "ThreadGroup.delay"; - /** Action to be taken when a Sampler error occurs */ - public final static String ON_SAMPLE_ERROR = "ThreadGroup.on_sample_error"; // int - - /** Continue, i.e. ignore sampler errors */ - public final static String ON_SAMPLE_ERROR_CONTINUE = "continue"; - - /** Stop current thread if sampler error occurs */ - public final static String ON_SAMPLE_ERROR_STOPTHREAD = "stopthread"; - - /** Stop test (all threads) if sampler error occurs */ - public final static String ON_SAMPLE_ERROR_STOPTEST = "stoptest"; - - /** Stop test NOW (all threads) if sampler error occurs */ - public final static String ON_SAMPLE_ERROR_STOPTEST_NOW = "stoptestnow"; - - // @GuardedBy("this") - private int numberOfThreads = 0; // Number of active threads in this group - /** * No-arg constructor. */ public ThreadGroup() { } - /** - * Set the total number of threads to start - * - * @param numThreads - * the number of threads. - */ - public void setNumThreads(int numThreads) { - setProperty(new IntegerProperty(NUM_THREADS, numThreads)); - } /** - * Increment the number of active threads - */ - synchronized void incrNumberOfThreads() { - numberOfThreads++; - } - - /** - * Decrement the number of active threads - */ - synchronized void decrNumberOfThreads() { - numberOfThreads--; - } - - /** - * Get the number of active threads - */ - public synchronized int getNumberOfThreads() { - return numberOfThreads; - } - - /** {@inheritDoc} */ - public boolean isDone() { - return getSamplerController().isDone(); - } - - /** {@inheritDoc} */ - public Sampler next() { - return getSamplerController().next(); - } - - /** * Set whether scheduler is being used * * @param Scheduler true is scheduler is to be used @@ -242,86 +172,46 @@ return getPropertyAsInt(ThreadGroup.RAMP_TIME); } - /** - * Get the sampler controller. - * - * @return the sampler controller. - */ - public Controller getSamplerController() { - Controller c = (Controller) getProperty(MAIN_CONTROLLER).getObjectValue(); - return c; - } + @Override + public void scheduleThread(JMeterThread thread) + { + int rampUp = getRampUp(); + float perThreadDelay = ((float) (rampUp * 1000) / (float) getNumThreads()); + thread.setInitialDelay((int) (perThreadDelay * thread.getThreadNum())); - /** - * Set the sampler controller. - * - * @param c - * the sampler controller. - */ - public void setSamplerController(LoopController c) { - c.setContinueForever(false); - setProperty(new TestElementProperty(MAIN_CONTROLLER, c)); - } + scheduleThread(thread, this); + } /** - * Get the number of threads. + * This will schedule the time for the JMeterThread. * - * @return the number of threads. + * @param thread + * @param group */ - public int getNumThreads() { - return this.getPropertyAsInt(ThreadGroup.NUM_THREADS); - } + private void scheduleThread(JMeterThread thread, ThreadGroup group) { + // if true the Scheduler is enabled + if (group.getScheduler()) { + long now = System.currentTimeMillis(); + // set the start time for the Thread + if (group.getDelay() > 0) {// Duration is in seconds + thread.setStartTime(group.getDelay() * 1000 + now); + } else { + long start = group.getStartTime(); + if (start < now) { + start = now; // Force a sensible start time + } + thread.setStartTime(start); + } - /** - * Add a test element. - * - * @param child - * the test element to add. - */ - @Override - public void addTestElement(TestElement child) { - getSamplerController().addTestElement(child); - } + // set the endtime for the Thread + if (group.getDuration() > 0) {// Duration is in seconds + thread.setEndTime(group.getDuration() * 1000 + (thread.getStartTime())); + } else { + thread.setEndTime(group.getEndTime()); + } - /** {@inheritDoc} */ - public void addIterationListener(LoopIterationListener lis) { - getSamplerController().addIterationListener(lis); + // Enables the scheduler + thread.setScheduled(true); + } } - - /** {@inheritDoc} */ - public void initialize() { - Controller c = getSamplerController(); - JMeterProperty property = c.getProperty(TestElement.NAME); - property.setObjectValue(getName()); // Copy our name into that of the controller - property.setRunningVersion(property.isRunningVersion());// otherwise name reverts - c.initialize(); - } - - /** - * Check if a sampler error should cause thread to stop. - * - * @return true if thread should stop - */ - public boolean getOnErrorStopThread() { - return getPropertyAsString(ThreadGroup.ON_SAMPLE_ERROR).equalsIgnoreCase(ON_SAMPLE_ERROR_STOPTHREAD); - } - - /** - * Check if a sampler error should cause test to stop. - * - * @return true if test (all threads) should stop - */ - public boolean getOnErrorStopTest() { - return getPropertyAsString(ThreadGroup.ON_SAMPLE_ERROR).equalsIgnoreCase(ON_SAMPLE_ERROR_STOPTEST); - } - - /** - * Check if a sampler error should cause test to stop now. - * - * @return true if test (all threads) should stop immediately - */ - public boolean getOnErrorStopTestNow() { - return getPropertyAsString(ThreadGroup.ON_SAMPLE_ERROR).equalsIgnoreCase(ON_SAMPLE_ERROR_STOPTEST_NOW); - } - } Index: src/core/org/apache/jmeter/threads/JMeterContext.java =================================================================== --- src/core/org/apache/jmeter/threads/JMeterContext.java (revision 910417) +++ src/core/org/apache/jmeter/threads/JMeterContext.java (working copy) @@ -43,7 +43,7 @@ private JMeterThread thread; - private ThreadGroup threadGroup; + private AbstractThreadGroup threadGroup; private int threadNum; @@ -145,11 +145,11 @@ this.thread = thread; } - public ThreadGroup getThreadGroup() { + public AbstractThreadGroup getThreadGroup() { return this.threadGroup; } - public void setThreadGroup(ThreadGroup threadgrp) { + public void setThreadGroup(AbstractThreadGroup threadgrp) { this.threadGroup = threadgrp; } Index: src/core/org/apache/jmeter/threads/JMeterThread.java =================================================================== --- src/core/org/apache/jmeter/threads/JMeterThread.java (revision 910417) +++ src/core/org/apache/jmeter/threads/JMeterThread.java (working copy) @@ -102,7 +102,7 @@ // based on this scheduler is enabled or disabled // Gives access to parent thread threadGroup - private ThreadGroup threadGroup; + private AbstractThreadGroup threadGroup; private StandardJMeterEngine engine = null; // For access to stop methods. @@ -764,7 +764,7 @@ onErrorStopThread = b; } - public void setThreadGroup(ThreadGroup group) { + public void setThreadGroup(AbstractThreadGroup group) { this.threadGroup = group; } Index: src/core/org/apache/jmeter/engine/ConvertListeners.java =================================================================== --- src/core/org/apache/jmeter/engine/ConvertListeners.java (revision 910417) +++ src/core/org/apache/jmeter/engine/ConvertListeners.java (working copy) @@ -30,7 +30,7 @@ import org.apache.jmeter.samplers.SampleListener; import org.apache.jmeter.testelement.TestListener; import org.apache.jmeter.testelement.ThreadListener; -import org.apache.jmeter.threads.ThreadGroup; +import org.apache.jmeter.threads.AbstractThreadGroup; import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTreeTraverser; import org.apache.jorphan.logging.LoggingManager; @@ -53,8 +53,8 @@ Iterator iter = subTree.list().iterator(); while (iter.hasNext()) { Object item = iter.next(); - if (item instanceof ThreadGroup) { - log.info("num threads = " + ((ThreadGroup) item).getNumThreads()); + if (item instanceof AbstractThreadGroup) { + log.info("num threads = " + ((AbstractThreadGroup) item).getNumThreads()); } if (item instanceof Remoteable) { if (item instanceof ThreadListener){ Index: src/core/org/apache/jmeter/engine/StandardJMeterEngine.java =================================================================== --- src/core/org/apache/jmeter/engine/StandardJMeterEngine.java (revision 910417) +++ src/core/org/apache/jmeter/engine/StandardJMeterEngine.java (working copy) @@ -44,7 +44,7 @@ import org.apache.jmeter.threads.JMeterThreadMonitor; import org.apache.jmeter.threads.ListenerNotifier; import org.apache.jmeter.threads.TestCompiler; -import org.apache.jmeter.threads.ThreadGroup; +import org.apache.jmeter.threads.AbstractThreadGroup; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.ListedHashTree; @@ -257,7 +257,7 @@ Iterator iter = elements.iterator(); while (iter.hasNext()) { Object item = iter.next(); - if (item instanceof ThreadGroup) { + if (item instanceof AbstractThreadGroup) { iter.remove(); } else if (!(item instanceof TestElement)) { iter.remove(); @@ -420,13 +420,13 @@ List testLevelElements = new LinkedList(test.list(test.getArray()[0])); removeThreadGroups(testLevelElements); - SearchByClass searcher = new SearchByClass(ThreadGroup.class); + SearchByClass searcher = new SearchByClass(AbstractThreadGroup.class); test.traverse(searcher); TestCompiler.initialize(); // for each thread group, generate threads // hand each thread the sampler controller // and the listeners, and the timer - Iterator iter = searcher.getSearchResults().iterator(); + Iterator iter = searcher.getSearchResults().iterator(); /* * Here's where the test really starts. Run a Full GC now: it's no harm @@ -443,16 +443,14 @@ startingGroups = true; while (running && iter.hasNext()) {// for each thread group groupCount++; - ThreadGroup group = iter.next(); + AbstractThreadGroup group = iter.next(); int numThreads = group.getNumThreads(); JMeterContextService.addTotalThreads(numThreads); boolean onErrorStopTest = group.getOnErrorStopTest(); boolean onErrorStopTestNow = group.getOnErrorStopTestNow(); boolean onErrorStopThread = group.getOnErrorStopThread(); String groupName = group.getName(); - int rampUp = group.getRampUp(); - float perThreadDelay = ((float) (rampUp * 1000) / (float) numThreads); - log.info("Starting " + numThreads + " threads for group " + groupName + ". Ramp up = " + rampUp + "."); + log.info("Starting " + numThreads + " threads for group " + groupName + "."); if (onErrorStopTest) { log.info("Test will stop on error"); @@ -463,7 +461,6 @@ } else { log.info("Thread will continue on error"); } - ListedHashTree threadGroupTree = (ListedHashTree) searcher.getSubTree(group); threadGroupTree.add(group, testLevelElements); for (int i = 0; running && i < numThreads; i++) { @@ -471,18 +468,15 @@ jmeterThread.setThreadNum(i); jmeterThread.setThreadGroup(group); jmeterThread.setInitialContext(JMeterContextService.getContext()); - jmeterThread.setInitialDelay((int) (perThreadDelay * i)); final String threadName = groupName + " " + (groupCount) + "-" + (i + 1); jmeterThread.setThreadName(threadName); - - scheduleThread(jmeterThread, group); - - // Set up variables for stop handling jmeterThread.setEngine(this); jmeterThread.setOnErrorStopTest(onErrorStopTest); jmeterThread.setOnErrorStopTestNow(onErrorStopTestNow); jmeterThread.setOnErrorStopThread(onErrorStopThread); + group.scheduleThread(jmeterThread); + Thread newThread = new Thread(jmeterThread); newThread.setName(threadName); allThreads.put(jmeterThread, newThread); @@ -503,39 +497,6 @@ startingGroups = false; } - /** - * This will schedule the time for the JMeterThread. - * - * @param thread - * @param group - */ - private void scheduleThread(JMeterThread thread, ThreadGroup group) { - // if true the Scheduler is enabled - if (group.getScheduler()) { - long now = System.currentTimeMillis(); - // set the start time for the Thread - if (group.getDelay() > 0) {// Duration is in seconds - thread.setStartTime(group.getDelay() * 1000 + now); - } else { - long start = group.getStartTime(); - if (start < now) { - start = now; // Force a sensible start time - } - thread.setStartTime(start); - } - - // set the endtime for the Thread - if (group.getDuration() > 0) {// Duration is in seconds - thread.setEndTime(group.getDuration() * 1000 + (thread.getStartTime())); - } else { - thread.setEndTime(group.getEndTime()); - } - - // Enables the scheduler - thread.setScheduled(true); - } - } - private boolean verifyThreadsStopped() { boolean stoppedAll = true; List threadsToCheck = new ArrayList(allThreads.size()); Index: src/core/org/apache/jmeter/resources/messages.properties =================================================================== --- src/core/org/apache/jmeter/resources/messages.properties (revision 910417) +++ src/core/org/apache/jmeter/resources/messages.properties (working copy) @@ -488,6 +488,7 @@ menu_edit=Edit menu_expand_all=Expand All menu_generative_controller=Sampler +menu_threads=Threads (Users) menu_listener=Listener menu_logic_controller=Logic Controller menu_merge=Merge Index: src/core/org/apache/jmeter/util/JMeterVersion.java =================================================================== --- src/core/org/apache/jmeter/util/JMeterVersion.java (revision 910417) +++ src/core/org/apache/jmeter/util/JMeterVersion.java (working copy) @@ -44,7 +44,7 @@ * This ensures that JMeterUtils always gets the correct * version, even if JMeterUtils is not re-compiled during the build. */ - private static final String VERSION = "2.4"; + private static final String VERSION = "2.4.20100216"; static final String COPYRIGHT = "Copyright (c) 1998-2009 The Apache Software Foundation"; Index: src/reports/org/apache/jmeter/testelement/ReportPlan.java =================================================================== --- src/reports/org/apache/jmeter/testelement/ReportPlan.java (revision 910417) +++ src/reports/org/apache/jmeter/testelement/ReportPlan.java (working copy) @@ -32,7 +32,7 @@ import org.apache.jmeter.testelement.property.CollectionProperty; import org.apache.jmeter.testelement.property.StringProperty; import org.apache.jmeter.testelement.property.TestElementProperty; -import org.apache.jmeter.threads.ThreadGroup; +import org.apache.jmeter.threads.AbstractThreadGroup; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.logging.LoggingManager; import org.apache.log.Logger; @@ -50,7 +50,7 @@ public static final String BASEDIR = "ReportPlan.basedir"; - private transient List reportPages = new LinkedList(); + private transient List reportPages = new LinkedList(); private transient List configs = new LinkedList(); @@ -128,14 +128,14 @@ @Override public void addTestElement(TestElement tg) { super.addTestElement(tg); - if (tg instanceof ThreadGroup && !isRunningVersion()) { - addReportPage((ThreadGroup) tg); + if (tg instanceof AbstractThreadGroup && !isRunningVersion()) { + addReportPage((AbstractThreadGroup) tg); } } public void addJMeterComponent(TestElement child) { - if (child instanceof ThreadGroup) { - addReportPage((ThreadGroup) child); + if (child instanceof AbstractThreadGroup) { + addReportPage((AbstractThreadGroup) child); } } @@ -144,7 +144,7 @@ * * @return the ThreadGroups value */ - public Collection getReportPages() { + public Collection getReportPages() { return reportPages; } @@ -159,12 +159,12 @@ } /** - * Adds a feature to the ThreadGroup attribute of the TestPlan object. + * Adds a feature to the AbstractThreadGroup attribute of the TestPlan object. * * @param group - * the feature to be added to the ThreadGroup attribute + * the feature to be added to the AbstractThreadGroup attribute */ - public void addReportPage(ThreadGroup group) { + public void addReportPage(AbstractThreadGroup group) { reportPages.add(group); }