public void TestNoData() { var buffer = new PagedLogBuffer(1024, 10, Core.Columns.RawContent); buffer.ResizeTo(12); var destination = new LogBufferArray(12, PageBufferedLogSource.RetrievalState, Core.Columns.RawContent); destination[0].RawContent = "Foo"; destination[1].RawContent = "Bar"; destination[10].RawContent = "Big Smoke"; destination[11].RawContent = "Sup"; buffer.TryGetEntries(new LogSourceSection(0, 10), destination, 1).Should().BeFalse("because the cache is completely empty and thus no data should have been retrieved"); destination[0].RawContent.Should() .Be("Foo", "because only the data from the specified offset onward may have been overwritten"); for (int i = 1; i < 11; ++i) { destination[i].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotCached); destination[i].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue, "because when the region couldn't be read from the cache, then it should have been defaulted"); } destination[11].RawContent.Should().Be("Sup"); }
public void TestRequestPartiallyCached_Segmented_ReadFromTwoPages() { var buffer = new PagedLogBuffer(1024, 10, Core.Columns.RawContent); buffer.ResizeTo(12); var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent) { new LogEntry(), new LogEntry { RawContent = "Dina", }, new LogEntry { RawContent = "Jesse" } }; buffer.TryAdd(new LogSourceSection(7, 2), data, 1); var destination = new LogBufferArray(11, Core.Columns.Index, Core.Columns.RawContent); buffer.TryGetEntries(new LogSourceSection(4, 5), destination, 6).Should().BeFalse("because we managed to only retrieve the data partially"); for (int i = 6; i < 9; ++i) { destination[i].Index.Should().Be(Core.Columns.Index.DefaultValue); destination[i].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue); } destination[9].Index.Should().Be(7); destination[9].RawContent.Should().Be("Dina"); destination[10].Index.Should().Be(8); destination[10].RawContent.Should().Be("Jesse"); }
public void TestCopyFromUnknownColumn() { var buffer = new LogBufferArray(2, Core.Columns.Timestamp); new Action(() => buffer.CopyFrom(Core.Columns.RawContent, 0, new string[0], 0, 0)) .Should().Throw <NoSuchColumnException>(); }
public void TestTryGetEntries_DestinationTooSmall() { var buffer = new PagedLogBuffer(4, 2, Core.Columns.RawContent); buffer.ResizeTo(4); var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent) { new LogEntry { RawContent = "A" }, new LogEntry { RawContent = "B" }, new LogEntry { RawContent = "C" }, new LogEntry { RawContent = "D" } }; buffer.TryAdd(new LogSourceSection(0, 8), data, 0); var destination = new LogBufferArray(2, Core.Columns.Index, Core.Columns.RawContent); destination[0].RawContent = "1"; destination[1].RawContent = "2"; new Action(() => buffer.TryGetEntries(new LogSourceSection(0, 2), destination, 1)) .Should().Throw <ArgumentException>("because the destination is too small"); destination[0].RawContent.Should().Be("1", "because the original data may not have been overwritten"); destination[1].RawContent.Should().Be("2", "because the original data may not have been overwritten"); }
public void Export(IProgress <Percentage> progressReporter = null) { const int bufferSize = 1000; var buffer = new LogBufferArray(bufferSize, Columns.Index, Columns.RawContent); var count = _logSource.GetProperty(Properties.LogEntryCount); var index = 0; using (var writer = new StreamWriter(_stream, Encoding.UTF8, 1024, true)) { while (index < count) { var remaining = count - index; if (remaining > bufferSize) { remaining = bufferSize; } if (!ExportPortion(writer, buffer, index, remaining)) { break; } index += remaining; var progress = Percentage.Of(index, count); progressReporter?.Report(progress); } } }
private bool ExportPortion(StreamWriter writer, LogBufferArray array, int index, int count) { try { _logSource.GetEntries(new LogSourceSection(index, count), array); for (var i = 0; i < count; ++i) { if (_written) { writer.WriteLine(); } var logLine = array[i]; if (logLine.Index == LogLineIndex.Invalid) //< EOF { break; } writer.Write(logLine.RawContent); _written = true; } return(true); } catch (IndexOutOfRangeException) { // The file has been invalidated and reduced in size already. // That's okay and we can end this export.... return(false); } }
public void TestCopyFromNullColumn() { var buffer = new LogBufferArray(2, Core.Columns.Timestamp); new Action(() => buffer.CopyFrom(null, 0, new string[0], 0, 0)) .Should().Throw <ArgumentNullException>(); }
public PresentationLogSource(ITaskScheduler scheduler, ILogSource source, TimeSpan maximumWaitTime, TextSettings textSettings) : base(scheduler) { if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } if (source == null) { throw new ArgumentNullException(nameof(source)); } _maximumWaitTime = maximumWaitTime; _textSettings = textSettings; _source = source; _indices = new LogBufferList(IndexedColumns); _array = new LogBufferArray(MaximumLineCount, Core.Columns.RawContent); _pendingModifications = new ConcurrentQueue <PendingModification>(); _syncRoot = new object(); _source.AddListener(this, _maximumWaitTime, MaximumLineCount); StartTask(); }
public LogSourceSearch(ITaskScheduler taskScheduler, ILogSource logSource, string searchTerm, TimeSpan maximumWaitTime) { if (taskScheduler == null) { throw new ArgumentNullException(nameof(taskScheduler)); } if (logSource == null) { throw new ArgumentNullException(nameof(logSource)); } if (string.IsNullOrEmpty(searchTerm)) { throw new ArgumentException("searchTerm may not be empty"); } _logSource = logSource; _filter = new SubstringFilter(searchTerm, true); _matches = new List <LogMatch>(); _syncRoot = new object(); _listeners = new LogFileSearchListenerCollection(this); _pendingModifications = new ConcurrentQueue <LogSourceModification>(); _scheduler = taskScheduler; const int maximumLineCount = 1000; _maximumWaitTime = maximumWaitTime; _logLinesArray = new LogBufferArray(maximumLineCount, Columns.Index, Columns.RawContent); _matchesBuffer = new List <LogLineMatch>(); _logSource.AddListener(this, _maximumWaitTime, maximumLineCount); _task = _scheduler.StartPeriodic(FilterAllPending, TimeSpan.FromMilliseconds(100), string.Format("Search {0}", logSource)); }
protected override IReadOnlyLogEntry CreateEmpty() { // TODO: Swap var buffer = new LogBufferArray(1); return(buffer[0]); }
protected override IReadOnlyLogEntry CreateDefault() { // TODO: Swap var buffer = new LogBufferArray(1, Core.Columns.Minimum); return(buffer[0]); }
public void TestPrefetchAsyncBatch() { var pageSize = 100; var buffer = new PageBufferedLogSource(_taskScheduler, _source.Object, TimeSpan.Zero, pageSize: pageSize); var destination = new LogBufferArray(4, new IColumnDescriptor[] { Core.Columns.Index, Core.Columns.RawContent }); var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromCache | LogSourceQueryMode.FetchForLater); buffer.OnLogFileModified(_source.Object, LogSourceModification.Appended(0, 10)); var section1ToQuery = new LogSourceSection(2, 4); buffer.GetEntries(section1ToQuery, destination, 0, queryOptions); _source.Verify(x => x.GetEntries(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <ILogBuffer>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>()), Times.Never, "Because we didn't allow data to be retrieved on the calling thread"); var section2ToQuery = new LogSourceSection(7, 3); buffer.GetEntries(section2ToQuery, destination, 0, queryOptions); _source.Verify(x => x.GetEntries(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <ILogBuffer>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>()), Times.Never, "Because we didn't allow data to be retrieved on the calling thread"); _taskScheduler.RunOnce(); _source.Verify(x => x.GetEntries(new LogSourceSection(0, pageSize), It.IsAny <ILogBuffer>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>()), Times.Once, "Because the buffer should avoid reading the same data for the same page multiple times in a row"); }
public void TestRequestFullyCached_Contiguous_ReadFromMultiplePages() { var buffer = new PagedLogBuffer(1024, 10, Core.Columns.RawContent); var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent); for (int i = 0; i < 5 * 1024; ++i) { data.Add(new LogEntry { Index = i, RawContent = i.ToString() }); } buffer.ResizeTo(data.Count); buffer.TryAdd(new LogSourceSection(0, data.Count), data, 0); var destination = new LogBufferArray(2048, Core.Columns.Index, Core.Columns.RawContent); var readOffset = 1024; buffer.TryGetEntries(new LogSourceSection(readOffset, destination.Count), destination, 0).Should().BeTrue("because all requested data is part of the cache"); for (int i = 0; i < destination.Count; ++i) { var logEntry = destination[i]; logEntry.Index.Should().Be(readOffset + i); logEntry.RawContent.Should().Be((readOffset + i).ToString()); } }
public void TestRetrieveFromPartiallyFilledPage_CreatedBeforeResize() { var buffer = new PagedLogBuffer(10, 1, Core.Columns.RawContent); buffer.ResizeTo(2); var data = new LogBufferList(Core.Columns.RawContent) { new LogEntry { RawContent = "A" }, new LogEntry { RawContent = "B" } }; buffer.TryAdd(new LogSourceSection(0, 2), data, 0); buffer.ResizeTo(4); var destination = new LogBufferArray(6, PageBufferedLogSource.RetrievalState, Core.Columns.RawContent); buffer.TryGetEntries(new LogSourceSection(0, 6), destination, 0).Should().BeFalse("because the cache is only partially filled"); destination[0].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.Retrieved); destination[1].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.Retrieved); destination[2].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotCached); destination[3].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotCached); destination[4].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotInSource); destination[5].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotInSource); }
public void TestConstruction2([Values(1, 2, 5, 10, 42, 100, 9001)] int count) { var buffer = new LogBufferArray(count); buffer.Columns.Should().BeEmpty(); buffer.Count.Should().Be(count); buffer.Should().HaveCount(count); }
public void TestCopyFrom() { var buffer = new LogBufferArray(1, Core.Columns.Timestamp); var timestamp = new DateTime(2017, 12, 11, 21, 41, 0); buffer.CopyFrom(Core.Columns.Timestamp, new DateTime?[] { timestamp }); buffer[0].Timestamp.Should().Be(timestamp, "Because we've just copied this timestamp to the buffer"); }
public void TestGetEntryByIndex1([Values(-1, 0, 1)] int invalidIndex) { var buffer = new LogBufferArray(0); new Action(() => { var unused = buffer[invalidIndex]; }).Should().Throw <IndexOutOfRangeException>(); }
public void TestIgnoreDataOutOfBounds() { var buffer = new PagedLogBuffer(4, 2, Core.Columns.RawContent); buffer.ResizeTo(4); var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent) { new LogEntry { RawContent = "A" }, new LogEntry { RawContent = "B" }, new LogEntry { RawContent = "C" }, new LogEntry { RawContent = "D" }, new LogEntry { RawContent = "E" }, new LogEntry { RawContent = "F" }, new LogEntry { RawContent = "G" }, new LogEntry { RawContent = "H" }, }; buffer.TryAdd(new LogSourceSection(0, 8), data, 0); var destination = new LogBufferArray(8, Core.Columns.Index, PageBufferedLogSource.RetrievalState, Core.Columns.RawContent); buffer.TryGetEntries(new LogSourceSection(0, 8), destination, 0).Should().BeFalse("because even though we've tried to add 8 elements to the buffer, only the first 4 are part of the entire log file section and thus the others should have been ignored"); destination[0].RawContent.Should().Be("A"); destination[1].RawContent.Should().Be("B"); destination[2].RawContent.Should().Be("C"); destination[3].RawContent.Should().Be("D"); for (int i = 0; i < 4; ++i) { destination[i].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.Retrieved); } for (int i = 4; i < 8; ++i) { destination[i].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue); destination[i].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotInSource); } }
public void TestCopyFromPartial3() { var buffer = new LogBufferArray(2, Core.Columns.Timestamp); var timestamp = new DateTime(2017, 12, 11, 21, 41, 0); buffer.CopyFrom(Core.Columns.Timestamp, 1, new DateTime?[] { timestamp }, 0, 1); buffer[0].Timestamp.Should().BeNull("because we didn't copy any data for this timestamp"); buffer[1].Timestamp.Should().Be(timestamp, "Because we've just copied this timestamp to the buffer"); }
public void TestSkipSourceIfNotAllowed() { var buffer = new PageBufferedLogSource(_taskScheduler, _source.Object, TimeSpan.Zero); var destination = new LogBufferArray(4, new IColumnDescriptor[] { Core.Columns.Index, Core.Columns.RawContent }); var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromCache); buffer.GetEntries(new LogSourceSection(10, 4), destination, 0, queryOptions); _source.Verify(x => x.GetEntries(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <ILogBuffer>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>()), Times.Never, "because we didn't allow the data to be retrieved from the source under any circumstances"); }
public void TestConstruction3([Values(1, 2, 5, 10, 42, 100, 9001)] int count) { var buffer = new LogBufferArray(count, new List <IColumnDescriptor> { Core.Columns.RawContent, Core.Columns.DeltaTime }); buffer.Columns.Should().Equal(new object[] { Core.Columns.RawContent, Core.Columns.DeltaTime }); buffer.Count.Should().Be(count); buffer.Should().HaveCount(count); }
public void TestFetchFromSourceWhenNotAllowedFromCache() { var buffer = new PageBufferedLogSource(_taskScheduler, _source.Object, TimeSpan.Zero); var destination = new LogBufferArray(4, new IColumnDescriptor[] { Core.Columns.Index, Core.Columns.RawContent }); var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromSource); buffer.GetEntries(new LogSourceSection(10, 4), destination, 0, queryOptions); _source.Verify(x => x.GetEntries(new LogSourceSection(10, 4), destination, 0, queryOptions), Times.Once); }
public void TestCopyFromManyRows() { const int count = 1000; var buffer = new LogBufferArray(count, Core.Columns.OriginalIndex); buffer.CopyFrom(Core.Columns.OriginalIndex, Enumerable.Range(0, count).Select(i => (LogLineIndex)i).ToArray()); for (int i = 0; i < count; ++i) { buffer[i].OriginalIndex.Should().Be(i); } }
public void TestCopyFromOverwrite() { var buffer = new LogBufferArray(2, Core.Columns.RawContent); buffer[0].RawContent.Should().BeNull(); buffer[1].RawContent.Should().BeNull(); buffer.CopyFrom(Core.Columns.RawContent, new [] { "foo", "bar" }); buffer[0].RawContent.Should().Be("foo"); buffer[1].RawContent.Should().Be("bar"); }
public void TestContainsColumn() { var buffer = new LogBufferArray(42, new IColumnDescriptor[] { Core.Columns.LogLevel, Core.Columns.Index, Core.Columns.RawContent }); buffer.Contains(Core.Columns.LogLevel).Should().BeTrue(); buffer.Contains(Core.Columns.Index).Should().BeTrue(); buffer.Contains(Core.Columns.RawContent).Should().BeTrue(); buffer.Contains(Core.Columns.Message).Should().BeFalse(); buffer.Contains(Core.Columns.OriginalLineNumber).Should().BeFalse(); buffer.Contains(Core.Columns.DeltaTime).Should().BeFalse(); }
public void TestAccessUnavailableColumn() { var buffer = new LogBufferArray(1); new Action(() => { var unused = buffer[0].RawContent; }).Should().Throw <ColumnNotRetrievedException>(); new Action(() => { var unused = buffer[0].Index; }).Should().Throw <ColumnNotRetrievedException>(); new Action(() => { var unused = buffer[0].OriginalIndex; }).Should().Throw <ColumnNotRetrievedException>(); new Action(() => { var unused = buffer[0].LineNumber; }).Should().Throw <ColumnNotRetrievedException>(); new Action(() => { var unused = buffer[0].OriginalLineNumber; }).Should().Throw <ColumnNotRetrievedException>(); new Action(() => { var unused = buffer[0].Timestamp; }).Should().Throw <ColumnNotRetrievedException>(); new Action(() => { var unused = buffer[0].ElapsedTime; }).Should().Throw <ColumnNotRetrievedException>(); new Action(() => { var unused = buffer[0].DeltaTime; }).Should().Throw <ColumnNotRetrievedException>(); }
public void TestFillInvalidLength() { var buffer = new LogBufferArray(10, Core.Columns.LineNumber); buffer.Fill(Core.Columns.LineNumber, 42, 0, 10); new Action(() => buffer.Fill(Core.Columns.LineNumber, 9001, 0, 11)) .Should().Throw <ArgumentException>(); for (int i = 0; i < 10; ++i) { buffer[i].LineNumber.Should().Be(42, "because nothing may have been overwritten"); } }
public void TestReadPreviouslyInvalidatedButNowAvailableRegions_PartialPageEviction() { var buffer = new PagedLogBuffer(4, 2, Core.Columns.RawContent); buffer.ResizeTo(16); var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent) { new LogEntry { RawContent = "A" }, new LogEntry { RawContent = "B" }, new LogEntry { RawContent = "C" }, new LogEntry { RawContent = "D" }, new LogEntry { RawContent = "E" }, new LogEntry { RawContent = "F" }, new LogEntry { RawContent = "G" }, new LogEntry { RawContent = "H" }, }; buffer.TryAdd(new LogSourceSection(0, 8), data, 0); buffer.ResizeTo(6); buffer.ResizeTo(8); var destination = new LogBufferArray(8, Core.Columns.Index, Core.Columns.RawContent); buffer.TryGetEntries(new LogSourceSection(0, 8), destination, 0).Should().BeFalse("because the data has been partially invalidated"); destination[0].RawContent.Should().Be("A"); destination[1].RawContent.Should().Be("B"); destination[2].RawContent.Should().Be("C"); destination[3].RawContent.Should().Be("D"); destination[4].RawContent.Should().Be("E"); destination[5].RawContent.Should().Be("F"); destination[6].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue, "because this row has been invalidated when the log source was downsized"); destination[7].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue, "because this row has been invalidated when the log source was downsized"); }
public void TestRequestFullyCached_Contiguous() { var buffer = new PagedLogBuffer(1024, 10, Core.Columns.RawContent); buffer.ResizeTo(12); var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent) { new LogEntry { Index = 2, RawContent = "Scrambled Data", }, new LogEntry { Index = 3, RawContent = "This is awesome" }, new LogEntry { Index = 4, RawContent = "Yup" }, new LogEntry { Index = 5, RawContent = "Twist!" }, new LogEntry { Index = 10, RawContent = "I shouldn't be cached" } }; buffer.TryAdd(new LogSourceSection(3, 3), data, 1); var destination = new LogBufferArray(5, Core.Columns.Index, Core.Columns.RawContent); destination[0].Index = 32; destination[0].RawContent = "Foo"; destination[1].Index = 42; destination[1].RawContent = "Bar"; destination[4].Index = 9001; destination[4].RawContent = "His power level is over 9000!"; buffer.TryGetEntries(new LogSourceSection(3, 2), destination, 2).Should().BeTrue(); destination[0].Index.Should().Be(32, "because we specified an offset and the data before it should not have been overwritten"); destination[0].RawContent.Should().Be("Foo", "because we specified an offset and the data before it should not have been overwritten"); destination[1].Index.Should().Be(42, "because we specified an offset and the data before it should not have been overwritten"); destination[1].RawContent.Should().Be("Bar", "because we specified an offset and the data before it should not have been overwritten"); destination[2].Index.Should().Be(data[1].Index); destination[2].RawContent.Should().Be(data[1].RawContent); destination[3].Index.Should().Be(data[2].Index); destination[3].RawContent.Should().Be(data[2].RawContent); destination[4].Index.Should().Be(9001, "because the data after the requested region shouldn't have been overwritten"); destination[4].RawContent.Should().Be("His power level is over 9000!", "because the data after the requested region shouldn't have been overwritten"); }
public void TestCopyFromMultipleColumns() { var buffer = new LogBufferArray(2, Core.Columns.Index, Core.Columns.Timestamp); buffer.CopyFrom(Core.Columns.Index, new LogLineIndex[] { 1, 42 }); buffer.CopyFrom(Core.Columns.Timestamp, new DateTime?[] { DateTime.MinValue, DateTime.MaxValue }); buffer[0].Index.Should().Be(1); buffer[0].Timestamp.Should().Be(DateTime.MinValue); buffer[1].Index.Should().Be(42); buffer[1].Timestamp.Should().Be(DateTime.MaxValue); }