JD2022-TU1/main/tools/apps/Packager/Builder.cs

165 lines
No EOL
5.1 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Runtime.ExceptionServices;
using JD.Core.ProjectManaging;
using Packager.BuildConfigurations;
using Packager.Parameters;
using Packager.Tasks;
using LogCategory = JD.LogService.LogCategory;
namespace Packager
{
/// <summary>
/// Builder takes in the build configuration's tasklist and executes each task in the list sequentially.
/// </summary>
public class Builder : IDisposable
{
private readonly TaskList _buildTasks;
private readonly BuildConfiguration _buildProfile;
private engineWrapper _engine;
private cookerWrapper _cooker;
private readonly bool _stopOnErrors;
private bool _exit;
public MessageLogger Logger { get; } = new MessageLogger(nameof(Builder));
public Builder(BuildConfiguration profile, bool stopOnErrors)
{
_buildProfile = profile;
_buildTasks = _buildProfile.Tasks;
_stopOnErrors = stopOnErrors;
}
public void BuildTaskList(int startTask = 0)
{
var taskNameString = string.Join(";", _buildTasks.Select(task => task.InstanceName));
Logger.LogInfo("[Tasklist]" + taskNameString);
foreach (var task in _buildTasks.Skip(startTask))
{
if (_exit)
{
Logger.LogTaskMessage(task, "Aborting the build as StopOnError is on", LogCategory.Error);
break;
}
Logger.LogInfo($"{task.InstanceName} task was created, its log file can be found at \"{task.Logger.LogFilePath}\".");
ExecuteCurrentTask(task);
CheckTaskErrors(task);
TaskFinishCleanUp(task);
}
}
[HandleProcessCorruptedStateExceptions]
private void ExecuteCurrentTask(Task task)
{
try
{
string outputPath = task.TaskOutputFolder;
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
Logger.LogStartedTask(task);
TaskUtility.ValidateTaskInput(task);
if (task.NeedCooker)
{
_engine = new engineWrapper("Packager");
_cooker = new cookerWrapper();
_cooker.init(DataPath.Value);
Logger.AttachCookerWrapper(_cooker);
}
task.Start(_buildProfile, _cooker);
}
catch (AccessViolationException ex)
{
HandleAccessViolationError(task, ex);
}
catch (Exception ex)
{
HandleLaunchError(task, ex);
}
}
private void CheckTaskErrors(Task task)
{
if (task.ErrorCode == 0)
{
return;
}
Logger.LogTaskMessage(task, $"Returns error {task.ErrorCode}", LogCategory.Error);
CheckToStopExecution();
}
private void HandleLaunchError(Task task, Exception ex)
{
var message = $"When launching the task \"{task.InstanceName}\": {ex.Message}. Details: {ex}";
Logger.LogTaskMessage(task, message, ex is EmptyInputException ? LogCategory.Warning : LogCategory.Error);
CheckToStopExecution();
}
private void HandleAccessViolationError(Task task, Exception ex)
{
var message = $"Access Violation Exception when launching the task \"{task.InstanceName}\". If this error occurs in ITF.EngineSignature.computeEngineSignature(), please check with the engine and ggp teams if changes were made in serializable classes. Please check {Logger.LogFilePath} for the stacktrace. Details: {ex}";
Logger.LogTaskMessage(task, message, LogCategory.Error);
//Force stop execution because an access violation error is not recoverable
_exit = true;
}
private void CheckToStopExecution()
{
if (_stopOnErrors)
{
_exit = true;
}
}
public void TaskFinishCleanUp(Task task)
{
if (_cooker != null)
{
Logger.DetachCookerWrapper(_cooker);
_cooker.destroy();
_cooker = null;
}
if (_engine != null)
{
_engine.destroy();
_engine = null;
}
SaveTaskOutput(task);
Logger.LogEndedTask(task);
}
private void SaveTaskOutput(Task task)
{
try
{
task.SaveOutputs(task.TaskOutputFile);
}
catch (Exception ex)
{
Logger.LogTaskMessage(task, $"Error while saving the task outputs: {ex.Message}", LogCategory.Error);
}
}
public void Dispose()
{
_cooker?.Dispose();
}
}
}