예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <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);
        }