diff --git a/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java b/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java index f9a7b01b93..db325c3ed3 100644 --- a/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java +++ b/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java @@ -64,6 +64,7 @@ public class ActionTrackingServiceImpl implements ActionTrackingService * quickest and easiest way. */ private short nextExecutionId = 1; + private short wrapExecutionIdAfter = Short.MAX_VALUE/2; /** How we separate bits of the cache key */ private static final char cacheKeyPartSeparator = '='; @@ -106,10 +107,18 @@ public class ActionTrackingServiceImpl implements ActionTrackingService public void recordActionPending(Action action) { - ((ActionImpl)action).setExecutionStatus(ActionStatus.Pending); + recordActionPending((ActionImpl)action); + } + public void recordActionPending(ActionImpl action) + { + action.setExecutionStatus(ActionStatus.Pending); } public void recordActionComplete(Action action) + { + recordActionComplete((ActionImpl)action); + } + private void recordActionComplete(ActionImpl action) { if (logger.isDebugEnabled() == true) { @@ -117,9 +126,9 @@ public class ActionTrackingServiceImpl implements ActionTrackingService } // Mark it as having worked - ((ActionImpl)action).setExecutionEndDate(new Date()); - ((ActionImpl)action).setExecutionStatus(ActionStatus.Completed); - ((ActionImpl)action).setExecutionFailureMessage(null); + action.setExecutionEndDate(new Date()); + action.setExecutionStatus(ActionStatus.Completed); + action.setExecutionFailureMessage(null); if(action.getNodeRef() != null) { runtimeActionService.saveActionImpl(action.getNodeRef(), action); @@ -131,6 +140,10 @@ public class ActionTrackingServiceImpl implements ActionTrackingService } public void recordActionExecuting(Action action) + { + recordActionExecuting((ActionImpl)action); + } + private void recordActionExecuting(ActionImpl action) { if (logger.isDebugEnabled() == true) { @@ -138,14 +151,34 @@ public class ActionTrackingServiceImpl implements ActionTrackingService } // Mark the action as starting - ((ActionImpl)action).setExecutionStartDate(new Date()); - ((ActionImpl)action).setExecutionStatus(ActionStatus.Running); + action.setExecutionStartDate(new Date()); + action.setExecutionStatus(ActionStatus.Running); - // TODO assign it a (unique) execution ID + // Assign it a (unique) execution ID // (Keep checking to see if the key is used as we // increase nextExecutionId until it isn't) - ((ActionImpl)action).setExecutionInstance(nextExecutionId++); // TODO - String key = generateCacheKey(action); + String key = null; + boolean assigned = false; + while(!assigned) { + // Try + action.setExecutionInstance(nextExecutionId++); + key = generateCacheKey(action); + + // Is it ok? + if(executingActionsCache.get(key) == null) { + assigned = true; + } + + // Do we need to wrap? + // (Wrap before absolutely needed, makes things simpler) + if(nextExecutionId > wrapExecutionIdAfter) { + synchronized (this) { + while(nextExecutionId > wrapExecutionIdAfter) { + nextExecutionId -= wrapExecutionIdAfter; + } + } + } + } // Put it into the cache ExecutionDetails details = buildExecutionDetails(action); diff --git a/source/java/org/alfresco/repo/action/ActionTrackingServiceImplTest.java b/source/java/org/alfresco/repo/action/ActionTrackingServiceImplTest.java index 49b6f0d724..2d59f42415 100644 --- a/source/java/org/alfresco/repo/action/ActionTrackingServiceImplTest.java +++ b/source/java/org/alfresco/repo/action/ActionTrackingServiceImplTest.java @@ -175,9 +175,22 @@ public class ActionTrackingServiceImplTest extends TestCase } /** Running an action gives it an execution ID */ - public void testExecutionInstanceAssignment() + public void testExecutionInstanceAssignment() throws Exception { - // TODO + ActionImpl action = (ActionImpl)createWorkingSleepAction("1234"); + assertEquals(-1, action.getExecutionInstance()); + + // Have it run, will get the ID of 1 + actionTrackingService.recordActionExecuting(action); + assertEquals(1, action.getExecutionInstance()); + + // And again, gets 2 + actionTrackingService.recordActionExecuting(action); + assertEquals(2, action.getExecutionInstance()); + + // And again, gets 3 + actionTrackingService.recordActionExecuting(action); + assertEquals(3, action.getExecutionInstance()); } /** @@ -489,8 +502,71 @@ public class ActionTrackingServiceImplTest extends TestCase assertEquals( 1, actionTrackingService.getExecutingActions(moveAction).size() ); + - // TODO Multiple actions of the same instance + // Check for multiple instances of the same action + runtimeActionService.saveActionImpl(nodeRef, sleepAction1); + ((ActionTrackingServiceImpl)actionTrackingService).resetNextExecutionId(); + + ActionImpl sa11 = (ActionImpl)runtimeActionService.createAction(nodeRef); + ActionImpl sa12 = (ActionImpl)runtimeActionService.createAction(nodeRef); + ActionImpl sa13 = (ActionImpl)runtimeActionService.createAction(nodeRef); + sa11 = new ActionImpl(sa11, SleepActionExecuter.NAME); + sa12 = new ActionImpl(sa12, SleepActionExecuter.NAME); + sa13 = new ActionImpl(sa13, SleepActionExecuter.NAME); + + actionTrackingService.recordActionExecuting(sa11); + actionTrackingService.recordActionExecuting(sa12); + actionTrackingService.recordActionExecuting(sa13); + assertEquals(1, sa11.getExecutionInstance()); + assertEquals(2, sa12.getExecutionInstance()); + assertEquals(3, sa13.getExecutionInstance()); + + assertEquals( + 4, actionTrackingService.getAllExecutingActions().size() + ); + assertEquals( + 0, actionTrackingService.getExecutingActions("test").size() + ); + assertEquals( + 3, actionTrackingService.getExecutingActions(SleepActionExecuter.NAME).size() + ); + assertEquals( + 1, actionTrackingService.getExecutingActions(moveAction).size() + ); + assertEquals( + 3, actionTrackingService.getExecutingActions(sa11).size() + ); + assertEquals( + 3, actionTrackingService.getExecutingActions(sa12).size() + ); + assertEquals( + 3, actionTrackingService.getExecutingActions(sa13).size() + ); + + + actionTrackingService.recordActionComplete(sa13); + actionTrackingService.recordActionComplete(moveAction); + + + assertEquals( + 2, actionTrackingService.getAllExecutingActions().size() + ); + assertEquals( + 0, actionTrackingService.getExecutingActions("test").size() + ); + assertEquals( + 2, actionTrackingService.getExecutingActions(SleepActionExecuter.NAME).size() + ); + assertEquals( + 2, actionTrackingService.getExecutingActions(sa11).size() + ); + assertEquals( + 2, actionTrackingService.getExecutingActions(sa12).size() + ); + assertEquals( + 2, actionTrackingService.getExecutingActions(sa13).size() // Others still going + ); } /** Cancel related */