[jbpm-commits] JBoss JBPM SVN: r5069 - in jbpm4/trunk/modules/test-concurrent/src: test/java/org/jbpm/test/concurrent and 1 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Fri Jun 19 13:26:38 EDT 2009


Author: jbarrez
Date: 2009-06-19 13:26:38 -0400 (Fri, 19 Jun 2009)
New Revision: 5069

Added:
   jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/CommandExecutionSynchronization.java
   jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/SynchronizableCommandExecutor.java
   jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/AsyncForkTest.java
Removed:
   jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulator.java
   jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorPool.java
   jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorSynchronization.java
Modified:
   jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/ConcurrentJbpmTestCase.java
   jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/OptimisticLockTestGround.java
   jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/TimerVsSignalConcurrencyTest.java
   jbpm4/trunk/modules/test-concurrent/src/test/resources/jbpm.cfg.xml
Log:
Commit intermediate work on concurrent testing (work in progress - doesnt work yet)

Copied: jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/CommandExecutionSynchronization.java (from rev 5049, jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorSynchronization.java)
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/CommandExecutionSynchronization.java	                        (rev 0)
+++ jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/CommandExecutionSynchronization.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -0,0 +1,47 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+/**
+ * 
+ */
+package org.jbpm.test.concurrent;
+
+/**
+ * Implementations can extend this class to add logic to sync points of the
+ * {@link SynchronizableCommandExecutor}.
+ * 
+ * @author Joram Barrez
+ */
+public abstract class CommandExecutionSynchronization {
+  
+  public void beforeTransactionStarts() { }
+  
+  public void afterTransactionStarted() { }
+  
+  public void beforeExecution() { }
+  
+  public void afterExecution() { }
+  
+  public void beforeTransactionDone() { }
+  
+  public void afterTransactionDone() { }
+
+}

Modified: jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/ConcurrentJbpmTestCase.java
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/ConcurrentJbpmTestCase.java	2009-06-19 15:53:46 UTC (rev 5068)
+++ jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/ConcurrentJbpmTestCase.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -39,37 +39,7 @@
 
   protected void setUp() throws Exception {
     super.setUp();
-    this.environmentFactory = (EnvironmentFactory) processEngine; // Is there a better way to do this?
+    this.environmentFactory = (EnvironmentFactory) processEngine;
   }
-  
-  protected class OffloadThread extends Thread {
-    
-    private ThreadCallback threadCallback;
-    
-    private Exception exception;
-    
-    public OffloadThread(ThreadCallback threadCallback) {
-      this.threadCallback = threadCallback;
-    }
 
-    public void run() {
-      try {
-       threadCallback.executeInThread(); 
-      } catch (Exception e) {
-        this.exception = e;
-      }
-    }
-
-    public Exception getException() {
-      return exception;
-    }
-    
-  }
-  
-  protected interface ThreadCallback {
-    
-    void executeInThread();
-    
-  }
-
 }

