[jbpm-commits] JBoss JBPM SVN: r7060 - in jbpm3/branches/jbpm-3.2-soa/core/src: test/java/org/jbpm and 1 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Feb 21 21:14:44 EST 2012


Author: marco.rietveld
Date: 2012-02-21 21:14:43 -0500 (Tue, 21 Feb 2012)
New Revision: 7060

Added:
   jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm3416/
   jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm3416/JBPM3416Test.java
Modified:
   jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/logging/exe/LoggingInstance.java
Log:
JBPM-3416: LoggingInstance concurrency issue. 

Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/logging/exe/LoggingInstance.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/logging/exe/LoggingInstance.java	2012-02-22 02:13:14 UTC (rev 7059)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/logging/exe/LoggingInstance.java	2012-02-22 02:14:43 UTC (rev 7060)
@@ -25,6 +25,7 @@
 import java.io.ObjectInputStream;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
@@ -51,16 +52,16 @@
   public LoggingInstance() {
   }
 
-  public void startCompositeLog(CompositeLog compositeLog) {
+  public synchronized void startCompositeLog(CompositeLog compositeLog) {
     addLog(compositeLog);
     compositeLogStack.add(compositeLog);
   }
 
-  public void endCompositeLog() {
+  public synchronized void endCompositeLog() {
     compositeLogStack.remove(compositeLogStack.size() - 1);
   }
 
-  public void addLog(ProcessLog processLog) {
+  public synchronized void addLog(ProcessLog processLog) {
     if (!compositeLogStack.isEmpty()) {
       CompositeLog compositeLog = (CompositeLog) compositeLogStack.get(compositeLogStack.size() - 1);
       compositeLog.addChild(processLog);
@@ -71,14 +72,14 @@
   }
 
   public List getLogs() {
-    return logs;
+    return Collections.unmodifiableList(logs);
   }
 
   /**
    * get logs, filtered by log type.
    */
   public List getLogs(Class filterClass) {
-    return getLogs(logs, filterClass);
+    return getLogs(getLogs(), filterClass);
   }
 
   public static List getLogs(Collection logs, Class filterClass) {
@@ -93,7 +94,7 @@
   }
 
   List getCompositeLogStack() {
-    return compositeLogStack;
+    return Collections.unmodifiableList(compositeLogStack);
   }
 
   public void logLogs() {

Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm3416/JBPM3416Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm3416/JBPM3416Test.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm3416/JBPM3416Test.java	2012-02-22 02:14:43 UTC (rev 7060)
@@ -0,0 +1,148 @@
+package org.jbpm.jbpm3416;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jbpm.AbstractJbpmTestCase;
+import org.jbpm.context.exe.ContextInstance;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+import org.jbpm.graph.exe.Token;
+
+/**
+ * 2 threads concurrently call Token#signal() and ContextThread#setVariable() on the same process instance.
+ * THREAD_NUM is the number of threads which concurrently execute the test. Each thread spawns 2 threads as described above.
+ * LOOP_NUM is the number of test iterations. You may increase it to reproduce the Exception for sure.
+ * 
+ * @see <a href="https://jira.jboss.org/jira/browse/JBPM-3416">JBPM-3416</a>
+ */
+public class JBPM3416Test extends AbstractJbpmTestCase {
+
+  private static final int LOOP_NUM = 100;
+  private static final int THREAD_NUM = 1000;
+
+  private static List exceptionList = new ArrayList();
+
+  public boolean doNotRunUnlessManually = true;
+  
+  public void testConcurrentAccessToLoggingInstance() {
+    if( doNotRunUnlessManually ) { 
+      return;
+    }
+
+    ProcessDefinition processDefinition = ProcessDefinition
+        .parseXmlString(
+              "<process-definition>"
+            + "  <start-state name='start'>"
+            + "    <transition to='s' />"
+            + "  </start-state>"
+            + "  <state name='s'>"
+            + "    <transition to='end' />"
+            + "  </state>"
+            + "  <end-state name='end' />"
+            + "</process-definition>");
+
+    for (int i = 0; i < LOOP_NUM; i++) {
+      ArrayList threads = new ArrayList();
+      for (int idx = 0; idx < THREAD_NUM; idx++) {
+        threads.add(new JobThread(processDefinition, idx));
+      }
+
+      for (int idx = 0; idx < THREAD_NUM; idx++) {
+        ((Thread) threads.get(idx)).start();
+      }
+
+      for (int idx = 0; idx < THREAD_NUM; idx++) {
+        try {
+          ((Thread) threads.get(idx)).join();
+        } catch (InterruptedException e) {
+          // ignore
+        }
+      }
+      if (exceptionList.size() > 0) {
+        ((RuntimeException) exceptionList.get(exceptionList.size()-1)).printStackTrace();
+        fail("[" + i + "] Found RuntimeException : exceptionList.size() = "
+            + exceptionList.size() + ", exceptionList.get(0) = "
+            + exceptionList.get(0));
+      }
+    }
+
+
+  }
+
+  private class JobThread extends Thread {
+    ProcessDefinition processDefinition = null;
+    int id = -1;
+
+    public JobThread(ProcessDefinition processDefinition, int id) {
+      this.processDefinition = processDefinition;
+      this.id = id;
+    }
+
+    public void run() {
+      ProcessInstance processInstance = new ProcessInstance(processDefinition);
+
+      TokenThread tokenThread = new TokenThread(processInstance);
+      ContextThread contextThread = new ContextThread(processInstance);
+      tokenThread.start();
+      contextThread.start();
+      try {
+        tokenThread.join();
+      } catch (InterruptedException e) {
+        // ignore;
+      }
+      try {
+        contextThread.join();
+      } catch (InterruptedException e) {
+        // ignore
+      }
+      
+      this.processDefinition = null;
+    }
+  }
+
+  /*
+   * Thread for Token#signal
+   */
+  private class TokenThread extends Thread {
+    ProcessInstance processInstance = null;
+
+    public TokenThread(ProcessInstance processInstance) {
+      this.processInstance = processInstance;
+    }
+
+    public void run() {
+      Token token = processInstance.getRootToken();
+      try {
+        token.signal();
+        token.signal();
+      } catch (RuntimeException e) {
+        exceptionList.add(e);
+      }
+      this.processInstance = null;
+    }
+  }
+
+  /*
+   * Thread for ContextThread#setVariable
+   */
+  private class ContextThread extends Thread {
+    ProcessInstance processInstance = null;
+
+    public ContextThread(ProcessInstance processInstance ) {
+      this.processInstance = processInstance;
+    }
+
+    public void run() {
+
+      ContextInstance contextInstance = processInstance.getContextInstance();
+      try {
+        contextInstance.setVariable("RESULT", "OK");
+      } catch (RuntimeException e) {
+        exceptionList.add(e);
+      }
+      this.processInstance = null;
+
+    }
+  }
+}


Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm3416/JBPM3416Test.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native



More information about the jbpm-commits mailing list