Example #1
0
        /// <summary>
        /// Starts the execution of an R script.
        /// </summary>
        /// <param name="fileName">Path to an R script. May be a file on disk, or an embedded resource.</param>
        /// <param name="arguments">Command line arguments to pass to the script.</param>
        public void RunAsync(string fileName, params string[] arguments)
        {
            string scriptName = fileName;

            if (!File.Exists(scriptName) && Assembly.GetExecutingAssembly().GetManifestResourceInfo(scriptName) != null)
            {
                // If the file doesn't exist, we check the list of resources.
                string script = string.Empty;
                using (Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(scriptName))
                    using (StreamReader reader = new StreamReader(s))
                        script = reader.ReadToEnd();
                scriptName = Path.ChangeExtension(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()), ".r");
                File.WriteAllText(scriptName, script);
            }

            // Each command line argument must be quoted in case it contains spaces.
            string args = "";

            if (arguments.Length > 0)
            {
                args = arguments.Aggregate((x, y) => $"\"{x}\" \"{y}\"");
            }

            proc         = new ProcessUtilities.ProcessWithRedirectedOutput();
            proc.Exited += OnExited;
            proc.Start(rScript, "\"" + scriptName + "\" " + args, workingDirectory, true);
        }
        /// <summary>
        /// Main task thread for working with a single APSIMRunner.exe process using
        /// an anonymous pipe.
        /// </summary>
        private void PipeServerTaskThread()
        {
            // Create 2 anonymous pipes (read and write) for duplex communications
            // (each pipe is one-way)
            using (var pipeRead = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
                using (var pipeWrite = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
                {
                    var pipeHandles = pipeRead.GetClientHandleAsString() + " " + pipeWrite.GetClientHandleAsString();

                    // Run a APSIMRunner process passing the pipe read and write handles as arguments.
                    var runnerProcess = new ProcessUtilities.ProcessWithRedirectedOutput();
                    runnerProcess.Exited += OnExited;
                    var runnerExecutable = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "APSIMRunner.exe");
                    runnerProcess.Start(executable: runnerExecutable,
                                        arguments: pipeHandles,
                                        workingDirectory: Directory.GetCurrentDirectory(),
                                        redirectOutput: true,
                                        writeToConsole: false);

                    // Release the local handles that were created with the above GetClientHandleAsString calls
                    pipeRead.DisposeLocalCopyOfClientHandle();
                    pipeWrite.DisposeLocalCopyOfClientHandle();

                    try
                    {
                        // Get the next job to run.
                        var job = GetJobToRun();

                        while (job != null)
                        {
                            var startTime = DateTime.Now;

                            // Send the job to APSIMRunner.exe - this will run the simulation.
                            PipeUtilities.SendObjectToPipe(pipeWrite, job.JobSentToClient);

                            pipeWrite.WaitForPipeDrain();

                            // Get the output data back from APSIMRunner.exe
                            var endJob = PipeUtilities.GetObjectFromPipe(pipeRead) as JobOutput;

                            // Send the output data to storage.
                            endJob.WriteOutput(job.DataStore);

                            // Signal end of job.
                            InvokeJobCompleted(job.RunnableJob,
                                               job.JobManager,
                                               startTime,
                                               endJob.ErrorMessage);

                            // Get the next job to run.
                            job = GetJobToRun();
                        }
                    }
                    catch (Exception err)
                    {
                        AddException(err);
                    }
                }
        }
Example #3
0
 /// <summary>
 /// Gets the path to an executable (uses the Unix which utility).
 /// Throws if the package does not exist. Obviously this will not
 /// work on Windows.
 /// </summary>
 private string GetPathToPackage(string package)
 {
     ProcessUtilities.ProcessWithRedirectedOutput findR = new ProcessUtilities.ProcessWithRedirectedOutput();
     findR.Start("/usr/bin/which", package, Path.GetTempPath(), true);
     findR.WaitForExit();
     if (string.IsNullOrEmpty(findR.StdOut) && !string.IsNullOrEmpty(findR.StdErr))
     {
         // If the shell command generated anything in StdErr, we display that message.
         throw new Exception("Encountered an error while searching for " + package + " installation: " + findR.StdErr);
     }
     return(findR.StdOut);
 }
Example #4
0
        /// <summary>A runner process has exited. Check for errors</summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event arguments</param>
        private void OnExited(object sender, EventArgs e)
        {
            ProcessUtilities.ProcessWithRedirectedOutput p = sender as ProcessUtilities.ProcessWithRedirectedOutput;
            if (p.ExitCode != 0)
            {
                errors += p.StdOut + Environment.NewLine;
            }

            if (Process.GetProcessesByName("APSIMRunner").Length == 0)
            {
                Stop();
            }
        }
Example #5
0
        /// <summary>Create one job runner process for each CPU</summary>
        /// <param name="numberOfProcessors">The maximum number of cores to use</param>
        private void CreateRunners(int numberOfProcessors)
        {
            int numRunners = Process.GetProcessesByName("APSIMRunner").Length;

            for (int i = numRunners; i < numberOfProcessors; i++)
            {
                string workingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                string runnerFileName   = Path.Combine(workingDirectory, "APSIMRunner.exe");
                ProcessUtilities.ProcessWithRedirectedOutput runnerProcess = new ProcessUtilities.ProcessWithRedirectedOutput();
                runnerProcess.Exited += OnExited;
                runnerProcess.Start(runnerFileName, null, workingDirectory, false);
            }
        }
        /// <summary>A runner process has exited. Check for errors</summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event arguments</param>
        private void OnExited(object sender, EventArgs e)
        {
            ProcessUtilities.ProcessWithRedirectedOutput p = sender as ProcessUtilities.ProcessWithRedirectedOutput;
            if (p.ExitCode != 0)
            {
                var exception = new Exception(p.StdOut + Environment.NewLine + p.StdErr);
                AddException(exception);
            }

            if (Process.GetProcessesByName("APSIMRunner").Length == 0)
            {
                allStopped = true;
            }
        }
Example #7
0
        public static string RunModels(string arguments)
        {
            string pathToModels = typeof(IModel).Assembly.Location;

            ProcessUtilities.ProcessWithRedirectedOutput proc = new ProcessUtilities.ProcessWithRedirectedOutput();
            proc.Start(pathToModels, arguments, Path.GetTempPath(), true);
            proc.WaitForExit();

            if (proc.ExitCode != 0)
            {
                throw new Exception(proc.StdOut);
            }

            return(proc.StdOut);
        }
Example #8
0
        public void OnCreatedShouldFailRun()
        {
            string json     = ReflectionUtilities.GetResourceAsString("UnitTests.Core.ApsimFile.OnCreatedError.apsimx");
            string fileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".apsimx");

            File.WriteAllText(fileName, json);

            Assembly models    = typeof(IModel).Assembly;
            string   modelsExe = AppDomain.CurrentDomain.GetAssemblies().First(a => string.Equals(a.FullName, models.FullName, StringComparison.Ordinal)).Location;

            var proc = new ProcessUtilities.ProcessWithRedirectedOutput();

            proc.Start(modelsExe, fileName, Path.GetTempPath(), true);
            proc.WaitForExit();

            Assert.AreNotEqual(0, proc.ExitCode, "A file ran without error when an exception should have been thrown while opening the file.");
        }
