コード例 #1
0
        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()));
        }
コード例 #2
0
        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);
        }
コード例 #3
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));
        }
コード例 #4
0
        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));
        }
コード例 #5
0
        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.");
                }
            }
        }
コード例 #6
0
 public void SetUp()
 {
     queue       = new ConcurrentBoundedQueue <string>(Capacity);
     drainResult = new string[Capacity];
 }
コード例 #7
0
 public ConsoleLogMuxer(IEventsWriter eventsWriter, int eventsQueueCapacity, int temporaryBufferCapacity)
 {
     this.eventsWriter = eventsWriter;
     temporaryBuffer   = new LogEventInfo[temporaryBufferCapacity];
     events            = new ConcurrentBoundedQueue <LogEventInfo>(eventsQueueCapacity);
 }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
 public RotatingRequestLogger(int capacity, LogLevel level)
 {
     _innerQueue = new ConcurrentBoundedQueue <LogEntryEventArgs>(capacity);
     Level       = level;
 }