Deleted: jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulator.java
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulator.java	2009-06-19 15:53:46 UTC (rev 5068)
+++ jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulator.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -1,302 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-/**
- * 
- */
-package org.jbpm.test.concurrent;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-
-import org.jbpm.api.env.Environment;
-import org.jbpm.api.env.EnvironmentFactory;
-import org.jbpm.api.job.Job;
-import org.jbpm.pvm.internal.cmd.ExecuteJobCmd;
-import org.jbpm.pvm.internal.tx.StandardTransaction;
-
-/**
- * Emulates the JobExecutorThread by executing the ExecuteJobCmd in 
- * a dedicated thread. 
- * 
- * Has several sync points available (see {@link JobExecutorEmulatorSynchronization}):
- * - before/after transaction is started
- * - before/after job execution
- * - before/after transaction is done (ie commit)
- * 
- * TODO: implement transaction sync, now only sync on job execution is done - waiting until use case passes by
- * 
- * @author Joram Barrez
- */
-public class JobExecutorEmulator extends Thread {
-    
-    /** Used to create environment blocks */
-    private EnvironmentFactory environmentFactory;
-  
-    /** The database id of the job that is executed by this JobExecutorEmulator */
-    private Long jobId;
-    
-    /** 
-     * If an exception occurs in a thread that is not the JUnit thread, then
-     * the JUnit thread will never notice this. The solution is to catch the
-     * exception and store it in this field, so the JUnit thread can check
-     * if there were any exceptions when executing the job.
-     */
-    private Exception exception;
-    
-    /** Indicates if the thread must be blocked (ie this.wait() must be called) */
-    private boolean threadBlocked;
-    
-    /**
-     * List of synchronizations that will be called on specific point in the
-     * execution of this thread.
-     */
-    private List<JobExecutorEmulatorSynchronization> synchronizations;
-    
-    /* SYNC PRIMITIVES */
-    
-    /** Sync point when the job is executed */
-    private CyclicBarrier afterJobExecutionBarrier;
-    
-    private List<String> afterJobExecutionSyncThreads;
-    
-    /** Sync point before the job is executed */
-    private CyclicBarrier beforeJobExecutionBarrier;
-    
-    private List<String> beforeJobExecutionSyncThreads;
-    
-    /**
-     * Constructor.
-     * 
-     * @param job The job that must be executred by this emulator.
-     */
-    public JobExecutorEmulator(EnvironmentFactory environmentFactory, Job job) {
-      this.environmentFactory = environmentFactory;
-      this.jobId = job.getDbid();
-      this.threadBlocked = false;
-      
-      this.synchronizations = new ArrayList<JobExecutorEmulatorSynchronization>();
-      synchronizations.add(new DefaultSynchronization());
-    }
-    
-    public void run() {
-      
-      Environment environment = environmentFactory.openEnvironment();
-      StandardTransaction standardTransaction = environment.get(StandardTransaction.class);
-      standardTransaction.begin();
-
-      try {
-        
-        handleBeforeJobExecutionSynchronizations();
-        ExecuteJobCmd executeJobCmd = new ExecuteJobCmd(jobId);
-        executeJobCmd.execute(environment);
-        handleAfterJobExecutionSynchronizations(); // Sync point: after job execution
-        
-      } catch (Exception e) {
-        
-        standardTransaction.setRollbackOnly();
-        this.exception = e;
-        
-      } finally {
-                
-        if (standardTransaction.isRollbackOnly()) {
-          exception = new Exception("Transaction was rollbacked due to an exception");
-        }
-        
-        try {
-          standardTransaction.complete();
-        } catch (Exception e) {
-          
-        }
-        
-      }
-      environment.close();
-    }
-    
-    /**
-     * Executes all synchronizations that must be executed before the job is executed
-     */
-    private void handleBeforeJobExecutionSynchronizations() {
-      for (JobExecutorEmulatorSynchronization synchronization : synchronizations) {
-        synchronization.beforeJobExecution();
-      }
-    }
-    
-    /**
-     * Executes all synchronizations that must be executed when the job is executed
-     */
-    private void handleAfterJobExecutionSynchronizations() {
-      for (JobExecutorEmulatorSynchronization synchronization : synchronizations) {
-        synchronization.afterJobExecution();
-      }
-    }
-    
-    /**
-     * Unit tests that use this class can use this method to synchronize
-     * when the job just has been executed.
-     * 
-     * @param blockJobExecutor If true, the jobExecutor will be halted
-     * when leaving the synchronisation point
-     */
-    public void waitUntilJobExecuted(boolean blockJobExecutor) {
-      if (afterJobExecutionBarrier != null) {
-        try {
-          threadBlocked = blockJobExecutor;
-          afterJobExecutionBarrier.await();
-        } catch (InterruptedException e) {
-          e.printStackTrace();
-        } catch (BrokenBarrierException e) {
-          e.printStackTrace();
-        }
-      }
-    }
-    
-    public JobExecutorEmulator synchroniseAfterJobExecution(String threadName) {
-      if (isAlive()) {
-        throw new RuntimeException("Cannot set synchronization point once the JobExecutorEmulator has been started");
-      }
-      
-      if (afterJobExecutionSyncThreads == null) {
-        afterJobExecutionSyncThreads = new ArrayList<String>();
-      }
-      
-      if (afterJobExecutionBarrier == null ) {
-        afterJobExecutionBarrier = new CyclicBarrier(2);
-      } else {
-        afterJobExecutionBarrier = new CyclicBarrier(afterJobExecutionBarrier.getParties() + 1);
-      }
-      
-      return this;
-    }
-    
-    public JobExecutorEmulator synchroniseBeforeJobExecution(String threadName) {
-      if (isAlive()) {
-        throw new RuntimeException("Cannot set synchronization point once the JobExecutorEmulator has been started");
-      }
-      
-      if (beforeJobExecutionBarrier == null) {
-        beforeJobExecutionSyncThreads = new ArrayList<String>();
-      }
-      
-      if (beforeJobExecutionBarrier == null ) {
-        beforeJobExecutionBarrier = new CyclicBarrier(2);
-      } else {
-        beforeJobExecutionBarrier = new CyclicBarrier(beforeJobExecutionBarrier.getParties() + 1);
-      }
-      
-      return this;
-    }
-    
-    /**
-     * Helper method: check if the flag 'threadBlocked' has been raised.
-     * If so, this thread will block until it is notified again.
-     */
-    private void blockIfNeeded() {
-      if (threadBlocked) {
-        synchronized (this) {
-          try {
-            threadBlocked = false;
-            wait();
-          } catch (InterruptedException e) {
-            e.printStackTrace();
-          }
-        }
-      }
-    }
-    
-    /**
-     * Unit tests can use this method to proceed a halted JobExecutorEmulator.
-     * (ie this means that the wait() was called on this thread in the past).
-     */
-    public void goOn() {
-      synchronized (this) {
-          notify();
-      };
-    }
-    
-    /**
-     * Adds a custom synchronization to the JobExecutorEmulator.
-     */
-    public void addSynchronization(JobExecutorEmulatorSynchronization synchronization) {
-      synchronizations.add(synchronization);
-    }
-    
-    /* GETTERS AND SETTERS */
-    
-    public Exception getException() {
-      return exception;
-    }
-    
-    public boolean isBlockThread() {
-      return threadBlocked;
-    }
-
-    public void setBlockThread(boolean blockThread) {
-      this.threadBlocked = blockThread;
-    }
-
-    public void setAfterJobExecutionBarrier(CyclicBarrier afterJobExecutionBarrier) {
-      this.afterJobExecutionBarrier = afterJobExecutionBarrier;
-    }
-
-    public void setBeforeJobExecutionBarrier(CyclicBarrier beforeJobExecutionBarrier) {
-      this.beforeJobExecutionBarrier = beforeJobExecutionBarrier;
-    }
-
-    /**
-     * Default synchronization, executed by all JobExecutorEmulators.
-     * The default logic will synchronize at every sync point (ie barrier) 
-     * which is not null and will check if any external caller has raised
-     * the 'threadBlocked' flag.
-     */
-    private class DefaultSynchronization extends JobExecutorEmulatorSynchronization {
-      
-      public void afterJobExecution() {;
-        if (afterJobExecutionBarrier != null) {
-          try {
-            afterJobExecutionBarrier.await();
-            blockIfNeeded();
-          } catch (InterruptedException e) {
-            e.printStackTrace();
-          } catch (BrokenBarrierException e) {
-            e.printStackTrace();
-          }
-        }
-      }
-      
-      public void beforeJobExecution() {;
-      if (beforeJobExecutionBarrier != null) {
-        try {
-          beforeJobExecutionBarrier.await();
-          blockIfNeeded();
-        } catch (InterruptedException e) {
-          e.printStackTrace();
-        } catch (BrokenBarrierException e) {
-          e.printStackTrace();
-        }
-      }
-    }
-      
-    }
-
-}

