From a91dd6398da2d3d10ca92caf766efac69da911af Mon Sep 17 00:00:00 2001 From: Konstantina Chremmou Date: Mon, 21 Feb 2022 21:53:43 +0000 Subject: [PATCH 1/2] Compacted ParallelAction and MultipleAction constructors. Signed-off-by: Konstantina Chremmou --- XenAdmin/Core/HealthCheck.cs | 2 +- XenAdmin/Core/Updates.cs | 3 +- .../MissingMultipleFCSRsProblem.cs | 11 +-- XenAdmin/Dialogs/MoveVirtualDiskDialog.cs | 10 ++- XenAdmin/Wizards/NewSRWizard.cs | 6 +- .../PatchingWizard_PrecheckPage.cs | 5 +- XenModel/Actions/MultipleAction.cs | 44 ++++------ XenModel/Actions/MultipleActionLauncher.cs | 4 +- XenModel/Actions/ParallelAction.cs | 81 +++++++------------ 9 files changed, 69 insertions(+), 97 deletions(-) diff --git a/XenAdmin/Core/HealthCheck.cs b/XenAdmin/Core/HealthCheck.cs index 5959ec133..2b0b964d8 100644 --- a/XenAdmin/Core/HealthCheck.cs +++ b/XenAdmin/Core/HealthCheck.cs @@ -63,7 +63,7 @@ namespace XenAdmin.Core } else if (actions.Count > 1) { - var parallelAction = new ParallelAction(null, "", "", "", actions, true, true); + var parallelAction = new ParallelAction("", "", "", actions, suppressHistory: true, showSubActionsDetails: true); parallelAction.Completed += actionCompleted; parallelAction.RunAsync(); } diff --git a/XenAdmin/Core/Updates.cs b/XenAdmin/Core/Updates.cs index f36df770d..d1a498277 100644 --- a/XenAdmin/Core/Updates.cs +++ b/XenAdmin/Core/Updates.cs @@ -764,7 +764,8 @@ namespace XenAdmin.Core foreach (IXenConnection connection in ConnectionsManager.XenConnectionsCopy) actions.Add(new RestoreDismissedUpdatesAction(connection)); - var action = new ParallelAction(Messages.RESTORE_DISMISSED_UPDATES, Messages.RESTORING, Messages.COMPLETED, actions, true, false); + var action = new ParallelAction(Messages.RESTORE_DISMISSED_UPDATES, Messages.RESTORING, Messages.COMPLETED, + actions, suppressHistory: true, showSubActionsDetails: false); action.Completed += action_Completed; RestoreDismissedUpdatesStarted?.Invoke(); diff --git a/XenAdmin/Diagnostics/Problems/PoolProblem/MissingMultipleFCSRsProblem.cs b/XenAdmin/Diagnostics/Problems/PoolProblem/MissingMultipleFCSRsProblem.cs index 5276f3561..817f25291 100644 --- a/XenAdmin/Diagnostics/Problems/PoolProblem/MissingMultipleFCSRsProblem.cs +++ b/XenAdmin/Diagnostics/Problems/PoolProblem/MissingMultipleFCSRsProblem.cs @@ -109,11 +109,12 @@ namespace XenAdmin.Diagnostics.Problems.PoolProblem if (subActions.Count == 0) return null; - return subActions.Count == 1 - ? subActions[0] - : new ParallelAction(pool.Connection, Messages.ACTION_MULTIPLE_DR_TASK_CREATE_TITLE, - Messages.ACTION_MULTIPLE_DR_TASK_CREATE_START, - Messages.ACTION_MULTIPLE_DR_TASK_CREATE_END, subActions); + if (subActions.Count == 1) + return subActions[0]; + + return new ParallelAction(Messages.ACTION_MULTIPLE_DR_TASK_CREATE_TITLE, + Messages.ACTION_MULTIPLE_DR_TASK_CREATE_START, + Messages.ACTION_MULTIPLE_DR_TASK_CREATE_END, subActions, pool.Connection); } } diff --git a/XenAdmin/Dialogs/MoveVirtualDiskDialog.cs b/XenAdmin/Dialogs/MoveVirtualDiskDialog.cs index 0435ddb70..27abd18e8 100644 --- a/XenAdmin/Dialogs/MoveVirtualDiskDialog.cs +++ b/XenAdmin/Dialogs/MoveVirtualDiskDialog.cs @@ -120,8 +120,9 @@ namespace XenAdmin.Dialogs var batch = from VDI vdi in _vdis select (AsyncAction)new MoveVirtualDiskAction(connection, vdi, SelectedSR); - new ParallelAction(connection, title, Messages.ACTION_MOVING_X_VDIS_STARTED, - Messages.ACTION_MOVING_X_VDIS_COMPLETED, batch.ToList(), BATCH_SIZE).RunAsync(); + new ParallelAction(title, Messages.ACTION_MOVING_X_VDIS_STARTED, + Messages.ACTION_MOVING_X_VDIS_COMPLETED, batch.ToList(), + connection, maxNumberOfParallelActions: BATCH_SIZE).RunAsync(); } } @@ -160,8 +161,9 @@ namespace XenAdmin.Dialogs var batch = from VDI vdi in _vdis select (AsyncAction)new MigrateVirtualDiskAction(connection, vdi, SelectedSR); - new ParallelAction(connection, title, Messages.ACTION_MIGRATING_X_VDIS_STARTED, - Messages.ACTION_MIGRATING_X_VDIS_COMPLETED, batch.ToList(), BATCH_SIZE).RunAsync(); + new ParallelAction(title, Messages.ACTION_MIGRATING_X_VDIS_STARTED, + Messages.ACTION_MIGRATING_X_VDIS_COMPLETED, batch.ToList(), + connection, maxNumberOfParallelActions: BATCH_SIZE).RunAsync(); } } } diff --git a/XenAdmin/Wizards/NewSRWizard.cs b/XenAdmin/Wizards/NewSRWizard.cs index cc25554ae..a220b0d0b 100644 --- a/XenAdmin/Wizards/NewSRWizard.cs +++ b/XenAdmin/Wizards/NewSRWizard.cs @@ -536,9 +536,9 @@ namespace XenAdmin.Wizards if (actionList.Count == 1) FinalAction = actionList[0]; else - FinalAction = new ParallelAction(xenConnection, Messages.NEW_SR_WIZARD_FINAL_ACTION_TITLE, - Messages.NEW_SR_WIZARD_FINAL_ACTION_START, - Messages.NEW_SR_WIZARD_FINAL_ACTION_END, actionList); + FinalAction = new ParallelAction(Messages.NEW_SR_WIZARD_FINAL_ACTION_TITLE, + Messages.NEW_SR_WIZARD_FINAL_ACTION_START, + Messages.NEW_SR_WIZARD_FINAL_ACTION_END, actionList, xenConnection); // if this is a Disaster Recovery Task, it could be either a "Find existing SRs" or an "Attach SR needed for DR" case if (m_srWizardType.DisasterRecoveryTask) diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_PrecheckPage.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_PrecheckPage.cs index f97484283..c5cab19e7 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_PrecheckPage.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_PrecheckPage.cs @@ -815,7 +815,10 @@ namespace XenAdmin.Wizards.PatchingWizard } } } - resolvePrechecksAction = new ParallelAction(Messages.PATCHINGWIZARD_PRECHECKPAGE_RESOLVING_ALL, Messages.PATCHINGWIZARD_PRECHECKPAGE_RESOLVING_ALL, Messages.COMPLETED, actions, true, false); + + resolvePrechecksAction = new ParallelAction(Messages.PATCHINGWIZARD_PRECHECKPAGE_RESOLVING_ALL, + Messages.PATCHINGWIZARD_PRECHECKPAGE_RESOLVING_ALL, Messages.COMPLETED, + actions, suppressHistory: true, showSubActionsDetails: false); StartResolvePrechecksAction(); } diff --git a/XenModel/Actions/MultipleAction.cs b/XenModel/Actions/MultipleAction.cs index 6470cea59..921e7da2e 100644 --- a/XenModel/Actions/MultipleAction.cs +++ b/XenModel/Actions/MultipleAction.cs @@ -44,38 +44,24 @@ namespace XenAdmin.Actions { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - protected readonly List subActions; + private readonly List subActions; private readonly string endDescription; - public bool ShowSubActionsDetails { get; private set; } + public bool ShowSubActionsDetails { get; } public string SubActionTitle { get; private set; } public string SubActionDescription { get; private set; } - public bool StopOnFirstException { get; private set; } + private readonly bool _stopOnFirstException; - public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription, List subActions, bool suppressHistory) + public MultipleAction(IXenConnection connection, string title, string startDescription, + string endDescription, List subActions, bool suppressHistory = false, + bool showSubActionsDetails = false, bool stopOnFirstException = false) : base(connection, title, startDescription, suppressHistory) { this.endDescription = endDescription; this.subActions = subActions; - this.Completed += MultipleAction_Completed; - RegisterEvents(); - } - - public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription, List subActions) - : this(connection, title, startDescription, endDescription, subActions, false) - {} - - public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription, - List subActions, bool suppressHistory, bool showSubActionsDetails) - : this(connection, title, startDescription, endDescription, subActions, suppressHistory) - { ShowSubActionsDetails = showSubActionsDetails; - } - - public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription, - List subActions, bool suppressHistory, bool showSubActionsDetails, bool stopOnFirstException) - : this(connection, title, startDescription, endDescription, subActions, suppressHistory, showSubActionsDetails) - { - StopOnFirstException = stopOnFirstException; + _stopOnFirstException = stopOnFirstException; + Completed += MultipleAction_Completed; + RegisterEvents(); } // The multiple action gets its ApiMethodsToRoleCheck by accumulating the lists from each of the subactions @@ -90,7 +76,7 @@ namespace XenAdmin.Actions } } - protected override void Run() + protected sealed override void Run() { PercentComplete = 0; var exceptions = new List(); @@ -138,8 +124,7 @@ namespace XenAdmin.Actions private void SubActionChanged(ActionBase sender) { - AsyncAction subAction = sender as AsyncAction; - if (subAction != null) + if (sender is AsyncAction subAction) { SubActionTitle = subAction.Title; SubActionDescription = subAction.Description; @@ -154,7 +139,7 @@ namespace XenAdmin.Actions int n = subActions.Count; foreach (var action in subActions) total += action.PercentComplete; - PercentComplete = (int)(total / n); + PercentComplete = total / n; } protected virtual void RunSubActions(List exceptions) @@ -170,8 +155,7 @@ namespace XenAdmin.Actions } catch (Exception e) { - Failure f = e as Failure; - if (f != null && Connection != null && f.ErrorDescription[0] == Failure.RBAC_PERMISSION_DENIED) + if (e is Failure f && Connection != null && f.ErrorDescription[0] == Failure.RBAC_PERMISSION_DENIED) { Failure.ParseRBACFailure(f, Connection, Session ?? Connection.Session); } @@ -179,7 +163,7 @@ namespace XenAdmin.Actions // Record the first exception we come to. Though later if there are more than one we will replace this with non specific one. if (Exception == null) Exception = e; - if (StopOnFirstException) + if (_stopOnFirstException) break; } } diff --git a/XenModel/Actions/MultipleActionLauncher.cs b/XenModel/Actions/MultipleActionLauncher.cs index 76891da01..29974d117 100644 --- a/XenModel/Actions/MultipleActionLauncher.cs +++ b/XenModel/Actions/MultipleActionLauncher.cs @@ -91,7 +91,7 @@ namespace XenAdmin.Actions else { if (_runActionInParallel) - new ParallelAction(connection, _title, _startDescription, _endDescription, actionsByConnection[connection]).RunAsync(); + new ParallelAction(_title, _startDescription, _endDescription, actionsByConnection[connection], connection).RunAsync(); else new MultipleAction(connection, _title, _startDescription, _endDescription, actionsByConnection[connection]).RunAsync(); } @@ -104,7 +104,7 @@ namespace XenAdmin.Actions else if (actionsWithNoConnection.Count > 1) { if (_runActionInParallel) - new ParallelAction(null, _title, _startDescription, _endDescription, actionsWithNoConnection).RunAsync(); + new ParallelAction(_title, _startDescription, _endDescription, actionsWithNoConnection).RunAsync(); else new MultipleAction(null, _title, _startDescription, _endDescription, actionsWithNoConnection).RunAsync(); } diff --git a/XenModel/Actions/ParallelAction.cs b/XenModel/Actions/ParallelAction.cs index e4230a03a..d7f3dd024 100644 --- a/XenModel/Actions/ParallelAction.cs +++ b/XenModel/Actions/ParallelAction.cs @@ -54,66 +54,48 @@ namespace XenAdmin.Actions private ProduceConsumerQueue queueWithNoConnection; private readonly int maxNumberOfParallelActions; - private int actionsCount; + private readonly int actionsCount; + private readonly object _lock = new object(); + private volatile int i ; - public ParallelAction(IXenConnection connection, string title, string startDescription, string endDescription, List subActions, bool suppressHistory, bool showSubActionsDetails, int maxNumberOfParallelActions = DEFAULT_MAX_NUMBER_OF_PARALLEL_ACTIONS) - : base(connection, title, startDescription, endDescription, subActions, suppressHistory, showSubActionsDetails) - { - if (Connection != null) - { - actionsByConnection.Add(Connection, subActions); - actionsCount = subActions.Count; - } - else - GroupActionsByConnection(); - this.maxNumberOfParallelActions = maxNumberOfParallelActions; - } - - public ParallelAction(IXenConnection connection, string title, string startDescription, string endDescription, List subActions, int maxNumberOfParallelActions = DEFAULT_MAX_NUMBER_OF_PARALLEL_ACTIONS) - : this(connection, title, startDescription, endDescription, subActions, false, false, maxNumberOfParallelActions) - { } - /// /// Use this constructor to create a cross connection ParallelAction. /// It takes a list of any number of actions, separates them by connections /// and runs a certain number of them simultaneously on each connection, all connections in parallel. - /// Once one simultaneous action is finished the next one in the queue is started until all are complete. + /// Once a simultaneous action is finished the next one in the queue is started until all are complete. /// - public ParallelAction(string title, string startDescription, string endDescription, List subActions, bool suppressHistory, bool showSubActionsDetails, int maxNumberOfParallelActions = DEFAULT_MAX_NUMBER_OF_PARALLEL_ACTIONS) - : base(null, title, startDescription, endDescription, subActions, suppressHistory, showSubActionsDetails) + public ParallelAction(string title, string startDescription, string endDescription, + List subActions, IXenConnection connection = null, + bool suppressHistory = false, bool showSubActionsDetails = false, + int maxNumberOfParallelActions = DEFAULT_MAX_NUMBER_OF_PARALLEL_ACTIONS) + : base(connection, title, startDescription, endDescription, subActions, suppressHistory, showSubActionsDetails) { - GroupActionsByConnection(); - this.maxNumberOfParallelActions = maxNumberOfParallelActions; - } - - public ParallelAction(string title, string startDescription, string endDescription, List subActions, int maxNumberOfParallelActions = DEFAULT_MAX_NUMBER_OF_PARALLEL_ACTIONS) - : this(title, startDescription, endDescription, subActions, false, false, maxNumberOfParallelActions) - { } - - private void GroupActionsByConnection() - { - actionsCount = 0; - foreach (AsyncAction action in subActions) + if (Connection == null) { - if (action.Connection != null) + foreach (AsyncAction action in subActions) { - if (action.Connection.IsConnected) + if (action.Connection == null) + { + actionsWithNoConnection.Add(action); + actionsCount++; + } + else if (action.Connection.IsConnected) { if (!actionsByConnection.ContainsKey(action.Connection)) - { actionsByConnection.Add(action.Connection, new List()); - } actionsByConnection[action.Connection].Add(action); actionsCount++; } } - else - { - actionsWithNoConnection.Add(action); - actionsCount++; - } } + else + { + actionsByConnection.Add(Connection, subActions); + actionsCount = subActions.Count; + } + + this.maxNumberOfParallelActions = maxNumberOfParallelActions; } @@ -145,7 +127,7 @@ namespace XenAdmin.Actions } } - void EnqueueAction(AsyncAction action, ProduceConsumerQueue queue, List exceptions) + private void EnqueueAction(AsyncAction action, ProduceConsumerQueue queue, List exceptions) { action.Completed += action_Completed; queue.EnqueueItem( @@ -159,8 +141,7 @@ namespace XenAdmin.Actions } catch (Exception e) { - Failure f = e as Failure; - if (f != null && Connection != null && + if (e is Failure f && Connection != null && f.ErrorDescription[0] == Failure.RBAC_PERMISSION_DENIED) { Failure.ParseRBACFailure(f, action.Connection, action.Session ?? action.Connection.Session); @@ -179,20 +160,20 @@ namespace XenAdmin.Actions return; int total = 0; + foreach (IXenConnection connection in actionsByConnection.Keys) { foreach (var action in actionsByConnection[connection]) total += action.PercentComplete; } + foreach (var action in actionsWithNoConnection) total += action.PercentComplete; - PercentComplete = (int)(total / actionsCount); + + PercentComplete = total / actionsCount; } - private readonly object _lock = new object(); - private volatile int i = 0; - - void action_Completed(ActionBase sender) + private void action_Completed(ActionBase sender) { sender.Completed -= action_Completed; lock (_lock) From 81d5c508a190237259f3afbde13584ee83abbcb5 Mon Sep 17 00:00:00 2001 From: Konstantina Chremmou Date: Mon, 28 Mar 2022 13:43:24 +0100 Subject: [PATCH 2/2] Refactoring suggested by code review (largely naming conventions). Signed-off-by: Konstantina Chremmou --- XenAdmin/Core/HealthCheck.cs | 3 +- XenModel/Actions/MultipleAction.cs | 58 +++++++++++---------- XenModel/Actions/ParallelAction.cs | 81 +++++++++++++++--------------- 3 files changed, 74 insertions(+), 68 deletions(-) diff --git a/XenAdmin/Core/HealthCheck.cs b/XenAdmin/Core/HealthCheck.cs index 2b0b964d8..9427b9953 100644 --- a/XenAdmin/Core/HealthCheck.cs +++ b/XenAdmin/Core/HealthCheck.cs @@ -63,7 +63,8 @@ namespace XenAdmin.Core } else if (actions.Count > 1) { - var parallelAction = new ParallelAction("", "", "", actions, suppressHistory: true, showSubActionsDetails: true); + var parallelAction = new ParallelAction(string.Empty, string.Empty, string.Empty, actions, + suppressHistory: true, showSubActionsDetails: true); parallelAction.Completed += actionCompleted; parallelAction.RunAsync(); } diff --git a/XenModel/Actions/MultipleAction.cs b/XenModel/Actions/MultipleAction.cs index 921e7da2e..c9ecdff9c 100644 --- a/XenModel/Actions/MultipleAction.cs +++ b/XenModel/Actions/MultipleAction.cs @@ -39,38 +39,43 @@ using System.Linq; namespace XenAdmin.Actions { - // Run several actions. The outer action is asynchronous, but the subactions are run synchronously within that. + /// + /// Run several actions. The outer action is asynchronous, but the sub-actions are run synchronously within it. + /// public class MultipleAction : AsyncAction, IDisposable { - private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private readonly List _subActions; + private readonly string _endDescription; + private readonly bool _stopOnFirstException; - private readonly List subActions; - private readonly string endDescription; public bool ShowSubActionsDetails { get; } public string SubActionTitle { get; private set; } public string SubActionDescription { get; private set; } - private readonly bool _stopOnFirstException; public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription, List subActions, bool suppressHistory = false, bool showSubActionsDetails = false, bool stopOnFirstException = false) : base(connection, title, startDescription, suppressHistory) { - this.endDescription = endDescription; - this.subActions = subActions; + _endDescription = endDescription; + _subActions = subActions; ShowSubActionsDetails = showSubActionsDetails; _stopOnFirstException = stopOnFirstException; Completed += MultipleAction_Completed; RegisterEvents(); } - // The multiple action gets its ApiMethodsToRoleCheck by accumulating the lists from each of the subactions + /// + /// The multiple action gets its ApiMethodsToRoleCheck by accumulating the lists from each of the sub-actions + /// public override RbacMethodList GetApiMethodsToRoleCheck { get { - RbacMethodList list = new RbacMethodList(); - foreach (AsyncAction subAction in subActions) + var list = new RbacMethodList(); + foreach (var subAction in _subActions) list.AddRange(subAction.GetApiMethodsToRoleCheck); return list; } @@ -84,12 +89,12 @@ namespace XenAdmin.Actions RunSubActions(exceptions); - Tick(100, endDescription); + Tick(100, _endDescription); if (exceptions.Count > 1) { - foreach (Exception e in exceptions) - log.Error(e); + foreach (var e in exceptions) + _log.Error(e); Exception = new Exception(Messages.SOME_ERRORS_ENCOUNTERED); } @@ -99,12 +104,12 @@ namespace XenAdmin.Actions public override void RecomputeCanCancel() { - CanCancel = !this.IsCompleted && subActions.Any(a => !a.IsCompleted); + CanCancel = !IsCompleted && _subActions.Any(a => !a.IsCompleted); } protected override void CancelRelatedTask() { - foreach (AsyncAction subAction in subActions.Where(a => !a.IsCompleted)) + foreach (var subAction in _subActions.Where(a => !a.IsCompleted)) { subAction.Cancel(); } @@ -112,13 +117,13 @@ namespace XenAdmin.Actions private void RegisterEvents() { - foreach (AsyncAction subAction in subActions) + foreach (var subAction in _subActions) subAction.Changed += SubActionChanged; } - private void DeregisterEvents() + private void DeRegisterEvents() { - foreach (AsyncAction subAction in subActions) + foreach (var subAction in _subActions) subAction.Changed -= SubActionChanged; } @@ -136,15 +141,15 @@ namespace XenAdmin.Actions protected virtual void RecalculatePercentComplete() { int total = 0; - int n = subActions.Count; - foreach (var action in subActions) + int n = _subActions.Count; + foreach (var action in _subActions) total += action.PercentComplete; PercentComplete = total / n; } protected virtual void RunSubActions(List exceptions) { - foreach (AsyncAction subAction in subActions) + foreach (var subAction in _subActions) { if (Cancelling) // don't start any more actions break; @@ -156,9 +161,8 @@ namespace XenAdmin.Actions catch (Exception e) { if (e is Failure f && Connection != null && f.ErrorDescription[0] == Failure.RBAC_PERMISSION_DENIED) - { Failure.ParseRBACFailure(f, Connection, Session ?? Connection.Session); - } + exceptions.Add(e); // Record the first exception we come to. Though later if there are more than one we will replace this with non specific one. if (Exception == null) @@ -173,9 +177,9 @@ namespace XenAdmin.Actions { // The MultipleAction can sometimes complete prematurely, for example // if the sudo dialog is cancelled, of (less likely) if one of the - // subactions throws an exception in its GetApiMethodsToRoleCheck. - // In this case, we need to cancel this action's subactions. - foreach (AsyncAction subAction in subActions) + // sub-actions throws an exception in its GetApiMethodsToRoleCheck. + // In this case, we need to cancel this action's sub-actions. + foreach (var subAction in _subActions) { if (!subAction.IsCompleted) subAction.Cancel(); @@ -186,7 +190,7 @@ namespace XenAdmin.Actions public void Dispose() { - DeregisterEvents(); + DeRegisterEvents(); } #endregion diff --git a/XenModel/Actions/ParallelAction.cs b/XenModel/Actions/ParallelAction.cs index d7f3dd024..2a14c912c 100644 --- a/XenModel/Actions/ParallelAction.cs +++ b/XenModel/Actions/ParallelAction.cs @@ -44,19 +44,21 @@ namespace XenAdmin.Actions /// public class ParallelAction : MultipleAction { - //Change parameter to increase the number of concurrent actions running + /// + /// Change this to increase the number of concurrent actions running + /// private const int DEFAULT_MAX_NUMBER_OF_PARALLEL_ACTIONS = 25; - private Dictionary> actionsByConnection = new Dictionary>(); - private Dictionary queuesByConnection = new Dictionary(); + private readonly Dictionary> _actionsByConnection = new Dictionary>(); + private readonly Dictionary _queuesByConnection = new Dictionary(); - private List actionsWithNoConnection = new List(); - private ProduceConsumerQueue queueWithNoConnection; + private readonly List _actionsWithNoConnection = new List(); + private ProduceConsumerQueue _queueWithNoConnection; - private readonly int maxNumberOfParallelActions; - private readonly int actionsCount; + private readonly int _maxNumberOfParallelActions; + private readonly int _actionsCount; private readonly object _lock = new object(); - private volatile int i ; + private volatile int _completedActionsCount ; /// /// Use this constructor to create a cross connection ParallelAction. @@ -72,53 +74,53 @@ namespace XenAdmin.Actions { if (Connection == null) { - foreach (AsyncAction action in subActions) + foreach (var action in subActions) { if (action.Connection == null) { - actionsWithNoConnection.Add(action); - actionsCount++; + _actionsWithNoConnection.Add(action); + _actionsCount++; } else if (action.Connection.IsConnected) { - if (!actionsByConnection.ContainsKey(action.Connection)) - actionsByConnection.Add(action.Connection, new List()); + if (!_actionsByConnection.ContainsKey(action.Connection)) + _actionsByConnection.Add(action.Connection, new List()); - actionsByConnection[action.Connection].Add(action); - actionsCount++; + _actionsByConnection[action.Connection].Add(action); + _actionsCount++; } } } else { - actionsByConnection.Add(Connection, subActions); - actionsCount = subActions.Count; + _actionsByConnection.Add(Connection, subActions); + _actionsCount = subActions.Count; } - this.maxNumberOfParallelActions = maxNumberOfParallelActions; + _maxNumberOfParallelActions = maxNumberOfParallelActions; } protected override void RunSubActions(List exceptions) { - if (actionsCount == 0) + if (_actionsCount == 0) return; - foreach (IXenConnection connection in actionsByConnection.Keys) + foreach (var connection in _actionsByConnection.Keys) { - queuesByConnection[connection] = new ProduceConsumerQueue(Math.Min(maxNumberOfParallelActions, actionsByConnection[connection].Count)); - foreach (AsyncAction subAction in actionsByConnection[connection]) + _queuesByConnection[connection] = new ProduceConsumerQueue(Math.Min(_maxNumberOfParallelActions, _actionsByConnection[connection].Count)); + foreach (AsyncAction subAction in _actionsByConnection[connection]) { - EnqueueAction(subAction, queuesByConnection[connection], exceptions); + EnqueueAction(subAction, _queuesByConnection[connection], exceptions); } } - if (actionsWithNoConnection.Count > 0) - queueWithNoConnection = new ProduceConsumerQueue(Math.Min(maxNumberOfParallelActions, actionsWithNoConnection.Count)); + if (_actionsWithNoConnection.Count > 0) + _queueWithNoConnection = new ProduceConsumerQueue(Math.Min(_maxNumberOfParallelActions, _actionsWithNoConnection.Count)); - foreach (AsyncAction subAction in actionsWithNoConnection) + foreach (var subAction in _actionsWithNoConnection) { - EnqueueAction(subAction, queueWithNoConnection, exceptions); + EnqueueAction(subAction, _queueWithNoConnection, exceptions); } lock (_lock) @@ -146,6 +148,7 @@ namespace XenAdmin.Actions { Failure.ParseRBACFailure(f, action.Connection, action.Session ?? action.Connection.Session); } + exceptions.Add(e); // Record the first exception we come to. Though later if there are more than one we will replace this with non specific one. if (Exception == null) @@ -156,21 +159,21 @@ namespace XenAdmin.Actions protected override void RecalculatePercentComplete() { - if (actionsCount == 0) + if (_actionsCount == 0) return; int total = 0; - foreach (IXenConnection connection in actionsByConnection.Keys) + foreach (var connection in _actionsByConnection.Keys) { - foreach (var action in actionsByConnection[connection]) + foreach (var action in _actionsByConnection[connection]) total += action.PercentComplete; } - foreach (var action in actionsWithNoConnection) + foreach (var action in _actionsWithNoConnection) total += action.PercentComplete; - PercentComplete = total / actionsCount; + PercentComplete = total / _actionsCount; } private void action_Completed(ActionBase sender) @@ -178,8 +181,8 @@ namespace XenAdmin.Actions sender.Completed -= action_Completed; lock (_lock) { - i++; - if (i == actionsCount) + _completedActionsCount++; + if (_completedActionsCount == _actionsCount) { Monitor.Pulse(_lock); PercentComplete = 100; @@ -191,13 +194,11 @@ namespace XenAdmin.Actions { base.MultipleAction_Completed(sender); - foreach (IXenConnection connection in queuesByConnection.Keys) - { - queuesByConnection[connection].StopWorkers(false); - } + foreach (var connection in _queuesByConnection.Keys) + _queuesByConnection[connection].StopWorkers(false); - if (queueWithNoConnection != null) - queueWithNoConnection.StopWorkers(false); + + _queueWithNoConnection?.StopWorkers(false); } } }