You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2014/07/18 18:13:18 UTC

svn commit: r1611689 - in /jmeter/trunk: src/components/org/apache/jmeter/control/ src/components/org/apache/jmeter/control/gui/ src/core/org/apache/jmeter/resources/ xdocs/ xdocs/usermanual/

Author: pmouawad
Date: Fri Jul 18 16:13:18 2014
New Revision: 1611689

URL: http://svn.apache.org/r1611689
Log:
Bug 56728 - New Critical Section Controller to serialize blocks of a Test
Bugzilla Id: 56728

Added:
    jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java   (with props)
Modified:
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
    jmeter/trunk/xdocs/changes.xml
    jmeter/trunk/xdocs/usermanual/component_reference.xml

Added: jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java?rev=1611689&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java Fri Jul 18 16:13:18 2014
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.jmeter.control;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jmeter.samplers.Sampler;
+import org.apache.jmeter.testelement.TestStateListener;
+import org.apache.jmeter.testelement.ThreadListener;
+import org.apache.jmeter.testelement.property.StringProperty;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+/**
+ * This is a Critical Section Controller; it will execute the set of statements
+ * (samplers/controllers, etc) under named lock.
+ * <p>
+ * In a programming world - this is equivalent of :
+ * 
+ * <pre>
+ * try {
+ *          named_lock.lock();
+ *          statements ....
+ * } finally {
+ *          named_lock.unlock();
+ * }
+ * </pre>
+ * 
+ * In JMeter you may have :
+ * 
+ * <pre>
+ * Thread-Group (set to loop a number of times or indefinitely,
+ *    ... Samplers ... (e.g. Counter )
+ *    ... Other Controllers ....
+ *    ... CriticalSectionController ( lock name like "foobar" )
+ *       ... statements to perform when lock acquired
+ *       ...
+ *    ... Other Controllers /Samplers }
+ * </pre>
+ * 
+ * @since 2.12
+ */
+public class CriticalSectionController extends GenericController implements
+        ThreadListener, TestStateListener {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 4362876132435968088L;
+
+    private static final Logger logger = LoggingManager.getLoggerForClass();
+
+    private static final String LOCK_NAME = "CriticalSectionController.lockName"; //$NON-NLS-1$
+
+    private static final ConcurrentHashMap<String, ReentrantLock> lockMap = new ConcurrentHashMap<String, ReentrantLock>();
+
+    private transient ReentrantLock currentLock;
+
+    /**
+     * constructor
+     */
+    public CriticalSectionController() {
+        super();
+    }
+
+    /**
+     * constructor
+     */
+    public CriticalSectionController(String name) {
+        super();
+        this.setName(name);
+    }
+
+    /**
+     * Condition Accessor - this is gonna be any string value
+     */
+    public void setLockName(String name) {
+        setProperty(new StringProperty(LOCK_NAME, name));
+    }
+
+    /**
+     * Function for autocreate and get lock
+     * 
+     * @return named lock
+     */
+    private ReentrantLock getLock() {
+        ReentrantLock lock = lockMap.get(getLockName());
+        ReentrantLock prev = null;
+        if (lock != null) {
+            return lock;
+        }
+        lock = new ReentrantLock();
+        prev = lockMap.putIfAbsent(getLockName(), lock);
+        return prev == null ? lock : prev;
+    }
+
+    /**
+     * Lock name
+     */
+    public String getLockName() {
+        return getPropertyAsString(LOCK_NAME);
+    }
+
+    /**
+     * @see org.apache.jmeter.control.Controller#next()
+     */
+    @Override
+    public Sampler next() {
+        if (StringUtils.isEmpty(getLockName())) {
+            logger.warn("Empty lock name in Critical Section Controller:"
+                    + getName());
+            return super.next();
+        }
+        if (isFirst()) {
+            // Take the lock for first child element
+            long startTime = System.currentTimeMillis();
+            if (this.currentLock == null) {
+                this.currentLock = getLock();
+            }
+            this.currentLock.lock();
+            long endTime = System.currentTimeMillis();
+            if (logger.isDebugEnabled()) {
+                logger.debug(Thread.currentThread().getName()
+                        + " acquired lock:'" + getLockName()
+                        + "' in Critical Section Controller " + getName()
+                        + " in:" + (endTime - startTime) + " ms");
+            }
+        }
+        return super.next();
+    }
+
+    /**
+     * Called after execution of last child of the controller We release lock
+     * 
+     * @see org.apache.jmeter.control.GenericController#reInitialize()
+     */
+    @Override
+    protected void reInitialize() {
+        if (this.currentLock != null) {
+            if (currentLock.isHeldByCurrentThread()) {
+                this.currentLock.unlock();
+            }
+            this.currentLock = null;
+        }
+        super.reInitialize();
+    }
+
+    @Override
+    public void threadStarted() {
+        this.currentLock = null;
+    }
+
+    @Override
+    public void threadFinished() {
+        if (this.currentLock != null
+                && this.currentLock.isHeldByCurrentThread()) {
+            logger.warn("Lock " + getLockName() + " not released in:"
+                    + getName() + ", releasing in threadFinished");
+            this.currentLock.unlock();
+        }
+        this.currentLock = null;
+    }
+
+    @Override
+    public void testStarted() {
+        // NOOP
+    }
+
+    @Override
+    public void testStarted(String host) {
+        // NOOP
+    }
+
+    @Override
+    public void testEnded() {
+        lockMap.clear();
+    }
+
+    @Override
+    public void testEnded(String host) {
+        testEnded();
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java?rev=1611689&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java Fri Jul 18 16:13:18 2014
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.jmeter.control.gui;
+
+import java.awt.BorderLayout;
+
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import org.apache.jmeter.control.CriticalSectionController;
+import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.util.JMeterUtils;
+
+/**
+ * The user interface for a controller which specifies that its subcomponents
+ * should be executed while a condition holds. This component can be used
+ * standalone or embedded into some other component.
+ * 
+ * @since 2.12
+ */
+public class CriticalSectionControllerGui extends AbstractControllerGui {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 7177285850634344095L;
+
+    /**
+     * A field allowing the user to specify the number of times the controller
+     * should loop.
+     */
+    private JTextField tfLockName;
+
+    /**
+     * Boolean indicating whether or not this component should display its name.
+     * If true, this is a standalone component. If false, this component is
+     * intended to be used as a subpanel for another component.
+     */
+    private boolean displayName = true;
+
+    /**
+     * Create a new LoopControlPanel as a standalone component.
+     */
+    public CriticalSectionControllerGui() {
+        this(true);
+    }
+
+    /**
+     * Create a new IfControllerPanel as either a standalone or an embedded
+     * component.
+     * 
+     * @param displayName
+     *            indicates whether or not this component should display its
+     *            name. If true, this is a standalone component. If false, this
+     *            component is intended to be used as a subpanel for another
+     *            component.
+     */
+    public CriticalSectionControllerGui(boolean displayName) {
+        this.displayName = displayName;
+        init();
+    }
+
+    /**
+     * A newly created component can be initialized with the contents of a Test
+     * Element object by calling this method. The component is responsible for
+     * querying the Test Element object for the relevant information to display
+     * in its GUI.
+     * 
+     * @param element
+     *            the TestElement to configure
+     */
+    @Override
+    public void configure(TestElement element) {
+        super.configure(element);
+        if (element instanceof CriticalSectionController) {
+            CriticalSectionController controller = (CriticalSectionController) element;
+            tfLockName.setText(controller.getLockName());
+        }
+
+    }
+
+    /**
+     * Implements JMeterGUIComponent.createTestElement()
+     */
+    @Override
+    public TestElement createTestElement() {
+        CriticalSectionController controller = new CriticalSectionController();
+        modifyTestElement(controller);
+        return controller;
+    }
+
+    /**
+     * Implements JMeterGUIComponent.modifyTestElement(TestElement)
+     */
+    @Override
+    public void modifyTestElement(TestElement controller) {
+        configureTestElement(controller);
+        if (controller instanceof CriticalSectionController) {
+            CriticalSectionController csController = (CriticalSectionController) controller;
+            csController.setLockName(tfLockName.getText());
+        }
+    }
+
+    /**
+     * Implements JMeterGUIComponent.clearGui
+     */
+    @Override
+    public void clearGui() {
+        super.clearGui();
+        tfLockName.setText("global_lock"); // $NON-NLS-1$
+    }
+
+    @Override
+    public String getLabelResource() {
+        return "critical_section_controller_title"; // $NON-NLS-1$
+    }
+
+    /**
+     * Initialize the GUI components and layout for this component.
+     */
+    private void init() {
+        // Standalone
+        if (displayName) {
+            setLayout(new BorderLayout(0, 5));
+            setBorder(makeBorder());
+            add(makeTitlePanel(), BorderLayout.NORTH);
+
+            JPanel mainPanel = new JPanel(new BorderLayout());
+            mainPanel.add(createConditionPanel(), BorderLayout.NORTH);
+            add(mainPanel, BorderLayout.CENTER);
+
+        } else {
+            // Embedded
+            setLayout(new BorderLayout());
+            add(createConditionPanel(), BorderLayout.NORTH);
+        }
+    }
+
+    /**
+     * Create a GUI panel containing the condition.
+     * 
+     * @return a GUI panel containing the condition components
+     */
+    private JPanel createConditionPanel() {
+        JPanel conditionPanel = new JPanel(new BorderLayout(5, 0));
+
+        // Condition LABEL
+        JLabel conditionLabel = new JLabel(
+                JMeterUtils.getResString("critical_section_controller_label")); // $NON-NLS-1$
+        conditionPanel.add(conditionLabel, BorderLayout.WEST);
+
+        // TEXT FIELD
+        tfLockName = new JTextField(""); // $NON-NLS-1$
+        conditionLabel.setLabelFor(tfLockName);
+        conditionPanel.add(tfLockName, BorderLayout.CENTER);
+
+        conditionPanel
+                .add(Box.createHorizontalStrut(conditionLabel
+                        .getPreferredSize().width
+                        + tfLockName.getPreferredSize().width),
+                        BorderLayout.NORTH);
+
+        return conditionPanel;
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=1611689&r1=1611688&r2=1611689&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Fri Jul 18 16:13:18 2014
@@ -209,6 +209,8 @@ counter_config_title=Counter
 counter_per_user=Track counter independently for each user
 counter_reset_per_tg_iteration=Reset counter on each Thread Group Iteration
 countlim=Size limit
+critical_section_controller_label=Lock name
+critical_section_controller_title=Critical Section Controller
 csvread_file_file_name=CSV file to get values from | *alias
 cut=Cut
 cut_paste_function=Copy and paste function string

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties?rev=1611689&r1=1611688&r2=1611689&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties Fri Jul 18 16:13:18 2014
@@ -197,6 +197,8 @@ counter_config_title=Compteur
 counter_per_user=Suivre le compteur ind\u00E9pendamment pour chaque unit\u00E9 de test
 counter_reset_per_tg_iteration=R\u00E9initialiser le compteur \u00E0 chaque it\u00E9ration du groupe d'unit\u00E9s
 countlim=Limiter le nombre d'\u00E9l\u00E9ments retourn\u00E9s \u00E0
+critical_section_controller_label=Nom du verrou
+critical_section_controller_title=Contr\u00F4leur section critique
 cssjquery_attribute=Attribut
 cssjquery_impl=Impl\u00E9mentation CSS/JQuery\:
 cssjquery_render_no_text=Les donn\u00E9es de r\u00E9ponse ne sont pas du texte.

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1611689&r1=1611688&r2=1611689&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml (original)
+++ jmeter/trunk/xdocs/changes.xml Fri Jul 18 16:13:18 2014
@@ -1,4 +1,4 @@
-<?xml version="1.0"?> 
+Crti<?xml version="1.0"?> 
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -201,6 +201,7 @@ A workaround is to use a Java 7 update 4
 
 <h3>Controllers</h3>
 <ul>
+<li><bugzilla>56728</bugzilla> - New Critical Section Controller to serialize blocks of a Test. Based partly on a patch contributed by Mikhail Epikhin(epihin-m at yandex.ru)</li>
 </ul>
 
 <h3>Listeners</h3>

Modified: jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=1611689&r1=1611688&r2=1611689&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jmeter/trunk/xdocs/usermanual/component_reference.xml Fri Jul 18 16:13:18 2014
@@ -2518,6 +2518,17 @@ be saved under the Recording Controller.
 
 </component>
 
+<component name="Critical Section Controller" index="&sect-num;.2.17" width="420" height="79" screenshot="logic-controller/critical-section-controller.png">
+<description>
+<p>The Critical Section Controller ensures that its children elements (samplers/controllers, etc) will be executed 
+by only one thread as a named lock will be taken before executing children of controller.</p>
+
+</description>
+<properties>
+        <property name="Lock Name" required="Yes">Lock that will be taken by controller, ensure you use different lock names for unrelated sections</property>
+</properties>
+
+</component>
 
 <a href="#">^</a>
 



Re: svn commit: r1611689 - in /jmeter/trunk: src/components/org/apache/jmeter/control/ src/components/org/apache/jmeter/control/gui/ src/core/org/apache/jmeter/resources/ xdocs/ xdocs/usermanual/

Posted by sebb <se...@gmail.com>.
On 18 July 2014 17:13,  <pm...@apache.org> wrote:
> Author: pmouawad
> Date: Fri Jul 18 16:13:18 2014
> New Revision: 1611689
>
> URL: http://svn.apache.org/r1611689
> Log:
> Bug 56728 - New Critical Section Controller to serialize blocks of a Test
> Bugzilla Id: 56728
>
> Added:
>     jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java   (with props)
>     jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java   (with props)
> Modified:
>     jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
>     jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
>     jmeter/trunk/xdocs/changes.xml
>     jmeter/trunk/xdocs/usermanual/component_reference.xml
>
> Added: jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java
> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java?rev=1611689&view=auto
> ==============================================================================
> --- jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java (added)
> +++ jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java Fri Jul 18 16:13:18 2014
> @@ -0,0 +1,201 @@
> +/*
> + * 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.
> + *
> + */
> +
> +package org.apache.jmeter.control;
> +
> +import java.util.concurrent.ConcurrentHashMap;
> +import java.util.concurrent.locks.ReentrantLock;
> +
> +import org.apache.commons.lang3.StringUtils;
> +import org.apache.jmeter.samplers.Sampler;
> +import org.apache.jmeter.testelement.TestStateListener;
> +import org.apache.jmeter.testelement.ThreadListener;
> +import org.apache.jmeter.testelement.property.StringProperty;
> +import org.apache.jorphan.logging.LoggingManager;
> +import org.apache.log.Logger;
> +
> +/**
> + * This is a Critical Section Controller; it will execute the set of statements
> + * (samplers/controllers, etc) under named lock.
> + * <p>
> + * In a programming world - this is equivalent of :
> + *
> + * <pre>
> + * try {
> + *          named_lock.lock();
> + *          statements ....
> + * } finally {
> + *          named_lock.unlock();
> + * }
> + * </pre>
> + *
> + * In JMeter you may have :
> + *
> + * <pre>
> + * Thread-Group (set to loop a number of times or indefinitely,
> + *    ... Samplers ... (e.g. Counter )
> + *    ... Other Controllers ....
> + *    ... CriticalSectionController ( lock name like "foobar" )
> + *       ... statements to perform when lock acquired
> + *       ...
> + *    ... Other Controllers /Samplers }
> + * </pre>
> + *
> + * @since 2.12
> + */
> +public class CriticalSectionController extends GenericController implements
> +        ThreadListener, TestStateListener {
> +
> +    /**
> +     *
> +     */
> +    private static final long serialVersionUID = 4362876132435968088L;
> +
> +    private static final Logger logger = LoggingManager.getLoggerForClass();
> +
> +    private static final String LOCK_NAME = "CriticalSectionController.lockName"; //$NON-NLS-1$
> +
> +    private static final ConcurrentHashMap<String, ReentrantLock> lockMap = new ConcurrentHashMap<String, ReentrantLock>();

s/lockMap/LOCK_MAP/ ?

This is a static constant, so should normally be upper case.

> +
> +    private transient ReentrantLock currentLock;

Does this need to be volatile/or synch?
Is it accessed by multiple threads?

The reInitialize() method suggests that multiple threads do access the
same variable.

> +
> +    /**
> +     * constructor
> +     */
> +    public CriticalSectionController() {
> +        super();
> +    }
> +
> +    /**
> +     * constructor
> +     */
> +    public CriticalSectionController(String name) {
> +        super();
> +        this.setName(name);
> +    }
> +
> +    /**
> +     * Condition Accessor - this is gonna be any string value

Javadoc does not match code/methof name

> +     */
> +    public void setLockName(String name) {
> +        setProperty(new StringProperty(LOCK_NAME, name));
> +    }
> +
> +    /**
> +     * Function for autocreate and get lock

Javadoc is misleading.

> +     *
> +     * @return named lock
> +     */
> +    private ReentrantLock getLock() {
> +        ReentrantLock lock = lockMap.get(getLockName());

Should fetch the lock name once ... i.e. cache the string in a local variable.

> +        ReentrantLock prev = null;
> +        if (lock != null) {
> +            return lock;
> +        }
> +        lock = new ReentrantLock();
> +        prev = lockMap.putIfAbsent(getLockName(), lock);

Re-use the cached lock name here.

Apart from reducing the work needed, it's vital that the same string
is used here.

> +        return prev == null ? lock : prev;
> +    }
> +
> +    /**
> +     * Lock name
> +     */
> +    public String getLockName() {
> +        return getPropertyAsString(LOCK_NAME);
> +    }
> +
> +    /**
> +     * @see org.apache.jmeter.control.Controller#next()
> +     */
> +    @Override
> +    public Sampler next() {
> +        if (StringUtils.isEmpty(getLockName())) {
> +            logger.warn("Empty lock name in Critical Section Controller:"
> +                    + getName());
> +            return super.next();
> +        }
> +        if (isFirst()) {
> +            // Take the lock for first child element
> +            long startTime = System.currentTimeMillis();
> +            if (this.currentLock == null) {
> +                this.currentLock = getLock();
> +            }
> +            this.currentLock.lock();
> +            long endTime = System.currentTimeMillis();
> +            if (logger.isDebugEnabled()) {
> +                logger.debug(Thread.currentThread().getName()
> +                        + " acquired lock:'" + getLockName()
> +                        + "' in Critical Section Controller " + getName()
> +                        + " in:" + (endTime - startTime) + " ms");
> +            }
> +        }
> +        return super.next();
> +    }
> +
> +    /**
> +     * Called after execution of last child of the controller We release lock
> +     *
> +     * @see org.apache.jmeter.control.GenericController#reInitialize()
> +     */
> +    @Override
> +    protected void reInitialize() {
> +        if (this.currentLock != null) {
> +            if (currentLock.isHeldByCurrentThread()) {
> +                this.currentLock.unlock();
> +            }
> +            this.currentLock = null;
> +        }
> +        super.reInitialize();
> +    }
> +
> +    @Override
> +    public void threadStarted() {
> +        this.currentLock = null;
> +    }
> +
> +    @Override
> +    public void threadFinished() {
> +        if (this.currentLock != null
> +                && this.currentLock.isHeldByCurrentThread()) {
> +            logger.warn("Lock " + getLockName() + " not released in:"
> +                    + getName() + ", releasing in threadFinished");
> +            this.currentLock.unlock();
> +        }
> +        this.currentLock = null;
> +    }
> +
> +    @Override
> +    public void testStarted() {
> +        // NOOP
> +    }
> +
> +    @Override
> +    public void testStarted(String host) {
> +        // NOOP
> +    }
> +
> +    @Override
> +    public void testEnded() {
> +        lockMap.clear();
> +    }
> +
> +    @Override
> +    public void testEnded(String host) {
> +        testEnded();
> +    }
> +}
>
> Propchange: jmeter/trunk/src/components/org/apache/jmeter/control/CriticalSectionController.java
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Added: jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java
> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java?rev=1611689&view=auto
> ==============================================================================
> --- jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java (added)
> +++ jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java Fri Jul 18 16:13:18 2014
> @@ -0,0 +1,183 @@
> +/*
> + * 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.
> + *
> + */
> +
> +package org.apache.jmeter.control.gui;
> +
> +import java.awt.BorderLayout;
> +
> +import javax.swing.Box;
> +import javax.swing.JLabel;
> +import javax.swing.JPanel;
> +import javax.swing.JTextField;
> +
> +import org.apache.jmeter.control.CriticalSectionController;
> +import org.apache.jmeter.testelement.TestElement;
> +import org.apache.jmeter.util.JMeterUtils;
> +
> +/**
> + * The user interface for a controller which specifies that its subcomponents
> + * should be executed while a condition holds. This component can be used
> + * standalone or embedded into some other component.
> + *
> + * @since 2.12
> + */
> +public class CriticalSectionControllerGui extends AbstractControllerGui {
> +
> +    /**
> +     *
> +     */
> +    private static final long serialVersionUID = 7177285850634344095L;
> +
> +    /**
> +     * A field allowing the user to specify the number of times the controller
> +     * should loop.

Incorrect Javadoc

> +     */
> +    private JTextField tfLockName;
> +
> +    /**
> +     * Boolean indicating whether or not this component should display its name.
> +     * If true, this is a standalone component. If false, this component is
> +     * intended to be used as a subpanel for another component.
> +     */
> +    private boolean displayName = true;
> +
> +    /**
> +     * Create a new LoopControlPanel as a standalone component.

Incorrect Javadoc

> +     */
> +    public CriticalSectionControllerGui() {
> +        this(true);
> +    }
> +
> +    /**
> +     * Create a new IfControllerPanel as either a standalone or an embedded
> +     * component.

Incorrect Javadoc

> +     *
> +     * @param displayName
> +     *            indicates whether or not this component should display its
> +     *            name. If true, this is a standalone component. If false, this
> +     *            component is intended to be used as a subpanel for another
> +     *            component.
> +     */
> +    public CriticalSectionControllerGui(boolean displayName) {
> +        this.displayName = displayName;
> +        init();
> +    }
> +
> +    /**
> +     * A newly created component can be initialized with the contents of a Test
> +     * Element object by calling this method. The component is responsible for
> +     * querying the Test Element object for the relevant information to display
> +     * in its GUI.
> +     *
> +     * @param element
> +     *            the TestElement to configure
> +     */
> +    @Override
> +    public void configure(TestElement element) {
> +        super.configure(element);
> +        if (element instanceof CriticalSectionController) {
> +            CriticalSectionController controller = (CriticalSectionController) element;
> +            tfLockName.setText(controller.getLockName());
> +        }
> +
> +    }
> +
> +    /**
> +     * Implements JMeterGUIComponent.createTestElement()
> +     */
> +    @Override
> +    public TestElement createTestElement() {
> +        CriticalSectionController controller = new CriticalSectionController();
> +        modifyTestElement(controller);
> +        return controller;
> +    }
> +
> +    /**
> +     * Implements JMeterGUIComponent.modifyTestElement(TestElement)
> +     */
> +    @Override
> +    public void modifyTestElement(TestElement controller) {
> +        configureTestElement(controller);
> +        if (controller instanceof CriticalSectionController) {
> +            CriticalSectionController csController = (CriticalSectionController) controller;
> +            csController.setLockName(tfLockName.getText());
> +        }
> +    }
> +
> +    /**
> +     * Implements JMeterGUIComponent.clearGui
> +     */
> +    @Override
> +    public void clearGui() {
> +        super.clearGui();
> +        tfLockName.setText("global_lock"); // $NON-NLS-1$
> +    }
> +
> +    @Override
> +    public String getLabelResource() {
> +        return "critical_section_controller_title"; // $NON-NLS-1$
> +    }
> +
> +    /**
> +     * Initialize the GUI components and layout for this component.
> +     */
> +    private void init() {
> +        // Standalone
> +        if (displayName) {
> +            setLayout(new BorderLayout(0, 5));
> +            setBorder(makeBorder());
> +            add(makeTitlePanel(), BorderLayout.NORTH);
> +
> +            JPanel mainPanel = new JPanel(new BorderLayout());
> +            mainPanel.add(createConditionPanel(), BorderLayout.NORTH);
> +            add(mainPanel, BorderLayout.CENTER);
> +
> +        } else {
> +            // Embedded
> +            setLayout(new BorderLayout());
> +            add(createConditionPanel(), BorderLayout.NORTH);
> +        }
> +    }
> +
> +    /**
> +     * Create a GUI panel containing the condition.
> +     *
> +     * @return a GUI panel containing the condition components
> +     */
> +    private JPanel createConditionPanel() {
> +        JPanel conditionPanel = new JPanel(new BorderLayout(5, 0));
> +
> +        // Condition LABEL
> +        JLabel conditionLabel = new JLabel(
> +                JMeterUtils.getResString("critical_section_controller_label")); // $NON-NLS-1$
> +        conditionPanel.add(conditionLabel, BorderLayout.WEST);
> +
> +        // TEXT FIELD
> +        tfLockName = new JTextField(""); // $NON-NLS-1$
> +        conditionLabel.setLabelFor(tfLockName);
> +        conditionPanel.add(tfLockName, BorderLayout.CENTER);
> +
> +        conditionPanel
> +                .add(Box.createHorizontalStrut(conditionLabel
> +                        .getPreferredSize().width
> +                        + tfLockName.getPreferredSize().width),
> +                        BorderLayout.NORTH);
> +
> +        return conditionPanel;
> +    }
> +}
>
> Propchange: jmeter/trunk/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=1611689&r1=1611688&r2=1611689&view=diff
> ==============================================================================
> --- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
> +++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Fri Jul 18 16:13:18 2014
> @@ -209,6 +209,8 @@ counter_config_title=Counter
>  counter_per_user=Track counter independently for each user
>  counter_reset_per_tg_iteration=Reset counter on each Thread Group Iteration
>  countlim=Size limit
> +critical_section_controller_label=Lock name
> +critical_section_controller_title=Critical Section Controller
>  csvread_file_file_name=CSV file to get values from | *alias
>  cut=Cut
>  cut_paste_function=Copy and paste function string
>
> Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties?rev=1611689&r1=1611688&r2=1611689&view=diff
> ==============================================================================
> --- jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties (original)
> +++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties Fri Jul 18 16:13:18 2014
> @@ -197,6 +197,8 @@ counter_config_title=Compteur
>  counter_per_user=Suivre le compteur ind\u00E9pendamment pour chaque unit\u00E9 de test
>  counter_reset_per_tg_iteration=R\u00E9initialiser le compteur \u00E0 chaque it\u00E9ration du groupe d'unit\u00E9s
>  countlim=Limiter le nombre d'\u00E9l\u00E9ments retourn\u00E9s \u00E0
> +critical_section_controller_label=Nom du verrou
> +critical_section_controller_title=Contr\u00F4leur section critique
>  cssjquery_attribute=Attribut
>  cssjquery_impl=Impl\u00E9mentation CSS/JQuery\:
>  cssjquery_render_no_text=Les donn\u00E9es de r\u00E9ponse ne sont pas du texte.
>
> Modified: jmeter/trunk/xdocs/changes.xml
> URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1611689&r1=1611688&r2=1611689&view=diff
> ==============================================================================
> --- jmeter/trunk/xdocs/changes.xml (original)
> +++ jmeter/trunk/xdocs/changes.xml Fri Jul 18 16:13:18 2014
> @@ -1,4 +1,4 @@
> -<?xml version="1.0"?>
> +Crti<?xml version="1.0"?>
>  <!--
>     Licensed to the Apache Software Foundation (ASF) under one or more
>     contributor license agreements.  See the NOTICE file distributed with
> @@ -201,6 +201,7 @@ A workaround is to use a Java 7 update 4
>
>  <h3>Controllers</h3>
>  <ul>
> +<li><bugzilla>56728</bugzilla> - New Critical Section Controller to serialize blocks of a Test. Based partly on a patch contributed by Mikhail Epikhin(epihin-m at yandex.ru)</li>
>  </ul>
>
>  <h3>Listeners</h3>
>
> Modified: jmeter/trunk/xdocs/usermanual/component_reference.xml
> URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=1611689&r1=1611688&r2=1611689&view=diff
> ==============================================================================
> --- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
> +++ jmeter/trunk/xdocs/usermanual/component_reference.xml Fri Jul 18 16:13:18 2014
> @@ -2518,6 +2518,17 @@ be saved under the Recording Controller.
>
>  </component>
>
> +<component name="Critical Section Controller" index="&sect-num;.2.17" width="420" height="79" screenshot="logic-controller/critical-section-controller.png">
> +<description>
> +<p>The Critical Section Controller ensures that its children elements (samplers/controllers, etc) will be executed
> +by only one thread as a named lock will be taken before executing children of controller.</p>
> +
> +</description>
> +<properties>
> +        <property name="Lock Name" required="Yes">Lock that will be taken by controller, ensure you use different lock names for unrelated sections</property>
> +</properties>
> +
> +</component>
>
>  <a href="#">^</a>
>
>
>