Skip to content

Commit

Permalink
Another step towards better logging
Browse files Browse the repository at this point in the history
  • Loading branch information
synhershko committed Jul 13, 2012
1 parent 13ff650 commit 96fe742
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 103 deletions.
4 changes: 1 addition & 3 deletions Samples/WinFormsProgressSample/LengthyTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace WinFormsProgressSample
{
public class LengthyTask : UpdateTaskBase
{
public override bool Prepare(IUpdateSource source)
public override void Prepare(IUpdateSource source)
{
for (int i = 0; i < 50; i++)
{
Expand All @@ -26,8 +26,6 @@ public override bool Prepare(IUpdateSource source)
Percentage = 100,
StillWorking = false,
});

return true;
}

public override TaskExecutionStatus Execute(bool coldRun)
Expand Down
5 changes: 5 additions & 0 deletions src/NAppUpdate.Framework/Common/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public Logger(List<LogItem> logItems)
LogItems = logItems;
}

public void Log(string message, params object[] args)
{
Log(SeverityLevel.Debug, message, args);
}

public void Log(SeverityLevel severity, string message, params object[] args)
{
LogItems.Add(new LogItem
Expand Down
164 changes: 83 additions & 81 deletions src/NAppUpdate.Framework/Tasks/FileUpdateTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,95 +5,97 @@
namespace NAppUpdate.Framework.Tasks
{
[Serializable]
[UpdateTaskAlias("fileUpdate")]
public class FileUpdateTask : UpdateTaskBase
{
[NauField("localPath", "The local path of the file to update", true)]
public string LocalPath { get; set; }

[NauField("updateTo",
"File name on the remote location; same name as local path will be used if left blank"
, false)]
public string UpdateTo { get; set; }

[NauField("sha256-checksum", "SHA-256 checksum to validate the file after download (optional)", false)]
public string Sha256Checksum { get; set; }

[NauField("hotswap",
"Default update action is a cold update; check here if a hot file swap should be attempted"
, false)]
public bool CanHotSwap { get; set; }

private string destinationFile, backupFile, tempFile;

public override bool Prepare(Sources.IUpdateSource source)
{
if (string.IsNullOrEmpty(LocalPath))
return true; // Errorneous case, but there's nothing to prepare to...

string fileName;
if (!string.IsNullOrEmpty(UpdateTo))
fileName = UpdateTo;
else
fileName = LocalPath;

tempFile = null;

try
{
string tempFileLocal = Path.Combine(UpdateManager.Instance.Config.TempFolder, Guid.NewGuid().ToString());
if (!source.GetData(fileName, UpdateManager.Instance.BaseUrl,
OnProgress,
ref tempFileLocal))
return false;

tempFile = tempFileLocal;
}
catch (Exception ex)
{
throw new UpdateProcessFailedException("Couldn't get Data from source", ex);
}

if (!string.IsNullOrEmpty(Sha256Checksum))
{
string checksum = Utils.FileChecksum.GetSHA256Checksum(tempFile);
if (!checksum.Equals(Sha256Checksum))
return false;
}

destinationFile = Path.Combine(Path.GetDirectoryName(UpdateManager.Instance.ApplicationPath), LocalPath);

return tempFile != null;
}
[UpdateTaskAlias("fileUpdate")]
public class FileUpdateTask : UpdateTaskBase
{
[NauField("localPath", "The local path of the file to update", true)]
public string LocalPath { get; set; }

[NauField("updateTo",
"File name on the remote location; same name as local path will be used if left blank"
, false)]
public string UpdateTo { get; set; }

[NauField("sha256-checksum", "SHA-256 checksum to validate the file after download (optional)", false)]
public string Sha256Checksum { get; set; }

[NauField("hotswap",
"Default update action is a cold update; check here if a hot file swap should be attempted"
, false)]
public bool CanHotSwap { get; set; }

private string _destinationFile, _backupFile, _tempFile;

public override void Prepare(Sources.IUpdateSource source)
{
if (string.IsNullOrEmpty(LocalPath))
{
UpdateManager.Instance.Logger.Log(Logger.SeverityLevel.Warning, "FileUpdateTask: LocalPath is empty, task is a noop");
return; // Errorneous case, but there's nothing to prepare to, and by default we prefer a noop over an error
}

string fileName;
if (!string.IsNullOrEmpty(UpdateTo))
fileName = UpdateTo;
else
fileName = LocalPath;

_tempFile = null;

string baseUrl = UpdateManager.Instance.BaseUrl;
string tempFileLocal = Path.Combine(UpdateManager.Instance.Config.TempFolder, Guid.NewGuid().ToString());

UpdateManager.Instance.Logger.Log("FileUpdateTask: Downloading {0} with BaseUrl of {1} to {2}", fileName, baseUrl, tempFileLocal);

if (!source.GetData(fileName, baseUrl, OnProgress, ref tempFileLocal))
throw new UpdateProcessFailedException("FileUpdateTask: Failed to get file from source");

_tempFile = tempFileLocal;
if (_tempFile == null)
throw new UpdateProcessFailedException("FileUpdateTask: Failed to get file from source");

if (!string.IsNullOrEmpty(Sha256Checksum))
{
string checksum = Utils.FileChecksum.GetSHA256Checksum(_tempFile);
if (!checksum.Equals(Sha256Checksum))
throw new UpdateProcessFailedException(string.Format("FileUpdateTask: Checksums do not match; expected {0} but got {1}", Sha256Checksum, checksum));
}

_destinationFile = Path.Combine(Path.GetDirectoryName(UpdateManager.Instance.ApplicationPath), LocalPath);
UpdateManager.Instance.Logger.Log("FileUpdateTask: Prepared successfully; destination file: {0}", _destinationFile);
}

public override TaskExecutionStatus Execute(bool coldRun)
{
if (string.IsNullOrEmpty(LocalPath))
return TaskExecutionStatus.Successful;
{
UpdateManager.Instance.Logger.Log(Logger.SeverityLevel.Warning, "FileUpdateTask: LocalPath is empty, task is a noop");
return TaskExecutionStatus.Successful; // Errorneous case, but there's nothing to prepare to, and by default we prefer a noop over an error
}

var dirName = Path.GetDirectoryName(destinationFile);
var dirName = Path.GetDirectoryName(_destinationFile);
if (!Directory.Exists(dirName))
Utils.FileSystem.CreateDirectoryStructure(dirName, false);

// Create a backup copy if target exists
if (backupFile == null && File.Exists(destinationFile))
if (_backupFile == null && File.Exists(_destinationFile))
{
if (!Directory.Exists(Path.GetDirectoryName(Path.Combine(UpdateManager.Instance.Config.BackupFolder, LocalPath))))
Utils.FileSystem.CreateDirectoryStructure(
Path.GetDirectoryName(Path.Combine(UpdateManager.Instance.Config.BackupFolder, LocalPath)), false);
backupFile = Path.Combine(UpdateManager.Instance.Config.BackupFolder, LocalPath);
File.Copy(destinationFile, backupFile, true);
_backupFile = Path.Combine(UpdateManager.Instance.Config.BackupFolder, LocalPath);
File.Copy(_destinationFile, _backupFile, true);
}

// Only allow execution if the apply attribute was set to hot-swap, or if this is a cold run
if (CanHotSwap || coldRun)
{
try
{
if (File.Exists(destinationFile))
File.Delete(destinationFile);
File.Move(tempFile, destinationFile);
tempFile = null;
if (File.Exists(_destinationFile))
File.Delete(_destinationFile);
File.Move(_tempFile, _destinationFile);
_tempFile = null;
}
catch (Exception ex)
{
Expand All @@ -113,24 +115,24 @@ public override TaskExecutionStatus Execute(bool coldRun)
return TaskExecutionStatus.Successful;

// Otherwise, figure out what restart method to use
if (File.Exists(destinationFile) && !Utils.PermissionsCheck.HaveWritePermissionsForFileOrFolder(destinationFile))
if (File.Exists(_destinationFile) && !Utils.PermissionsCheck.HaveWritePermissionsForFileOrFolder(_destinationFile))
{
return TaskExecutionStatus.RequiresPrivilegedAppRestart;
}
return TaskExecutionStatus.RequiresAppRestart;
}

public override bool Rollback()
{
if (string.IsNullOrEmpty(destinationFile))
return true;
public override bool Rollback()
{
if (string.IsNullOrEmpty(_destinationFile))
return true;

// Copy the backup copy back to its original position
if (File.Exists(destinationFile))
File.Delete(destinationFile);
File.Copy(backupFile, destinationFile, true);
// Copy the backup copy back to its original position
if (File.Exists(_destinationFile))
File.Delete(_destinationFile);
File.Copy(_backupFile, _destinationFile, true);

return true;
}
}
return true;
}
}
}
4 changes: 2 additions & 2 deletions src/NAppUpdate.Framework/Tasks/IUpdateTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public enum TaskExecutionStatus
{
Pending,
FailedToPrepare,
Prepared,
Successful,
Failed,
RequiresAppRestart,
Expand All @@ -27,8 +28,7 @@ public interface IUpdateTask : INauFieldsHolder
/// the final trivial operations required to actually perform the update.
/// </summary>
/// <param name="source">An update source object, in case more data is required</param>
/// <returns>True if successful, false otherwise</returns>
bool Prepare(Sources.IUpdateSource source);
void Prepare(Sources.IUpdateSource source);

/// <summary>
/// Execute the update. After all preparation is done, this call should be quite a short one
Expand Down
9 changes: 4 additions & 5 deletions src/NAppUpdate.Framework/Tasks/RegistryTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ protected object ValueToSet
return null;
}
}
private object originalValue;
private object _originalValue;

public override bool Prepare(Sources.IUpdateSource source)
public override void Prepare(Sources.IUpdateSource source)
{
// No preparation required
return true;
}

public override TaskExecutionStatus Execute(bool coldRun /* unused */)
Expand All @@ -59,7 +58,7 @@ public override TaskExecutionStatus Execute(bool coldRun /* unused */)
// Get the current value and store in case we need to rollback
// This is also used to prematurely detect incorrect key and value paths
// Any exception thrown in this stage would just keep this task in Pending state
originalValue = Registry.GetValue(KeyName, KeyValueName, null);
_originalValue = Registry.GetValue(KeyName, KeyValueName, null);

try
{
Expand All @@ -76,7 +75,7 @@ public override TaskExecutionStatus Execute(bool coldRun /* unused */)

public override bool Rollback()
{
Registry.SetValue(KeyName, KeyValueName, originalValue);
Registry.SetValue(KeyName, KeyValueName, _originalValue);
return true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/NAppUpdate.Framework/Tasks/UpdateTaskBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public virtual void OnProgress(UpdateProgressInfo pi)
ProgressDelegate(pi);
}

public abstract bool Prepare(IUpdateSource source);
public abstract void Prepare(IUpdateSource source);
public abstract TaskExecutionStatus Execute(bool coldRun);
public abstract bool Rollback();
}
Expand Down
29 changes: 22 additions & 7 deletions src/NAppUpdate.Framework/UpdateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ private UpdateManager()
UpdatesToApply = new List<IUpdateTask>();
ApplicationPath = Process.GetCurrentProcess().MainModule.FileName;
UpdateFeedReader = new NauXmlFeedReader();
Logger = new Logger();
Config = new NauConfigurations
{
TempFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()),
Expand Down Expand Up @@ -80,8 +81,8 @@ public enum UpdateProcessState

public IUpdateSource UpdateSource { get; set; }
public IUpdateFeedReader UpdateFeedReader { get; set; }
private Logger _logger = new Logger();

public Logger Logger { get; private set; }

public IEnumerable<IUpdateTask> Tasks { get { return UpdatesToApply; } }

Expand Down Expand Up @@ -231,7 +232,14 @@ public void PrepareUpdates()
throw new InvalidOperationException("No updates to prepare");

if (!Directory.Exists(Config.TempFolder))
{
Logger.Log("Creating Temp directory {0}", Config.TempFolder);
Directory.CreateDirectory(Config.TempFolder);
}
else
{
Logger.Log("Using existing Temp directory {0}", Config.TempFolder);
}

foreach (var task in UpdatesToApply)
{
Expand All @@ -241,11 +249,18 @@ public void PrepareUpdates()
var t = task;
task.ProgressDelegate += status => TaskProgressCallback(status, t);

if (!task.Prepare(UpdateSource))
try
{
task.ExecutionStatus = TaskExecutionStatus.FailedToPrepare; // TODO: lose this and rely on exceptions thrown from within Prepare()
throw new UpdateProcessFailedException("Failed to prepare task: " + task.Description);
task.Prepare(UpdateSource);
}
catch (Exception ex)
{
task.ExecutionStatus = TaskExecutionStatus.FailedToPrepare;
Logger.Log(ex);
throw new UpdateProcessFailedException("Failed to prepare task: " + task.Description, ex);
}

task.ExecutionStatus = TaskExecutionStatus.Prepared;
}

State = UpdateProcessState.Prepared;
Expand Down Expand Up @@ -432,7 +447,7 @@ public void ApplyUpdates(bool relaunchApplication, bool updaterDoLogging, bool u
AppPath = ApplicationPath,
WorkingDirectory = Environment.CurrentDirectory,
RelaunchApplication = relaunchApplication,
LogItems = _logger.LogItems,
LogItems = Logger.LogItems,
};

NauIpc.ExtractUpdaterFromResource(Config.TempFolder, Instance.Config.UpdateExecutableName);
Expand Down Expand Up @@ -487,7 +502,7 @@ public void ReinstateIfRestarted()
{
Config = dto.Configs;
UpdatesToApply = dto.Tasks;
_logger = new Logger(dto.LogItems);
Logger = new Logger(dto.LogItems);
State = UpdateProcessState.AfterRestart;
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/NAppUpdate.Updater/AppStart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private static void Main()
string logFile = string.Empty;
_args = ArgumentsParser.Get();

_logger = new Logger();
_logger = UpdateManager.Instance.Logger;
_args.ParseCommandLineArgs();
if (_args.ShowConsole)
{
Expand Down Expand Up @@ -76,9 +76,9 @@ private static void Main()

if (dto.LogItems != null) // shouldn't really happen
{
dto.LogItems.AddRange(_logger.LogItems);
_logger = new Logger(dto.LogItems);
_logger.LogItems.InsertRange(0, dto.LogItems);
}
dto.LogItems = _logger.LogItems;

// Get some required environment variables
string appPath = dto.AppPath;
Expand Down Expand Up @@ -235,7 +235,7 @@ private static void Log(Exception ex)
{
_console.WriteLine("*********************************");
_console.WriteLine(" An error has occurred:");
_console.WriteLine(" " + ex.Message);
_console.WriteLine(" " + ex);
_console.WriteLine("*********************************");

_console.WriteLine();
Expand Down

0 comments on commit 96fe742

Please sign in to comment.