View | Details | Raw Unified | Return to bug 56728
Collapse All | Expand All

(-)/Users/schizophrenia/Documents/workspace/jmeter-CriticalSectionController/src/components/org/apache/jmeter/control/CriticalSectionController.java (-169 lines)
Lines 1-169 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
19
package org.apache.jmeter.control;
20
21
import java.io.Serializable;
22
import java.util.concurrent.ConcurrentHashMap;
23
import java.util.concurrent.atomic.AtomicBoolean;
24
import java.util.concurrent.locks.Lock;
25
import java.util.concurrent.locks.ReentrantLock;
26
27
import org.apache.jmeter.samplers.Sampler;
28
import org.apache.jmeter.testelement.TestElement;
29
import org.apache.jmeter.testelement.ThreadListener;
30
import org.apache.jmeter.testelement.property.StringProperty;
31
import org.apache.jorphan.logging.LoggingManager;
32
import org.apache.log.Logger;
33
34
/**
35
 *
36
 *
37
 * This is a Critical Section Controller; it will execute the set of statements
38
 * (samplers/controllers, etc) under named lock.
39
 * <p>
40
 * In a programming world - this is equivalant of :
41
 * <pre>
42
 * try {
43
 *          named_lock.lock();
44
 *          statements ....
45
 * } finally {
46
 *          named_lock.unlock();
47
 * }
48
 * </pre>
49
 * In JMeter you may have :
50
 * <pre> 
51
 * Thread-Group (set to loop a number of times or indefinitely,
52
 *    ... Samplers ... (e.g. Counter )
53
 *    ... Other Controllers ....
54
 *    ... CriticalSectionController ( lock name like "foobar" )
55
 *       ... statements to perform when lock acquired
56
 *       ...
57
 *    ... Other Controllers /Samplers }
58
 * </pre>
59
 */
