public async Task <HttpResponseMessage> DeleteBlob(string container, string blob, string snapshot = null) { var requestWrapper = DashHttpRequestWrapper.Create(this.Request); var headers = requestWrapper.Headers; var queryParams = requestWrapper.QueryParameters; bool dataBlobDeleted = false; return(await DoHandlerAsync(String.Format("BlobController.DeleteBlob: {0}/{1}", container, blob), async() => await NamespaceHandler.PerformNamespaceOperation(container, blob, async(namespaceBlob) => { // We only need to delete the actual blob. We are leaving the namespace entry alone as a sort of cache. if (!(await namespaceBlob.ExistsAsync()) || namespaceBlob.IsMarkedForDeletion) { return this.CreateResponse(HttpStatusCode.NotFound, headers); } // Delete the real data blob by forwarding the request onto the data account if (!dataBlobDeleted) { var forwardedResponse = await ForwardRequestHandler(namespaceBlob, StorageOperationTypes.DeleteBlob); if (!forwardedResponse.IsSuccessStatusCode) { return forwardedResponse; } dataBlobDeleted = true; } // See if we need to delete any replicas if (namespaceBlob.IsReplicated) { await BlobReplicationHandler.EnqueueBlobReplicationAsync(namespaceBlob, true, false); } // Mark the namespace blob for deletion await namespaceBlob.MarkForDeletionAsync(); return this.CreateResponse(HttpStatusCode.Accepted, headers); }))); }
static void CleanupAbortedBlobReplication(ICloudBlob destBlob) { if (destBlob == null) { return; } NamespaceHandler.PerformNamespaceOperation(destBlob.Container.Name, destBlob.Name, async(namespaceBlob) => { if (CleanupAbortedBlobReplication(namespaceBlob, destBlob)) { await namespaceBlob.SaveAsync(); return(true); } return(false); }).Wait(); }
static bool FinalizeBlobReplication(string dataAccount, string container, string blobName, bool deleteReplica, ICloudBlob destBlob = null) { return(NamespaceHandler.PerformNamespaceOperation(container, blobName, async(namespaceBlob) => { bool exists = await namespaceBlob.ExistsAsync(); if (!exists || namespaceBlob.IsMarkedForDeletion) { // It's ok for a deleted replica not to have a corresponding namespace blob if (!deleteReplica) { DashTrace.TraceWarning("Replication of blob [{0}] to account [{1}] cannot be completed because the namespace blob either does not exist or is marked for deletion.", PathUtils.CombineContainerAndBlob(container, blobName), dataAccount); // Attempt to not leave the replica orphaned if (CleanupAbortedBlobReplication(namespaceBlob, destBlob)) { await namespaceBlob.SaveAsync(); } } // Do not attempt retry in this state return true; } string message = "replicated to"; bool nsDirty = false; if (deleteReplica) { nsDirty = namespaceBlob.RemoveDataAccount(dataAccount); message = "dereplicated from"; } else { nsDirty = namespaceBlob.AddDataAccount(dataAccount); } if (nsDirty) { await namespaceBlob.SaveAsync(); DashTrace.TraceInformation("Blob [{0}] has been successfully {1} account [{2}].", PathUtils.CombineContainerAndBlob(container, blobName), message, dataAccount); } return true; }).Result); }