Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit 590a12cd authored by Markus Quaritsch's avatar Markus Quaritsch
Browse files

console: cancel current running jobs on ctlr-c

parent 10ead514
No related branches found
No related tags found
No related merge requests found
......@@ -14,14 +14,14 @@ using TUGraz.VectoCore.Models.Simulation.Impl;
namespace VectoConsole
{
internal static class Program
{
private static int NumLines;
private static int ProgessCounter { get; set; }
internal static class Program
{
private static int NumLines;
private static int ProgessCounter { get; set; }
private const string USAGE = @"Usage: vecto.exe [-h] [-v] FILE1.vecto [FILE2.vecto ...]";
private const string USAGE = @"Usage: vecto.exe [-h] [-v] FILE1.vecto [FILE2.vecto ...]";
private const string HELP = @"
private const string HELP = @"
Commandline Interface for Vecto.
Synopsis:
......@@ -50,173 +50,180 @@ Examples:
vecto.exe -h
";
private static int Main(string[] args)
{
try {
// on -h display help and terminate.
if (args.Contains("-h")) {
ShowVersionInformation();
Console.Write(HELP);
return 0;
}
// on -v: activate verbose console logger
var logLevel = LogLevel.Fatal;
// Fatal > Error > Warn > Info > Debug > Trace
var debugEnabled = false;
if (args.Contains("-v")) {
// display errors, warnings
logLevel = LogLevel.Warn;
debugEnabled = true;
} else if (args.Contains("-vv")) {
// also display info
logLevel = LogLevel.Info;
debugEnabled = true;
} else if (args.Contains("-vvv")) {
// display debug messages
logLevel = LogLevel.Debug;
debugEnabled = true;
} else if (args.Contains("-vvvv")) {
// display everything!
logLevel = LogLevel.Trace;
debugEnabled = true;
}
var config = LogManager.Configuration;
//config.LoggingRules.Add(new LoggingRule("*", logLevel, config.FindTargetByName("ConsoleLogger")));
config.LoggingRules.Add(new LoggingRule("*", logLevel, config.FindTargetByName("LogFile")));
LogManager.Configuration = config;
Trace.Listeners.Add(new ConsoleTraceListener(true));
if (args.Contains("-V") || debugEnabled) {
ShowVersionInformation();
}
args = args.Except(new[] { "-v", "-vv", "-vvv", "-vvvv", "-V", "-mod", "-eng", "-t" }).ToArray();
// if no other arguments given: display usage and terminate
if (!args.Any()) {
Console.Write(USAGE);
return 1;
}
var stopWatch = new Stopwatch();
var timings = new Dictionary<string, double>();
// process the file list and start simulation
var fileList = args;
var sumFileName = Path.Combine(Path.GetDirectoryName(fileList.First()) ?? "",
Path.GetFileNameWithoutExtension(fileList.First()) + Constants.FileExtensions.SumFile);
var sumWriter = new SummaryFileWriter(sumFileName);
var jobContainer = new JobContainer(sumWriter);
var mode = SimulatorFactory.FactoryMode.DeclarationMode;
if (args.Contains("-eng")) {
mode = SimulatorFactory.FactoryMode.EngineeringMode;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Switching to Engineering Mode. Make sure the job-file is saved in engineering mode!");
Console.ResetColor();
}
Console.WriteLine("Reading Job Files");
stopWatch.Start();
foreach (var file in fileList.Where(f => Path.GetExtension(f) == Constants.FileExtensions.VectoJobFile)) {
var runsFactory = new SimulatorFactory(mode, file);
if (args.Contains("-mod")) {
runsFactory.WriteModalResults = true;
}
jobContainer.AddRuns(runsFactory);
}
stopWatch.Stop();
timings.Add("Reading input files", stopWatch.Elapsed.TotalMilliseconds);
stopWatch.Reset();
Console.WriteLine("Starting simulation runs");
if (debugEnabled) {
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Debug-Output is enabled, executing simulation runs sequentially");
Console.ResetColor();
}
Console.WriteLine();
stopWatch.Start();
jobContainer.Execute(!debugEnabled);
Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) => {
var isCtrlC = e.SpecialKey == ConsoleSpecialKey.ControlC;
var isCtrlBreak = e.SpecialKey == ConsoleSpecialKey.ControlBreak;
if (isCtrlC) {
Console.WriteLine("Canceling simulation!");
}
};
//var x = Console.CursorLeft;
while (!jobContainer.AllCompleted) {
PrintProgress(jobContainer.GetProgress());
Thread.Sleep(250);
}
stopWatch.Stop();
timings.Add("Simulation runs", stopWatch.Elapsed.TotalMilliseconds);
PrintProgress(jobContainer.GetProgress(), args.Contains("-t"));
if (args.Contains("-t")) {
PrintTimings(timings);
}
} catch (Exception e) {
Console.Error.WriteLine(e.Message);
//Trace.TraceError(e.ToString());
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine("Please see log-file for further details (logs/log.txt)");
Console.ResetColor();
Environment.ExitCode = Environment.ExitCode != 0 ? Environment.ExitCode : 1;
}
return Environment.ExitCode;
}
private static void ShowVersionInformation()
{
var vectodll = AssemblyName.GetAssemblyName("VectoCore.dll");
Console.WriteLine("VectoConsole: {0}", Assembly.GetExecutingAssembly().GetName().Version);
Console.WriteLine("VectoCore: {0}", vectodll.Version);
}
private static void PrintProgress(Dictionary<string, JobContainer.ProgressEntry> progessData, bool showTiming = true)
{
Console.SetCursorPosition(0, Console.CursorTop - NumLines);
NumLines = 0;
var sumProgress = 0.0;
foreach (var progressEntry in progessData) {
if (progressEntry.Value.Success) {
Console.ForegroundColor = ConsoleColor.Green;
} else if (progressEntry.Value.Error != null) {
Console.ForegroundColor = ConsoleColor.Red;
}
var timingString = "";
if (showTiming && progressEntry.Value.ExecTime > 0) {
timingString = string.Format("{0,9:F2}s", progressEntry.Value.ExecTime / 1000.0);
}
Console.WriteLine("{0,-60} {1,8:P}{2}", progressEntry.Key, progressEntry.Value.Progress, timingString);
Console.ResetColor();
sumProgress += progressEntry.Value.Progress;
NumLines++;
}
sumProgress /= NumLines;
var spinner = "/-\\|"[ProgessCounter++ % 4];
var bar = new string('#', (int)(sumProgress * 100.0 / 2));
Console.WriteLine(string.Format(" {2} [{1,-50}] [{0,7:P}]", sumProgress, bar, spinner));
NumLines++;
}
private static void PrintTimings(Dictionary<string, double> timings)
{
Console.WriteLine();
Console.WriteLine("---- timing information ----");
foreach (var timing in timings) {
Console.WriteLine("{0,-20}: {1:F2}s", timing.Key, timing.Value / 1000);
}
}
}
private static JobContainer jobContainer;
private static int Main(string[] args)
{
try {
// on -h display help and terminate.
if (args.Contains("-h")) {
ShowVersionInformation();
Console.Write(HELP);
return 0;
}
// on -v: activate verbose console logger
var logLevel = LogLevel.Fatal;
// Fatal > Error > Warn > Info > Debug > Trace
var debugEnabled = false;
if (args.Contains("-v")) {
// display errors, warnings
logLevel = LogLevel.Warn;
debugEnabled = true;
} else if (args.Contains("-vv")) {
// also display info
logLevel = LogLevel.Info;
debugEnabled = true;
} else if (args.Contains("-vvv")) {
// display debug messages
logLevel = LogLevel.Debug;
debugEnabled = true;
} else if (args.Contains("-vvvv")) {
// display everything!
logLevel = LogLevel.Trace;
debugEnabled = true;
}
var config = LogManager.Configuration;
//config.LoggingRules.Add(new LoggingRule("*", logLevel, config.FindTargetByName("ConsoleLogger")));
config.LoggingRules.Add(new LoggingRule("*", logLevel, config.FindTargetByName("LogFile")));
LogManager.Configuration = config;
Trace.Listeners.Add(new ConsoleTraceListener(true));
if (args.Contains("-V") || debugEnabled) {
ShowVersionInformation();
}
args = args.Except(new[] { "-v", "-vv", "-vvv", "-vvvv", "-V", "-mod", "-eng", "-t" }).ToArray();
// if no other arguments given: display usage and terminate
if (!args.Any()) {
Console.Write(USAGE);
return 1;
}
var stopWatch = new Stopwatch();
var timings = new Dictionary<string, double>();
// process the file list and start simulation
var fileList = args;
var sumFileName = Path.Combine(Path.GetDirectoryName(fileList.First()) ?? "",
Path.GetFileNameWithoutExtension(fileList.First()) + Constants.FileExtensions.SumFile);
var sumWriter = new SummaryFileWriter(sumFileName);
jobContainer = new JobContainer(sumWriter);
var mode = SimulatorFactory.FactoryMode.DeclarationMode;
if (args.Contains("-eng")) {
mode = SimulatorFactory.FactoryMode.EngineeringMode;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(
"Switching to Engineering Mode. Make sure the job-file is saved in engineering mode!");
Console.ResetColor();
}
Console.WriteLine("Reading Job Files");
stopWatch.Start();
foreach (var file in fileList.Where(f => Path.GetExtension(f) == Constants.FileExtensions.VectoJobFile)) {
var runsFactory = new SimulatorFactory(mode, file);
if (args.Contains("-mod")) {
runsFactory.WriteModalResults = true;
}
jobContainer.AddRuns(runsFactory);
}
stopWatch.Stop();
timings.Add("Reading input files", stopWatch.Elapsed.TotalMilliseconds);
stopWatch.Reset();
Console.WriteLine("Starting simulation runs");
if (debugEnabled) {
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Debug-Output is enabled, executing simulation runs sequentially");
Console.ResetColor();
}
Console.WriteLine();
stopWatch.Start();
jobContainer.Execute(!debugEnabled);
Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) => {
var isCtrlC = e.SpecialKey == ConsoleSpecialKey.ControlC;
var isCtrlBreak = e.SpecialKey == ConsoleSpecialKey.ControlBreak;
if (!isCtrlC) {
return;
}
//Console.WriteLine("Canceling simulation!");
e.Cancel = true;
Program.jobContainer.CancelCurrent();
};
//var x = Console.CursorLeft;
while (!jobContainer.AllCompleted) {
PrintProgress(jobContainer.GetProgress());
Thread.Sleep(250);
}
stopWatch.Stop();
timings.Add("Simulation runs", stopWatch.Elapsed.TotalMilliseconds);
PrintProgress(jobContainer.GetProgress(), args.Contains("-t"));
if (args.Contains("-t")) {
PrintTimings(timings);
}
} catch (Exception e) {
Console.Error.WriteLine(e.Message);
//Trace.TraceError(e.ToString());
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine("Please see log-file for further details (logs/log.txt)");
Console.ResetColor();
Environment.ExitCode = Environment.ExitCode != 0 ? Environment.ExitCode : 1;
}
return Environment.ExitCode;
}
private static void ShowVersionInformation()
{
var vectodll = AssemblyName.GetAssemblyName("VectoCore.dll");
Console.WriteLine("VectoConsole: {0}", Assembly.GetExecutingAssembly().GetName().Version);
Console.WriteLine("VectoCore: {0}", vectodll.Version);
}
private static void PrintProgress(Dictionary<string, JobContainer.ProgressEntry> progessData,
bool showTiming = true)
{
Console.SetCursorPosition(0, Console.CursorTop - NumLines);
NumLines = 0;
var sumProgress = 0.0;
foreach (var progressEntry in progessData) {
if (progressEntry.Value.Success) {
Console.ForegroundColor = ConsoleColor.Green;
} else if (progressEntry.Value.Error != null) {
Console.ForegroundColor = ConsoleColor.Red;
}
var timingString = "";
if (showTiming && progressEntry.Value.ExecTime > 0) {
timingString = string.Format("{0,9:F2}s", progressEntry.Value.ExecTime / 1000.0);
}
Console.WriteLine("{0,-60} {1,8:P}{2}", progressEntry.Key, progressEntry.Value.Progress, timingString);
Console.ResetColor();
sumProgress += progressEntry.Value.Progress;
NumLines++;
}
sumProgress /= NumLines;
var spinner = "/-\\|"[ProgessCounter++ % 4];
var bar = new string('#', (int)(sumProgress * 100.0 / 2));
Console.WriteLine(string.Format(" {2} [{1,-50}] [{0,7:P}]", sumProgress, bar, spinner));
NumLines++;
}
private static void PrintTimings(Dictionary<string, double> timings)
{
Console.WriteLine();
Console.WriteLine("---- timing information ----");
foreach (var timing in timings) {
Console.WriteLine("{0,-20}: {1:F2}s", timing.Key, timing.Value / 1000);
}
}
}
}
\ No newline at end of file
......@@ -8,182 +8,191 @@ using TUGraz.VectoCore.Models.Simulation.Data;
namespace TUGraz.VectoCore.Models.Simulation.Impl
{
/// <summary>
/// Container for simulation jobs.
/// </summary>
public class JobContainer : LoggingObject
{
internal readonly List<JobEntry> Runs = new List<JobEntry>();
private readonly SummaryFileWriter _sumWriter;
private static int _jobNumber;
/// <summary>
/// Initializes a new empty instance of the <see cref="JobContainer"/> class.
/// </summary>
/// <param name="sumWriter">The sum writer.</param>
public JobContainer(SummaryFileWriter sumWriter)
{
_sumWriter = sumWriter;
}
public void AddRun(IVectoRun run)
{
_jobNumber++;
Runs.Add(new JobEntry() {
Run = run,
Container = this,
});
}
public void AddRuns(IEnumerable<IVectoRun> runs)
{
_jobNumber++;
//Runs.AddRange(runs);
foreach (var run in runs) {
Runs.Add(new JobEntry() {
Run = run,
Container = this,
});
}
}
public void AddRuns(SimulatorFactory factory)
{
factory.SumWriter = _sumWriter;
factory.JobNumber = _jobNumber++;
AddRuns(factory.SimulationRuns());
}
/// <summary>
/// Execute all runs, waits until finished.
/// </summary>
public void Execute(bool multithreaded = true)
{
Log.Info("VectoRun started running. Executing Runs.");
foreach (var job in Runs) {
job.Worker = new BackgroundWorker() {
WorkerSupportsCancellation = true,
WorkerReportsProgress = true,
};
job.Worker.DoWork += job.DoWork;
job.Worker.ProgressChanged += job.ProgressChanged;
job.Worker.RunWorkerCompleted += job.RunWorkerCompleted;
if (multithreaded) {
job.Started = true;
job.Worker.RunWorkerAsync();
}
}
if (!multithreaded) {
var entry = Runs.First();
entry.Started = true;
entry.Worker.RunWorkerAsync();
}
//Task.WaitAll(_runs.Select(r => Task.Factory.StartNew(r.Run)).ToArray());
_sumWriter.Finish();
}
public void Cancel()
{
foreach (var job in Runs) {
if (job.Worker != null && job.Worker.WorkerSupportsCancellation) {
job.Worker.CancelAsync();
}
}
}
private static AutoResetEvent resetEvent = new AutoResetEvent(false);
public void WaitFinished()
{
resetEvent.WaitOne();
}
private void JobCompleted(JobEntry jobEntry)
{
var next = Runs.FirstOrDefault(x => x.Started == false);
if (next != null) {
next.Started = true;
next.Worker.RunWorkerAsync();
}
if (Runs.Count(x => x.Done == true) == Runs.Count()) {
_sumWriter.Finish();
resetEvent.Set();
}
}
public Dictionary<string, ProgressEntry> GetProgress()
{
return Runs.ToDictionary(jobEntry => jobEntry.Run.Name, entry => new ProgressEntry() {
Progress = entry.Progress,
Done = entry.Done,
ExecTime = entry.ExecTime,
Success = entry.Success,
Canceled = entry.Canceled,
Error = entry.ExecException
});
}
public bool AllCompleted
{
get { return (Runs.Count(x => x.Done == true) == Runs.Count()); }
}
public class ProgressEntry
{
public double Progress;
public double ExecTime;
public Exception Error;
public bool Canceled;
public bool Success;
public bool Done;
}
internal class JobEntry : LoggingObject
{
public IVectoRun Run;
public JobContainer Container;
public double Progress;
public bool Done;
public bool Started;
public bool Success;
public bool Canceled;
public double ExecTime;
public Exception ExecException;
public BackgroundWorker Worker;
public void DoWork(object sender, DoWorkEventArgs e)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
var worker = sender as BackgroundWorker;
try {
Run.Run(worker);
} catch (Exception ex) {
Log.Error(ex, "Error during simulation run!");
ExecException = ex;
}
if (worker != null && worker.CancellationPending) {
e.Cancel = true;
Canceled = true;
}
stopWatch.Stop();
Success = Run.FinishedWithoutErrors;
Done = true;
ExecTime = stopWatch.Elapsed.TotalMilliseconds;
Container.JobCompleted(this);
}
public void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {}
public void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Progress = e.ProgressPercentage / 10000.0;
}
}
}
/// <summary>
/// Container for simulation jobs.
/// </summary>
public class JobContainer : LoggingObject
{
internal readonly List<JobEntry> Runs = new List<JobEntry>();
private readonly SummaryFileWriter _sumWriter;
private static int _jobNumber;
/// <summary>
/// Initializes a new empty instance of the <see cref="JobContainer"/> class.
/// </summary>
/// <param name="sumWriter">The sum writer.</param>
public JobContainer(SummaryFileWriter sumWriter)
{
_sumWriter = sumWriter;
}
public void AddRun(IVectoRun run)
{
_jobNumber++;
Runs.Add(new JobEntry() {
Run = run,
Container = this,
});
}
public void AddRuns(IEnumerable<IVectoRun> runs)
{
_jobNumber++;
//Runs.AddRange(runs);
foreach (var run in runs) {
Runs.Add(new JobEntry() {
Run = run,
Container = this,
});
}
}
public void AddRuns(SimulatorFactory factory)
{
factory.SumWriter = _sumWriter;
factory.JobNumber = _jobNumber++;
AddRuns(factory.SimulationRuns());
}
/// <summary>
/// Execute all runs, waits until finished.
/// </summary>
public void Execute(bool multithreaded = true)
{
Log.Info("VectoRun started running. Executing Runs.");
foreach (var job in Runs) {
job.Worker = new BackgroundWorker() {
WorkerSupportsCancellation = true,
WorkerReportsProgress = true,
};
job.Worker.DoWork += job.DoWork;
job.Worker.ProgressChanged += job.ProgressChanged;
job.Worker.RunWorkerCompleted += job.RunWorkerCompleted;
if (multithreaded) {
job.Started = true;
job.Worker.RunWorkerAsync();
}
}
if (!multithreaded) {
var entry = Runs.First();
entry.Started = true;
entry.Worker.RunWorkerAsync();
}
//Task.WaitAll(_runs.Select(r => Task.Factory.StartNew(r.Run)).ToArray());
_sumWriter.Finish();
}
public void Cancel()
{
foreach (var job in Runs) {
if (job.Worker != null && job.Worker.WorkerSupportsCancellation) {
job.Worker.CancelAsync();
}
}
}
public void CancelCurrent()
{
foreach (var job in Runs) {
if (job.Worker != null && job.Worker.IsBusy && job.Worker.WorkerSupportsCancellation) {
job.Worker.CancelAsync();
}
}
}
private static AutoResetEvent resetEvent = new AutoResetEvent(false);
public void WaitFinished()
{
resetEvent.WaitOne();
}
private void JobCompleted(JobEntry jobEntry)
{
var next = Runs.FirstOrDefault(x => x.Started == false);
if (next != null) {
next.Started = true;
next.Worker.RunWorkerAsync();
}
if (Runs.Count(x => x.Done == true) == Runs.Count()) {
_sumWriter.Finish();
resetEvent.Set();
}
}
public Dictionary<string, ProgressEntry> GetProgress()
{
return Runs.ToDictionary(jobEntry => jobEntry.Run.Name, entry => new ProgressEntry() {
Progress = entry.Progress,
Done = entry.Done,
ExecTime = entry.ExecTime,
Success = entry.Success,
Canceled = entry.Canceled,
Error = entry.ExecException
});
}
public bool AllCompleted
{
get { return (Runs.Count(x => x.Done == true) == Runs.Count()); }
}
public class ProgressEntry
{
public double Progress;
public double ExecTime;
public Exception Error;
public bool Canceled;
public bool Success;
public bool Done;
}
internal class JobEntry : LoggingObject
{
public IVectoRun Run;
public JobContainer Container;
public double Progress;
public bool Done;
public bool Started;
public bool Success;
public bool Canceled;
public double ExecTime;
public Exception ExecException;
public BackgroundWorker Worker;
public void DoWork(object sender, DoWorkEventArgs e)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
var worker = sender as BackgroundWorker;
try {
Run.Run(worker);
} catch (Exception ex) {
Log.Error(ex, "Error during simulation run!");
ExecException = ex;
}
if (worker != null && worker.CancellationPending) {
e.Cancel = true;
Canceled = true;
}
stopWatch.Stop();
Success = Run.FinishedWithoutErrors;
Done = true;
ExecTime = stopWatch.Elapsed.TotalMilliseconds;
Container.JobCompleted(this);
}
public void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {}
public void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Progress = e.ProgressPercentage / 10000.0;
}
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment