Esempio n. 1
0
        public async static Task <NamespaceBlob> FetchForBlobAsync(CloudBlockBlob namespaceBlob)
        {
            var retval = new NamespaceBlob(namespaceBlob);
            await retval.RefreshAsync();

            return(retval);
        }
Esempio n. 2
0
        public static async Task EnqueueBlobReplicationAsync(NamespaceBlob namespaceBlob, bool deleteReplica, bool saveNamespaceEntry = true)
        {
            if (!await namespaceBlob.ExistsAsync())
            {
                return;
            }
            // Trim down the namespace replication list to the first 'master' item. This is sufficient to ensure that the
            // orphaned blobs are not effectively in the account. The master blob will be replicated over the top of the
            // orphaned blobs.
            string primaryAccount = namespaceBlob.PrimaryAccountName;
            if (namespaceBlob.IsReplicated)
            {
                namespaceBlob.PrimaryAccountName = primaryAccount;
                if (saveNamespaceEntry)
                {
                    await namespaceBlob.SaveAsync();
                }
            }
            // This rest of this method does not block. Enqueueing the replication is a completely async process
            var task = Task.Factory.StartNew(() =>
            {
                var queue = new AzureMessageQueue();
                var tasks = DashConfiguration.DataAccounts
                    .Where(dataAccount => !dataAccount.Credentials.AccountName.Equals(primaryAccount, StringComparison.OrdinalIgnoreCase))
                    .Select(async dataAccount => await queue.EnqueueAsync(ConstructReplicationMessage(deleteReplica,
                                                                                                        primaryAccount,
                                                                                                        dataAccount.Credentials.AccountName,
                                                                                                        namespaceBlob.Container,
                                                                                                        namespaceBlob.BlobName,
                                                                                                        deleteReplica ? await GetBlobETagAsync(dataAccount, namespaceBlob.Container, namespaceBlob.BlobName) : null)))
                    .ToArray();
                Task.WhenAll(tasks)
                    .ContinueWith(antecedent =>
                        {
                            if (antecedent.Exception != null)
                            {
                                DashTrace.TraceWarning("Error queueing replication message for blob: {0}. Details: {1}",
                                    PathUtils.CombineContainerAndBlob(namespaceBlob.Container, namespaceBlob.BlobName),
                                    antecedent.Exception.Flatten());
                            }
                            else
                            {
                                DashTrace.TraceInformation("Blob: {0} has been enqueued for replication.",
                                    PathUtils.CombineContainerAndBlob(namespaceBlob.Container, namespaceBlob.BlobName));
                            }
                        });

            });
        }
Esempio n. 3
0
        public static async Task EnqueueBlobReplicationAsync(NamespaceBlob namespaceBlob, bool deleteReplica, bool saveNamespaceEntry = true)
        {
            if (!await namespaceBlob.ExistsAsync())
            {
                return;
            }
            // Trim down the namespace replication list to the first 'master' item. This is sufficient to ensure that the
            // orphaned blobs are not effectively in the account. The master blob will be replicated over the top of the
            // orphaned blobs.
            string primaryAccount = namespaceBlob.PrimaryAccountName;

            if (namespaceBlob.IsReplicated)
            {
                namespaceBlob.PrimaryAccountName = primaryAccount;
                if (saveNamespaceEntry)
                {
                    await namespaceBlob.SaveAsync();
                }
            }
            // This rest of this method does not block. Enqueueing the replication is a completely async process
            var task = Task.Factory.StartNew(() =>
            {
                var queue = new AzureMessageQueue();
                var tasks = DashConfiguration.DataAccounts
                            .Where(dataAccount => !dataAccount.Credentials.AccountName.Equals(primaryAccount, StringComparison.OrdinalIgnoreCase))
                            .Select(async dataAccount => await queue.EnqueueAsync(ConstructReplicationMessage(deleteReplica,
                                                                                                              primaryAccount,
                                                                                                              dataAccount.Credentials.AccountName,
                                                                                                              namespaceBlob.Container,
                                                                                                              namespaceBlob.BlobName,
                                                                                                              deleteReplica ? await GetBlobETagAsync(dataAccount, namespaceBlob.Container, namespaceBlob.BlobName) : null)));
                Task.WhenAll(tasks)
                .ContinueWith(antecedent =>
                {
                    if (antecedent.Exception != null)
                    {
                        DashTrace.TraceWarning("Error queueing replication message for blob: {0}. Details: {1}",
                                               PathUtils.CombineContainerAndBlob(namespaceBlob.Container, namespaceBlob.BlobName),
                                               antecedent.Exception.Flatten());
                    }
                    else
                    {
                        DashTrace.TraceInformation("Blob: {0} has been enqueued for replication.",
                                                   PathUtils.CombineContainerAndBlob(namespaceBlob.Container, namespaceBlob.BlobName));
                    }
                });
            });
        }
