public virtual void testConcurrentExclusiveCorrelation()
        {
            InvocationLogListener.reset();

            // given a process instance
            runtimeService.StartProcessInstanceByKey("testProcess");

            // and two threads correlating in parallel
            ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", true));

            thread1.ReportInterrupts();
            ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", true));

            thread2.ReportInterrupts();

            // both threads open a transaction and wait before correlating the message
            thread1.WaitForSync();
            thread2.WaitForSync();

            // thread one correlates and acquires the exclusive lock
            thread1.MakeContinue();
            thread1.WaitForSync();

            // the service task was executed once
            Assert.AreEqual(1, InvocationLogListener.Invocations);

            // thread two attempts to acquire the exclusive lock but can't since thread 1 hasn't released it yet
            thread2.MakeContinue();
            Thread.Sleep(2000);

            // let the first thread ends its transaction
            thread1.MakeContinue();
            Assert.IsNull(thread1.Exception);

            // thread 2 can't continue because the event subscription it tried to lock was deleted
            thread2.WaitForSync();
            Assert.True(thread2.Exception != null);
            Assert.True(thread2.Exception is ProcessEngineException);
            AssertTextPresent("does not have a subscription to a message event with name 'Message'", thread2.Exception.Message);

            // the first thread ended successfully without an exception
            thread1.Join();
            Assert.IsNull(thread1.Exception);

            // the follow-up task was reached
            ITask afterMessageTask = taskService.CreateTaskQuery().First();

            Assert.AreEqual(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask");

            // the service task was not executed a second time
            Assert.AreEqual(1, InvocationLogListener.Invocations);
        }
        public virtual void FAILING_testConcurrentMixedCorrelationCase2()
        {
            InvocationLogListener.reset();

            // given a process instance
            runtimeService.StartProcessInstanceByKey("testProcess");

            // and two threads correlating in parallel (one exclusive, one non-exclusive)
            ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", false));

            thread1.ReportInterrupts();
            ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", true));

            thread2.ReportInterrupts();

            // both threads open a transaction and wait before correlating the message
            thread1.WaitForSync();
            thread2.WaitForSync();

            // thread one correlates and acquires no lock
            thread1.MakeContinue();
            thread1.WaitForSync();

            // thread two acquires a lock and succeeds because thread one hasn't acquired one
            thread2.MakeContinue();
            thread2.WaitForSync();

            // the service task was executed twice
            Assert.AreEqual(2, InvocationLogListener.Invocations);

            // thread one ends its transaction and blocks on flush when it attempts to Delete the event subscription
            thread1.MakeContinue();
            Thread.Sleep(5000);
            Assert.IsNull(thread1.Exception);

            Assert.AreEqual(0, taskService.CreateTaskQuery().Count());

            // thread 2 flushes successfully and releases the lock
            thread2.WaitUntilDone();
            Assert.IsNull(thread2.Exception);

            ITask afterMessageTask = taskService.CreateTaskQuery().First();

            Assert.NotNull(afterMessageTask);
            Assert.AreEqual(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask");

            // thread 1 flush fails with optimistic locking
            thread1.Join();
            Assert.True(thread1.Exception != null);
            Assert.True(thread1.Exception is OptimisticLockingException);
        }
        public virtual void testTimeoutOnUpdate()
        {
            createJobEntity();

            thread1 = ExecuteControllableCommand(new UpdateJobCommand("p1"));
            // wait for thread 1 to perform UPDATE
            thread1.WaitForSync();

            thread2 = ExecuteControllableCommand(new UpdateJobCommand("p2"));
            // wait for thread 2 to perform UPDATE
            thread2.WaitForSync();

            // perform FLUSH for thread 1 (but no commit of transaction)
            thread1.MakeContinue();
            // wait for thread 1 to perform FLUSH
            thread1.WaitForSync();

            // perform FLUSH for thread 2
            thread2.MakeContinue();
            // wait for thread 2 to cancel FLUSH because of timeout
            thread2.ReportInterrupts();
            thread2.WaitForSync(TEST_TIMEOUT_IN_MILLIS);

            Assert.NotNull(thread2.Exception, "expected timeout exception");
        }
        protected internal virtual void deployOnTwoConcurrentThreads(IDeploymentBuilder deploymentOne, IDeploymentBuilder deploymentTwo)
        {
            Assert.That(deploymentOne, Is.Not.EqualTo(deploymentTwo));

            // STEP 1: bring two threads to a point where they have
            // 1) started a new transaction
            // 2) are ready to deploy
            ThreadControl thread1 = ExecuteControllableCommand(new ControllableDeployCommand(deploymentOne));

            thread1.WaitForSync();

            ThreadControl thread2 = ExecuteControllableCommand(new ControllableDeployCommand(deploymentTwo));

            thread2.WaitForSync();

            // STEP 2: make Thread 1 proceed and wait until it has deployed but not yet committed
            // -> will still hold the exclusive lock
            thread1.MakeContinue();
            thread1.WaitForSync();

            // STEP 3: make Thread 2 continue
            // -> it will attempt to acquire the exclusive lock and block on the lock
            thread2.MakeContinue();

            // wait for 2 seconds (Thread 2 is blocked on the lock)
            Thread.Sleep(2000);

            // STEP 4: allow Thread 1 to terminate
            // -> Thread 1 will commit and release the lock
            thread1.WaitUntilDone();

            // STEP 5: wait for Thread 2 to terminate
            thread2.WaitForSync();
            thread2.WaitUntilDone();
        }
        public virtual void testConcurrentFetchAndDelete()
        {
            Deployment(ESS.FW.Bpm.Model.Bpmn.Bpmn.CreateExecutableProcess("test").StartEvent().UserTask().EndEvent().Done());

            //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
            //ORIGINAL LINE: final java.util.List<String> listVar = java.util.("a", "b");
            IList <string> listVar = new List <string> {
                "a", "b"
            };
            string pid = runtimeService.StartProcessInstanceByKey("test", ESS.FW.Bpm.Engine.Variable.Variables.CreateVariables().PutValue("listVar", listVar)).Id;

            // start a controlled Fetch variable command
            asyncThread = ExecuteControllableCommand <object>(new FetchVariableCmd(pid, "listVar"));

            // wait for async thread to load the variable (but not the byte array)
            asyncThread.WaitForSync();

            // now Delete the process instance
            runtimeService.DeleteProcessInstance(pid, null);

            // make the second thread continue
            // => this will a flush the FetchVariableCmd Context.
            // if the flush performs an update to the variable, it will Assert.Fail with an OLE
            asyncThread.MakeContinue();
            asyncThread.WaitUntilDone();
        }
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: public void testRunTwoHistoryCleanups() throws InterruptedException
        public virtual void testRunTwoHistoryCleanups()
        {
            ThreadControl thread1 = ExecuteControllableCommand(new ControllableHistoryCleanupCommand());

            thread1.WaitForSync();

            ThreadControl thread2 = ExecuteControllableCommand(new ControllableHistoryCleanupCommand());

            thread2.WaitForSync();

            thread1.MakeContinue();
            thread1.WaitForSync();

            thread2.MakeContinue();

            Thread.Sleep(2000);

            thread1.WaitUntilDone();

            thread2.WaitForSync();
            thread2.WaitUntilDone();

            //only one history cleanup job exists -> no exception
            IJob historyCleanupJob = ProcessEngine.HistoryService.FindHistoryCleanupJob();

            Assert.NotNull(historyCleanupJob);

            Assert.IsNull(thread1.Exception);
            Assert.IsNull(thread2.Exception);
        }
        public virtual void testEventSubprocess()
        {
            InvocationLogListener.reset();

            // given a process instance
            runtimeService.StartProcessInstanceByKey("testProcess");

            // and two threads correlating in parallel
            ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("incoming", false));

            thread1.ReportInterrupts();
            ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("incoming", false));

            thread2.ReportInterrupts();

            // both threads open a transaction and wait before correlating the message
            thread1.WaitForSync();
            thread2.WaitForSync();

            // both threads correlate
            thread1.MakeContinue();
            thread2.MakeContinue();

            thread1.WaitForSync();
            thread2.WaitForSync();

            // the first thread ends its transaction
            thread1.WaitUntilDone();
            Assert.IsNull(thread1.Exception);

            // the second thread ends its transaction and fails with optimistic locking exception
            thread2.WaitUntilDone();
            Assert.True(thread2.Exception != null);
            Assert.True(thread2.Exception is OptimisticLockingException);
        }
        public virtual void testConcurrentMixedCorrelation()
        {
            InvocationLogListener.reset();

            // given a process instance
            runtimeService.StartProcessInstanceByKey("testProcess");

            // and two threads correlating in parallel (one exclusive, one non-exclusive)
            ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", true));

            thread1.ReportInterrupts();
            ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", false));

            thread2.ReportInterrupts();

            // both threads open a transaction and wait before correlating the message
            thread1.WaitForSync();
            thread2.WaitForSync();

            // thread one correlates and acquires the exclusive lock
            thread1.MakeContinue();
            thread1.WaitForSync();

            // thread two correlates since it does not need a pessimistic lock
            thread2.MakeContinue();
            thread2.WaitForSync();

            // the service task was executed twice
            Assert.AreEqual(2, InvocationLogListener.Invocations);

            // the first thread ends its transaction and releases the lock; the event subscription is now gone
            thread1.WaitUntilDone();
            Assert.IsNull(thread1.Exception);

            ITask afterMessageTask = taskService.CreateTaskQuery().First();

            Assert.AreEqual(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask");

            // thread two attempts to end its transaction and fails with optimistic locking
            thread2.MakeContinue();
            thread2.WaitForSync();

            Assert.True(thread2.Exception != null);
            Assert.True(thread2.Exception is OptimisticLockingException);
        }
        public virtual void testConcurrentExclusiveCorrelationToDifferentExecutions()
        {
            InvocationLogListener.reset();

            // given a process instance
            IProcessInstance instance1 = runtimeService.StartProcessInstanceByKey("testProcess");
            IProcessInstance instance2 = runtimeService.StartProcessInstanceByKey("testProcess");

            // and two threads correlating in parallel to each of the two instances
            ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", instance1.Id, true));

            thread1.ReportInterrupts();
            ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", instance2.Id, true));

            thread2.ReportInterrupts();

            // both threads open a transaction and wait before correlating the message
            thread1.WaitForSync();
            thread2.WaitForSync();

            // thread one correlates and acquires the exclusive lock on the event subscription of instance1
            thread1.MakeContinue();
            thread1.WaitForSync();

            // the service task was executed once
            Assert.AreEqual(1, InvocationLogListener.Invocations);

            // thread two correlates and acquires the exclusive lock on the event subscription of instance2
            // depending on the database and locking used, this may block thread2
            thread2.MakeContinue();

            // thread 1 completes successfully
            thread1.WaitUntilDone();
            Assert.IsNull(thread1.Exception);

            // thread2 should be able to continue at least after thread1 has finished and released its lock
            thread2.WaitForSync();

            // the service task was executed the second time
            Assert.AreEqual(2, InvocationLogListener.Invocations);

            // thread 2 completes successfully
            thread2.WaitUntilDone();
            Assert.IsNull(thread2.Exception);

            // the follow-up task was reached in both instances
            Assert.AreEqual(2, taskService.CreateTaskQuery(c => c.TaskDefinitionKey == "afterMessageUserTask").Count());
        }
        public virtual void testConcurrentCorrelationFailsWithOptimisticLockingException()
        {
            InvocationLogListener.reset();

            // given a process instance
            runtimeService.StartProcessInstanceByKey("testProcess");

            // and two threads correlating in parallel
            ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", false));

            thread1.ReportInterrupts();
            ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", false));

            thread2.ReportInterrupts();

            // both threads open a transaction and wait before correlating the message
            thread1.WaitForSync();
            thread2.WaitForSync();

            // both threads correlate
            thread1.MakeContinue();
            thread2.MakeContinue();

            thread1.WaitForSync();
            thread2.WaitForSync();

            // the service task was executed twice
            Assert.AreEqual(2, InvocationLogListener.Invocations);

            // the first thread ends its transcation
            thread1.WaitUntilDone();
            Assert.IsNull(thread1.Exception);

            ITask afterMessageTask = taskService.CreateTaskQuery().First();

            Assert.AreEqual(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask");

            // the second thread ends its transaction and fails with optimistic locking exception
            thread2.WaitUntilDone();
            Assert.True(thread2.Exception != null);
            Assert.True(thread2.Exception is OptimisticLockingException);
        }
Beispiel #11
0
        /// <summary>
        /// In this test, we run two transactions concurrently.
        /// The transactions have the following behavior:
        ///
        /// (1) INSERT row into a table
        /// (2) SELECT ALL rows from that table
        ///
        /// We execute it with two threads in the following interleaving:
        ///
        ///      Thread 1             Thread 2
        ///      ========             ========
        /// ------INSERT---------------------------   |
        /// ---------------------------INSERT------   |
        /// ---------------------------SELECT------   v time
        /// ------SELECT---------------------------
        ///
        /// Deadlocks may occur if readers are not properly isolated from writers.
        ///
        /// </summary>
        public virtual void testTransactionIsolation()
        {
            thread1 = ExecuteControllableCommand(new TestCommand("p1"));

            // wait for Thread 1 to perform INSERT
            thread1.WaitForSync();

            thread2 = ExecuteControllableCommand(new TestCommand("p2"));

            // wait for Thread 2 to perform INSERT
            thread2.WaitForSync();

            // wait for Thread 2 to perform SELECT
            thread2.MakeContinue();

            // wait for Thread 1  to perform same SELECT => deadlock
            thread1.MakeContinue();

            thread2.WaitForSync();
            thread1.WaitForSync();
        }