/// <summary> /// Runs an <see cref="IJobManager"/> with all implementations of <see cref="IJobRunner"/>. /// </summary> /// <param name="jobManager">The job manager to run.</param> /// <param name="onSimulationCompleted">Event handler which will be invoked by each job runner after it finishes running.</param> private void TestWithAllJobRunners(IJobManager jobManager, EventHandler <AllCompletedArgs> onSimulationCompleted) { IJobRunner jobRunner = new JobRunnerSync(); jobRunner.AllJobsCompleted += onSimulationCompleted; Assert.DoesNotThrow(() => jobRunner.Run(jobManager, true)); jobRunner.AllJobsCompleted -= onSimulationCompleted; jobRunner = new JobRunnerAsync(); jobRunner.AllJobsCompleted += onSimulationCompleted; Assert.DoesNotThrow(() => jobRunner.Run(jobManager, true)); jobRunner.AllJobsCompleted -= onSimulationCompleted; jobRunner = new JobRunnerMultiProcess(false); jobRunner.AllJobsCompleted += onSimulationCompleted; Assert.DoesNotThrow(() => jobRunner.Run(jobManager, true)); jobRunner.AllJobsCompleted -= onSimulationCompleted; }
/// <summary> /// Main program entry point. /// </summary> /// <param name="args"> Command line arguments</param> /// <returns> Program exit code (0 for success)</returns> public static int Main(string[] args) { int exitCode = 0; try { string fileName = null; // Extract file name from command line arguments. if (args.Length >= 1) { fileName = args[0]; } string usageMessage = "Usage: Models ApsimXFileSpec [/Recurse] [/SingleThreaded] [/RunTests] [/Csv] [/Version] [/Verbose] [/Upgrade] [/m] [/?]"; if (args.Contains("/?")) { string detailedHelpInfo = usageMessage; detailedHelpInfo += Environment.NewLine + Environment.NewLine; detailedHelpInfo += "ApsimXFileSpec: The path to an .apsimx file. May include wildcard."; detailedHelpInfo += Environment.NewLine + Environment.NewLine + "Options:" + Environment.NewLine; detailedHelpInfo += " /Recurse Recursively search subdirectories for files matching ApsimXFileSpec" + Environment.NewLine; detailedHelpInfo += " /SingleThreaded Run all simulations in a single thread." + Environment.NewLine; detailedHelpInfo += " /RunTests Run all tests." + Environment.NewLine; detailedHelpInfo += " /Csv Export all reports to .csv files." + Environment.NewLine; detailedHelpInfo += " /Version Display the version number." + Environment.NewLine; detailedHelpInfo += " /Verbose Write messages to StdOut when a simulation starts/finishes. Only has an effect when running a directory of .apsimx files (*.apsimx)." + Environment.NewLine; detailedHelpInfo += " /Upgrade Upgrades a file to the latest version of the .apsimx file format. Does not run the file." + Environment.NewLine; detailedHelpInfo += " /m Use the experimental multi-process job runner." + Environment.NewLine; detailedHelpInfo += " /? Show detailed help information."; Console.WriteLine(detailedHelpInfo); return(1); } if (args.Length < 1 || args.Length > 10) { Console.WriteLine(usageMessage); return(1); } if (args.Contains("/Version")) { Model m = new Model(); Console.WriteLine(m.ApsimVersion); return(0); } if (args.Contains("/Upgrade")) { string dir = Path.GetDirectoryName(fileName); if (string.IsNullOrWhiteSpace(dir)) { dir = Directory.GetCurrentDirectory(); } string[] files = Directory.EnumerateFiles(dir, Path.GetFileName(fileName), args.Contains("/Recurse") ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).ToArray(); foreach (string file in files) { List <Exception> errors; IModel sims = FileFormat.ReadFromFile <Model>(file, out errors); if (errors != null && errors.Count > 0) { foreach (Exception error in errors) { Console.Error.WriteLine(error.ToString()); } } File.WriteAllText(file, FileFormat.WriteToString(sims)); Console.WriteLine("Successfully upgraded " + file); } return(0); } Stopwatch timer = new Stopwatch(); timer.Start(); // If the filename argument has a wildcard then create a IJobManager to go look for matching files to run. // Otherwise, create a JobManager to open the filename and run it in a separate, external process IJobManager job; bool hasWildcard = fileName.Contains('*') || fileName.Contains('?'); if (hasWildcard) { job = Runner.ForFolder(fileName, args.Contains("/Recurse"), args.Contains("/RunTests"), args.Contains("/Verbose"), args.Contains("/m")); } else { job = Runner.ForFile(fileName, args.Contains("/RunTests")); } // Run the job created above using either a single thread or multi threaded (default) IJobRunner jobRunner; if (args.Contains("/SingleThreaded")) { jobRunner = new JobRunnerSync(); } else if (args.Contains("/m")) { // If the multi-process switch has been provided as well as a wildcard in the filename, // we want to use the single threaded job runner, but run each job in multi-process mode. // TODO : might be useful to allow users to run a directory of apsimx files via the multi- // process job runner. This could be faster if they have many small files. if (hasWildcard) { jobRunner = new JobRunnerSync(); } else { jobRunner = new JobRunnerMultiProcess(args.Contains("/Verbose")); } } else { jobRunner = new JobRunnerAsync(); } if (args.Select(arg => arg.ToLower()).Contains("/csv")) { string dir = Path.GetDirectoryName(fileName); if (dir == "") { dir = Directory.GetCurrentDirectory(); } files = Directory.GetFiles( dir, Path.GetFileName(fileName), args.Contains("/Recurse") ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).ToList(); jobRunner.AllJobsCompleted += GenerateCsvFiles; } jobRunner.JobCompleted += OnJobCompleted; jobRunner.AllJobsCompleted += OnAllJobsCompleted; jobRunner.Run(job, wait: true); // If errors occurred, write them to the console. if (errors != string.Empty) { Console.WriteLine("ERRORS FOUND!!"); Console.WriteLine(errors); exitCode = 1; } else { exitCode = 0; } timer.Stop(); Console.WriteLine("Finished running simulations. Duration " + timer.Elapsed.TotalSeconds.ToString("#.00") + " sec."); } catch (Exception err) { Console.WriteLine(err.ToString()); exitCode = 1; } return(exitCode); }