60
61
// TODO: write unit test
62
63
public class CriticalSectionController extends GenericController implements Serializable, TestElement, ThreadListener {
64
65
    private static final Logger logger = LoggingManager.getLoggerForClass();
66
67
    private static final long serialVersionUID = 240L;
68
69
    private static final String LOCK_NAME = "CriticalSectionController.lockName"; //$NON-NLS-1$
70
71
    protected static final ConcurrentHashMap<String, ReentrantLock> lockMap =
72
    		new ConcurrentHashMap<String, ReentrantLock>();
73
    
74
    protected ReentrantLock currentLock;
75
    
76
    /**
77
     * constructor
78
     */
79
    public CriticalSectionController() {
80
        super();
81
    }
82
83
    /**
84
     * constructor
85
     */
86
    public CriticalSectionController(String name) {
87
        super();
88
        this.setName(name);
89
    }
90
    
91
    /**
92
     * Condition Accessor - this is gonna be any string value
93
     */
94
    public void setLockName(String name) {
95
        setProperty(new StringProperty(LOCK_NAME, name));
96
    }
97
    
98
    /**
99
     * Function for autocreate and get lock
100
     * @return named lock
101
     */
102
    public ReentrantLock getLock() {
103
    	ReentrantLock lock = lockMap.get(getLockName()), prev = null;
104
    	if(lock != null)	return lock;
105
    	lock = new ReentrantLock();
106
    	prev = lockMap.putIfAbsent(getLockName(), lock);
107
    	return prev == null ? lock : prev; 
108
    }
109
    
110
    protected static void clearLockMap() {
111
    	if(lockMap == null) return;
112
    	if(!lockMap.isEmpty()) {
113
			synchronized(lockMap) {
114
				if(!lockMap.isEmpty()) {
115
					lockMap.clear();
116
				}
117
			}
118
		}
119
    }
120
121
    /**
122
     * Lock name
123
     */
124
    public String getLockName() {
125
        return getPropertyAsString(LOCK_NAME);
126
    }
127
128
    /**
129
     * @see org.apache.jmeter.control.Controller#next()
130
     */
131
    @Override
132
    public Sampler next() {
133
    	if(getLockName() == null) return super.next();
134
    	if(getLockName().isEmpty()) return super.next();
135
    	long startTime = System.currentTimeMillis(), endTime;
136
    	if(this.currentLock == null) {
137
    		this.currentLock = getLock();
138
    		this.currentLock.lock();
139
        }    	
140
    	endTime = System.currentTimeMillis();
141
    	logger.debug("acquire time for named lock \"" + getLockName() +
142
    			"\" in Critical Section Controller is " + (endTime - startTime) + "ms");
143
    	return super.next();
144
    }
145
    
146
    @Override
147
    public void setDone(boolean done) {
148
    	if(done && this.currentLock != null) {
149
    		// TODO create policy for remove unused locks
150
    		if(this.currentLock.isHeldByCurrentThread()) {
151
    			this.currentLock.unlock();
152
    		}
153
    		this.currentLock = null;
154
    	}
155
    	super.setDone(done);
156
    }
157
158
	public void threadStarted() {
159
		this.currentLock = null;
160
	}
161
	
162
	public void threadFinished() {
163
		if(this.currentLock.isHeldByCurrentThread()) {
164
			this.currentLock.unlock();
165
		}
166
		this.currentLock = null;
167
		clearLockMap();
168
	}
169
}
(-)/Users/schizophrenia/Documents/workspace/jmeter-CriticalSectionController/src/components/org/apache/jmeter/control/gui/CriticalSectionControllerGui.java (-178 lines)
Lines 1-178 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
19
package org.apache.jmeter.control.gui;
20
21
import java.awt.BorderLayout;
22
23
import javax.swing.Box;
24
import javax.swing.JCheckBox;
25
import javax.swing.JLabel;
26
import javax.swing.JPanel;
27
import javax.swing.JTextField;
28
29
import org.apache.jmeter.control.CriticalSectionController;
30
import org.apache.jmeter.control.IfController;
31
import org.apache.jmeter.testelement.TestElement;
32
import org.apache.jmeter.util.JMeterUtils;
33
34
/**
35
 * The user interface for a controller which specifies that its subcomponents
36
 * should be executed while a condition holds. This component can be used
37
 * standalone or embedded into some other component.
38
 *
39
 */