Deleted: jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorPool.java
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorPool.java	2009-06-19 15:53:46 UTC (rev 5068)
+++ jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorPool.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -1,53 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-/**
- * 
- */
-package org.jbpm.test.concurrent;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.jbpm.api.env.EnvironmentFactory;
-import org.jbpm.api.job.Job;
-
-
-/**
- * @author Joram Barrez
- */
-public class JobExecutorEmulatorPool {
-  
-  private EnvironmentFactory environmentFactory;
-  
-  private List<JobExecutorEmulator> jobExecutorEmulators;
-  
-  public JobExecutorEmulatorPool(EnvironmentFactory environmentFactory) {
-    this.environmentFactory = environmentFactory;
-    this.jobExecutorEmulators = new ArrayList<JobExecutorEmulator>();
-  }
-  
-  public void emulateJobExecution(Collection<Job> jobs) {
-    
-  }
-
-}

Deleted: jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorSynchronization.java
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorSynchronization.java	2009-06-19 15:53:46 UTC (rev 5068)
+++ jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulatorSynchronization.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -1,47 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-/**
- * 
- */
-package org.jbpm.test.concurrent;
-
-/**
- * Implementations can extend this class to add logic to sync points of the
- * {@link JobExecutorEmulator}.
- * 
- * @author Joram Barrez
- */
-public abstract class JobExecutorEmulatorSynchronization {
-  
-  public void beforeTransactionStarts() { }
-  
-  public void afterTransactionStarted() { }
-  
-  public void beforeJobExecution() { }
-  
-  public void afterJobExecution() { }
-  
-  public void beforeTransactionDone() { }
-  
-  public void afterTransactionDone() { }
-
-}

