private LogEventInfo CreateOverflowEvent(ConcurrentBoundedQueue <LogEventInfo> queue, long discardedEvents) { var message = $"[{nameof(FileLog)}] Buffer overflow. {discardedEvents} log events were lost (events queue capacity = {queue.Capacity})."; var logEvent = new LogEvent(LogLevel.Warn, DateTimeOffset.Now, message); return(new LogEventInfo(logEvent, new FileLogSettings())); }
public void TestSetup() { writer = Substitute.For <IEventsWriter>(); writerProvider = Substitute.For <IEventsWriterProvider>(); writerProvider.ObtainWriterAsync(Arg.Any <CancellationToken>()).Returns(writer); worker = new SingleFileWorker(); events = new ConcurrentBoundedQueue <LogEventInfo>(2); buffer = new LogEventInfo[1]; eventsLost = new AtomicLong(0); }
public void TryEnqueueTryDequeue() { var queue = new ConcurrentBoundedQueue <int>(100); int value = 0; Assert.False(queue.TryDequeue(out value)); Assert.True(queue.TryEnqueue(1)); Assert.True(queue.TryEnqueue(2)); Assert.True(queue.TryDequeue(out value)); Assert.AreEqual(1, value); Assert.True(queue.TryDequeue(out value)); Assert.AreEqual(2, value); Assert.False(queue.TryDequeue(out value)); }
public void TryEnqueueQueueFull() { var queue = new ConcurrentBoundedQueue <int>(3); Assert.True(queue.TryEnqueue(1)); Assert.True(queue.TryEnqueue(2)); Assert.True(queue.TryEnqueue(3)); Assert.False(queue.TryEnqueue(4)); int value = -1; Assert.True(queue.TryDequeue(out value)); Assert.AreEqual(1, value); Assert.True(queue.TryEnqueue(5)); Assert.False(queue.TryEnqueue(6)); }
public void Should_not_have_race_between_Add_and_Drain_that_turns_queue_wait_task_to_inconsistent_state() { for (var j = 0; j < 10; ++j) { var queue = new ConcurrentBoundedQueue <object>(100); var o = new object(); var addTask = Task.Run( () => { for (var i = 0; i < 1000000; i++) { if (!queue.TryAdd(o)) { i--; } } }); var drainTask = Task.Run( () => { var arr = new object[1000]; while (true) { var drained = queue.Drain(arr, 0, arr.Length); if (drained == 0 && addTask.IsCompleted) { return; } } }); Task.WhenAll(drainTask, addTask).GetAwaiter().GetResult(); if (queue.WaitForNewItemsAsync().IsCompleted&& queue.Count == 0) { Assert.Fail("Queue is broken: TryWaitForNewItemsAsync is completed, but queue is empty."); } } }
public void SetUp() { queue = new ConcurrentBoundedQueue <string>(Capacity); drainResult = new string[Capacity]; }
public ConsoleLogMuxer(IEventsWriter eventsWriter, int eventsQueueCapacity, int temporaryBufferCapacity) { this.eventsWriter = eventsWriter; temporaryBuffer = new LogEventInfo[temporaryBufferCapacity]; events = new ConcurrentBoundedQueue <LogEventInfo>(eventsQueueCapacity); }
public async Task <bool> WritePendingEventsAsync( IEventsWriterProvider writerProvider, ConcurrentBoundedQueue <LogEventInfo> queue, LogEventInfo[] buffer, AtomicLong eventsLostCurrently, AtomicLong eventsLostSinceLastIteration, CancellationToken cancellation) { var eventsToDrain = queue.Count; if (eventsToDrain == 0) { return(true); } var writer = await writerProvider.ObtainWriterAsync(cancellation).ConfigureAwait(false); if (writer == null) { return(false); } while (eventsToDrain > 0) { var eventsDrained = queue.Drain(buffer, 0, buffer.Length); if (eventsDrained == 0) { break; } eventsToDrain -= eventsDrained; try { writer.WriteEvents(buffer, eventsDrained); } catch (Exception error) { eventsLostCurrently.Add(eventsDrained); SafeConsole.ReportError("Failure in writing log events to a file:", error); break; } finally { Array.Clear(buffer, 0, eventsDrained); } } var lostEventsAfterWriting = eventsLostCurrently.Value; if (lostEventsAfterWriting > eventsLostSinceLastIteration) { buffer[0] = CreateOverflowEvent(queue, lostEventsAfterWriting - eventsLostSinceLastIteration); try { writer.WriteEvents(buffer, 1); } catch { // ignored } eventsLostSinceLastIteration.Value = lostEventsAfterWriting; return(false); } return(true); }
public void All_successfully_added_items_should_be_eventually_consumed(int capacity, int writersCount) { var addedItemsCount = 0; var drainedItemsCount = 0; var queue = new ConcurrentBoundedQueue <object>(capacity); var cancellation = new CancellationTokenSource(); var cancellationToken = cancellation.Token; var trigger = new CountdownEvent(writersCount + 1); var writers = Enumerable.Range(0, writersCount) .Select( _ => Task.Run( () => { trigger.Signal(); trigger.Wait(); while (!cancellationToken.IsCancellationRequested) { var item = new object(); if (queue.TryAdd(item)) { Interlocked.Increment(ref addedItemsCount); } } })) .ToArray(); var reader = Task.Run( async() => { trigger.Signal(); trigger.Wait(); var buffer = new object[10]; while (!cancellation.IsCancellationRequested || writers.Any(w => !w.IsCompleted) || queue.Count > 0) { if (!await queue.TryWaitForNewItemsAsync(100.Milliseconds()).ConfigureAwait(false)) { if (writers.Any(w => !w.IsCompleted)) { throw new Exception("Wait seems to be stuck."); } } var count = queue.Drain(buffer, 0, buffer.Length); drainedItemsCount += count; } }); Thread.Sleep(10.Seconds()); cancellation.Cancel(); Task.WaitAll(writers); reader.Wait(); Console.WriteLine($"added: {addedItemsCount}, drained: {drainedItemsCount}"); queue.Count.Should().Be(0); drainedItemsCount.Should().Be(addedItemsCount); }
public RotatingRequestLogger(int capacity, LogLevel level) { _innerQueue = new ConcurrentBoundedQueue <LogEntryEventArgs>(capacity); Level = level; }