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 ); } } }
private void ShowSelectedTestInformation( string testID ) { // Make the test panel visible... AreaInfoPanel.Visible = false; TestEditPanel.Visible = true; HistoryPanel.Visible = false; TestEditLabel.Text = "Edit/View Test"; Test testInformation = dbConnection.RetrieveTest( testID ); EditTestTestName.Text = testInformation.Name; EditTestTestDescription.Text = testInformation.Description; // First, clear out the test owners list... EditTestOwnerList.Items.Clear( ); // Populate the owner list... foreach ( User user in dbConnection.RetrieveAllUsers( ) ) { EditTestOwnerList.Items.Add( new ListItem( user.Name, user.Name ) ); } // Set the currently selected item to the test owner in the user list... EditTestOwnerList.SelectedValue = dbConnection.RetrieveUser( testInformation.OwnerID ).Name; // Clear any selections in the priority list box... EditTestTestPriorityListBox.ClearSelection( ); // Now, select the current priority given to the test... ListItem priorityItem = EditTestTestPriorityListBox.Items.FindByText( "P" + testInformation.Priority ); if ( priorityItem != null ) priorityItem.Selected = true; EditTestExecutionPath.Text = testInformation.ExecutionPath; EditTestExecutionName.Text = testInformation.ExecutionBinary; EditTestExecutionArgs.Text = testInformation.ExecutionArgs; if ( EditTestOS.Items.FindByValue( testInformation.OperatingSystem ) != null ) EditTestOS.SelectedValue = testInformation.OperatingSystem; if ( EditTestOSVersion.Items.FindByValue( testInformation.OSVersion ) != null ) EditTestOSVersion.SelectedValue = testInformation.OSVersion; // Figure out the date and time components of the interval and set them... RunFrequency runFrequency = new RunFrequency( testInformation.RunFrequency ); RunFreqMonths.Text = ( runFrequency.Interval.Days / 30 ).ToString( ); // Get number of months... RunFreqDays.Text = ( runFrequency.Interval.Days % 30 ).ToString( ); // Get number of days (left from months)... RunFreqHours.Text = runFrequency.Interval.Hours.ToString( ); RunFreqMinutes.Text = runFrequency.Interval.Minutes.ToString( ); EditTestRunNumberOfTimes.Text = runFrequency.RunNumberOfTimes.ToString( ); if ( runFrequency.RunInfinite ) { EditTestInfinite.Checked = true; EditTestInfiniteNoCare.Checked = false; } else { EditTestInfiniteNoCare.Checked = true; EditTestInfinite.Checked = true; } EditTestState.Text = testInformation.State; EditTestInternalID.Text = testInformation.ID; }