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="§-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="§-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>
>
>
>