Esempio n. 4
0
        private async Task<HttpResponseMessage> ForwardRequestHandler(NamespaceBlob namespaceBlob, StorageOperationTypes operation)
        {
            // Clone the inbound request
            var sourceRequest = this.Request;
            // We always target the primary data account for forwarded messages. If the operation invalidates the replicas, then
            // separate logic will enqueue the new blob to be replicated.
            var clonedRequest = new HttpRequestMessage(sourceRequest.Method,
                ControllerOperations.GetRedirectUri(sourceRequest.RequestUri,
                    sourceRequest.Method.Method,
                    DashConfiguration.GetDataAccountByAccountName(namespaceBlob.PrimaryAccountName),
                    namespaceBlob.Container,
                    namespaceBlob.BlobName, 
                    false));
            clonedRequest.Version = sourceRequest.Version;
            foreach (var property in sourceRequest.Properties)
            {
                clonedRequest.Properties.Add(property);
            }
            foreach (var header in sourceRequest.Headers)
            {
                if (!_noCopyHeaders.Contains(header.Key))
                {
                    clonedRequest.Headers.TryAddWithoutValidation(header.Key, header.Value);
                }
            }
            // Depending on the operation, we have to do some fixup to unwind HttpRequestMessage a bit - we also have to fixup some responses
            switch (operation)
            {
                case StorageOperationTypes.GetBlob:
                case StorageOperationTypes.GetBlobMetadata:
                case StorageOperationTypes.GetBlobProperties:
                case StorageOperationTypes.GetBlockList:
                case StorageOperationTypes.GetPageRanges:
                case StorageOperationTypes.LeaseBlob:
                case StorageOperationTypes.SetBlobMetadata:
                case StorageOperationTypes.SetBlobProperties:
                case StorageOperationTypes.SnapshotBlob:
                    // Push any headers that are assigned to Content onto the request itself as these operations do not have any body
                    if (sourceRequest.Content != null)
                    {
                        foreach (var header in sourceRequest.Content.Headers)
                        {
                            clonedRequest.Headers.TryAddWithoutValidation(header.Key, header.Value);
                        }
                    }
                    break;

                default:
                    clonedRequest.Content = sourceRequest.Content;
                    break;
            }
            var client = new HttpClient();
            var response = await client.SendAsync(clonedRequest, HttpCompletionOption.ResponseHeadersRead);
            // Fixup response for HEAD requests
            switch (operation)
            {
                case StorageOperationTypes.GetBlobProperties:
                    var content = response.Content;
                    if (response.IsSuccessStatusCode && content != null)
                    {
                        string mediaType = null;
                        string dummyContent = String.Empty;
                        if (content.Headers.ContentType != null)
                        {
                            mediaType = content.Headers.ContentType.MediaType;
                        }
                        // For some reason, a HEAD request requires some content otherwise the Content-Length is set to 0
                        dummyContent = "A";
                        response.Content = new StringContent(dummyContent, null, mediaType);
                        foreach (var header in content.Headers)
                        {
                            response.Content.Headers.TryAddWithoutValidation(header.Key, header.Value);
                        }
                        response.Content.Headers.ContentLength = content.Headers.ContentLength;
                        content.Dispose();
                    }
                    break;
            }
            return response;
        }
Esempio n. 5
0
 public static bool ShouldReplicateBlob(ILookup<string, string> headers, NamespaceBlob namespaceBlob)
 {
     return ShouldReplicateBlob(headers, namespaceBlob.Container, namespaceBlob.BlobName);
 }
Esempio n. 6
0
 static bool CleanupAbortedBlobReplication(NamespaceBlob namespaceBlob, ICloudBlob destBlob)
 {
     try
     {
         destBlob.DeleteIfExists();
     }
     catch (Exception ex1)
     {
         DashTrace.TraceWarning("Error deleting aborted replication target [{0}][{1}]. Details: {2}",
             destBlob.ServiceClient.Credentials.AccountName,
             destBlob.Name,
             ex1);
     }
     return namespaceBlob.RemoveDataAccount(destBlob.ServiceClient.Credentials.AccountName);
 }
Esempio n. 7
0
 public async static Task<NamespaceBlob> FetchForBlobAsync(CloudBlockBlob namespaceBlob)
 {
     var retval = new NamespaceBlob(namespaceBlob);
     await retval.RefreshAsync();
     return retval;
 }
Esempio n. 8
0
 public static async Task <NamespaceBlob> FetchNamespaceBlobAsync(string container, string blobName, string snapshot = null)
 {
     return(await NamespaceBlob.FetchForBlobAsync(
                (CloudBlockBlob)GetBlobByName(DashConfiguration.NamespaceAccount, container, blobName, snapshot)));
 }
Esempio n. 9
0
 public static bool ShouldReplicateBlob(ILookup <string, string> headers, NamespaceBlob namespaceBlob)
 {
     return(ShouldReplicateBlob(headers, namespaceBlob.Container, namespaceBlob.BlobName));
 }