New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
using semaphores in jmeter (block critical regions) #2012
Comments
Christoph (migrated from Bugzilla): jakarta-jmeter-2.3_Semaphores.java.patchIndex: jakarta-jmeter-2.3/src/core/org/apache/jmeter/engine/StandardJMeterEngine.java
===================================================================
--- jakarta-jmeter-2.3/src/core/org/apache/jmeter/engine/StandardJMeterEngine.java (revision 1)
+++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/engine/StandardJMeterEngine.java (working copy)
@@ -313,6 +313,9 @@
if (((TestPlan) plan[0]).isSerialized()) {
serialized = true;
}
+
+ JMeterUtils.clearSemaphores();
+
JMeterContextService.startTest();
try {
compileTree();
Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/threads/JMeterThread.java
===================================================================
--- jakarta-jmeter-2.3/src/core/org/apache/jmeter/threads/JMeterThread.java (revision 1)
+++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/threads/JMeterThread.java (working copy)
@@ -195,6 +195,8 @@
long delay = System.currentTimeMillis() - endTime;
if ((delay >= 0)) {
running = false;
+ //release all semaphores of threadgroup
+ org.apache.jmeter.util.JMeterUtils.releaseSemaphoresForThreadGroup(threadGroup.getName());
}
}
Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/util/JMeterUtils.java
===================================================================
--- jakarta-jmeter-2.3/src/core/org/apache/jmeter/util/JMeterUtils.java (revision 1)
+++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/util/JMeterUtils.java (working copy)
@@ -38,7 +38,11 @@
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.Vector;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+import java.util.HashMap;
+
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
@@ -86,6 +90,63 @@
// Provide Random numbers to whomever wants one
private static Random rand = new Random();
+ // Provide a means to synchronize threads
+ private static HashMap<String, Pair> semaphores = new HashMap<String, Pair>();
+
+ public static void releaseAllSemaphores() {
+ Iterator it = semaphores.values().iterator();
+ //iterate trough hashmap and release all semaphores of current threadgroup
+ while (it.hasNext()) {
+ Pair pair = (Pair)it.next();
+ Semaphore sem = (Semaphore)pair.second;
+ if (sem != null) {
+ sem.release();
+ }
+ }
+ }
+
+ public static void releaseSemaphoresForThreadGroup(String tgroup) {
+ Iterator it = semaphores.values().iterator();
+ //iterate trough hashmap and release all semaphores of current threadgroup
+ while (it.hasNext()) {
+ Pair pair = (Pair)it.next();
+ Semaphore sem = (Semaphore)pair.second;
+ ArrayList al = (ArrayList)pair.first;
+ if (al.contains(tgroup)) {
+ if (sem != null) {
+ sem.release();
+ }
+ }
+ }
+ }
+
+ public static void acquireSemaphore(String name, String tgroup, int count) throws java.lang.InterruptedException {
+ Pair pair = semaphores.get(name);
+ if (pair == null) {
+ //create arraylist with one element (name of threadgroup)
+ ArrayList al = new ArrayList();
+ al.add(tgroup);
+ pair = new Pair(al, new Semaphore(count, true));
+ semaphores.put(name, pair);
+ } else {
+ //add threadgroup-name to arraylist
+ ((ArrayList)pair.first).add(tgroup);
+ }
+ ((Semaphore)pair.second).acquire();
+ }
+
+ public static void releaseSemaphore(String name) {
+ Pair pair = (Pair)semaphores.get(name);
+ Semaphore sem = (Semaphore)pair.second;
+ if (sem != null) {
+ sem.release();
+ }
+ }
+
+ public static void clearSemaphores() {
+ semaphores.clear();
+ }
+
/**
* Gets Perl5Matcher for this thread.
*/
@@ -1102,4 +1163,5 @@
}
return f;
}
+
}
Index: jakarta-jmeter-2.3/src/core/org/apache/jmeter/util/Pair.java
===================================================================
--- jakarta-jmeter-2.3/src/core/org/apache/jmeter/util/Pair.java (revision 0)
+++ jakarta-jmeter-2.3/src/core/org/apache/jmeter/util/Pair.java (revision 0)
@@ -0,0 +1,16 @@
+package org.apache.jmeter.util;
+
+public class Pair{
+
+ public Object first;
+ public Object second;
+
+ public Pair(){
+ }
+
+ public Pair(Object first, Object second){
+ this.first = first;
+ this.second = second;
+ }
+
+}
Index: jakarta-jmeter-2.3/src/protocol/java/org/apache/jmeter/protocol/java/test/AcquireSemaphore.java
===================================================================
--- jakarta-jmeter-2.3/src/protocol/java/org/apache/jmeter/protocol/java/test/AcquireSemaphore.java (revision 0)
+++ jakarta-jmeter-2.3/src/protocol/java/org/apache/jmeter/protocol/java/test/AcquireSemaphore.java (revision 0)
@@ -0,0 +1,62 @@
+package org.apache.jmeter.protocol.java.test;
+
+import java.io.Serializable;
+
+import org.apache.jmeter.threads.JMeterContext;
+import org.apache.jmeter.threads.JMeterContextService;
+import org.apache.jmeter.config.Arguments;
+import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
+import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
+import org.apache.jmeter.samplers.SampleResult;
+
+public class AcquireSemaphore extends AbstractJavaSamplerClient implements Serializable {
+
+ public static final String SEMAPHORE_NAME = "";
+ public static final int SEMAPHORE_COUNT = 1;
+
+ private String name;
+ private int count;
+
+ public AcquireSemaphore() {
+ }
+
+ public void setupTest(JavaSamplerContext context) {
+ name = context.getParameter("Name", SEMAPHORE_NAME);
+ count = context.getIntParameter("Count", SEMAPHORE_COUNT);
+ }
+
+ public SampleResult runTest(JavaSamplerContext context) {
+ JMeterContext jmctx = JMeterContextService.getContext();
+ String tgname = jmctx.getThreadGroup().getName();
+ SampleResult results = new SampleResult();
+ results.sampleStart();
+ try {
+ results.setSampleLabel(tgname);
+ org.apache.jmeter.util.JMeterUtils.acquireSemaphore(getName(), tgname, getCount());
+ results.setSuccessful(true);
+ } catch (Exception e) {
+ results.setSuccessful(false);
+ } finally {
+ results.sampleEnd();
+ }
+ return results;
+ }
+
+ public void teardownTest(JavaSamplerContext context) {
+ }
+
+ public Arguments getDefaultParameters() {
+ Arguments params = new Arguments();
+ params.addArgument("Name", String.valueOf(SEMAPHORE_NAME));
+ params.addArgument("Count", String.valueOf(SEMAPHORE_COUNT));
+ return params;
+ }
+
+ private String getName() {
+ return name;
+ }
+
+ private int getCount() {
+ return count;
+ }
+}
Index: jakarta-jmeter-2.3/src/protocol/java/org/apache/jmeter/protocol/java/test/ReleaseSemaphore.java
===================================================================
--- jakarta-jmeter-2.3/src/protocol/java/org/apache/jmeter/protocol/java/test/ReleaseSemaphore.java (revision 0)
+++ jakarta-jmeter-2.3/src/protocol/java/org/apache/jmeter/protocol/java/test/ReleaseSemaphore.java (revision 0)
@@ -0,0 +1,54 @@
+package org.apache.jmeter.protocol.java.test;
+
+import java.io.Serializable;
+
+import org.apache.jmeter.threads.JMeterContext;
+import org.apache.jmeter.threads.JMeterContextService;
+import org.apache.jmeter.config.Arguments;
+import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
+import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
+import org.apache.jmeter.samplers.SampleResult;
+
+public class ReleaseSemaphore extends AbstractJavaSamplerClient implements Serializable {
+
+ public static final String SEMAPHORE_NAME = "";
+
+ private String name;
+
+ public ReleaseSemaphore() {
+ }
+
+ public void setupTest(JavaSamplerContext context) {
+ name = context.getParameter("Name", SEMAPHORE_NAME);
+ }
+
+ public SampleResult runTest(JavaSamplerContext context) {
+ JMeterContext jmctx = JMeterContextService.getContext();
+ String tgname = jmctx.getThreadGroup().getName();
+ SampleResult results = new SampleResult();
+ results.sampleStart();
+ try {
+ results.setSampleLabel(tgname);
+ org.apache.jmeter.util.JMeterUtils.releaseSemaphore(getName());
+ results.setSuccessful(true);
+ } catch (Exception e) {
+ results.setSuccessful(false);
+ } finally {
+ results.sampleEnd();
+ }
+ return results;
+ }
+
+ public void teardownTest(JavaSamplerContext context) {
+ }
+
+ public Arguments getDefaultParameters() {
+ Arguments params = new Arguments();
+ params.addArgument("Name", String.valueOf(SEMAPHORE_NAME));
+ return params;
+ }
+
+ private String getName() {
+ return name;
+ }
+} |
Sebb (migrated from Bugzilla): However the functionality would be useful. I believe there is a library containing semaphores which runs on 1.4. Provided |
Sebb (migrated from Bugzilla): |
Sebb (migrated from Bugzilla):
That's a bug in the web-app ...
Again that's something that independent users may encounter normally. So I don't think these use cases are typical. AFAICT, in your case, the semaphores are being used to avoid triggering the errors. However, it may still be useful as a way of configuring a test. I'm not sure that a sampler is the correct test element to use; that needs to be given more thought. Would a Timer be better? After all, that's the effect of the semaphore. |
@pmouawad (migrated from Bugzilla): |
Christoph (Bug 43384):
hi,
in our testplans, we needed a sort of "semaphore" mechanism, e.g.:
can delete a channel that another thread tries to rename.
these are only 2 examples, but since we implemented this controller, we use it
very often.
for this improvement, JMeterUtils.java has methods for acquiring and releasing
semaphores. StandardJMeterEngine.java was patched to clear all semaphores when
starting a test (if someone stops the test and there exists a sempaphore that
was not released). Moreover, JMeterThread.java was patched, that all semaphores
in a threadgroup are released if the scheduler stops the test (before releasing
the semaphore with a sampler).
acquiring and releasing a semaphore can be either done by calling the 2 methods
acquireSemaphore and releaseSemaphore, or by using the 2 samplers that come
with the patch (Java Request). If you are interested in this Feature, i would
implement a SemaphoreSampler with a nice GUI :)
The sampler works like this:
With the "AcquireSemaphore" sampler, you can define the begin of the critical
region by calling the acquireSemaphore-function. It acquires the given number
of permits (count-parameter) from this semaphore, blocking until all are
available. When leaving the critical region, use the ReleaseSemaphore sampler
with the unique semaphore name as parameter.
setting the "count" parameter to "1" would cause this sampler to work like
a "mutex".
Semaphores are supported since Java 1.5, so the build script has to be updated
to build JMeter with Java Version 1.5.
greets,
chris
Votes in Bugzilla: 1
OS: other
Duplicates:
Duplicated by:
The text was updated successfully, but these errors were encountered: