コード例 #1
0
        public void MoveNextReturnsFalseAfterDataEnds()
        {
            var data   = new[] { 1 };
            var cursor = new AsyncCursor <Int32>(data);

            cursor.MoveNext().Should().BeTrue();
            cursor.MoveNext().Should().BeFalse();
        }
コード例 #2
0
        public void CurrentReturnsDataAfterMoveNext()
        {
            var data   = new[] { 1 };
            var cursor = new AsyncCursor <Int32>(data);

            cursor.MoveNext().Should().BeTrue();
            cursor.Current.Should().BeSameAs(data);
        }
コード例 #3
0
        public async Task CurrentReturnsDataAfterMoveNextAsync()
        {
            var data   = new[] { 1 };
            var cursor = new AsyncCursor <Int32>(data);

            var moveNextResult = await cursor.MoveNextAsync();

            moveNextResult.Should().BeTrue();
            cursor.Current.Should().BeSameAs(data);
        }
コード例 #4
0
        public void CurrentThrowsExceptionBeforeMoveNext()
        {
            var data   = new[] { 1 };
            var cursor = new AsyncCursor <int>(data);

            using (cursor)
            {
                Func <IEnumerable <int> > func = () => cursor.Current;
                func.Should().Throw <InvalidOperationException>();
            }
        }
コード例 #5
0
        public void MoveNextThrowsExceptionAfterEnumerationFinishes()
        {
            var data   = new[] { 1 };
            var cursor = new AsyncCursor <Int32>(data);

            cursor.MoveNext();
            cursor.MoveNext();

            Action action = () => cursor.MoveNext();

            action.ShouldThrow <InvalidOperationException>();
        }
コード例 #6
0
        public void CurrentThrowsExceptionBeforeMoveNext()
        {
            var data   = new[] { 1 };
            var cursor = new AsyncCursor <Int32>(data);

            Action action = () =>
            {
                var c = cursor.Current;
            };

            action.ShouldThrow <InvalidOperationException>();
        }
コード例 #7
0
        // public methods
        public IEnumerator <BsonDocument> GetEnumerator()
        {
            if (_outputCollectionName != null)
            {
                var database           = _collection.Database;
                var collectionSettings = new MongoCollectionSettings {
                    ReadPreference = ReadPreference.Primary
                };
                var collection = database.GetCollection <BsonDocument>(_outputCollectionName, collectionSettings);
                return(collection.FindAll().GetEnumerator());
            }

            var result = _collection.RunAggregateCommand(_args);

            if (result.CursorId != 0)
            {
                var batchSize      = _args.BatchSize ?? 0;
                var cursorId       = result.CursorId;
                var firstBatch     = result.ResultDocuments.ToList();
                var query          = new BsonDocument(); // TODO: what should the query be?
                var readPreference = _collection.Settings.ReadPreference ?? ReadPreference.Primary;
                var serializer     = BsonDocumentSerializer.Instance;

                using (var binding = _collection.Database.Server.GetReadBinding(readPreference))
                    using (var connectionSource = binding.GetReadConnectionSource(Timeout.InfiniteTimeSpan, CancellationToken.None))
                    {
                        var cursor = new AsyncCursor <BsonDocument>(
                            connectionSource.Fork(),
                            new CollectionNamespace(_collection.Database.Name, _collection.Name),
                            query,
                            firstBatch,
                            cursorId,
                            batchSize,
                            0, // limit
                            serializer,
                            _messageEncoderSettings,
                            Timeout.InfiniteTimeSpan,
                            CancellationToken.None);

                        return(new AsyncCursorEnumeratorAdapter <BsonDocument>(cursor).GetEnumerator());
                    }
            }
            else if (result.ResultDocuments != null)
            {
                return(result.ResultDocuments.GetEnumerator());
            }
            else
            {
                throw new NotSupportedException("Unexpected response to aggregate command.");
            }
        }
コード例 #8
0
        public void constructor_should_initialize_instance()
        {
            var channelSource = Substitute.For<IChannelSource>();
            var databaseNamespace = new DatabaseNamespace("test");
            var collectionNamespace = new CollectionNamespace(databaseNamespace, "test");
            var query = new BsonDocument("x", 1);
            var firstBatch = new BsonDocument[] { new BsonDocument("y", 2) };
            var cursorId = 1L;
            var batchSize = 2;
            var limit = 3;
            var serializer = BsonDocumentSerializer.Instance;
            var messageEncoderSettings = new MessageEncoderSettings();
            var maxTime = TimeSpan.FromSeconds(1);

            var result = new AsyncCursor<BsonDocument>(
                channelSource,
                collectionNamespace,
                query,
                firstBatch,
                cursorId,
                batchSize,
                limit,
                serializer,
                messageEncoderSettings,
                maxTime);

            var reflector = new Reflector(result);
            reflector.BatchSize.Should().Be(batchSize);
            reflector.ChannelSource.Should().Be(channelSource);
            reflector.CollectionNamespace.Should().Be(collectionNamespace);
            reflector.Count.Should().Be(firstBatch.Length);
            reflector.CurrentBatch.Should().BeNull();
            reflector.CursorId.Should().Be(cursorId);
            reflector.Disposed.Should().BeFalse();
            reflector.FirstBatch.Should().Equal(firstBatch);
            reflector.Limit.Should().Be(limit);
            reflector.MaxTime.Should().Be(maxTime);
            reflector.MessageEncoderSettings.Should().BeEquivalentTo(messageEncoderSettings);
            reflector.Query.Should().Be(query);
            reflector.Serializer.Should().Be(serializer);
        }
