public void MoveNextReturnsFalseAfterDataEnds() { var data = new[] { 1 }; var cursor = new AsyncCursor <Int32>(data); cursor.MoveNext().Should().BeTrue(); cursor.MoveNext().Should().BeFalse(); }
public void CurrentReturnsDataAfterMoveNext() { var data = new[] { 1 }; var cursor = new AsyncCursor <Int32>(data); cursor.MoveNext().Should().BeTrue(); cursor.Current.Should().BeSameAs(data); }
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); }
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>(); } }
public void MoveNextThrowsExceptionAfterEnumerationFinishes() { var data = new[] { 1 }; var cursor = new AsyncCursor <Int32>(data); cursor.MoveNext(); cursor.MoveNext(); Action action = () => cursor.MoveNext(); action.ShouldThrow <InvalidOperationException>(); }
public void CurrentThrowsExceptionBeforeMoveNext() { var data = new[] { 1 }; var cursor = new AsyncCursor <Int32>(data); Action action = () => { var c = cursor.Current; }; action.ShouldThrow <InvalidOperationException>(); }
// 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."); } }
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); }
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(); }
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; }
public static long _cursorId(this AsyncCursor <BsonDocument> obj) => (long)Reflector.GetFieldValue(obj, nameof(_cursorId));
// constructors public Reflector(AsyncCursor<BsonDocument> instance) { _instance = instance; }
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; }
// 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); }
public UnifiedCloseCursorOperation(AsyncCursor <T> cursor) { _cursor = Ensure.IsNotNull(cursor, nameof(cursor)); }
public static int?_batchSize(this AsyncCursor <BsonDocument> obj) => (int?)Reflector.GetFieldValue(obj, nameof(_batchSize));