AutomaticBackgroundThread and SemiAutomaticBackgroundThread simplification: moved

common code to the base class BackgroundThreadBase; removed classes inheriting from
EventArgs; use Action/Action<T> delegates instead of EventHandler<T>.

Signed-off-by: Konstantina Chremmou <konstantina.chremmou@citrix.com>
This commit is contained in:
Konstantina Chremmou 2013-12-21 11:36:20 +00:00
parent 17512a4cb1
commit a128847717
7 changed files with 148 additions and 244 deletions

View File

@ -31,9 +31,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using log4net;
using XenAdmin.Core;
using XenAdmin.Wizards.PatchingWizard.PlanActions;
using XenAPI;
@ -41,21 +39,8 @@ using XenAPI;
namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
{
class AutomaticBackgroundThread
class AutomaticBackgroundThread : BackgroundThreadBase
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Thread _bw;
private IDictionary<Host, List<PlanAction>> _planActions;
private PlanAction _revertAction;
private IEnumerable<Host> _mastersToUpgrade;
public event EventHandler<ReportHostDoneArgs> ReportHostDone;
public event EventHandler<ReportRunningArgs> ReportRunning;
public event EventHandler<ReportExceptionArgs> ReportException;
public event EventHandler<ReportRevertDoneArgs> ReportRevertDone;
public event EventHandler Completed;
public AutomaticBackgroundThread(IEnumerable<Host> mastersToUpgrade, IDictionary<Host, List<PlanAction>> planActions, PlanAction revertAction)
{
_planActions = planActions;
@ -64,14 +49,6 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
_bw = new Thread(BworkerDoWork) { IsBackground = true };
}
public void Start()
{
_bw.Start();
}
private void BworkerDoWork()
{
Host currentHost = null;
@ -81,52 +58,55 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
{
if (_cancel)
return;
Pool pool = Helpers.GetPoolOfOne(selectedMaster.Connection);
foreach (var host in pool.HostsToUpgrade)
{
log.InfoFormat("Host '{0}' upgrading from version '{1}'", host.Name, host.LongProductVersion);
currentHost = host;
bool allactionsDone = true;
foreach (var planAction in _planActions[host])
{
try
{
string hostVersion = host.LongProductVersion;
ReportRunning(this, new ReportRunningArgs(planAction, host));
OnReportRunning(planAction, host);
planAction.Run();
if (_cancel)
return;
if (planAction is UpgradeHostPlanAction)
{
Host hostAfterReboot = host.Connection.Resolve(new XenRef<Host>(host.opaque_ref));
if (Helpers.SameServerVersion(hostAfterReboot, hostVersion))
{
log.ErrorFormat("Host '{0}' rebooted with the same version '{1}'", hostAfterReboot.Name, hostAfterReboot.LongProductVersion);
ReportException.Raise(this,
new ReportExceptionArgs(
new Exception(Messages.REBOOT_WITH_SAME_VERSION),
planAction, host));
OnReportException(new Exception(Messages.REBOOT_WITH_SAME_VERSION),
planAction, host);
allactionsDone = false;
if (hostAfterReboot.IsMaster())
_cancel = true;
}
log.InfoFormat("Host '{0}' upgraded with version '{1}'", hostAfterReboot.Name, hostAfterReboot.LongProductVersion);
}
}
catch (Exception e)
{
ReportException.Raise(this, new ReportExceptionArgs(e, planAction, host));
OnReportException(e, planAction, host);
allactionsDone = false;
_cancel = true;
}
if (_cancel)
return;
}
if (allactionsDone)
ReportHostDone.Raise(this, new ReportHostDoneArgs(host));
}
if (allactionsDone)
OnReportHostDone(host);
}
}
}
catch (Exception excep)
@ -139,29 +119,19 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
try
{
log.Debug("Reverting prechecks");
ReportRunning.Raise(this, () => new ReportRunningArgs(_revertAction, currentHost));
OnReportRunning(_revertAction, currentHost);
_revertAction.Run();
ReportRevertDone.Raise(this, () => new ReportRevertDoneArgs(_revertAction));
OnReportRevertDone();
}
catch (Exception excep)
{
log.Error("Exception reverting prechecks", excep);
ReportException.Raise(this, () => new ReportExceptionArgs(excep, _revertAction, currentHost));
OnReportException(excep, _revertAction, currentHost);
}
Completed.Raise(this);
OnCompleted();
}
Completed.Raise(this);
}
private volatile bool _cancel = false;
internal void Cancel()
{
_cancel = true;
}
}
}