Example #9
0
        /// <summary>
        /// Starts the execution of an R script.
        /// </summary>
        /// <param name="fileName">Path to an R script.</param>
        public void RunAsync(string fileName)
        {
            if (File.Exists(fileName))
            {
                string rScript = GetRExePath();
                // Create a temporary working directory.
                workingDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
                if (!Directory.Exists(workingDirectory)) // I would be very suprised if it did already exist
                {
                    Directory.CreateDirectory(workingDirectory);
                }

                proc         = new ProcessUtilities.ProcessWithRedirectedOutput();
                proc.Exited += OnExited;
                proc.Start(rScript, fileName + " ", workingDirectory, true);
            }
        }
Example #10
0
        /// <summary>
        /// Starts the execution of an R script.
        /// </summary>
        /// <param name="fileName">Path to an R script. May be a file on disk, or an embedded resource.</param>
        /// <param name="arguments">Command line arguments to pass to the script.</param>
        public void RunAsync(string fileName, string arguments = "")
        {
            string scriptName = fileName;

            if (!File.Exists(scriptName) && Assembly.GetExecutingAssembly().GetManifestResourceInfo(scriptName) != null)
            {
                // If the file doesn't exist, we check the list of resources.
                string script = string.Empty;
                using (Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(scriptName))
                    using (StreamReader reader = new StreamReader(s))
                        script = reader.ReadToEnd();
                scriptName = Path.ChangeExtension(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()), ".r");
                File.WriteAllText(scriptName, script);
            }

            proc         = new ProcessUtilities.ProcessWithRedirectedOutput();
            proc.Exited += OnExited;
            proc.Start(rScript, "\"" + scriptName + "\" " + arguments, workingDirectory, true);
        }