Copied: jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/SynchronizableCommandExecutor.java (from rev 5049, jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/JobExecutorEmulator.java)
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/SynchronizableCommandExecutor.java	                        (rev 0)
+++ jbpm4/trunk/modules/test-concurrent/src/main/java/org/jbpm/test/concurrent/SynchronizableCommandExecutor.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -0,0 +1,330 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+/**
+ * 
+ */
+package org.jbpm.test.concurrent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+import org.jbpm.api.cmd.Command;
+import org.jbpm.api.env.Environment;
+import org.jbpm.api.env.EnvironmentFactory;
+import org.jbpm.api.job.Job;
+import org.jbpm.pvm.internal.cmd.ExecuteJobCmd;
+import org.jbpm.pvm.internal.tx.StandardTransaction;
+
+/**
+ * Executes a given command in a separate thread.
+ * 
+ * Has several sync points available (see {@link CommandExecutionSynchronization}):
+ * - before/after transaction is started
+ * - before/after job execution
+ * - before/after transaction is done (ie commit)
+ * 
+ * TODO: implement transaction sync, now only sync on job execution is done - waiting until use case passes by
+ * 
+ * @author Joram Barrez
+ */
+public class SynchronizableCommandExecutor extends Thread {
+    
+    /** Used to create environment blocks */
+    private EnvironmentFactory environmentFactory;
+  
+    /** The database id of the job that will be executed */
+    private Long jobId;
+    
+    /** The command that will be executed */
+    private Command command;
+    
+    /** 
+     * If an exception occurs in a thread that is not the JUnit thread, then
+     * the JUnit thread will never notice this. The solution is to catch the
+     * exception and store it in this field, so the JUnit thread can check
+     * if there were any exceptions when executing the job.
+     */
+    private Exception exception;
+    
+    /** Indicates if the thread must be blocked (ie this.wait() must be called) */
+    private boolean threadBlocked;
+    
+    /**
+     * List of synchronizations that will be called on specific point in the
+     * execution of this thread.
+     */
+    private List<CommandExecutionSynchronization> synchronizations;
+    
+    /* SYNC PRIMITIVES */
+    
+    private CyclicBarrier afterExecutionBarrier;
+    
+    private CyclicBarrier beforeExecutionBarrier;
+    
+    /**
+     * Constructor to be used when the thread must execute a job
+     */
+    public SynchronizableCommandExecutor(EnvironmentFactory environmentFactory, Job job) {
+      this.environmentFactory = environmentFactory;
+      this.jobId = job.getDbid();
+      this.threadBlocked = false;
+      
+      this.synchronizations = new ArrayList<CommandExecutionSynchronization>();
+      synchronizations.add(new DefaultSynchronization());
+    }
+    
+    /**
+     * Constructor to be used when the thread must execute a command
+     */
+    public SynchronizableCommandExecutor(EnvironmentFactory environmentFactory, Command command) {
+      this.environmentFactory = environmentFactory;
+      this.command = command;
+      this.threadBlocked = false;
+      
+      this.synchronizations = new ArrayList<CommandExecutionSynchronization>();
+      synchronizations.add(new DefaultSynchronization());
+    }
+    
+    public void run() {
+      
+      Environment environment = environmentFactory.openEnvironment();
+      StandardTransaction standardTransaction = environment.get(StandardTransaction.class);
+      standardTransaction.begin();
+
+      try {
+        
+        handleBeforeExecutionSynchronizations();
+        
+        if (jobId != null) {
+          ExecuteJobCmd executeJobCmd = new ExecuteJobCmd(jobId);
+          executeJobCmd.execute(environment);
+        }
+        
+        if (command !=  null) {
+          command.execute(environment);
+        }
+        
+        handleAfterExecutionSynchronizations();
+        
+      } catch (Exception e) {
+        standardTransaction.setRollbackOnly();
+        this.exception = e;
+        
+      } finally {
+        
+        try {
+          standardTransaction.complete();
+        } catch (Exception e) {
+          this.exception = e;
+        }
+        
+      }
+      environment.close();
+    }
+    
+    /**
+     * Executes all synchronizations that must be executed before the job is executed
+     */
+    private void handleBeforeExecutionSynchronizations() {
+      for (CommandExecutionSynchronization synchronization : synchronizations) {
+        synchronization.beforeExecution();
+      }
+    }
+    
+    /**
+     * Executes all synchronizations that must be executed when the job is executed
+     */
+    private void handleAfterExecutionSynchronizations() {
+      for (CommandExecutionSynchronization synchronization : synchronizations) {
+        synchronization.afterExecution();
+      }
+    }
+    
+    /**
+     * Unit tests that use this class can use this method to synchronize
+     * when the job just has been executed.
+     * 
+     * @param blockJobExecutor If true, the jobExecutor will be halted
+     * when leaving the synchronisation point
+     */
+    public void waitUntilExecutionFinished(boolean blockJobExecutor) {
+      if (afterExecutionBarrier != null) {
+        try {
+          threadBlocked = blockJobExecutor;
+          afterExecutionBarrier.await();
+        } catch (InterruptedException e) {
+          e.printStackTrace();
+        } catch (BrokenBarrierException e) {
+          e.printStackTrace();
+        }
+      }
+    }
+    
+    public SynchronizableCommandExecutor synchroniseAfterExecution() {
+      if (isAlive()) {
+        throw new RuntimeException("Cannot set synchronization point once the thread has been started");
+      }
+      
+      if (afterExecutionBarrier == null ) {
+        afterExecutionBarrier = new CyclicBarrier(2);
+      } else {
+        afterExecutionBarrier = new CyclicBarrier(afterExecutionBarrier.getParties() + 1);
+      }
+      
+      return this;
+    }
+    
+    public SynchronizableCommandExecutor synchroniseAfterExecution(SynchronizableCommandExecutor otherExecutor) {
+      if (this.isAlive() || otherExecutor.isAlive()) {
+        throw new RuntimeException("Cannot set synchronization point once the thread has been started");
+      }
+      
+      int threadsInvolved = 0;
+      if (afterExecutionBarrier != null) {
+        threadsInvolved += afterExecutionBarrier.getParties();
+      } else {
+        threadsInvolved++;
+      }
+      
+      if (otherExecutor.afterExecutionBarrier != null) {
+        threadsInvolved += otherExecutor.afterExecutionBarrier.getParties();
+      } else {
+        threadsInvolved++;
+      }
+      
+      this.afterExecutionBarrier = new CyclicBarrier(threadsInvolved);
+      otherExecutor.afterExecutionBarrier = this.afterExecutionBarrier;
+      
+      return this; 
+    }
+    
+    public SynchronizableCommandExecutor synchroniseBeforeExecution() {
+      if (isAlive()) {
+        throw new RuntimeException("Cannot set synchronization point once the JobExecutorEmulator has been started");
+      }
+      
+      if (beforeExecutionBarrier == null ) {
+        beforeExecutionBarrier = new CyclicBarrier(2);
+      } else {
+        beforeExecutionBarrier = new CyclicBarrier(beforeExecutionBarrier.getParties() + 1);
+      }
+      
+      return this;
+    }
+    
+    /**
+     * Helper method: check if the flag 'threadBlocked' has been raised.
+     * If so, this thread will block until it is notified again.
+     */
+    private void blockIfNeeded() {
+      if (threadBlocked) {
+        synchronized (this) {
+          try {
+            threadBlocked = false;
+            wait();
+          } catch (InterruptedException e) {
+            e.printStackTrace();
+          }
+        }
+      }
+    }
+    
+    /**
+     * Unit tests can use this method to proceed a halted JobExecutorEmulator.
+     * (ie this means that the wait() was called on this thread in the past).
+     */
+    public void goOn() {
+      synchronized (this) {
+          notify();
+      };
+    }
+    
+    /**
+     * Adds a custom synchronization to the JobExecutorEmulator.
+     */
+    public void addSynchronization(CommandExecutionSynchronization synchronization) {
+      synchronizations.add(synchronization);
+    }
+    
+    /* GETTERS AND SETTERS */
+    
+    public Exception getException() {
+      return exception;
+    }
+    
+    public boolean isBlockThread() {
+      return threadBlocked;
+    }
+
+    public void setBlockThread(boolean blockThread) {
+      this.threadBlocked = blockThread;
+    }
+    
+    public void setAfterExecutionBarrier(CyclicBarrier afterExecutionBarrier) {
+      this.afterExecutionBarrier = afterExecutionBarrier;
+    }
+
+    public void setBeforeExecutionBarrier(CyclicBarrier beforeExecutionBarrier) {
+      this.beforeExecutionBarrier = beforeExecutionBarrier;
+    }
+
+    /**
+     * Default synchronization, executed by all threads.
+     * The default logic will synchronize at every sync point (ie barrier) 
+     * which is not null and will check if any external caller has raised
+     * the 'threadBlocked' flag.
+     */
+    private class DefaultSynchronization extends CommandExecutionSynchronization {
+      
+      public void afterExecution() {
+      
+      if (afterExecutionBarrier != null) {
+        try {
+          afterExecutionBarrier.await();
+          blockIfNeeded();
+        } catch (InterruptedException e) {
+          e.printStackTrace();
+        } catch (BrokenBarrierException e) {
+          e.printStackTrace();
+        }
+      }
+    }
+
+    public void beforeExecution() {
+      
+      if (beforeExecutionBarrier != null) {
+        try {
+          beforeExecutionBarrier.await();
+          blockIfNeeded();
+        } catch (InterruptedException e) {
+          e.printStackTrace();
+        } catch (BrokenBarrierException e) {
+          e.printStackTrace();
+        }
+      }
+    }
+
+  }
+
+}

Added: jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/AsyncForkTest.java
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/AsyncForkTest.java	                        (rev 0)
+++ jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/AsyncForkTest.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -0,0 +1,58 @@
+package org.jbpm.test.concurrent;
+
+import java.util.List;
+
+import org.hibernate.StaleStateException;
+import org.jbpm.api.ProcessInstance;
+import org.jbpm.api.job.Job;
+
+
+public class AsyncForkTest extends ConcurrentJbpmTestCase {
+  
+  public void testAsyncForkNoOptimisticLockingFailure() {
+    deployJpdlXmlString(
+            "<process name='asyncFork'>" +
+            "  <start>" +
+            "    <transition to='theFork' />" +
+            "  </start>" +
+            "  <fork name='theFork'>" +
+            "    <on event='end' continue='async' />" +
+            "    <transition to='pathA' />" +
+            "    <transition to='pathB' />" +
+            "  </fork>" +
+            "  <custom name='pathA' class='org.jbpm.test.concurrent.PassThroughActivity' >" +
+            "    <transition to='theJoin' />" +
+            "  </custom>" + 
+            "  <custom name='pathB' class='org.jbpm.test.concurrent.PassThroughActivity' >" +
+            "    <transition to='theJoin' />" +
+            "  </custom>" + 
+            "  <join name='theJoin'>" +
+            "    <transition to='test' />" +
+            "  </join>" + 
+            "  <state name='test' >" +
+            "    <transition to='end' /> " +
+            "  </state>" +
+            "  <end name='end' />" +
+            "</process>"
+          );
+    
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey("asyncFork");
+    final List<Job> jobs = managementService.createJobQuery().processInstanceId(processInstance.getId()).list();
+    assertEquals(2, jobs.size()); 
+    
+    SynchronizableCommandExecutor executor1 = new SynchronizableCommandExecutor(environmentFactory, jobs.get(0));
+    SynchronizableCommandExecutor executor2 = new SynchronizableCommandExecutor(environmentFactory, jobs.get(1));
+    
+    executor1.synchroniseAfterExecution(executor2);
+    executor1.synchroniseAfterExecution();
+
+    executor1.start();
+    executor2.start();
+    
+    if (executor1.getException() instanceof StaleStateException
+            || executor2.getException() instanceof StaleStateException) {
+      fail("A StaleStaeException was thrown, altough this shouldn't happen");
+    }
+  }
+
+}


