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; } }
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)); }
public override Task <TableResult> ExecuteAsync(TableOperation operation, TableRequestOptions requestOptions = null, OperationContext operationContext = null) { return(annotatableCallProxy.ExecuteAsync(operation, requestOptions, operationContext)); }