コード例 #9
0
        public void SortedMapNotifierTest()
        {
            var rounds = 100_000;

            for (int r = 0; r < rounds; r++)
            {
                var count = 1_000_000;
                var cnt1  = 0;
                var cnt2  = 0;
                var cnt3  = 0;
                var cnt4  = 0;

                var sm1 = new MutableSeries <int, int>();
                // sm1._isSynchronized = false;
                var addTask = Task.Run(async() =>
                {
                    // await Task.Delay(5000);
                    try
                    {
                        // sm1.TryAddLast(0, 0);
                        for (int i = 0; i < count; i++)
                        {
                            if (i != 2)
                            {
                                sm1.TryAppend(i, i);
                                Thread.SpinWait(5);

                                //if (i % 250000 == 0)
                                //{
                                //    GC.Collect(0, GCCollectionMode.Forced, false);
                                //}
                            }
                        }

                        sm1.MarkReadOnly();
                        //Console.WriteLine("cnt1: " + cnt1);
                        //Console.WriteLine("cnt2: " + cnt2);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex);
                    }
                });

                // addTask.Wait();
                using (Benchmark.Run("SM.Updated", count * 5))
                {
                    var t1 = Task.Run(async() =>
                    {
                        Thread.CurrentThread.Name = "MNA1";
                        try
                        {
                            using (var cursor1 = sm1.GetAsyncCursor())
                            {
                                // Console.WriteLine("MNA1 started");
                                while (await cursor1.MoveNextAsync())
                                {
                                    AsyncCursor.LogFinished();
                                    if (cnt1 == 2)
                                    {
                                        cnt1++;
                                        // Console.WriteLine("MNA1 moving");
                                    }

                                    if (cursor1.CurrentKey != cnt1)
                                    {
                                        ThrowHelper.ThrowInvalidOperationException("Wrong cursor enumeration");
                                    }

                                    cnt1++;
                                    //if (c % 250000 == 0)
                                    //{
                                    //    GC.Collect(0, GCCollectionMode.Forced, false);
                                    //    Console.WriteLine(c);
                                    //}
                                }

                                if (cnt1 != count)
                                {
                                    ThrowHelper.ThrowInvalidOperationException($"1 Cannot move to count: c={cnt1}, count={count}");
                                }

                                if (AsyncCursor.SyncCount == 0)
                                {
                                    Console.WriteLine("SyncCount == 0");
                                }

                                Thread.MemoryBarrier();
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("MNA1 ex: " + e);
                        }
                    });

                    var t2 = Task.Run(async() =>
                    {
                        Thread.CurrentThread.Name = "MNA2";
                        try
                        {
                            using (var cursor2 = sm1.GetAsyncCursor())
                            {
                                // Console.WriteLine("MNA2 started");
                                while (await cursor2.MoveNextAsync())
                                {
                                    AsyncCursor.LogFinished();
                                    if (cnt2 == 2)
                                    {
                                        cnt2++;
                                        // Console.WriteLine("MNA2 moving");
                                    }

                                    if (cursor2.CurrentKey != cnt2)
                                    {
                                        ThrowHelper.ThrowInvalidOperationException("Wrong cursor enumeration");
                                    }

                                    cnt2++;
                                }

                                if (cnt2 != count)
                                {
                                    ThrowHelper.ThrowInvalidOperationException($"2 Cannot move to count: c={cnt2}, count={count}");
                                }

                                if (AsyncCursor.SyncCount == 0)
                                {
                                    Console.WriteLine("SyncCount == 0");
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("MNA2 ex: " + e);
                        }
                    });

                    var t3 = Task.Run(async() =>
                    {
                        Thread.CurrentThread.Name = "MNA3";
                        try
                        {
                            using (var cursor3 = sm1.GetAsyncCursor())
                            {
                                // Console.WriteLine("MNA2 started");
                                while (await cursor3.MoveNextAsync())
                                {
                                    AsyncCursor.LogFinished();
                                    if (cnt3 == 2)
                                    {
                                        cnt3++;
                                        // Console.WriteLine("MNA2 moving");
                                    }

                                    if (cursor3.CurrentKey != cnt3)
                                    {
                                        ThrowHelper.ThrowInvalidOperationException("Wrong cursor enumeration");
                                    }

                                    cnt3++;
                                }

                                if (cnt3 != count)
                                {
                                    ThrowHelper.ThrowInvalidOperationException($"3 Cannot move to count: c={cnt3}, count={count}");
                                }

                                if (AsyncCursor.SyncCount == 0)
                                {
                                    Console.WriteLine("SyncCount == 0");
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("MNA3 ex: " + e);
                        }
                    });

                    var t4 = Task.Run(async() =>
                    {
                        Thread.CurrentThread.Name = "MNA4";
                        try
                        {
                            using (var cursor4 = sm1.GetAsyncCursor())
                            {
                                // Console.WriteLine("MNA2 started");
                                while (await cursor4.MoveNextAsync())
                                {
                                    AsyncCursor.LogFinished();
                                    if (cnt4 == 2)
                                    {
                                        cnt4++;
                                        // Console.WriteLine("MNA2 moving");
                                    }

                                    if (cursor4.CurrentKey != cnt4)
                                    {
                                        ThrowHelper.ThrowInvalidOperationException("Wrong cursor enumeration");
                                    }

                                    cnt4++;
                                }

                                if (cnt4 != count)
                                {
                                    ThrowHelper.ThrowInvalidOperationException($"4 Cannot move to count: c={cnt4}, count={count}");
                                }

                                if (AsyncCursor.SyncCount == 0)
                                {
                                    Console.WriteLine("SyncCount == 0");
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("MNA3 ex: " + e);
                        }
                    });

                    var finished = false;
                    while (!finished)
                    {
                        finished = Task.WhenAll(addTask, t1, t2, t3, t4).Wait(2000);
                        //Console.WriteLine("cnt1: " + cnt1);
                        //Console.WriteLine("cnt2: " + cnt2);
                    }
                    Console.WriteLine($"{r}: Sync: {AsyncCursor.SyncCount}, Async: {AsyncCursor.AsyncCount}, Await: {AsyncCursor.AwaitCount}, Skipped: {AsyncCursor.SkippedCount}, Missed: {AsyncCursor.MissedCount}, Finished: {AsyncCursor.FinishedCount}");
                    AsyncCursor.ResetCounters();
                }
            }
            Benchmark.Dump();
        }
コード例 #10
0
ファイル: AsyncCursorTests.cs プロジェクト: forki/Spreads
        public async Task CouldReadDataStreamWhileWritingFromManyThreads()
        {
            var map = new SortedMap <int, int>();

            var count  = 1_000_000;
            var rounds = 5;

            var writeTask = Task.Run(async() =>
            {
                using (Benchmark.Run("Write", count * rounds, true))
                {
                    for (int j = 0; j < rounds; j++)
                    {
                        var t1 = Task.Run(async() =>
                        {
                            try
                            {
                                for (int i = j * count; i < (j + 1) * count; i++)
                                {
                                    await map.TryAddLast(i, i);
                                    Thread.SpinWait(10);
                                }
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e);
                                throw;
                            }
                        });
                        await t1;
                    }
                }
            });

            AsyncCursor <int, int, SortedMapCursor <int, int> > cursor = null;
            var cnt      = 0L;
            var readTask = Task.Run(async() =>
            {
                for (int r = 0; r < 1; r++)
                {
                    using (cursor = new AsyncCursor <int, int, SortedMapCursor <int, int> >(map.GetCursor()))
                    {
                        using (Benchmark.Run("Read", count * rounds, true))
                        {
                            try
                            {
                                while (await cursor.MoveNextAsync())
                                {
                                    Interlocked.Increment(ref cnt);
                                }
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e);
                                throw;
                            }


                            // Left from coreclr 19161 tests, TODO remove when everything works OK
                            // here is a strong reference to cursor with side effects of printing to console
                            // Console.WriteLine("Last value: " + cursor.Current.Key);
                            // another strong reference after while loop, we dereference it's value and return from task
                            // lastKey1 = cursor.CurrentKey;
                        }
                    }
                }
            });



            var monitor = true;
            var t       = Task.Run(async() =>
            {
                try
                {
                    while (monitor)
                    {
                        await Task.Delay(1000);
                        Console.WriteLine($"Key {cursor.CurrentKey}");
                        cursor.TryComplete(false);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            });

            await writeTask;
            await map.Complete();

            map.NotifyUpdate(true);
            Console.WriteLine("Read after map complete:" + Interlocked.Read(ref cnt));
            await readTask;

            Console.WriteLine("Read after finish:" + Interlocked.Read(ref cnt));
            // Console.WriteLine("Last key: " + lastKey);

            Benchmark.Dump();

            map.Dispose();
            monitor = false;
        }
コード例 #11
0
 public static long _cursorId(this AsyncCursor <BsonDocument> obj) =>
 (long)Reflector.GetFieldValue(obj, nameof(_cursorId));
コード例 #12
0
 // constructors
 public Reflector(AsyncCursor<BsonDocument> instance)
 {
     _instance = instance;
 }
コード例 #13
0
        public async Task CouldReadDataStreamWhileWritingFromManyThreads()
        {
            var map = new AppendSeries <int, int>();

            var writeCount = 0L;

            var count  = 1000_000_000;
            var rounds = 1;

            var writeTask = Task.Run(async() =>
            {
                using (Benchmark.Run("Write", count * rounds, true))
                {
                    for (int j = 0; j < rounds; j++)
                    {
                        var t1 = Task.Run(() =>
                        {
                            try
                            {
                                for (int i = j * count; i < (j + 1) * count; i++)
                                {
                                    map.DangerousTryAppend(i, i);
                                    // Thread.SpinWait(10);
                                    // Thread.Yield();
                                    Interlocked.Increment(ref writeCount);
                                }
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e);
                                throw;
                            }
                        });
                        await t1;
                    }
                }
            });

            AsyncCursor <int, int, SCursor <int, int> > cursor = null;
            var cnt      = 0L;
            var readTask = Task.Run(async() =>
            {
                for (int r = 0; r < 1; r++)
                {
                    using (cursor = new AsyncCursor <int, int, SCursor <int, int> >(map.GetCursor()))
                    {
                        using (Benchmark.Run("Read", count * rounds, true))
                        {
                            try
                            {
                                while (await cursor.MoveNextAsync())
                                {
                                    Interlocked.Increment(ref cnt);
                                    // Thread.Sleep(1);
                                }
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e);
                                throw;
                            }


                            // Left from coreclr 19161 tests, TODO remove when everything works OK
                            // here is a strong reference to cursor with side effects of printing to console
                            // Console.WriteLine("Last value: " + cursor.Current.Key);
                            // another strong reference after while loop, we dereference it's value and return from task
                            // lastKey1 = cursor.CurrentKey;
                        }
                    }
                }
            });


            var monitor     = true;
            var monitorTask = Task.Run(async() =>
            {
                try
                {
                    var previousR = cursor?.CurrentKey;
                    var previousW = Volatile.Read(ref writeCount);
                    while (monitor)
                    {
                        await Task.Delay(1000);
                        var r = cursor.CurrentKey;
                        var w = Volatile.Read(ref writeCount);
                        Console.WriteLine($"R: {r:N0} - {((r - previousR) / 1000000.0):N2} Mops \t | W: {w:N0}- {((w - previousW) / 1000000.0):N2} Mops");

                        if (r == previousR)
                        {
                            Console.WriteLine($"IsAwaiting {cursor.IsTaskAwating} IsCompl {cursor.IsCompleted} Counter {cursor._counter}");
                        }

                        previousR = r;
                        previousW = w;
                        // cursor.TryComplete(false);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            });

            await writeTask;

            Console.WriteLine("COMPLETE");
            map.MarkReadOnly();
            map.NotifyUpdate();
            Console.WriteLine("Read after map complete:" + Interlocked.Read(ref cnt));
            await readTask;

            Console.WriteLine("Read after finish:" + Interlocked.Read(ref cnt));
            // Console.WriteLine("Last key: " + lastKey);

            Benchmark.Dump();
            GC.KeepAlive(cursor);
            map.Dispose();
            monitor = false;
        }
コード例 #14
0
        // private methods
        private AsyncCursorEnumerator<BsonDocument> CreateSubject(int count)
        {
            var firstBatch = Enumerable.Range(0, count)
                .Select(i => new BsonDocument("_id", i))
                .ToArray();

            var cursor = new AsyncCursor<BsonDocument>(
                channelSource: Substitute.For<IChannelSource>(),
                collectionNamespace: new CollectionNamespace("foo", "bar"),
                query: new BsonDocument(),
                firstBatch: firstBatch,
                cursorId: 0,
                batchSize: null,
                limit: null,
                serializer: BsonDocumentSerializer.Instance,
                messageEncoderSettings: new MessageEncoderSettings());

            return new AsyncCursorEnumerator<BsonDocument>(cursor, CancellationToken.None);
        }
コード例 #15
0
 public UnifiedCloseCursorOperation(AsyncCursor <T> cursor)
 {
     _cursor = Ensure.IsNotNull(cursor, nameof(cursor));
 }
コード例 #16
0
 public static int?_batchSize(this AsyncCursor <BsonDocument> obj) => (int?)Reflector.GetFieldValue(obj, nameof(_batchSize));