/// <summary> /// Calling this function uses the current date and time to update the queue with run Items... /// </summary> private void UpdateQueueWithRunItems( ) { foreach (RunItem item in RunItems) { try { // Pull the frequency string into the RunFrequency class to split into its components... RunFrequency runFrequency = new RunFrequency(item.Frequency); DateTime runTime = new DateTime(0); // Is it time for the application to run? if (runFrequency.StartDate + runFrequency.Interval <= DateTime.Now) { // Has the app already run the number of times it is allowed to? if ((runFrequency.RunInfinite) || (runFrequency.RunNumberOfTimes != 0)) { // Is the application already in the queue, or is it already running? if ((!IsRunItemInQueue(item)) && (!(item.IsRunning))) { // If everything checked out ok, we add the application to the queue. // Perform a query on the Test ID to get the Test object back... Test testRun = dbConnection.RetrieveTest(item.TestID); // Create a QueueEntry item... QueueEntry queueEntry = new QueueEntry(testRun); // Add the item to the queue... ExecutionQueue.Enqueue(queueEntry); } } } } catch (Exception e) { // We catch all exceptions and log them to the event log... WriteExceptionToLog(e); } } }
/// <summary> /// Performs a blocking execution based on the Test information in the queue entry that is /// passed. The method will NOT exit until the test has completed running. /// </summary> /// <param name="entry"></param> private int ExecuteQueueEntry(QueueEntry entry) { // We create a run string using the execution path... Note, that if the path is also included in // the filename, we truncate and remove just the file first. string RunString = entry.TestInformation.ExecutionPath + "\\" + System.IO.Path.GetFileName(entry.TestInformation.ExecutionBinary); Process appProc = new Process( ); // Set information for the process... appProc.StartInfo.WorkingDirectory = entry.TestInformation.ExecutionPath; appProc.StartInfo.FileName = RunString; appProc.StartInfo.UseShellExecute = false; // Set the arguments to be passed to the application if they are provided... if (entry.TestInformation.ExecutionArgs.Length != 0) { appProc.StartInfo.Arguments = entry.TestInformation.ExecutionArgs; } try { // Start the process... appProc.Start( ); // Wait for the process to exit before allowing any other processes to run... appProc.WaitForExit( ); //appProc.ExitCode this represents success or failure... return(appProc.ExitCode); } catch (Exception e) { WriteExceptionToLog(e); } // If we get here, we failed... return(1); }
private void Executer( ) { int exitCode = 0; TestHistory testHistory = null; for (;;) { Thread.Sleep(ExecutionDelay); // If there are items waiting on the queue, we will remove the first item and begin // execution... if (ExecutionQueue.Count > 0) { updateMutex.WaitOne( ); // Start waiting for the mutex... // Pull out the queue entry... QueueEntry entry = (QueueEntry)ExecutionQueue.Dequeue( ); // Set a flag on the RunItem to show that it is out of the queue and currently // running. foreach (RunItem item in RunItems) { if (item.TestID == entry.TestInformation.ID) { item.IsRunning = true; } } updateMutex.ReleaseMutex( ); // Release the mutex when done... // Add a new history entry to record that the test is now starting... testHistory = new TestHistory( ); testHistory.TestID = entry.TestInformation.ID; testHistory.Runtime = DateTime.Now; testHistory.Status = "STARTED"; dbConnection.AddTestHistory(testHistory); // Update the CURRENT state of the test... UpdateTestState(entry.TestInformation.ID, "RUNNING"); // Now, outside the main mutex, we perform our concurrent action for running the // executable, but this time using a different mutex. This makes sure that // each application never runs more than one at a time. executionMutex.WaitOne( ); exitCode = ExecuteQueueEntry(entry); executionMutex.ReleaseMutex( ); // We must grab the mutex again to mess with the RunItem structure... updateMutex.WaitOne( ); // Since the position or location of the RunItem in memory cannot be guaranteed because we // left the mutex for the run of the program, we must go back and find it again... foreach (RunItem item in RunItems) { if (item.TestID == entry.TestInformation.ID) { // The application is no longer running, so update that state in the current // memory structure... item.IsRunning = false; // Modify the existing runFrequency trackingItem definition to contain the current // time as the start time... RunFrequency runFrequency = new RunFrequency(item.Frequency); runFrequency.StartDate = DateTime.Now; // If this test is supposed to run a static number of times, we decrement the counter... if (!runFrequency.RunInfinite) { runFrequency.RunNumberOfTimes--; } // Update the item already in memory with the new changes... item.Frequency = runFrequency.GetFrequencyString( ); // Now, update the SQL database with this information... UpdateRunItemFrequency(item.TestID, runFrequency.GetFrequencyString( )); // Add a new history entry to record the results of the test... testHistory = new TestHistory( ); testHistory.TestID = item.TestID; testHistory.Runtime = runFrequency.StartDate; if (exitCode == 0) { testHistory.Status = "SUCCESS"; SendEmail(item, true); } else { testHistory.Status = "FAILURE (" + exitCode.ToString( ) + ")"; SendEmail(item, false); } // Update the CURRENT state of the test... - SUCCESS or FAILURE (either determines that // the test is no longer running - STOPPED). UpdateTestState(item.TestID, testHistory.Status); dbConnection.AddTestHistory(testHistory); } else { // We should NEVER get here... eventLog.WriteEntry("An item existed in the execution queue which didn't exist in the database!", System.Diagnostics.EventLogEntryType.Error); } } // Release the mutex so that further threads may modify the RunItem structures... updateMutex.ReleaseMutex( ); } } }
/// <summary> /// Calling this function uses the current date and time to update the queue with run Items... /// </summary> private void UpdateQueueWithRunItems( ) { foreach ( RunItem item in RunItems ) { try { // Pull the frequency string into the RunFrequency class to split into its components... RunFrequency runFrequency = new RunFrequency( item.Frequency ); DateTime runTime = new DateTime( 0 ); // Is it time for the application to run? if ( runFrequency.StartDate + runFrequency.Interval <= DateTime.Now ) { // Has the app already run the number of times it is allowed to? if ( ( runFrequency.RunInfinite ) || ( runFrequency.RunNumberOfTimes != 0 ) ) { // Is the application already in the queue, or is it already running? if ( ( !IsRunItemInQueue( item ) ) && ( !( item.IsRunning ) ) ) { // If everything checked out ok, we add the application to the queue. // Perform a query on the Test ID to get the Test object back... Test testRun = dbConnection.RetrieveTest( item.TestID ); // Create a QueueEntry item... QueueEntry queueEntry = new QueueEntry( testRun ); // Add the item to the queue... ExecutionQueue.Enqueue( queueEntry ); } } } } catch ( Exception e ) { // We catch all exceptions and log them to the event log... WriteExceptionToLog( e ); } } }
/// <summary> /// Performs a blocking execution based on the Test information in the queue entry that is /// passed. The method will NOT exit until the test has completed running. /// </summary> /// <param name="entry"></param> private int ExecuteQueueEntry( QueueEntry entry ) { // We create a run string using the execution path... Note, that if the path is also included in // the filename, we truncate and remove just the file first. string RunString = entry.TestInformation.ExecutionPath + "\\" + System.IO.Path.GetFileName( entry.TestInformation.ExecutionBinary ); Process appProc = new Process( ); // Set information for the process... appProc.StartInfo.WorkingDirectory = entry.TestInformation.ExecutionPath; appProc.StartInfo.FileName = RunString; appProc.StartInfo.UseShellExecute = false; // Set the arguments to be passed to the application if they are provided... if ( entry.TestInformation.ExecutionArgs.Length != 0 ) appProc.StartInfo.Arguments = entry.TestInformation.ExecutionArgs; try { // Start the process... appProc.Start( ); // Wait for the process to exit before allowing any other processes to run... appProc.WaitForExit( ); //appProc.ExitCode this represents success or failure... return appProc.ExitCode; } catch ( Exception e ) { WriteExceptionToLog( e ); } // If we get here, we failed... return 1; }