示例#1
0
        private void LogEvents()
        {
            var eventsToDrain = events.Count;

            while (eventsToDrain > 0)
            {
                var eventsDrained = events.Drain(temporaryBuffer, 0, temporaryBuffer.Length);
                if (eventsDrained == 0)
                {
                    break;
                }

                eventsToDrain -= eventsDrained;

                try
                {
                    eventsWriter.WriteEvents(temporaryBuffer, eventsDrained);
                }
                catch
                {
                    Interlocked.Add(ref eventsLost, eventsDrained);
                    throw;
                }
            }

            var currentEventsLost = EventsLost;

            if (currentEventsLost > eventsLostSinceLastIteration)
            {
                temporaryBuffer[0] = CreateOverflowEvent(currentEventsLost - eventsLostSinceLastIteration);
                eventsWriter.WriteEvents(temporaryBuffer, 1);

                eventsLostSinceLastIteration = currentEventsLost;
            }
        }
        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 Drain_should_return_empty_array_when_queue_is_empty()
 {
     queue.Drain(drainResult, 0, drainResult.Length);
     drainResult.Should().Equal(Enumerable.Repeat((string)null, Capacity));
 }
示例#4
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);
        }
        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);
        }