View File

@ -0,0 +1,93 @@
/* Copyright (c) Citrix Systems Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using XenAdmin.Wizards.PatchingWizard.PlanActions;
using XenAPI;
namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
{
class BackgroundThreadBase
{
protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected Thread _bw;
protected IDictionary<Host, List<PlanAction>> _planActions;
protected PlanAction _revertAction;
protected IEnumerable<Host> _mastersToUpgrade;
public event Action<Host> ReportHostDone;
public event Action<PlanAction, Host> ReportRunning;
public event Action<Exception, PlanAction, Host> ReportException;
public event Action ReportRevertDone;
public event Action Completed;
public void Start()
{
_bw.Start();
}
protected volatile bool _cancel = false;
internal void Cancel()
{
_cancel = true;
}
protected void OnReportHostDone(Host host)
{
if (ReportRevertDone != null)
ReportHostDone(host);
}
protected void OnReportRunning(PlanAction planAction, Host host)
{
if (ReportRunning != null)
ReportRunning(planAction, host);
}
protected void OnReportException(Exception ex, PlanAction planAction, Host host)
{
if (ReportException != null)
ReportException(ex, planAction, host);
}
protected void OnReportRevertDone()
{
if (ReportRevertDone != null)
ReportRevertDone();
}
protected void OnCompleted()
{
if (Completed != null)
Completed();
}
}
}

View File

@ -31,29 +31,15 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using log4net;
using XenAdmin.Wizards.PatchingWizard.PlanActions;
using XenAPI;
namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
{
class SemiAutomaticBackgroundThread
class SemiAutomaticBackgroundThread : BackgroundThreadBase
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Thread _bw;
private IDictionary<Host, List<PlanAction>> _planActions;
private PlanAction _revertAction;
private IEnumerable<Host> _mastersToUpgrade;
public event EventHandler<ReportHostDoneArgs> ReportHostDone;
public event EventHandler<ManageSemiAutomaticPlanActionArgs> ManageSemiAutomaticPlanAction;
public event EventHandler<ReportRunningArgs> ReportRunning;
public event EventHandler<ReportExceptionArgs> ReportException;
public event EventHandler<ReportRevertDoneArgs> ReportRevertDone;
public event EventHandler Completed;
public event Action<UpgradeManualHostPlanAction> ManageSemiAutomaticPlanAction;
public SemiAutomaticBackgroundThread(IEnumerable<Host> mastersToUpgrade, IDictionary<Host, List<PlanAction>> planActions, PlanAction revertAction)
{
@ -63,12 +49,6 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
_bw = new Thread(BworkerDoWork) { IsBackground = true };
}
public void Start()
{
_bw.Start();
}
private static List<Host> GetAllHosts(IEnumerable<Host> masters)
{
var hosts = new List<Host>();
@ -113,7 +93,6 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
Host currentHost = null;
try
{
List<Host> hosts = GetAllHosts(_mastersToUpgrade);
bool currentMasterFailed = false;
@ -147,14 +126,17 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
if (_cancel && !(planAction is BringBabiesBackAction))
continue;
PlanAction action = planAction;
ReportRunning.Raise(this, () => new ReportRunningArgs(action, host));
OnReportRunning(planAction, host);
try
{
if (planAction is UpgradeManualHostPlanAction)
{
var upgradeAction = (UpgradeManualHostPlanAction)planAction;
ManageSemiAutomaticPlanAction.Raise(this, () => new ManageSemiAutomaticPlanActionArgs(upgradeAction));
if (ManageSemiAutomaticPlanAction != null)
ManageSemiAutomaticPlanAction(upgradeAction);
if (host.IsMaster())
poolHigherProductVersion = upgradeAction.Host.LongProductVersion;
}
@ -166,7 +148,9 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
{
log.Error(string.Format("Exception in host '{0}' while it was upgraded", host.Name), excep);
PlanAction action1 = planAction;
ReportException.Raise(this, () => new ReportExceptionArgs(excep, action1, host));
OnReportException(excep, action1, host);
if (host.IsMaster())
currentMasterFailed = true;
allActionsDone = false;
@ -175,9 +159,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
}
if (allActionsDone)
{
ReportHostDone.Raise(this, () => new ReportHostDoneArgs(host));
}
OnReportHostDone(host);
//Skip slaves if master failed
if (currentMasterFailed)
@ -185,8 +167,6 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
i = SkipSlaves(hosts, i);
}
}
}
catch (Exception excep)
{
@ -198,82 +178,18 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
try
{
log.Debug("Reverting prechecks");
ReportRunning.Raise(this, () => new ReportRunningArgs(_revertAction, currentHost));
OnReportRunning(_revertAction, currentHost);
_revertAction.Run();
ReportRevertDone.Raise(this, () => new ReportRevertDoneArgs(_revertAction));
OnReportRevertDone();
}
catch (Exception excep)
{
log.Error("Exception reverting prechecks", excep);
ReportException.Raise(this, () => new ReportExceptionArgs(excep, _revertAction, currentHost));
OnReportException(excep, _revertAction, currentHost);
}
Completed.Raise(this);
OnCompleted();
}
}
private volatile bool _cancel = false;
internal void Cancel()
{
_cancel = true;
}
}
internal class ReportRevertDoneArgs : EventArgs
{
public ReportRevertDoneArgs(PlanAction planAction)
{
PlanAction = planAction;
}
public PlanAction PlanAction { get; private set; }
}
internal class ReportExceptionArgs : EventArgs
{
public ReportExceptionArgs(Exception excep, PlanAction action, Host host)
{
Exception = excep;
Action = action;
Host = host;
}
public Exception Exception { get; private set; }
public PlanAction Action { get; private set; }
public Host Host { get; private set; }
}
internal class ReportRunningArgs : EventArgs
{
public ReportRunningArgs(PlanAction action, Host host)
{
Host = host;
Action = action;
}
public Host Host { get; private set; }
public PlanAction Action { get; private set; }
}
internal class ManageSemiAutomaticPlanActionArgs : EventArgs
{
public ManageSemiAutomaticPlanActionArgs(UpgradeManualHostPlanAction action)
{
Action = action;
}
public UpgradeManualHostPlanAction Action { get; private set; }
}
internal class ReportHostDoneArgs : EventArgs
{
public ReportHostDoneArgs(Host host)
{
Host = host;
}
public Host Host { get; private set; }
}
}

View File

@ -218,7 +218,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
UpgradeStatus = RollingUpgradeStatus.Started;
}
private void ReportRevertDone(object sender, ReportRevertDoneArgs e)
private void ReportRevertDone()
{
Program.BeginInvoke(this, () =>
{
@ -227,7 +227,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
});
}
private void Completed(object sender, EventArgs eventArgs)
private void Completed()
{
Program.BeginInvoke(this, () =>
{
@ -238,29 +238,29 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
});
}
private void ReportRunning(object sender, ReportRunningArgs reportRunningArgs)
private void ReportRunning(PlanAction planAction, Host host)
{
Program.BeginInvoke(this, () =>
{
progressBar1.Value = progressBar1.Value < 100
? progressBar1.Value + 2
: progressBar1.Value;
var row = reportRunningArgs.Action is UnwindProblemsAction
var row = planAction is UnwindProblemsAction
? FindRow(null)
: FindRow(reportRunningArgs.Host);
: FindRow(host);
if (row != null)
row.UpdateStatus(HostUpgradeState.Upgrading, reportRunningArgs.Action.TitlePlan);
row.UpdateStatus(HostUpgradeState.Upgrading, planAction.TitlePlan);
});
}
private void ManageSemiAutomaticPlanAction(object sender, ManageSemiAutomaticPlanActionArgs e)
private void ManageSemiAutomaticPlanAction(UpgradeManualHostPlanAction planAction)
{
if (UpgradeStatus == RollingUpgradeStatus.Cancelled)
return;
var upgradeHostPlanAction = e.Action;
var upgradeHostPlanAction = planAction;
//Show dialog prepare host boot from CD or PXE boot and click OK to reboot
string msg = string.Format(Messages.ROLLING_UPGRADE_REBOOT_MESSAGE, upgradeHostPlanAction.Host.Name);
string msg = string.Format(Messages.ROLLING_UPGRADE_REBOOT_MESSAGE, planAction.Host.Name);
UpgradeManualHostPlanAction action = upgradeHostPlanAction;
@ -327,21 +327,21 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
}
}
private void ReportException(object sender, ReportExceptionArgs reportExceptionArgs)
private void ReportException(Exception exception, PlanAction planAction, Host host)
{
Program.Invoke(this, () =>
{
if (reportExceptionArgs.Host != null && !reportExceptionArgs.Host.enabled)
new EnableHostAction(reportExceptionArgs.Host, false,
AddHostToPoolCommand.EnableNtolDialog).RunExternal(reportExceptionArgs.Host.Connection.Session);
if (host != null && !host.enabled)
new EnableHostAction(host, false,
AddHostToPoolCommand.EnableNtolDialog).RunExternal(host.Connection.Session);
});
Program.BeginInvoke(this, () =>
{
var row = reportExceptionArgs.Action is UnwindProblemsAction
var row = planAction is UnwindProblemsAction
? FindRow(null)
: FindRow(reportExceptionArgs.Host);
: FindRow(host);
row.UpdateStatus(HostUpgradeState.Error, reportExceptionArgs.Exception.Message);
row.UpdateStatus(HostUpgradeState.Error, exception.Message);
UpgradeProgress(row.Index + 1);
@ -350,11 +350,11 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
}
private void ReportHostDone(object sender, ReportHostDoneArgs reportHostDoneArgs)
private void ReportHostDone(Host host)
{
Program.BeginInvoke(this, () =>
{
var row = FindRow(reportHostDoneArgs.Host);
var row = FindRow(host);
row.UpdateStatus(HostUpgradeState.Upgraded, Messages.COMPLETED);
labelOverallProgress.Text = string.Format(Messages.OVERALL_PROGRESS, row.Index + 1, dataGridView1.Rows.Count - 1);

View File

@ -3429,6 +3429,7 @@
<DependentUpon>TvmIpPage.cs</DependentUpon>
</Compile>
<Compile Include="Wizards\PatchingWizard\PatchingWizardModeGuidanceBuilder.cs" />
<Compile Include="Wizards\RollingUpgradeWizard\PlanActions\BackgroundThreadBase.cs" />
<Compile Include="Wizards\RollingUpgradeWizard\RollingUpgradeReadyToUpgradePage.cs">
<SubType>UserControl</SubType>
</Compile>

View File

@ -1,75 +0,0 @@
/* Copyright (c) Citrix Systems Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
namespace System
{
public static class EventHandlerExtensions
{
//Raise with no args
public static void Raise(this EventHandler handler, object sender)
{
if (handler != null)
{
handler(sender, EventArgs.Empty);
}
}
/// <summary>
/// Raise with args
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="handler"></param>
/// <param name="sender"></param>
/// <param name="args"></param>
public static void Raise<T>(this EventHandler<T> handler, object sender, T args)
where T:EventArgs
{
if (handler != null)
{
handler(sender, args);
}
}
/// <summary>
/// Lazy creation of args
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="handler"></param>
/// <param name="sender"></param>
/// <param name="args"></param>
public static void Raise<T>(this EventHandler<T> handler, object sender, Func<T> args)
where T : EventArgs
{
if (handler != null)
{
handler(sender, args());
}
}
}
}

View File

@ -75,7 +75,6 @@
<Compile Include="ChangeableList.cs" />
<Compile Include="EmailAddressValidator.cs" />
<Compile Include="EncryptionUtils.cs" />
<Compile Include="EventHandlerExtensions.cs" />
<Compile Include="ExceptionEventHandler.cs" />
<Compile Include="ComparableAddress.cs" />
<Compile Include="ComparableList.cs" />