Example #11
0
        /// <summary>
        /// Starts the execution of an R script.
        /// </summary>
        /// <param name="fileName">Path to an R script. May be a file on disk, or an embedded resource.</param>
        /// <param name="arguments">Command line arguments to pass to the script.</param>
        public void RunAsync(string fileName, params string[] arguments)
        {
            string scriptName = fileName;

            if (!File.Exists(scriptName) && Assembly.GetExecutingAssembly().GetManifestResourceInfo(scriptName) != null)
            {
                // If the file doesn't exist, we check the list of resources.
                string script = string.Empty;
                using (Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(scriptName))
                    using (StreamReader reader = new StreamReader(s))
                        script = reader.ReadToEnd();
                scriptName = Path.ChangeExtension(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()), ".r");
                File.WriteAllText(scriptName, script);
            }

            // Each command line argument must be quoted in case it contains spaces.
            string args = "";

            if (arguments.Length > 0)
            {
                args = arguments.Aggregate((x, y) => $"\"{x}\" \"{y}\"");
            }

            // Don't load the user's .RProfile. Load a custom APSIM-specific
            // one instead, by setting the R_PROFILE_USER environment variable.
            Dictionary <string, string> environment = new Dictionary <string, string>();

            environment["R_PROFILE_USER"] = startupFile;

            proc         = new ProcessUtilities.ProcessWithRedirectedOutput();
            proc.Exited += OnExited;

            if (OutputReceived != null)
            {
                proc.OutputReceived += OutputReceived;
            }
            if (ErrorReceived != null)
            {
                proc.ErrorReceived += ErrorReceived;
            }

            proc.Start(rScript, "\"" + scriptName + "\" " + args, workingDirectory, true, cancelToken, environment: environment);
        }
Example #12
0
        /// <summary>
        /// Runs the R installer.
        /// </summary>
        /// <param name="installerPath">Path to the installer.</param>
        private void InstallR(string installerPath)
        {
            if (installerPath == null)
            {
                return;
            }

            // Setup a working directory.
            string workingDirectory = Path.Combine(Path.GetTempPath(), "RSetup");

            if (!Directory.Exists(workingDirectory))
            {
                Directory.CreateDirectory(workingDirectory);
            }

            // Copy installer to working directory.
            try
            {
                string newInstallerPath = Path.Combine(workingDirectory, Path.GetFileNameWithoutExtension(installerPath));
                File.Copy(installerPath, newInstallerPath);
                installerPath = newInstallerPath;
            }
            catch
            {
            }
            // Check to see if installer is already running for whatever reason.
            // Kill them if found.
            foreach (var process in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(installerPath)))
            {
                process.Kill();
            }

            // Run the installer.
            var installer = new ProcessUtilities.ProcessWithRedirectedOutput();

            installer.Start(installerPath, "", workingDirectory, false);
            installer.WaitForExit();
        }