Property changes on: jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/AsyncForkTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/OptimisticLockTestGround.java
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/OptimisticLockTestGround.java	2009-06-19 15:53:46 UTC (rev 5068)
+++ jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/OptimisticLockTestGround.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -41,8 +41,7 @@
  * Class to test different approaches to the concurrency problem.
  * 
  * Doesnt work anymore, but dont delete yet, I need some stuff in here for later!
- * 
- * @author Joram Barrez
+ *  * @author Joram Barrez
  */
 public class OptimisticLockTestGround extends JbpmTestCase {
 

Modified: jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/TimerVsSignalConcurrencyTest.java
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/TimerVsSignalConcurrencyTest.java	2009-06-19 15:53:46 UTC (rev 5068)
+++ jbpm4/trunk/modules/test-concurrent/src/test/java/org/jbpm/test/concurrent/TimerVsSignalConcurrencyTest.java	2009-06-19 17:26:38 UTC (rev 5069)
@@ -25,13 +25,12 @@
 package org.jbpm.test.concurrent;
 
 import java.util.List;
-import java.util.concurrent.CyclicBarrier;
 
+import org.hibernate.StaleStateException;
 import org.jbpm.api.Execution;
 import org.jbpm.api.ProcessInstance;
-import org.jbpm.api.env.EnvironmentFactory;
 import org.jbpm.api.job.Job;
-import org.jbpm.test.JbpmTestCase;
+import org.jbpm.pvm.internal.cmd.SignalCmd;
 
 
 /**
@@ -60,56 +59,35 @@
     final List<Job> jobs = managementService.createJobQuery().processInstanceId(processInstance.getId()).list();
     assertEquals(1, jobs.size());
 
-    JobExecutorEmulator jobExecutorEmulator = new JobExecutorEmulator(environmentFactory, jobs.get(0));
-    jobExecutorEmulator.synchroniseAfterJobExecution(Thread.currentThread().getName());
+    //SynchronizableCommandExecutor jobExecutorEmulator = new SynchronizableCommandExecutor(environmentFactory, jobs.get(0));
+    SynchronizableCommandExecutor jobExecutorEmulator = new SynchronizableCommandExecutor(environmentFactory, jobs.get(0));
+    jobExecutorEmulator.synchroniseAfterExecution();
     jobExecutorEmulator.start();
 
-    jobExecutorEmulator.waitUntilJobExecuted(true); // transaction will be stalled
+    jobExecutorEmulator.waitUntilExecutionFinished(true); // transaction will be stalled until signal is done
     
     // Cause conflicting transaction
     final Execution executionAtState = processInstance.findActiveExecutionIn("wait");
     assertNotNull(executionAtState);
-    OffloadThread signalThread = new OffloadThread(new ThreadCallback() {
-      public void executeInThread() {
-        executionService.signalExecutionById(executionAtState.getId(), "go on");
-      }
-    });
+    
+    SignalCmd signalCmd = new SignalCmd(executionAtState.getId(), "go on", null);
+    SynchronizableCommandExecutor signalThread = new SynchronizableCommandExecutor(environmentFactory, signalCmd);
     signalThread.start();
     
-    /*
-    // Checking current stacktrace of thread
-    int i = 1;
-    while (i == 1) {
-      System.out.println("-----------> STATE = " + temp.getState());
-      StackTraceElement[] stack = temp.getStackTrace();
-      for (StackTraceElement e : stack) {
-        System.out.println("-----------> " + e);
-      }
-      
-      synchronized (this) {
-        try {
-          wait(1000L);
-        } catch (InterruptedException e) {
-          // TODO Auto-generated catch block
-          e.printStackTrace();
-        }
-      }
-    }
-    */
-    
     // Best effort: wait 1 sec and see if the staleObjectException has been caused
     synchronized (this) {
       wait(1000L);
     }
     
     jobExecutorEmulator.goOn();
+    
     jobExecutorEmulator.join();
+    signalThread.join();
 
     
-    if (jobExecutorEmulator.getException() != null) {
-      fail("Error while executing job: " + jobExecutorEmulator.getException().getMessage());
-    } if (signalThread.getException() != null) {
-      fail("Error while executing signal " + signalThread.getException().getMessage());
+    if (!(jobExecutorEmulator.getException() instanceof StaleStateException
+            || signalThread.getException() instanceof StaleStateException)) {
+      fail("None of the threads threw a StaleStateException");
     }
     
   }

Modified: jbpm4/trunk/modules/test-concurrent/src/test/resources/jbpm.cfg.xml
===================================================================
--- jbpm4/trunk/modules/test-concurrent/src/test/resources/jbpm.cfg.xml	2009-06-19 15:53:46 UTC (rev 5068)
+++ jbpm4/trunk/modules/test-concurrent/src/test/resources/jbpm.cfg.xml	2009-06-19 17:26:38 UTC (rev 5069)
@@ -4,8 +4,24 @@
 
   <import resource="jbpm.default.cfg.xml" />
   <import resource="jbpm.jpdl.cfg.xml" />
+  
+  <!-- we need to remove the retry interceptor, so we cant use the default 
   <import resource="jbpm.tx.hibernate.cfg.xml" />
+  -->
+  
+  <process-engine-context>
+    <command-service>
+      <environment-interceptor />
+      <standard-transaction-interceptor />
+    </command-service>
+  </process-engine-context>
 
+  <transaction-context>
+    <transaction />
+    <hibernate-session />
+  </transaction-context>
+  
+
 	<!--
 		In the concurrency tests, we'll emulate the job executor to have full
 		control on when syncing occurs 




More information about the jbpm-commits mailing list