/// <inheritdoc /> protected override TimeSpan RunOnce(CancellationToken token) { bool performedWork = false; LogFileSection section; while (_pendingModifications.TryDequeue(out section) && !token.IsCancellationRequested) { if (section.IsReset) { Clear(); _lastLogEntry.Clear(); _currentSourceIndex = 0; } else if (section.IsInvalidate) { LogLineIndex startIndex = section.Index; _fullSourceSection = new LogFileSection(0, (int)startIndex); if (_currentSourceIndex > _fullSourceSection.LastIndex) { _currentSourceIndex = (int)section.Index; } Invalidate(_currentSourceIndex); RemoveInvalidatedLines(_lastLogEntry, _currentSourceIndex); } else { _fullSourceSection = LogFileSection.MinimumBoundingLine(_fullSourceSection, section); } performedWork = true; } if (!_fullSourceSection.IsEndOfSection(_currentSourceIndex)) { int remaining = _fullSourceSection.Index + _fullSourceSection.Count - _currentSourceIndex; int nextCount = Math.Min(remaining, BatchSize); var nextSection = new LogFileSection(_currentSourceIndex, nextCount); _source.GetSection(nextSection, _buffer); for (int i = 0; i < nextCount; ++i) { if (token.IsCancellationRequested) { break; } LogLine line = _buffer[i]; if (_lastLogEntry.Count == 0 || _lastLogEntry[0].LogEntryIndex == line.LogEntryIndex) { TryAddLogLine(line); } else if (line.LogEntryIndex != _lastLogEntry[0].LogEntryIndex) { TryAddLogEntry(_lastLogEntry); _lastLogEntry.Clear(); TryAddLogLine(line); } } _currentSourceIndex += nextCount; } if (_fullSourceSection.IsEndOfSection(_currentSourceIndex)) { TryAddLogEntry(_lastLogEntry); Listeners.OnRead(_indices.Count); if (_source.EndOfSourceReached) { SetEndOfSourceReached(); } } if (performedWork) { return(TimeSpan.Zero); } return(_maximumWaitTime); }
/// <inheritdoc /> protected override TimeSpan RunOnce(CancellationToken token) { var lastCount = _fullSourceSection.Count; bool performedWork = false; LogFileSection section; while (_pendingModifications.TryDequeue(out section) && !token.IsCancellationRequested) { if (section.IsReset) { Clear(); } else if (section.IsInvalidate) { Invalidate(section); } else { _fullSourceSection = LogFileSection.MinimumBoundingLine(_fullSourceSection, section); } performedWork = true; } if (!_fullSourceSection.IsEndOfSection(_currentSourceIndex)) { var remaining = Math.Min(_fullSourceSection.Count - _currentSourceIndex, MaximumBatchSize); var buffer = new LogLine[remaining]; _source.GetSection(new LogFileSection(_currentSourceIndex, remaining), buffer); LogLineIndex?resetIndex = null; lock (_syncRoot) { for (var i = 0; i < remaining; ++i) { var line = buffer[i]; if (_currentLogEntry.EntryIndex.IsInvalid || line.Level != LevelFlags.None || _currentLogEntryLevel == LevelFlags.None) { _currentLogEntry = _currentLogEntry.NextEntry(line.LineIndex); _currentLogEntryLevel = line.Level; } else if (_currentLogEntry.FirstLineIndex < lastCount && resetIndex == null) { var index = _currentLogEntry.FirstLineIndex; resetIndex = index; _currentLogEntryLevel = _source.GetLine((int)index).Level; } _indices.Add(_currentLogEntry); } } if (resetIndex != null) { var resetCount = lastCount - resetIndex.Value; if (resetCount > 0) { Listeners.Invalidate((int)resetIndex.Value, resetCount); } } _currentSourceIndex += remaining; } // Now we can perform a block-copy of all properties. _source.GetValues(_properties); _maxCharactersPerLine = _source.MaxCharactersPerLine; if (_indices.Count != _currentSourceIndex) { Log.ErrorFormat("Inconsistency detected: We have {0} indices for {1} lines", _indices.Count, _currentSourceIndex); } Listeners.OnRead((int)_currentSourceIndex); if (_source.EndOfSourceReached && _fullSourceSection.IsEndOfSection(_currentSourceIndex)) { SetEndOfSourceReached(); } if (performedWork) { return(TimeSpan.Zero); } return(_maximumWaitTime); }