40
41
public class CriticalSectionControllerGui extends AbstractControllerGui {
42
43
    private static final long serialVersionUID = 240L;
44
45
    /**
46
     * A field allowing the user to specify the number of times the controller
47
     * should loop.
48
     */
49
    private JTextField tfLockName;
50
51
    /**
52
     * Boolean indicating whether or not this component should display its name.
53
     * If true, this is a standalone component. If false, this component is
54
     * intended to be used as a subpanel for another component.
55
     */
56
    private boolean displayName = true;
57
58
    /**
59
     * Create a new LoopControlPanel as a standalone component.
60
     */
61
    public CriticalSectionControllerGui() {
62
        this(true);
63
    }
64
65
    /**
66
     * Create a new IfControllerPanel as either a standalone or an embedded
67
     * component.
68
     *
69
     * @param displayName
70
     *            indicates whether or not this component should display its
71
     *            name. If true, this is a standalone component. If false, this
72
     *            component is intended to be used as a subpanel for another
73
     *            component.
74
     */
75
    public CriticalSectionControllerGui(boolean displayName) {
76
        this.displayName = displayName;
77
        init();
78
    }
79
80
    /**
81
     * A newly created component can be initialized with the contents of a Test
82
     * Element object by calling this method. The component is responsible for
83
     * querying the Test Element object for the relevant information to display
84
     * in its GUI.
85
     *
86
     * @param element
87
     *            the TestElement to configure
88
     */
89
    @Override
90
    public void configure(TestElement element) {
91
        super.configure(element);
92
        if (element instanceof CriticalSectionController) {
93
        	CriticalSectionController controller = (CriticalSectionController) element;
94
        	tfLockName.setText(controller.getLockName());
95
        }
96
97
    }
98
99
    /**
100
     * Implements JMeterGUIComponent.createTestElement()
101
     */
102
    @Override
103
    public TestElement createTestElement() {
104
    	CriticalSectionController controller = new CriticalSectionController();
105
        modifyTestElement(controller);
106
        return controller;
107
    }
108
109
    /**
110
     * Implements JMeterGUIComponent.modifyTestElement(TestElement)
111
     */
112
    @Override
113
    public void modifyTestElement(TestElement controller) {
114
        configureTestElement(controller);
115
        if (controller instanceof CriticalSectionController) {
116
        	CriticalSectionController csController = (CriticalSectionController) controller;
117
        	csController.setLockName(tfLockName.getText());
118
        }
119
    }
120
121
    /**
122
     * Implements JMeterGUIComponent.clearGui
123
     */
124
    @Override
125
    public void clearGui() {
126
        super.clearGui();
127
        tfLockName.setText("global_lock"); // $NON-NLS-1$
128
    }
129
130
    @Override
131
    public String getLabelResource() {
132
        return "critical_section_controller_title"; // $NON-NLS-1$
133
    }
134
135
    /**
136
     * Initialize the GUI components and layout for this component.
137
     */
138
    private void init() {
139
        // Standalone
140
        if (displayName) {
141
            setLayout(new BorderLayout(0, 5));
142
            setBorder(makeBorder());
143
            add(makeTitlePanel(), BorderLayout.NORTH);
144
145
            JPanel mainPanel = new JPanel(new BorderLayout());
146
            mainPanel.add(createConditionPanel(), BorderLayout.NORTH);
147
            add(mainPanel, BorderLayout.CENTER);
148
149
        } else {
150
            // Embedded
151
            setLayout(new BorderLayout());
152
            add(createConditionPanel(), BorderLayout.NORTH);
153
        }
154
    }
155
156
    /**
157
     * Create a GUI panel containing the condition.
158
     *
159
     * @return a GUI panel containing the condition components
160
     */
161
    private JPanel createConditionPanel() {
162
        JPanel conditionPanel = new JPanel(new BorderLayout(5, 0));
163
164
        // Condition LABEL
165
        JLabel conditionLabel = new JLabel(JMeterUtils.getResString("critical_section_controller_label")); // $NON-NLS-1$
166
        conditionPanel.add(conditionLabel, BorderLayout.WEST);
167
168
        // TEXT FIELD
169
        tfLockName = new JTextField(""); // $NON-NLS-1$
170
        conditionLabel.setLabelFor(tfLockName);
171
        conditionPanel.add(tfLockName, BorderLayout.CENTER);
172
       
173
        conditionPanel.add(Box.createHorizontalStrut(conditionLabel.getPreferredSize().width
174
                + tfLockName.getPreferredSize().width), BorderLayout.NORTH);
175
176
        return conditionPanel;
177
    }
178
}
(-)/Users/schizophrenia/Documents/workspace/jmeter-CriticalSectionController/src/core/org/apache/jmeter/resources/messages.properties (-2 lines)
Lines 398-405 Link Here
398
if_controller_expression=Interpret Condition as Variable Expression?
398
if_controller_expression=Interpret Condition as Variable Expression?
399
if_controller_label=Condition (default Javascript)
399
if_controller_label=Condition (default Javascript)
400
if_controller_title=If Controller
400
if_controller_title=If Controller
401
critical_section_controller_label=Lock name
402
critical_section_controller_title=Critical Section Controller
403
ignore_subcontrollers=Ignore sub-controller blocks
401
ignore_subcontrollers=Ignore sub-controller blocks
404
include_controller=Include Controller
402
include_controller=Include Controller
405
include_equals=Include Equals?
403
include_equals=Include Equals?

Return to bug 56728