Formatted Alfresco-style

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22322 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2010-09-08 10:39:51 +00:00
parent 808ff739a3
commit 7f4402ac58

View File

@@ -26,7 +26,6 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.alfresco.repo.cache.EhCacheAdapter;
import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
@@ -57,18 +56,15 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
private static Log logger = LogFactory.getLog(ActionTrackingServiceImpl.class); private static Log logger = LogFactory.getLog(ActionTrackingServiceImpl.class);
private SimpleCache<String, ExecutionDetails> executingActionsCache; private SimpleCache<String, ExecutionDetails> executingActionsCache;
private TransactionService transactionService; private TransactionService transactionService;
private RuntimeActionService runtimeActionService; private RuntimeActionService runtimeActionService;
/** /**
* Doesn't need to be cluster unique, is just used * Doesn't need to be cluster unique, is just used to try to reduce the
* to try to reduce the chance of clashes in the * chance of clashes in the quickest and easiest way.
* quickest and easiest way.
*/ */
private short nextExecutionId = 1; private short nextExecutionId = 1;
private short wrapExecutionIdAfter = Short.MAX_VALUE / 2; private short wrapExecutionIdAfter = Short.MAX_VALUE / 2;
/** How we separate bits of the cache key */ /** How we separate bits of the cache key */
private static final char cacheKeyPartSeparator = '='; private static final char cacheKeyPartSeparator = '=';
@@ -93,25 +89,25 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
} }
/** /**
* Sets the cache used to store details of * Sets the cache used to store details of currently executing actions,
* currently executing actions, cluster wide. * cluster wide.
*/ */
public void setExecutingActionsCache(SimpleCache<String, ExecutionDetails> executingActionsCache) public void setExecutingActionsCache(SimpleCache<String, ExecutionDetails> executingActionsCache)
{ {
this.executingActionsCache = executingActionsCache; this.executingActionsCache = executingActionsCache;
} }
/** Used by unit tests only */ /** Used by unit tests only */
protected void resetNextExecutionId() { protected void resetNextExecutionId()
{
this.nextExecutionId = 1; this.nextExecutionId = 1;
} }
public void recordActionPending(Action action) public void recordActionPending(Action action)
{ {
recordActionPending((ActionImpl) action); recordActionPending((ActionImpl) action);
} }
public void recordActionPending(ActionImpl action) public void recordActionPending(ActionImpl action)
{ {
// Set the status // Set the status
@@ -129,6 +125,7 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
{ {
recordActionComplete((ActionImpl) action); recordActionComplete((ActionImpl) action);
} }
private void recordActionComplete(ActionImpl action) private void recordActionComplete(ActionImpl action)
{ {
if (logger.isDebugEnabled() == true) if (logger.isDebugEnabled() == true)
@@ -154,11 +151,13 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
{ {
recordActionExecuting((ActionImpl) action); recordActionExecuting((ActionImpl) action);
} }
private void recordActionExecuting(ActionImpl action) private void recordActionExecuting(ActionImpl action)
{ {
if (logger.isDebugEnabled() == true) if (logger.isDebugEnabled() == true)
{ {
logger.debug("Action " + action + " with provisional key " + generateCacheKey(action) + " has begun exection"); logger.debug("Action " + action + " with provisional key " + generateCacheKey(action)
+ " has begun exection");
} }
// Grab what status it was before // Grab what status it was before
@@ -180,13 +179,11 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
ExecutionDetails details = executingActionsCache.get(key); ExecutionDetails details = executingActionsCache.get(key);
// Check it's really there, warn + fix if not // Check it's really there, warn + fix if not
if(details == null) { if (details == null)
logger.warn( {
"Went to mark the start of execution of " + logger.warn("Went to mark the start of execution of " + action + " with key " + key
action + " with key " + key + + " but it wasn't in the running actions cache! "
" but it wasn't in the running actions cache! " + + "Your running actions cache is probably too small");
"Your running actions cache is probably too small"
);
} }
// Update and save into the cache // Update and save into the cache
@@ -196,9 +193,8 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
} }
/** /**
* For an action that needs to go into the cache * For an action that needs to go into the cache (async action that is
* (async action that is pending, or sync action * pending, or sync action that is running), assign an execution instance
* that is running), assign an execution instance
* and put into the cache * and put into the cache
*/ */
private void placeActionInCache(ActionImpl action) private void placeActionInCache(ActionImpl action)
@@ -208,21 +204,26 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
// increase nextExecutionId until it isn't) // increase nextExecutionId until it isn't)
String key = null; String key = null;
boolean assigned = false; boolean assigned = false;
while(!assigned) { while (!assigned)
{
// Try // Try
action.setExecutionInstance(nextExecutionId++); action.setExecutionInstance(nextExecutionId++);
key = generateCacheKey(action); key = generateCacheKey(action);
// Is it ok? // Is it ok?
if(executingActionsCache.get(key) == null) { if (executingActionsCache.get(key) == null)
{
assigned = true; assigned = true;
} }
// Do we need to wrap? // Do we need to wrap?
// (Wrap before absolutely needed, makes things simpler) // (Wrap before absolutely needed, makes things simpler)
if(nextExecutionId > wrapExecutionIdAfter) { if (nextExecutionId > wrapExecutionIdAfter)
synchronized (this) { {
while(nextExecutionId > wrapExecutionIdAfter) { synchronized (this)
{
while (nextExecutionId > wrapExecutionIdAfter)
{
nextExecutionId -= wrapExecutionIdAfter; nextExecutionId -= wrapExecutionIdAfter;
} }
} }
@@ -240,8 +241,8 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
} }
/** /**
* Schedule the recording of the action failure to occur * Schedule the recording of the action failure to occur in another
* in another transaction * transaction
*/ */
public void recordActionFailure(Action action, Throwable exception) public void recordActionFailure(Action action, Throwable exception)
{ {
@@ -253,7 +254,8 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
} }
else else
{ {
logger.debug("Will shortly record failure of action " + action + " due to " + exception.getMessage()); logger.debug("Will shortly record failure of action " + action + " due to "
+ exception.getMessage());
} }
} }
@@ -291,8 +293,8 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
// Have the details updated on the action as soon // Have the details updated on the action as soon
// as the transaction has finished rolling back // as the transaction has finished rolling back
AlfrescoTransactionSupport.bindListener( AlfrescoTransactionSupport.bindListener(new TransactionListenerAdapter()
new TransactionListenerAdapter() { {
public void afterRollback() public void afterRollback()
{ {
transactionService.getRetryingTransactionHelper().doInTransaction( transactionService.getRetryingTransactionHelper().doInTransaction(
@@ -301,12 +303,14 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
public Object execute() throws Throwable public Object execute() throws Throwable
{ {
// Update the action as the system user // Update the action as the system user
return AuthenticationUtil.runAs(new RunAsWork<Action>() { return AuthenticationUtil.runAs(new RunAsWork<Action>()
{
public Action doWork() throws Exception public Action doWork() throws Exception
{ {
// Grab the latest version of the action // Grab the latest version of the
ActionImpl action = (ActionImpl) // action
runtimeActionService.createAction(actionNode); ActionImpl action = (ActionImpl) runtimeActionService
.createAction(actionNode);
// Update it // Update it
action.setExecutionStartDate(startedAt); action.setExecutionStartDate(startedAt);
@@ -317,7 +321,9 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
if (logger.isDebugEnabled() == true) if (logger.isDebugEnabled() == true)
{ {
logger.debug("Recorded failure of action " + actionId + ", node " + actionNode + " due to " + message); logger.debug("Recorded failure of action "
+ actionId + ", node " + actionNode
+ " due to " + message);
} }
// All done // All done
@@ -325,11 +331,9 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
} }
}, AuthenticationUtil.SYSTEM_USER_NAME); }, AuthenticationUtil.SYSTEM_USER_NAME);
} }
}, false, true }, false, true);
);
} }
} });
);
} }
} }
@@ -341,17 +345,14 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
// (Probably means the cache is too small) // (Probably means the cache is too small)
String key = generateCacheKey(action); String key = generateCacheKey(action);
ExecutionDetails details = getExecutionDetails(buildExecutionSummary(key)); ExecutionDetails details = getExecutionDetails(buildExecutionSummary(key));
if(details == null) { if (details == null)
{
Exception e = new Exception("Cancellation status missing from cache"); Exception e = new Exception("Cancellation status missing from cache");
e.fillInStackTrace(); e.fillInStackTrace();
logger.warn( logger.warn("Unable to check cancellation status for running action " + action
"Unable to check cancellation status for running action " + + " with execution key " + key + " as it wasn't in the running actions cache! "
action + " with execution key " + key + + "Your running actions cache is probably too small", e);
" as it wasn't in the running actions cache! " +
"Your running actions cache is probably too small",
e
);
// Re-generate // Re-generate
details = buildExecutionDetails(action); details = buildExecutionDetails(action);
@@ -368,16 +369,12 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
public void requestActionCancellation(CancellableAction action) public void requestActionCancellation(CancellableAction action)
{ {
requestActionCancellation( requestActionCancellation(generateCacheKey(action));
generateCacheKey(action)
);
} }
public void requestActionCancellation(ExecutionSummary executionSummary) public void requestActionCancellation(ExecutionSummary executionSummary)
{ {
requestActionCancellation( requestActionCancellation(generateCacheKey(executionSummary));
generateCacheKey(executionSummary)
);
} }
private void requestActionCancellation(String actionKey) private void requestActionCancellation(String actionKey)
@@ -385,7 +382,8 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
// See if the action is in the cache // See if the action is in the cache
ExecutionDetails details = executingActionsCache.get(actionKey); ExecutionDetails details = executingActionsCache.get(actionKey);
if(details == null) { if (details == null)
{
// It isn't in the cache, so nothing to do // It isn't in the cache, so nothing to do
return; return;
} }
@@ -397,46 +395,53 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
executingActionsCache.put(actionKey, details); executingActionsCache.put(actionKey, details);
} }
public List<ExecutionSummary> getAllExecutingActions()
public List<ExecutionSummary> getAllExecutingActions() { {
Collection<String> actions = executingActionsCache.getKeys(); Collection<String> actions = executingActionsCache.getKeys();
List<ExecutionSummary> details = new ArrayList<ExecutionSummary>(actions.size()); List<ExecutionSummary> details = new ArrayList<ExecutionSummary>(actions.size());
for(String key : actions) { for (String key : actions)
{
details.add(buildExecutionSummary(key)); details.add(buildExecutionSummary(key));
} }
return details; return details;
} }
public List<ExecutionSummary> getExecutingActions(Action action) { public List<ExecutionSummary> getExecutingActions(Action action)
{
Collection<String> actions = executingActionsCache.getKeys(); Collection<String> actions = executingActionsCache.getKeys();
List<ExecutionSummary> details = new ArrayList<ExecutionSummary>(); List<ExecutionSummary> details = new ArrayList<ExecutionSummary>();
String match = action.getActionDefinitionName() + cacheKeyPartSeparator + String match = action.getActionDefinitionName() + cacheKeyPartSeparator + action.getId()
action.getId() + cacheKeyPartSeparator; + cacheKeyPartSeparator;
for(String key : actions) { for (String key : actions)
if(key.startsWith(match)) { {
if (key.startsWith(match))
{
details.add(buildExecutionSummary(key)); details.add(buildExecutionSummary(key));
} }
} }
return details; return details;
} }
public List<ExecutionSummary> getExecutingActions(String type) { public List<ExecutionSummary> getExecutingActions(String type)
{
Collection<String> actions = executingActionsCache.getKeys(); Collection<String> actions = executingActionsCache.getKeys();
List<ExecutionSummary> details = new ArrayList<ExecutionSummary>(); List<ExecutionSummary> details = new ArrayList<ExecutionSummary>();
String match = type + cacheKeyPartSeparator; String match = type + cacheKeyPartSeparator;
for(String key : actions) { for (String key : actions)
if(key.startsWith(match)) { {
if (key.startsWith(match))
{
details.add(buildExecutionSummary(key)); details.add(buildExecutionSummary(key));
} }
} }
return details; return details;
} }
public ExecutionDetails getExecutionDetails(ExecutionSummary executionSummary) { public ExecutionDetails getExecutionDetails(ExecutionSummary executionSummary)
ExecutionDetails details = executingActionsCache.get( {
generateCacheKey(executionSummary) ExecutionDetails details = executingActionsCache.get(generateCacheKey(executionSummary));
); if (details != null)
if(details != null) { {
details.setExecutionSummary(executionSummary); details.setExecutionSummary(executionSummary);
} }
return details; return details;
@@ -447,66 +452,59 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
*/ */
protected static String generateCacheKey(Action action) protected static String generateCacheKey(Action action)
{ {
return return action.getActionDefinitionName() + cacheKeyPartSeparator + action.getId()
action.getActionDefinitionName() + cacheKeyPartSeparator + + cacheKeyPartSeparator + ((ActionImpl) action).getExecutionInstance();
action.getId() + cacheKeyPartSeparator +
((ActionImpl)action).getExecutionInstance()
;
} }
protected static String generateCacheKey(ExecutionSummary summary) protected static String generateCacheKey(ExecutionSummary summary)
{ {
return return summary.getActionType() + cacheKeyPartSeparator + summary.getActionId()
summary.getActionType() + cacheKeyPartSeparator + + cacheKeyPartSeparator + summary.getExecutionInstance();
summary.getActionId() + cacheKeyPartSeparator +
summary.getExecutionInstance()
;
} }
/** /**
* Builds up the details to be stored in a cache * Builds up the details to be stored in a cache for a specific action
* for a specific action
*/ */
protected static ExecutionDetails buildExecutionDetails(Action action) protected static ExecutionDetails buildExecutionDetails(Action action)
{ {
// Where are we running? // Where are we running?
if(machineName == null) { if (machineName == null)
try { {
try
{
InetAddress localhost = InetAddress.getLocalHost(); InetAddress localhost = InetAddress.getLocalHost();
machineName = localhost.getHostAddress() + " : " + machineName = localhost.getHostAddress() + " : " + localhost.getHostName();
localhost.getHostName(); }
} catch(UnknownHostException e) { catch (UnknownHostException e)
{
machineName = "(machine details unavailable - server IP not known)"; machineName = "(machine details unavailable - server IP not known)";
} }
} }
// Generate // Generate
return new ExecutionDetails( return new ExecutionDetails(buildExecutionSummary(action), action.getNodeRef(),
buildExecutionSummary(action), machineName, action.getExecutionStartDate(), false);
action.getNodeRef(), machineName,
action.getExecutionStartDate(), false
);
} }
private static String machineName = null; private static String machineName = null;
/** /**
* Turns a cache key back into its constituent * Turns a cache key back into its constituent parts, for easier access.
* parts, for easier access.
*/ */
protected static ExecutionSummary buildExecutionSummary(String key) protected static ExecutionSummary buildExecutionSummary(String key)
{ {
StringTokenizer st = new StringTokenizer(key, new String(new char[]{cacheKeyPartSeparator})); StringTokenizer st = new StringTokenizer(key, new String(
new char[] { cacheKeyPartSeparator }));
String actionType = st.nextToken(); String actionType = st.nextToken();
String actionId = st.nextToken(); String actionId = st.nextToken();
int executionInstance = Integer.parseInt(st.nextToken()); int executionInstance = Integer.parseInt(st.nextToken());
return new ExecutionSummary(actionType, actionId, executionInstance); return new ExecutionSummary(actionType, actionId, executionInstance);
} }
protected static ExecutionSummary buildExecutionSummary(Action action) protected static ExecutionSummary buildExecutionSummary(Action action)
{ {
return new ExecutionSummary( return new ExecutionSummary(action.getActionDefinitionName(), action.getId(),
action.getActionDefinitionName(), ((ActionImpl) action).getExecutionInstance());
action.getId(),
((ActionImpl)action).getExecutionInstance()
);
} }
} }