Example #13
0
        public void TestEditing()
        {
            string configFile = Path.GetTempFileName();

            File.WriteAllLines(configFile, new[]
            {
                // Modify an array
                "[Report].VariableNames = x,y,z",

                // Modify a date - try a few different formats.
                "[Clock].StartDate = 2000-01-01",
                "[Clock].EndDate = 2000-01-10T00:00:00",

                // Modify a string
                "[Weather].FileName = fdsa.met",
                @"[Weather2].FullFileName = .\jkl.met",

                // Replace a model with a model from another file.
                $"[Weather3] = {extFile}",
                $"[Weather4] = {extFile};[w2]",

                // Change a property of a resource model.
                "[Wheat].Leaf.Photosynthesis.RUE.FixedValue = 0.4",

                // Change a property of a manager script.
                "[Manager].Script.Amount = 1234",

                // Set an entire array.
                "[Physical].BD = 1, 2, 3, 4, 5",

                // Modify a single element of an array.
                "[Physical].AirDry[2] = 6",

                // Modify multiple elements of an array.
                "[Physical].LL15[3:4] = 7",
            });

            string models = typeof(IModel).Assembly.Location;
            string args   = $"{fileName} /Edit {configFile}";

            var proc = new ProcessUtilities.ProcessWithRedirectedOutput();

            proc.Start(models, args, Path.GetTempPath(), true, writeToConsole: true);
            proc.WaitForExit();

            // Children of simulation are, in order:
            // Clock, summary, zone, Weather, Weather2, w1, w2
            Assert.AreEqual(null, proc.StdOut);
            Assert.AreEqual(null, proc.StdErr);

            Simulations file = FileFormat.ReadFromFile <Simulations>(fileName, out List <Exception> errors);

            if (errors != null && errors.Count > 0)
            {
                throw errors[0];
            }

            var report = Apsim.Find(file, typeof(Models.Report)) as Models.Report;

            string[] variableNames = new[] { "x", "y", "z" };
            Assert.AreEqual(variableNames, report.VariableNames);

            IModel sim = Apsim.Child(file, typeof(Simulation));

            // Use an index-based lookup to locate child models.
            // When we replace an entire model, we want to ensure
            // that the replacement is inserted at the correct index.

            Clock clock = sim.Children[0] as Clock;

            Assert.AreEqual(new DateTime(2000, 1, 1), clock.StartDate);
            Assert.AreEqual(new DateTime(2000, 1, 10), clock.EndDate);

            var weather = sim.Children[3] as Models.Weather;

            Assert.NotNull(weather);
            Assert.AreEqual("Weather", weather.Name);
            Assert.AreEqual("fdsa.met", weather.FileName);

            var weather2 = sim.Children[4] as Models.Weather;

            Assert.NotNull(weather2);
            Assert.AreEqual("Weather2", weather2.Name);
            Assert.AreEqual(@".\jkl.met", weather2.FileName);

            // Weather3 and Weather4 should have been
            // renamed to w1 and w2, respectively.
            var weather3 = sim.Children[5] as Models.Weather;

            Assert.NotNull(weather3);
            Assert.AreEqual("w1", weather3.Name);
            Assert.AreEqual("w1.met", weather3.FileName);

            var weather4 = sim.Children[6] as Models.Weather;

            Assert.NotNull(weather4);
            Assert.AreEqual("w2", weather4.Name);
            Assert.AreEqual("w2.met", weather4.FileName);

            // The edit file operation should have changed RUE value to 0.4.
            var wheat = sim.Children[2].Children[2] as Plant;
            var rue   = wheat.Children[6].Children[5].Children[0] as Constant;

            Assert.AreEqual(0.4, rue.FixedValue);

            double amount = (double)Apsim.Get(sim, "[Manager].Script.Amount");

            Assert.AreEqual(1234, amount);

            Physical physical = sim.Children[2].Children[4] as Physical;

            Assert.AreEqual(new double[5] {
                1, 2, 3, 4, 5
            }, physical.BD);
            Assert.AreEqual(new double[5] {
                0, 6, 0, 0, 0
            }, physical.AirDry);
            Assert.AreEqual(new double[5] {
                0, 0, 7, 7, 0
            }, physical.LL15);
        }
