internal async Task EnsurePartitionSwitchedAsync(string partitionKey, TableRequestOptions requestOptions, OperationContext operationContext)
        {
            var metaQuery = new TableQuery <MTableEntity>
            {
                FilterString = ChainTableUtils.GeneratePointRetrievalFilterCondition(
                    new PrimaryKey(partitionKey, ROW_KEY_PARTITION_META))
            };

Recheck:
            MTablePartitionState? state;
            if (IsBugEnabled(MTableOptionalBug.EnsurePartitionSwitchedFromPopulated))
            {
                state = null;
            }
            else
            {
                state =
                    (from r in (await oldTable.ExecuteQueryAtomicAsync(metaQuery, requestOptions, operationContext))
                     select r.partitionState).SingleOrDefault();
                await monitor.AnnotateLastBackendCallAsync();
            }
            switch (state)
            {
            case null:
                try
                {
                    await oldTable.ExecuteAsync(TableOperation.Insert(new MTableEntity
                    {
                        PartitionKey   = partitionKey,
                        RowKey         = ROW_KEY_PARTITION_META,
                        partitionState = MTablePartitionState.SWITCHED
                    }), requestOptions, operationContext);
                }
                catch (StorageException ex)
                {
                    if (ex.GetHttpStatusCode() != HttpStatusCode.Conflict)
                    {
                        throw ChainTableUtils.GenerateInternalException(ex);
                    }
                    if (!IsBugEnabled(MTableOptionalBug.EnsurePartitionSwitchedFromPopulated))
                    {
                        await monitor.AnnotateLastBackendCallAsync();

                        // We could now be in POPULATED or SWITCHED.
                        // XXX: In production, what's more likely?  Is it faster
                        // to recheck first or just try the case below?
                        goto Recheck;
                    }
                }
                await monitor.AnnotateLastBackendCallAsync();

                return;

            case MTablePartitionState.POPULATED:
                try
                {
                    var batch = new TableBatchOperation();
                    batch.Replace(new MTableEntity
                    {
                        PartitionKey   = partitionKey,
                        RowKey         = ROW_KEY_PARTITION_META,
                        ETag           = ChainTable2Constants.ETAG_ANY,
                        partitionState = MTablePartitionState.SWITCHED
                    });
                    batch.Delete(new MTableEntity
                    {
                        PartitionKey = partitionKey,
                        RowKey       = ROW_KEY_PARTITION_POPULATED_ASSERTION,
                        ETag         = ChainTable2Constants.ETAG_ANY,
                    });
                    await oldTable.ExecuteBatchAsync(batch, requestOptions, operationContext);
                }
                catch (ChainTableBatchException ex)
                {
                    // The only way this can fail (within the semantics) is
                    // if someone else moved the partition to SWITCHED.
                    if (!(ex.FailedOpIndex == 1 && ex.GetHttpStatusCode() == HttpStatusCode.NotFound))
                    {
                        throw ChainTableUtils.GenerateInternalException(ex);
                    }
                }
                await monitor.AnnotateLastBackendCallAsync();

                return;

            case MTablePartitionState.SWITCHED:
                // Nothing to do
                return;
            }
        }
Пример #2
0
 public override Task <TableResult> ExecuteAsync(TableOperation operation, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
 {
     //Trace.TraceInformation("{0} calling {1}.ExecuteAsync({2})", callerMachineId, debugName, BetterComparer.ToString(operation));
     return(tableCallEventProxy.ExecuteAsync(operation, requestOptions, operationContext));
 }
Пример #3
0
 public override Task <TableResult> ExecuteAsync(TableOperation operation, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
 {
     return(annotatableCallProxy.ExecuteAsync(operation, requestOptions, operationContext));
 }