/// <summary> /// A raw request file has been place in the requests area. A SimEngine request file is built. /// The format of the raw file is: /// * Lines beginning with # are comments /// * lines that are empty after trimming are ignored /// * lines beginning with "action:" are followed by action name and argument /// * actions are a comma list, with first token the action name (e.g. Experiment) /// and other tokens in key=value pairs. E.g. Experiment,Project=MyProject,Experiment=MyExperiment /// or "Status,ID=MyID" /// </summary> /// <param name="fileDropFolderPath"></param> /// <param name="action"></param> /// <param name="projectFilename"></param> /// <param name="argsList"></param> /// <param name="explanation"></param> /// <returns></returns> private static bool ParseRawRequestFile(string fileDropFolderPath, List <SimEngineRequest> requestsList, out string explanation) { explanation = ""; if (requestsList == null) { explanation = $"RequestsList cannot be null"; return(false); } requestsList.Clear(); StringBuilder sbComments = new StringBuilder(); try { string[] lines = File.ReadAllLines(fileDropFolderPath); foreach (string line in lines) { string trimmedLine = line.Trim(); if (string.IsNullOrEmpty(trimmedLine)) { goto GetNextLine; } if (trimmedLine.StartsWith("#")) { sbComments.AppendLine(trimmedLine); goto GetNextLine; } string[] argTokens = line.Trim().Split(','); int lineNbr = 0; string action = ""; string project = ""; List <RequestArgument> argsList = new List <RequestArgument>(); foreach (string argToken in argTokens.ToList()) { lineNbr++; string[] pairTokens = argToken.Split('='); if (pairTokens.Length != 2) { explanation = $"Line#={lineNbr} Pair={argToken} is missing '='"; return(false); } string key = pairTokens[0].ToLower(); switch (key) { case "action": { action = pairTokens[1]; } break; case "project": { project = pairTokens[1]; } break; default: { RequestArgument arg = new RequestArgument(pairTokens[0], pairTokens[1]); argsList.Add(arg); } break; } } // foreach argPair if (!string.IsNullOrEmpty(action) && !string.IsNullOrEmpty(project)) { SimEngineRequest request = new SimEngineRequest(action, project, argsList); requestsList.Add(request); } else { explanation = $"Invalid Request at Line={lineNbr}. No Action or Project specified."; return(false); } GetNextLine :; } return(true); } catch (Exception ex) { explanation = $"File={fileDropFolderPath} Err={ex.Message}"; return(false); } }
static void Main(string[] args) { string marker = "Begin."; try { string explanation = ""; string requestsFolder = Properties.Settings.Default.RequestsPath; if (!Directory.Exists(requestsFolder)) { Logit($"Requests Storage folder={requestsFolder} does not exist."); Environment.Exit(1003); } Logit($"Info: The Request folder={requestsFolder} was found."); string extensionsPath = Properties.Settings.Default.ExtensionsPath; if (!Directory.Exists(extensionsPath)) { Logit($"ExtensionsPath for Simio processing={extensionsPath} does not exist."); Environment.Exit(1005); } Logit($"Info: The Extensions folder={extensionsPath} was found."); string projectsFolder = Properties.Settings.Default.ProjectsPath; if (!Directory.Exists(projectsFolder)) { Logit($"Projects Storage folder={projectsFolder} does not exist."); Environment.Exit(1007); } Logit($"Info: The Projects folder={requestsFolder} was found."); bool done = false; marker = $"Requests={requestsFolder}. ExtensionDLLs={extensionsPath} Projects={projectsFolder}"; Logit($"Info: marker"); string successFolder = Path.Combine(requestsFolder, "Success"); if (!Directory.Exists(successFolder)) { Directory.CreateDirectory(successFolder); Logit($"Info: The Success folder={successFolder} was created."); } string failureFolder = Path.Combine(requestsFolder, "Failure"); if (!Directory.Exists(failureFolder)) { Directory.CreateDirectory(failureFolder); Logit($"Info: The Failure folder={successFolder} was created."); } string runningFolder = Path.Combine(requestsFolder, "Running"); if (!Directory.Exists(runningFolder)) { Directory.CreateDirectory(runningFolder); Logit($"Info: The Running folder={runningFolder} was created."); } Logit($"Starting Loop."); while (!done) { // Requests are queued by time and ID. SimEngineRequest request = SimEngineRequestHelper.GetNextRequest(requestsFolder, out explanation); if (request != null) { // Now we have the request. Figure out what to do. Logit($"Processing request. Action={request.Action} Project={request.ProjectFilename}"); // Run the project string projectFullPath = Path.Combine(projectsFolder, request.ProjectFilename); if (!File.Exists(projectFullPath)) { // Move to failure explanation = $"No ProjectFile found at={projectFullPath}"; goto FinishUp; } // Move to "running" folder. string runningPath = Path.Combine(runningFolder, Path.GetFileName(request.RequestPath)); if (File.Exists(runningPath)) { File.Delete(runningPath); } File.Move(request.RequestPath, runningPath); switch (request.Action.ToUpper()) { case "PLAN": { // Run the project if (!SimEngineHelpers.RunProjectPlan(extensionsPath, projectFullPath, request.ActionArguments, out explanation)) { request.RunResults = $"Error with Request={request.ID} Project={request.ProjectFilename} Error={explanation}."; // Move to Failure } else { request.RunResults = $"Success with Request={request.ID} Project={request.ProjectFilename}"; // Move to Success } } break; case "EXPERIMENT": { if (!SimEngineHelpers.RunProjectExperiment(extensionsPath, projectFullPath, request.ActionArguments, out explanation)) { request.RunResults = $"Error with Request={request.ID} Project={request.ProjectFilename} Error={explanation}."; // Move to Failure } else { request.RunResults = $"Success with Request={request.ID} Project={request.ProjectFilename}"; // Move to Success } } break; // Alter congifiguration, such as location of project case "CONFIGURATION": { // Todo: Alter configurations at run-time } break; case "STATUS": { //Todo: Given the ID, return a status } break; default: Logit($"Unknown ProjectAction={request.Action}"); break; } // switch FinishUp: string source = request.RequestPath; string fn = Path.GetFileName(source); if (string.IsNullOrEmpty(explanation)) { File.Move(source, Path.Combine(successFolder, fn)); } else { File.Move(source, Path.Combine(failureFolder, fn)); } } else { Logit($"Error Getting Request File from={requestsFolder}. Err={explanation}"); } // Take a break System.Threading.Thread.Sleep(1000); } ; // while } catch (Exception ex) { Logit($"Marker={marker}. Failure={ex.Message}"); Environment.Exit(1013); } } // main
private static void StartHttpServer(int port) { try { string projectsFolder = Properties.Settings.Default.ProjectsFolder; string queueFolder = Properties.Settings.Default.RequestsFolder; var route_config = new List <SimpleHttpServer.Models.Route>() { new Route { Name = "Hello Handler", UrlRegex = @"^/$", Method = "GET", Callable = (HttpRequest request) => { return(new HttpResponse() { ContentAsUTF8 = $"Hello from Simio HttpServer. Time is {DateTime.Now}." + " Options are Simio/SimEngine/yourModelName", ReasonPhrase = "OK", StatusCode = "200" }); } }, new Route { Name = "SimEngine Controller for Experiment", UrlRegex = @"^/SimEngine/Experiment.*$", Method = "GET", Callable = (HttpRequest request) => { string explanation = ""; string success = ""; Uri myUri = new Uri(request.Path); List <KeyValuePair <string, string> > parameterList = new List <KeyValuePair <string, string> >(); if (!ParseUrl(request.Path, parameterList, out explanation) || parameterList.Count == 0) { explanation = $"Bad Request. Err={explanation}"; goto DoneWithRequest; } //string projectName = WebUtility.UrlDecode(tokens[3]); //string arguments = WebUtility.UrlDecode(tokens[4]); string projectName = parameterList.SingleOrDefault(rr => rr.Key == "project").Value; if (projectName == null) { explanation = $"argument 'project' must be specified."; goto DoneWithRequest; } string projectPath = Path.Combine(projectsFolder, projectName); if (!File.Exists(projectPath)) { explanation = $"Cannot find Project={projectPath}"; goto DoneWithRequest; } string modelName = parameterList.SingleOrDefault(rr => rr.Key == "model").Value; // default if (modelName == null) { explanation = $"argument 'model' must be specified."; goto DoneWithRequest; } string experimentName = parameterList.SingleOrDefault(rr => rr.Key == "experiment").Value; // default if (experimentName == null) { explanation = $"argument 'experiment' must be specified."; goto DoneWithRequest; } List <RequestArgument> argList = new List <RequestArgument>(); SimEngineRequest newRequest = new SimEngineRequest(projectPath, "Experiment", argList); if (!SimEngineRequestHelper.PutRequest(queueFolder, newRequest, out explanation)) { explanation = $"Cannot Store Request. Err={explanation}"; goto DoneWithRequest; } DoneWithRequest :; if (!string.IsNullOrEmpty(explanation)) { return(new HttpResponse() { ContentAsUTF8 = $"{DateTime.Now}: SimEngine Request=[{request.Path}]. Error={explanation}", ReasonPhrase = "ERROR", StatusCode = "501" }); } else { return(new HttpResponse() { ContentAsUTF8 = $"{DateTime.Now}: SimEngine Request=[{request.Path}]. Success={success}", ReasonPhrase = "OK", StatusCode = "200" }); } } }, new Route { Name = "FileSystem Static Handler", UrlRegex = @"^/Static/(.*)$", Method = "GET", Callable = new FileSystemRouteHandler() { BasePath = @"C:\Temp", ShowDirectories = true }.Handle } }; HttpServer httpServer = new HttpServer(port, route_config); Thread thread = new Thread(new ThreadStart(httpServer.Listen)); thread.Start(); } catch (Exception ex) { Alert($"Err={ex.Message}"); } }