CA-210549: Make MultipleAction and ParallelAction cancellable

- The multiple action is cancellable if is at least one sub action is not completed
- When a multiple action is cancelled, we try to cancel all sub actions that are not completed
- Also changed the way we calculate the percent complete for the parent action, to report partial progress of the sub actions

Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
This commit is contained in:
Mihaela Stoica 2016-08-05 15:46:07 +01:00
parent 1065ca14eb
commit 56038e3eba
2 changed files with 41 additions and 8 deletions

View File

@ -34,6 +34,7 @@ using System.Collections.Generic;
using XenAdmin.Core;
using XenAdmin.Network;
using XenAPI;
using System.Linq;
namespace XenAdmin.Actions
@ -56,6 +57,7 @@ namespace XenAdmin.Actions
this.endDescription = endDescription;
this.subActions = subActions;
this.Completed += MultipleAction_Completed;
RegisterEvents();
}
public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription, List<AsyncAction> subActions)
@ -67,8 +69,6 @@ namespace XenAdmin.Actions
: this(connection, title, startDescription, endDescription, subActions, suppressHistory)
{
ShowSubActionsDetails = showSubActionsDetails;
if (showSubActionsDetails)
RegisterEvents();
}
public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription,
@ -94,7 +94,8 @@ namespace XenAdmin.Actions
{
PercentComplete = 0;
var exceptions = new List<Exception>();
RecomputeCanCancel();
RunSubActions(exceptions);
PercentComplete = 100;
@ -106,6 +107,21 @@ namespace XenAdmin.Actions
Exception = new Exception(Messages.SOME_ERRORS_ENCOUNTERED);
}
if (Cancelling)
Exception = new CancelledException();
}
public override void RecomputeCanCancel()
{
CanCancel = !this.IsCompleted && subActions.Any(a => !a.IsCompleted);
}
protected override void CancelRelatedTask()
{
foreach (AsyncAction subAction in subActions.Where(a => !a.IsCompleted))
{
subAction.Cancel();
}
}
private void RegisterEvents()
@ -127,15 +143,26 @@ namespace XenAdmin.Actions
{
SubActionTitle = subAction.Title;
SubActionDescription = subAction.Description;
RecalculatePercentComplete();
OnChanged();
}
}
private void RecalculatePercentComplete()
{
int total = 0;
int n = subActions.Count;
foreach (var action in subActions)
total += action.PercentComplete;
PercentComplete = (int)(total / n);
}
protected virtual void RunSubActions(List<Exception> exceptions)
{
int i = 0;
foreach (AsyncAction subAction in subActions)
{
if (Cancelling) // don't start any more actions
break;
try
{
subAction.RunExternal(Session);
@ -154,8 +181,6 @@ namespace XenAdmin.Actions
if (StopOnFirstException)
break;
}
i++;
PercentComplete = 100 * i / subActions.Count;
}
}

View File

@ -58,7 +58,10 @@ namespace XenAdmin.Actions
public ParallelAction(IXenConnection connection, string title, string startDescription, string endDescription, List<AsyncAction> subActions, bool suppressHistory, bool showSubActionsDetails, int maxNumberOfParallelActions = DEFAULT_MAX_NUMBER_OF_PARALLEL_ACTIONS)
: base(connection, title, startDescription, endDescription, subActions, suppressHistory, showSubActionsDetails)
{
actionsByConnection.Add(connection, subActions);
if (Connection != null)
actionsByConnection.Add(Connection, subActions);
else
GroupActionsByConnection();
this.maxNumberOfParallelActions = maxNumberOfParallelActions;
}
@ -138,6 +141,8 @@ namespace XenAdmin.Actions
queue.EnqueueItem(
() =>
{
if (Cancelling) // don't start any more actions
return;
try
{
action.RunExternal(action.Session);
@ -163,12 +168,15 @@ namespace XenAdmin.Actions
void action_Completed(ActionBase sender)
{
sender.Completed -= action_Completed;
lock (_lock)
{
i++;
PercentComplete = 100 * i / subActions.Count;
if (i == subActions.Count)
{
Monitor.Pulse(_lock);
PercentComplete = 100;
}
}
}