Beispiel #1
0
 private void UpdateScannerState()
 {
     DateTime now = Time.UtcNow;
     if (_scanTraits.Type == ScanType.Official)
     {
         if (now < _scanTraits.EventStart)
         {
             _scannerState = MatchScannerState.OfficialBaseline;
         }
         else if (now < _scanTraits.EventEnd)
         {
             _scannerState = MatchScannerState.OfficialInProgress;
         }
         else
         {
             _scannerState = MatchScannerState.OfficialFinishing;
         }
     }
 }
Beispiel #2
0
        private async Task RunScannerAsync()
        {
            Log.TraceInformation("Starting up the scanner loop");
            bool scanIsTotallyCompleted = false;

            if (_scanTraits.Type == ScanType.Manual)
            {
                _scannerState = MatchScannerState.ManualScan;
            }
            else if (_scanTraits.Type == ScanType.TestPass)
            {
                _scannerState = MatchScannerState.TestScan;
            }

            try
            {
                TimeSpan? tilNextUpdate = TimeSpan.Zero;
                while (tilNextUpdate.HasValue)
                {
                    AbortIfTestScanRunsLong();

                    UpdateScannerState();

                    // Sleep until there's more work to do or until the scan is canceled.
                    Log.TraceInformation("Sleeping for {0}", tilNextUpdate);
                    await UpdateAppState("Sleeping for " + tilNextUpdate.ToString()).ConfigureAwait(false);
                    if (_cancelScanEvent.WaitOne(tilNextUpdate.Value))
                    {
                        Log.TraceInformation("Breaking out of scan loop because the event was signaled");
                        break;
                    }

                    await _participationHandle.HeartbeatAsync().ConfigureAwait(false);

                    // Update the next partition.  The return value tells us whether or not there's 
                    // any more work to do.
                    var refreshResult = await RefreshNextPartitionAsync().ConfigureAwait(false);
                    tilNextUpdate = refreshResult.TimeTilNextUpdate;
                    if (!tilNextUpdate.HasValue)
                    {
                        Log.TraceInformation("Breaking out of scan loop because a next update time was not returned.");
                        break;
                    }

                    if (tilNextUpdate > _scannerHeartbeatPeriod)
                    {
                        tilNextUpdate = _scannerHeartbeatPeriod;
                    }

                    TimeSpan timeTilEnd = _scanTraits.EventEnd - Time.UtcNow;
                    if ((tilNextUpdate > timeTilEnd)
                        && (timeTilEnd > TimeSpan.Zero))
                    {
                        tilNextUpdate = _scanTraits.EventEnd - Time.UtcNow;
                    }
                    else if (timeTilEnd <= TimeSpan.Zero)
                    {
                        tilNextUpdate = TimeSpan.Zero;
                    }
                }

                // We broke out of the loop.  Determine the reason and report the result.
                scanIsTotallyCompleted = await WrapUpScanAsync().ConfigureAwait(false);
            }
            catch(Exception Ex)
            {
                // Make a best effort to report the exception data.
                Log.TraceEvent(TraceEventType.Critical, 0, "Scanner for event {0} encountered an exception and will terminate: {1}", this.Traits.EventId, Ex.ToString());

                string data = null;
                if (Ex is System.AggregateException)
                {
                    if (Ex.InnerException is System.Data.Entity.Validation.DbEntityValidationException)
                    {
                        StringBuilder sb = new StringBuilder();
                        var dbException = Ex.InnerException as System.Data.Entity.Validation.DbEntityValidationException;
                        foreach (var entry in dbException.EntityValidationErrors)
                        {
                            sb.AppendFormat("Entity Validation error: {0}", entry.Entry.ToString());
                            foreach (var subentry in entry.ValidationErrors)
                            {
                                sb.AppendFormat("Db validation error for property {0}: {1}", subentry.PropertyName, subentry.ErrorMessage);
                            }
                        }
                        data = sb.ToString();
                        Log.TraceEvent(TraceEventType.Critical, 0, "Validation errors: {0}", sb.ToString());
                    }
                }

                _participationHandle.AddInfoAsync(InfoLevel.Error, Ex.ToString(), data).Wait();
                _participationHandle.LeaveAsync(ParticipantState.Faulted).Wait();
                throw;
            }
            finally
            {
                // At this point, we've exited the scan loop.  It was either because the scan is done
                // or because we were canceled.  We may have already called out to our subscribers, but
                // if we didn't, make sure it happens now.
                if (!_scanEnded)
                {
                    Log.TraceInformation("Notifying subscribers that scan has ended, totallyComplete={0}, _canceled={1}", scanIsTotallyCompleted, _cancelScan);
                    _monitor.EndScan(this, scanIsTotallyCompleted, !_cancelScan);
                }

                if (OnWorkerFinished != null)
                {
                    // This is intentionally run asynchronously and not awaited.
                    Task.Run(() =>
                    {
                        OnWorkerFinished(scanIsTotallyCompleted);
                    });
                }
            }
        }