public Task <TElement> ReadRowAsync() { if (continuationKey == null) { return(Task.FromResult(default(TElement))); } List <DynamicTableEntity> possibleRows = outer.GetValidStreamReadRows(startRevision, filterExpr, continuationKey); int choiceIndex = PSharpNondeterminism.Choice(possibleRows.Count); DynamicTableEntity choice = possibleRows[choiceIndex]; Console.WriteLine("NondeterministicQueryStream: possibleRows {0}, choiceIndex {1}", BetterComparer.ToString(possibleRows), choiceIndex); continuationKey = (choice == null) ? null : ChainTableUtils.NextValidPrimaryKeyAfter(choice.GetPrimaryKey()); return(Task.FromResult((choice == null) ? default(TElement) : ChainTableUtils.CopyEntity <TElement>(choice))); }
internal async Task RunQueryStreamedAsync(TableQuery <DynamicTableEntity> query) { int startRevision = await peekProxy.GetReferenceTableRevisionAsync(); FilterExpression filterExpr = ChainTableUtils.ParseFilterString(query.FilterString); Console.WriteLine("{0} starting streaming query: {1}", machineId, query); using (IQueryStream <DynamicTableEntity> stream = await migratingTable.ExecuteQueryStreamedAsync(query)) { PrimaryKey lastKey = ChainTableUtils.FirstValidPrimaryKey; for (;;) { PrimaryKey returnedContinuationKey = await stream.GetContinuationPrimaryKeyAsync(); PSharpRuntime.Assert(returnedContinuationKey == null || returnedContinuationKey.CompareTo(lastKey) >= 0, "{0}: query stream continuation key is {1}, expected >= {2}", machineId, returnedContinuationKey, lastKey); DynamicTableEntity row = await stream.ReadRowAsync(); // may be null, meaning end of stream // Must be after ReadRowAsync, otherwise additional rows could become valid // due to a mutation between GetValidStreamReadRows and ReadRowAsync and // we would falsely report a bug if ReadRowAsync returns one of those rows. List <DynamicTableEntity> validRows = await peekProxy.GetValidStreamReadRows(startRevision, filterExpr, lastKey); // Three cheers for automatic use of covariance in overload resolution! PSharpRuntime.Assert(validRows.Contains(row, BetterComparer.Instance), "{0} query stream returned {1}, which is not one of the valid rows: {2}", machineId, BetterComparer.ToString(row), BetterComparer.ToString(validRows)); Console.WriteLine("{0} query stream returned row {1}, which is valid", machineId, BetterComparer.ToString(row)); if (row == null) { // Any returnedContinuationKey (including null) is less or equal to a row of null. break; } else { PSharpRuntime.Assert(returnedContinuationKey != null && returnedContinuationKey.CompareTo(row.GetPrimaryKey()) <= 0, "{0}: query stream continuation key is {1}, expected <= {2}", machineId, returnedContinuationKey, row.GetPrimaryKey()); lastKey = ChainTableUtils.NextValidPrimaryKeyAfter(row.GetPrimaryKey()); } } } Console.WriteLine("{0} finished streaming query", machineId); }
async Task DoQueryStreamed() { int startRevision = await peekProxy.GetReferenceTableRevisionAsync(); // XXX: Test the filtering? var query = new TableQuery <DynamicTableEntity>(); using (IQueryStream <DynamicTableEntity> stream = await migratingTable.ExecuteQueryStreamedAsync(query)) { PrimaryKey continuationKey = await stream.GetContinuationPrimaryKeyAsync(); await peekProxy.ValidateQueryStreamGapAsync(startRevision, null, continuationKey); do { DynamicTableEntity row = await stream.ReadRowAsync(); PrimaryKey newContinuationKey = await stream.GetContinuationPrimaryKeyAsync(); if (row == null) { PSharpRuntime.Assert(newContinuationKey == null); await peekProxy.ValidateQueryStreamGapAsync(startRevision, continuationKey, null); } else { await peekProxy.ValidateQueryStreamGapAsync(startRevision, continuationKey, row.GetPrimaryKey()); await peekProxy.ValidateQueryStreamRowAsync(startRevision, row); await peekProxy.ValidateQueryStreamGapAsync(startRevision, ChainTableUtils.NextValidPrimaryKeyAfter(row.GetPrimaryKey()), newContinuationKey); } continuationKey = newContinuationKey; } while (continuationKey != null); } }