Example #14
0
        public void TestSimNameRegex()
        {
            string models = typeof(IModel).Assembly.Location;
            IModel sim1   = Utilities.GetRunnableSim().Children[1];

            sim1.Name = "sim1";

            IModel sim2 = Utilities.GetRunnableSim().Children[1];

            sim2.Name = "sim2";

            IModel sim3 = Utilities.GetRunnableSim().Children[1];

            sim3.Name = "simulation3";

            IModel sim4 = Utilities.GetRunnableSim().Children[1];

            sim4.Name = "Base";

            Simulations sims = Simulations.Create(new[] { sim1, sim2, sim3, sim4, new DataStore() });

            sims.ParentAllDescendants();

            string apsimxFileName = Path.ChangeExtension(Path.GetTempFileName(), ".apsimx");

            sims.Write(apsimxFileName);

            // Need to quote the regex on unix systems.
            string args;

            if (ProcessUtilities.CurrentOS.IsWindows)
            {
                args = $@"{apsimxFileName} /Verbose /SimulationNameRegexPattern:sim\d";
            }
            else
            {
                args = $@"{apsimxFileName} /Verbose '/SimulationNameRegexPattern:sim\d'";
            }

            ProcessUtilities.ProcessWithRedirectedOutput proc = new ProcessUtilities.ProcessWithRedirectedOutput();
            proc.Start(models, args, Directory.GetCurrentDirectory(), true);
            proc.WaitForExit();

            Assert.Null(proc.StdErr);
            Assert.True(proc.StdOut.Contains("sim1"));
            Assert.True(proc.StdOut.Contains("sim2"));
            Assert.False(proc.StdOut.Contains("simulation3"));
            Assert.False(proc.StdOut.Contains("Base"));

            args = $@"{apsimxFileName} /Verbose /SimulationNameRegexPattern:sim1";
            proc = new ProcessUtilities.ProcessWithRedirectedOutput();
            proc.Start(models, args, Directory.GetCurrentDirectory(), true);
            proc.WaitForExit();

            Assert.Null(proc.StdErr);
            Assert.True(proc.StdOut.Contains("sim1"));
            Assert.False(proc.StdOut.Contains("sim2"));
            Assert.False(proc.StdOut.Contains("simulation3"));
            Assert.False(proc.StdOut.Contains("Base"));

            args = $@"{apsimxFileName} /Verbose /SimulationNameRegexPattern:(simulation3)|(Base)";
            proc = new ProcessUtilities.ProcessWithRedirectedOutput();
            proc.Start(models, args, Directory.GetCurrentDirectory(), true);
            proc.WaitForExit();

            Assert.Null(proc.StdErr);
            Assert.False(proc.StdOut.Contains("sim1"));
            Assert.False(proc.StdOut.Contains("sim2"));
            Assert.True(proc.StdOut.Contains("simulation3"));
            Assert.True(proc.StdOut.Contains("Base"));
        }
Example #15
0
        public void TestEditing()
        {
            string configFile = Path.GetTempFileName();

            File.WriteAllLines(configFile, new[]
            {
                // Modify an array
                "[Report].VariableNames = x,y,z",

                // Modify a date - try a few different formats.
                "[Clock].StartDate = 2000-01-01",
                "[Clock].EndDate = 2000-01-10T00:00:00",

                // Modify a string
                "[Weather].FileName = fdsa.met",
                @"[Weather2].FullFileName = .\jkl.met",

                // Replace a model with a model from another file.
                $"[Weather3] = {extFile}",
                $"[Weather4] = {extFile};[w2]",
            });

            string models = typeof(IModel).Assembly.Location;
            string args   = $"{fileName} /Edit {configFile}";

            var proc = new ProcessUtilities.ProcessWithRedirectedOutput();

            proc.Start(models, args, Path.GetTempPath(), true, true);
            proc.WaitForExit();

            // Children of simulation are, in order:
            // Clock, summary, zone, Weather, Weather2, w1, w2

            Assert.AreEqual(null, proc.StdOut);
            Assert.AreEqual(null, proc.StdErr);

            Simulations file = FileFormat.ReadFromFile <Simulations>(fileName, out List <Exception> errors);

            if (errors != null && errors.Count > 0)
            {
                throw errors[0];
            }

            var report = Apsim.Find(file, typeof(Models.Report)) as Models.Report;

            string[] variableNames = new[] { "x", "y", "z" };
            Assert.AreEqual(variableNames, report.VariableNames);

            IModel sim = Apsim.Child(file, typeof(Simulation));

            // Use an index-based lookup to locate child models.
            // When we replace an entire model, we want to ensure
            // that the replacement is inserted at the correct index.

            Clock clock = sim.Children[0] as Clock;

            Assert.AreEqual(new DateTime(2000, 1, 1), clock.StartDate);
            Assert.AreEqual(new DateTime(2000, 1, 10), clock.EndDate);

            var weather = sim.Children[3] as Models.Weather;

            Assert.NotNull(weather);
            Assert.AreEqual("Weather", weather.Name);
            Assert.AreEqual("fdsa.met", weather.FileName);

            var weather2 = sim.Children[4] as Models.Weather;

            Assert.NotNull(weather2);
            Assert.AreEqual("Weather2", weather2.Name);
            Assert.AreEqual(@".\jkl.met", weather2.FileName);

            // Weather3 and Weather4 should have been
            // renamed to w1 and w2, respectively.
            var weather3 = sim.Children[5] as Models.Weather;

            Assert.NotNull(weather3);
            Assert.AreEqual("w1", weather3.Name);
            Assert.AreEqual("w1.met", weather3.FileName);

            var weather4 = sim.Children[6] as Models.Weather;

            Assert.NotNull(weather4);
            Assert.AreEqual("w2", weather4.Name);
            Assert.AreEqual("w2.met", weather4.FileName);
        }