internal QueryStream(MigratingTable outer, TableQuery <TElement> query, TableRequestOptions requestOptions, OperationContext operationContext)
 {
     this.outer            = outer;
     origFilterExpr        = ChainTableUtils.ParseFilterString(query.FilterString);
     mtableQuery           = ChainTableUtils.CopyQuery <TElement, MTableEntity>(query);
     this.requestOptions   = requestOptions;
     this.operationContext = operationContext;
 }
Esempio n. 2
0
        public override Task <IQueryStream <TElement> > ExecuteQueryStreamedAsync <TElement>(TableQuery <TElement> query, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
        {
            FilterExpression filterExpr = ChainTableUtils.ParseFilterString(query.FilterString);

            if (query.SelectColumns != null)
            {
                throw new NotImplementedException("select");
            }
            if (query.TakeCount != null)
            {
                throw new NotImplementedException("top");
            }
            return(Task.FromResult((IQueryStream <TElement>)
                                   new NondeterministicQueryStream <TElement>(this, CurrentRevision, filterExpr)));
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        public override Task <IList <TElement> > ExecuteQueryAtomicAsync <TElement>(
            TableQuery <TElement> query, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
        {
            FilterExpression filterExpr = ChainTableUtils.ParseFilterString(query.FilterString);

            ChainTableUtils.GetSingleTargetedPartitionKey(filterExpr);  // validation, ignore result
            if (query.SelectColumns != null)
            {
                throw new NotImplementedException("select");
            }
            if (query.TakeCount != null)
            {
                throw new NotImplementedException("top");
            }
            return(Task.FromResult(
                       (IList <TElement>)(from kvp in table where filterExpr.Evaluate(kvp.Value)
                                          select ChainTableUtils.CopyEntity <TElement>(kvp.Value)).ToList()));
        }
Esempio n. 5
0
        public override Task <IQueryStream <TElement> > ExecuteQueryStreamedAsync <TElement>(
            TableQuery <TElement> query, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
        {
            FilterExpression filterExpr = ChainTableUtils.ParseFilterString(query.FilterString);

            if (query.SelectColumns != null)
            {
                throw new NotImplementedException("select");
            }
            if (query.TakeCount != null)
            {
                throw new NotImplementedException("top");
            }
            // Easy deterministic implementation compliant with IChainTable2
            // API: scan a snapshot.  InMemoryTableWithHistory has the
            // nondeterministic implementation.
            // XXX: Nobody calls this any more.  We could delete the code and
            // throw NotImplementedException.
            return(Task.FromResult((IQueryStream <TElement>) new QueryStream <TElement>(filterExpr, table.GetEnumerator())));
        }
        public override Task <IQueryStream <TElement> > ExecuteQueryStreamedAsync <TElement>(
            TableQuery <TElement> query, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
        {
            FilterExpression filterExpr = ChainTableUtils.ParseFilterString(query.FilterString);

            if (query.SelectColumns != null)
            {
                throw new NotImplementedException("select");
            }
            if (query.TakeCount != null)
            {
                throw new NotImplementedException("top");
            }
            // Easy deterministic implementation compliant with IChainTable2
            // API: scan a snapshot.
            // XXX: At least as an option, this should choose
            // nondeterministically (using P#) from all behaviors compliant with
            // the API to verify that callers can handle it.
            return(Task.FromResult((IQueryStream <TElement>) new QueryStream <TElement>(filterExpr, table.GetEnumerator())));
        }
        public override async Task <IList <TElement> > ExecuteQueryAtomicAsync <TElement>(TableQuery <TElement> query, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
        {
            if (query.SelectColumns != null)
            {
                throw new NotImplementedException("select");
            }
            if (query.TakeCount != null)
            {
                throw new NotImplementedException("top");
            }
            FilterExpression          origFilterExpr = ChainTableUtils.ParseFilterString(query.FilterString);
            string                    partitionKey   = ChainTableUtils.GetSingleTargetedPartitionKey(origFilterExpr);
            TableQuery <MTableEntity> mtableQuery    = ChainTableUtils.CopyQuery <TElement, MTableEntity>(query);

            MTableConfiguration config;

            using (configService.Subscribe(FixedSubscriber <MTableConfiguration> .Instance, out config))
            {
                IEnumerable <MTableEntity> results;
                if (config.state <= TableClientState.USE_OLD_HIDE_METADATA)
                {
                    results = await oldTable.ExecuteQueryAtomicAsync(mtableQuery, requestOptions, operationContext);

                    await monitor.AnnotateLastBackendCallAsync(wasLinearizationPoint : true);
                }
                else if (config.state >= TableClientState.USE_NEW_WITH_TOMBSTONES)
                {
                    results = await newTable.ExecuteQueryAtomicAsync(mtableQuery, requestOptions, operationContext);

                    await monitor.AnnotateLastBackendCallAsync(wasLinearizationPoint : true);
                }
                else
                {
                    // Modify the filter to make sure it matches the meta row.
                    if (origFilterExpr is ComparisonExpression)
                    {
                        // filterExpr must be "PartitionKey eq A", which already matches the meta row; nothing to do.
                    }
                    else
                    {
                        // filterExpr must be "(PartitionKey eq A) and (B)".
                        // Rewrite to "(PartitionKey eq A) and ((RowKey eq ROW_KEY_PARTITION_META) or (B))".
                        var boe = (BooleanOperatorExpression)origFilterExpr;
                        mtableQuery.FilterString =
                            TableQuery.CombineFilters(boe.Left.ToFilterString(), TableOperators.And,
                                                      TableQuery.CombineFilters(
                                                          TableQuery.GenerateFilterCondition(TableConstants.RowKey, QueryComparisons.Equal, ROW_KEY_PARTITION_META),
                                                          TableOperators.Or, boe.Right.ToFilterString()));
                    }
                    IList <MTableEntity> oldRows = await oldTable.ExecuteQueryAtomicAsync(mtableQuery, requestOptions, operationContext);

                    MTablePartitionState?state =
                        (from r in oldRows where r.RowKey == ROW_KEY_PARTITION_META select r.partitionState).SingleOrDefault();
                    IList <MTableEntity> newRows;
                    if (state == MTablePartitionState.SWITCHED)
                    {
                        await monitor.AnnotateLastBackendCallAsync();

                        // If the filter string includes conditions on user-defined properties,
                        // a row in the old table can be shadowed by a row in the new table
                        // that doesn't satisfy those conditions.  To make sure we retrieve all
                        // potential shadowing rows, retrieve the entire partition.
                        // XXX: At a minimum, we should try to keep conditions on the
                        // primary key, but how clever do we want to get with query rewriting?
                        if (!IsBugEnabled(MTableOptionalBug.QueryAtomicFilterShadowing))
                        {
                            mtableQuery.FilterString = TableQuery.GenerateFilterCondition(
                                TableConstants.PartitionKey, QueryComparisons.Equal, partitionKey);
                        }

                        newRows = await newTable.ExecuteQueryAtomicAsync(mtableQuery, requestOptions, operationContext);

                        await monitor.AnnotateLastBackendCallAsync(wasLinearizationPoint : true);
                    }
                    else
                    {
                        await monitor.AnnotateLastBackendCallAsync(wasLinearizationPoint : true);

                        newRows = new List <MTableEntity>();
                    }
                    // Merge lists.  Hopefully this is pretty clear.  Walking the lists
                    // in lockstep might be faster but is a lot more code.
                    var merged = new SortedDictionary <string, MTableEntity>(StringComparer.Ordinal);
                    foreach (MTableEntity ent in oldRows)
                    {
                        merged[ent.RowKey] = ent;
                    }
                    foreach (MTableEntity ent in newRows)
                    {
                        merged[ent.RowKey] = ent;
                    }
                    results = merged.Values;
                }
                return((from ent in results where !RowKeyIsInternal(ent.RowKey) &&
                        origFilterExpr.Evaluate(ent) && !ent.deleted
                        select ent.Export <TElement>()).ToList());
            }
        }