/// <summary> /// Get the Job XML data /// </summary> /// <param name="directory"></param> /// <param name="scanType"></param> /// <returns>Job xml data</returns> public static JobXmlData GetJobXmlFileInfo(string directory, DirectoryScanType scanType) { JobXmlData jobScanXmlData = new JobXmlData(); string baseDirectory = (scanType == DirectoryScanType.INPUT_BUFFER) ? IniData.InputDir : IniData.ProcessingDir; string job = directory.Replace(baseDirectory, "").Remove(0, 1); jobScanXmlData.Job = job; jobScanXmlData.JobDirectory = directory; jobScanXmlData.JobSerialNumber = job.Substring(0, job.IndexOf("_")); int start = job.IndexOf("_") + 1; jobScanXmlData.TimeStamp = job.Substring(start, job.Length - start); // Wait until the Xml file shows up bool xmlFileFound = false; do { string[] files = Directory.GetFiles(directory, "*.xml"); if (files.Length > 0) { jobScanXmlData.XmlFileName = Path.GetFileName(files[0]); xmlFileFound = true; } Thread.Yield(); }while (xmlFileFound == false); return(jobScanXmlData); }
/// <summary> /// Method to start new jobs from the Input Buffer /// </summary> /// <param name="directory"></param> public void StartInputJob(string directory) { // Get data found in Job xml file JobXmlData jobXmlData = StaticClass.GetJobXmlFileInfo(directory, DirectoryScanType.INPUT_BUFFER); if (jobXmlData == null) { StaticClass.Logger.LogError("InputJobsScanThread GetJobXmlData failed"); } // Display job xml data found StaticClass.Log("Input Job : " + jobXmlData.Job); StaticClass.Log("Input Job Directory : " + jobXmlData.JobDirectory); StaticClass.Log("Input Job Serial Number : " + jobXmlData.JobSerialNumber); StaticClass.Log("Input Job Time Stamp : " + jobXmlData.TimeStamp); StaticClass.Log("Input Job Xml File : " + jobXmlData.XmlFileName); StaticClass.Log(string.Format("Started Input Job {0} executing Slot {1} at {2:HH:mm:ss.fff}", jobXmlData.Job, StaticClass.NumberOfJobsExecuting + 1, DateTime.Now)); // Create a thread to run the job, and then start the thread JobRunThread jobRunThread = new JobRunThread(jobXmlData, DirectoryScanType.INPUT_BUFFER); if (jobRunThread == null) { StaticClass.Logger.LogError("InputJobsScanThread jobRunThread failed to instantiate"); } jobRunThread.ThreadProc(); }
/// <summary> /// Get the Job XML data /// </summary> /// <param name="directory"></param> /// <param name="scanType"></param> /// <returns>Job Xml data</returns> public static JobXmlData GetJobXmlFileInfo(string directory, DirectoryScanType scanType) { JobXmlData jobScanXmlData = new JobXmlData(); string baseDirectory = (scanType == DirectoryScanType.INPUT_BUFFER) ? IniData.InputDir : IniData.ProcessingDir; string job = directory.Replace(baseDirectory, "").Remove(0, 1); jobScanXmlData.Job = job; jobScanXmlData.JobDirectory = directory; jobScanXmlData.JobSerialNumber = job.Substring(0, job.IndexOf("_")); int start = job.IndexOf("_") + 1; jobScanXmlData.TimeStamp = job.Substring(start, job.Length - start); Log(string.Format("Job {0} waiting for it's Job xml file at {1:HH:mm:ss.fff}", job, DateTime.Now)); // Wait until Job xml file is present to continue partial job bool xmlFileFound = false; do { string[] files = Directory.GetFiles(directory, "*.xml"); if (files.Length > 0) { jobScanXmlData.XmlFileName = Path.GetFileName(files[0]); Log(string.Format("Job {0} found it's Job xml file {1} at {2:HH:mm:ss.fff}", job, jobScanXmlData.XmlFileName, DateTime.Now)); xmlFileFound = true; } Thread.Sleep(StaticClass.JOB_XML_FILE_READY_WAIT); }while (xmlFileFound == false); return(jobScanXmlData); }
/// <summary> /// Check if a Job directory is complete /// </summary> /// <param name="directory"></param> /// <returns>Job Files Complete or not</returns> public static bool CheckIfJobFilesComplete(string directory) { // Check if the Job Xml file exists string[] files = Directory.GetFiles(directory, "*.xml"); if (files.Length > 0) { JobXmlData jobXmlData = GetJobXmlFileInfo(directory, DirectoryScanType.INPUT_BUFFER); string jobXmlFileName = jobXmlData.JobDirectory + @"\" + jobXmlData.XmlFileName; if (CheckFileReady(jobXmlFileName)) { // Read Job xml file and get the top node XmlDocument jobXmlDoc = new XmlDocument(); jobXmlDoc.Load(jobXmlFileName); XmlElement root = jobXmlDoc.DocumentElement; string TopNode = root.LocalName; // Get nodes for the number of files and names of files to transfer from Job .xml file XmlNode ConsumedNode = jobXmlDoc.DocumentElement.SelectSingleNode("/" + TopNode + "/FileConfiguration/Consumed"); int numberOfFilesNeeded = Convert.ToInt32(ConsumedNode.InnerText); // Get the current number of files DirectoryInfo InputJobInfo = new DirectoryInfo(directory); if (InputJobInfo == null) { Logger.LogError("InputJobInfo failed to instantiate"); } int numberOfFilesFound = InputJobInfo.GetFiles().Length; // Return Job file start set complete or not return(numberOfFilesNeeded == numberOfFilesFound); } } return(false); }
/// <summary> /// Run Input Buffer Scan /// </summary> /// <param name="jobDirectory"></param> public void RunInputBufferPartialJob(string jobDirectory) { JobXmlData jobXmlData = StaticClass.GetJobXmlFileInfo(jobDirectory, DirectoryScanType.INPUT_BUFFER); if (jobXmlData.XmlFileName != string.Empty) { // Now start the new job StartInputJob(jobDirectory); } }
/// <summary> /// Start a Processing directory job /// </summary> /// <param name="directory"></param> public void StartProcessingJob(string directory) { // Delete the data.xml file in the Processing directory if found string dataXmlFile = directory + @"\" + "data.xml"; if (File.Exists(dataXmlFile)) { File.Delete(dataXmlFile); } // Get data found in job Xml file JobXmlData jobXmlData = StaticClass.GetJobXmlFileInfo(directory, DirectoryScanType.PROCESSING_BUFFER); if (jobXmlData == null) { StaticClass.Logger.LogError("ProcessingJobsScanThread GetJobXmlData failed"); } // Display job xml Data found StaticClass.Log("Processing Job : " + jobXmlData.Job); StaticClass.Log("Processing Job Directory : " + jobXmlData.JobDirectory); StaticClass.Log("Processing Job Serial Number : " + jobXmlData.JobSerialNumber); StaticClass.Log("Processing Job Time Stamp : " + jobXmlData.TimeStamp); StaticClass.Log("Processing Job Xml File : " + jobXmlData.XmlFileName); StaticClass.Log(string.Format("Starting Processing directory Job {0} Executing Slot {1} at {2:HH:mm:ss.fff}", jobXmlData.Job, StaticClass.NumberOfJobsExecuting + 1, DateTime.Now)); // Create a thread to run the job, and then start the thread JobRunThread jobRunThread = new JobRunThread(jobXmlData, DirectoryScanType.PROCESSING_BUFFER); if (jobRunThread == null) { StaticClass.Logger.LogError("ProcessingJobsScanThread jobRunThread failed to instantiate"); } jobRunThread.ThreadProc(); }
/// <summary> /// Check for new Input Buffer jobs /// </summary> public void RunInputJobsFound() { if (StaticClass.NumberOfJobsExecuting < StaticClass.IniData.ExecutionLimit) { if (StaticClass.GetTotalNumberOfJobs() > 0) { string job = StaticClass.GetJobFromList(StaticClass.CurrentJobIndex); if (job != string.Empty) { StaticClass.Log(string.Format("Input Job handler got Job {0} from list index {1} at {2:HH:mm:ss.fff}", job, StaticClass.CurrentJobIndex, DateTime.Now)); // Check for complete jobs and run them first string jobDirectory = StaticClass.IniData.InputDir + @"\" + job; if (StaticClass.CheckIfJobFilesComplete(jobDirectory) == true) { StaticClass.Log(string.Format("Starting Input Job {0} index {1} at {2:HH:mm:ss.fff}", jobDirectory, StaticClass.CurrentJobIndex, DateTime.Now)); // Start the new completely ready Job StartInputJob(jobDirectory); // Delete the job from the list and display the new list StaticClass.DeleteJobFromList(StaticClass.CurrentJobIndex); } else // Partial Job handling { // Skip Partial Job if there are more in the list int lastIndex = StaticClass.GetLastIndex(); if (StaticClass.CurrentJobIndex < lastIndex) { StaticClass.Log(string.Format("Input Job scanner skipping Job {0} index {1} as not ready at {2:HH:mm:ss.fff}", job, StaticClass.CurrentJobIndex, DateTime.Now)); StaticClass.CurrentJobIndex++; } else // Run last job in list { // Wait for the job xml file JobXmlData jobXmlData = StaticClass.GetJobXmlFileInfo(jobDirectory, DirectoryScanType.INPUT_BUFFER); if (jobXmlData.XmlFileName != string.Empty) { StaticClass.Log(string.Format("Starting Partial Input Job {0} index {1} at {2:HH:mm:ss.fff}", jobDirectory, StaticClass.CurrentJobIndex, DateTime.Now)); // Start the new partial job StartInputJob(jobDirectory); // Delete the job from the list StaticClass.DeleteJobFromList(StaticClass.CurrentJobIndex); } // If there is a skipped partial job, start it next by setting index to previous one int previousJobIndex = StaticClass.GetPreviousIndex(); if ((previousJobIndex > 0) && (StaticClass.CurrentJobIndex > previousJobIndex)) { StaticClass.CurrentJobIndex = previousJobIndex; } } } } } else { if (CurrentJobIndex != StaticClass.CurrentJobIndex) { StaticClass.Log(string.Format("Input Jobs Scanner Resetting Current Job Index from {0} to {1} at {2:HH:mm:ss.fff}", StaticClass.CurrentJobIndex, 1, DateTime.Now)); CurrentJobIndex = StaticClass.CurrentJobIndex = 1; } } } }
/// <summary> /// Get the data from the Job xml file /// </summary> /// <param name="jobXmlData"></param> /// <param name="monitorData"></param> /// <returns></returns> public StatusMonitorData GetJobXmlData(JobXmlData jobXmlData, StatusMonitorData monitorData) { // Wait for Job xml file to be ready string jobXmlFileName = jobXmlData.JobDirectory + @"\" + jobXmlData.XmlFileName; if (StaticClass.CheckFileReady(jobXmlFileName)) { // Read Job xml file and get the top node XmlDocument jobXmlDoc = new XmlDocument(); jobXmlDoc.Load(jobXmlFileName); XmlElement root = jobXmlDoc.DocumentElement; string TopNode = root.LocalName; // Get nodes for the number of files and names of files to transfer from Job .xml file XmlNode UnitNumberdNode = jobXmlDoc.DocumentElement.SelectSingleNode("/" + TopNode + "/listitem/value"); XmlNode ConsumedNode = jobXmlDoc.DocumentElement.SelectSingleNode("/" + TopNode + "/FileConfiguration/Consumed"); XmlNode ProducedNode = jobXmlDoc.DocumentElement.SelectSingleNode("/" + TopNode + "/FileConfiguration/Produced"); XmlNode TransferedNode = jobXmlDoc.DocumentElement.SelectSingleNode("/" + TopNode + "/FileConfiguration/Transfered"); XmlNode ModelerNode = jobXmlDoc.DocumentElement.SelectSingleNode("/" + TopNode + "/FileConfiguration/Modeler"); // Assign then increment port number for this Job monitorData.JobPortNumber = StaticClass.IniData.StartPort + StaticClass.JobPortIndex++; // Get the modeler and number of files to transfer int NumFilesToTransfer = 0; monitorData.UnitNumber = UnitNumberdNode.InnerText; monitorData.Modeler = ModelerNode.InnerText; monitorData.NumFilesConsumed = Convert.ToInt32(ConsumedNode.InnerText); monitorData.NumFilesProduced = Convert.ToInt32(ProducedNode.InnerText); if (TransferedNode != null) { NumFilesToTransfer = Convert.ToInt32(TransferedNode.InnerText); } monitorData.NumFilesToTransfer = NumFilesToTransfer; // Get the modeler and number of files to transfer StaticClass.Log($"Unit Number : {monitorData.UnitNumber}"); StaticClass.Log($"Modeler : {monitorData.Modeler}"); StaticClass.Log($"Num Files Consumed : {monitorData.NumFilesConsumed}"); StaticClass.Log($"Num Files Produced : {monitorData.NumFilesProduced}"); StaticClass.Log($"Num Files To Transfer : {monitorData.NumFilesToTransfer}"); StaticClass.Log($"Job Port Number : {monitorData.JobPortNumber}"); // Create the Transfered file list from the Xml file entries monitorData.TransferedFileList = new List <string>(NumFilesToTransfer); for (int i = 1; i < NumFilesToTransfer + 1; i++) { string transferFileNodeName = ("/" + TopNode + "/FileConfiguration/Transfered" + i.ToString()); XmlNode TransferedFileXml = jobXmlDoc.DocumentElement.SelectSingleNode(transferFileNodeName); monitorData.TransferedFileList.Add(TransferedFileXml.InnerText); StaticClass.Log(string.Format("Transfer File{0} : {1}", i, TransferedFileXml.InnerText)); } } else { StaticClass.Logger.LogError("File {0} is not available at {1:HH:mm:ss.fff}\n", jobXmlFileName, DateTime.Now); } return(monitorData); }
/// <summary> /// Run a job from Input or Processing Buffers /// </summary> /// <param name="dirScanType"></param> /// <param name="jobXmlData"></param> public void RunJob(JobXmlData jobXmlData, DirectoryScanType dirScanType) { // Increment number of Jobs executing in only one place! StaticClass.NumberOfJobsExecuting++; // Create the Job Run common strings string job = jobXmlData.Job; string xmlJobDirectory = jobXmlData.JobDirectory; string processingBufferDirectory = StaticClass.IniData.ProcessingDir; string processingBufferJobDir = processingBufferDirectory + @"\" + job; // Set the job start time StaticClass.JobStartTime[job] = DateTime.Now; // Create new status monitor data and fill it in with the job xml data StatusMonitorData monitorData = new StatusMonitorData { Job = job, JobDirectory = xmlJobDirectory, StartTime = DateTime.Now, JobSerialNumber = jobXmlData.JobSerialNumber, TimeStamp = jobXmlData.TimeStamp, XmlFileName = jobXmlData.XmlFileName }; // Add initial entry to status list StaticClass.StatusDataEntry(job, JobStatus.JOB_STARTED, JobType.TIME_RECEIVED); // Get the Job xml data monitorData = GetJobXmlData(jobXmlData, monitorData); // If this job comes from the Input directory, run the Input job check and start job if (dirScanType == DirectoryScanType.INPUT_BUFFER) { RunInputBufferScan(processingBufferJobDir, job, monitorData); } // If the shutdown flag is set, exit method if (StaticClass.ShutDownPauseCheck("Run Job") == true) { return; } // Add entry to status list StaticClass.StatusDataEntry(job, JobStatus.EXECUTING, JobType.TIME_START); StaticClass.Log(string.Format("Starting Job {0} with Modeler {1} on Port {2} with {3} CPU's at {4:HH:mm:ss.fff}", job, monitorData.Modeler, monitorData.JobPortNumber, StaticClass.IniData.CPUCores, DateTime.Now)); // Execute Modeler using the command line generator string executable = StaticClass.IniData.ModelerRootDir + @"\" + monitorData.Modeler + @"\" + monitorData.Modeler + ".exe"; string processingBuffer = processingBufferJobDir; int port = monitorData.JobPortNumber; int cpuCores = StaticClass.IniData.CPUCores; CommandLineGenerator cmdLineGenerator = new CommandLineGenerator( executable, processingBuffer, port, cpuCores); if (cmdLineGenerator == null) { StaticClass.Logger.LogError("JobRunThread cmdLineGenerator failed to instantiate"); } Process modelerProcess = cmdLineGenerator.ExecuteCommand(job); // Register with the Processing File Watcher class and start its thread ProcessingFileWatcherThread processingFileWatcher = new ProcessingFileWatcherThread(processingBufferJobDir, monitorData); if (processingFileWatcher == null) { StaticClass.Logger.LogError("JobRunThread ProcessingFileWatch failed to instantiate"); } processingFileWatcher.ThreadProc(); // Start the TCP/IP Communications thread before checking for Processing job files TcpIpListenThread tcpIpThread = new TcpIpListenThread(monitorData); if (tcpIpThread == null) { StaticClass.Logger.LogError("ProcessingFileWatcherThread tcpIpThread failed to instantiate"); } tcpIpThread.ThreadProc(); // Add entry to status list StaticClass.StatusDataEntry(job, JobStatus.MONITORING_PROCESSING, JobType.TIME_START); // Wait 45 seconds for Modeler to get started before reading it's information Thread.Sleep(StaticClass.DISPLAY_PROCESS_DATA_WAIT); // Display the Modeler Process information DisplayProcessInfo(job, modelerProcess); // Wait for the Processing job scan complete or shut down do { if (StaticClass.ShutDownPauseCheck("Run Job") == true) { return; } Thread.Yield(); }while ((StaticClass.ProcessingJobScanComplete[job] == false) && (StaticClass.JobShutdownFlag[job] == false)); // Wait to make sure the data.xml is done being handled Thread.Sleep(StaticClass.POST_PROCESS_WAIT); if (StaticClass.JobShutdownFlag[job] == false) { // Wait for the data.xml file to contain a result string dataXmlFileName = processingBufferJobDir + @"\" + "data.xml"; if (OverallResultEntryCheck(dataXmlFileName) == true) { StaticClass.Log(string.Format("Overall Results check confirmed for Job {0} at {1:HH:mm:ss.fff}", job, DateTime.Now)); } else { StaticClass.Log(string.Format("Overall Results check failed for Job {0} at {1:HH:mm:ss.fff}", job, DateTime.Now)); } } // Make sure Modeler Process is stopped if (StaticClass.ProcessHandles[job].HasExited == false) { StaticClass.Log(string.Format("Shutting down Modeler Executable for Job {0} at {1:HH:mm:ss.fff}", job, DateTime.Now)); StaticClass.ProcessHandles[job].Kill(); StaticClass.ProcessHandles.Remove(job); // Wait for Process to end Thread.Sleep(StaticClass.SHUTDOWN_PROCESS_WAIT); } // Run the Job Complete handler RunJobFileProcessing(job, monitorData); // Add entry to status list StaticClass.StatusDataEntry(job, JobStatus.COMPLETE, JobType.TIME_COMPLETE); // Show Job Complete message TimeSpan timeSpan = DateTime.Now - StaticClass.JobStartTime[job]; StaticClass.Log(string.Format("Job {0} Complete taking {1:hh\\:mm\\:ss}. Decrementing Job count to {2} at {3:HH:mm:ss.fff}", job, timeSpan, StaticClass.NumberOfJobsExecuting - 1, DateTime.Now)); // Decrement the number of Jobs executing in one place! StaticClass.NumberOfJobsExecuting--; }
/// <summary> /// Job Run Thread constructor obtains the state information /// </summary> /// <param name="dirScanType"></param> /// <param name="jobXmlData"></param> public JobRunThread(JobXmlData jobXmlData, DirectoryScanType dirScanType) { DirScanType = dirScanType; JobRunXmlData = jobXmlData; }