/// <summary>
        /// Implements the FetchAttributes method. The attributes are updated immediately.
        /// </summary>
        /// <param name="blobUri">The URI of the blob.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand{T}"/> that fetches the attributes.</returns>
        private RESTCommand <ICloudBlob> GetBlobReferenceImpl(Uri blobUri, AccessCondition accessCondition, BlobRequestOptions options)
        {
            RESTCommand <ICloudBlob> getCmd = new RESTCommand <ICloudBlob>(this.Credentials, blobUri);

            getCmd.ApplyRequestOptions(options);
            getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.GetProperties(uri, serverTimeout, null /* snapshot */, accessCondition, ctx);
            getCmd.SignRequest          = this.AuthenticationHandler.SignRequest;
            getCmd.PreProcessResponse   = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex, ctx);
                BlobAttributes attributes = new BlobAttributes();
                attributes.Uri = blobUri;
                CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false);
                switch (attributes.Properties.BlobType)
                {
                case BlobType.BlockBlob:
                    return(new CloudBlockBlob(attributes, this));

                case BlobType.PageBlob:
                    return(new CloudPageBlob(attributes, this));

                default:
                    throw new InvalidOperationException();
                }
            };

            return(getCmd);
        }
Example #2
0
        /// <summary>
        /// Generates a <see cref="RESTCommand"/> for acquiring a lease.
        /// </summary>
        /// <param name="blob">The blob object that is calling this method.</param>
        /// <param name="attributes">The blob's attributes.</param>
        /// <param name="leaseTime">A <see cref="TimeSpan"/> representing the span of time for which to acquire the lease, which will be rounded down to seconds. If null, an infinite lease will be acquired. If not null, this must be greater than zero.</param>
        /// <param name="proposedLeaseId">A string representing the proposed lease ID for the new lease, or <c>null</c> if no lease ID is proposed.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> implementing the acquire lease operation.</returns>
        internal static RESTCommand <string> AcquireLeaseImpl(ICloudBlob blob, BlobAttributes attributes, TimeSpan?leaseTime, string proposedLeaseId, AccessCondition accessCondition, BlobRequestOptions options)
        {
            int leaseDuration = -1;

            if (leaseTime.HasValue)
            {
                CommonUtility.AssertInBounds("leaseTime", leaseTime.Value, TimeSpan.FromSeconds(1), TimeSpan.MaxValue);
                leaseDuration = (int)leaseTime.Value.TotalSeconds;
            }

            RESTCommand <string> putCmd = new RESTCommand <string>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(putCmd);
            putCmd.Handler            = blob.ServiceClient.AuthenticationHandler;
            putCmd.BuildClient        = HttpClientFactory.BuildHttpClient;
            putCmd.BuildRequest       = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.Lease(uri, serverTimeout, LeaseAction.Acquire, proposedLeaseId, leaseDuration, null /* leaseBreakPeriod */, accessCondition, cnt, ctx);
            putCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, null /* retVal */, cmd, ex);
                CloudBlobSharedImpl.UpdateETagLMTAndSequenceNumber(attributes, resp);
                return(BlobHttpResponseParsers.GetLeaseId(resp));
            };

            return(putCmd);
        }
Example #3
0
        /// <summary>
        /// Generates a <see cref="RESTCommand"/> for breaking a lease.
        /// </summary>
        /// <param name="blob">The blob object that is calling this method.</param>
        /// <param name="attributes">The blob's attributes.</param>
        /// <param name="breakPeriod">The amount of time to allow the lease to remain, rounded down to seconds. If null, the break period is the remainder of the current lease, or zero for infinite leases.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> implementing the break lease operation.</returns>
        internal static RESTCommand <TimeSpan> BreakLeaseImpl(ICloudBlob blob, BlobAttributes attributes, TimeSpan?breakPeriod, AccessCondition accessCondition, BlobRequestOptions options)
        {
            int?breakSeconds = null;

            if (breakPeriod.HasValue)
            {
                CommonUtility.AssertInBounds("breakPeriod", breakPeriod.Value, TimeSpan.Zero, TimeSpan.MaxValue);
                breakSeconds = (int)breakPeriod.Value.TotalSeconds;
            }

            RESTCommand <TimeSpan> putCmd = new RESTCommand <TimeSpan>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(putCmd);
            putCmd.Handler            = blob.ServiceClient.AuthenticationHandler;
            putCmd.BuildClient        = HttpClientFactory.BuildHttpClient;
            putCmd.BuildRequest       = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.Lease(uri, serverTimeout, LeaseAction.Break, null /* proposedLeaseId */, null /* leaseDuration */, breakSeconds, accessCondition, cnt, ctx);
            putCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Accepted, resp, TimeSpan.Zero, cmd, ex);
                CloudBlobSharedImpl.UpdateETagLMTAndSequenceNumber(attributes, resp);

                int?remainingLeaseTime = BlobHttpResponseParsers.GetRemainingLeaseTime(resp);
                if (!remainingLeaseTime.HasValue)
                {
                    // Unexpected result from service.
                    throw new StorageException(cmd.CurrentResult, SR.LeaseTimeNotReceived, null /* inner */);
                }

                return(TimeSpan.FromSeconds(remainingLeaseTime.Value));
            };

            return(putCmd);
        }
        /// <summary>
        /// Implements the FetchAttributes method. The attributes are updated immediately.
        /// </summary>
        /// <param name="blob">The blob.</param>
        /// <param name="attributes">The attributes.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies any additional options for the request.</param>
        /// <returns>
        /// A <see cref="RESTCommand{T}" /> that fetches the attributes.
        /// </returns>
        internal static RESTCommand <NullType> FetchAttributesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options)
        {
            RESTCommand <NullType> getCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.Uri);

            getCmd.ApplyRequestOptions(options);
            getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.GetProperties(uri, serverTimeout, attributes.SnapshotTime, accessCondition, ctx);
            getCmd.SignRequest          = blob.ServiceClient.AuthenticationHandler.SignRequest;
            getCmd.PreProcessResponse   = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex, ctx);
                CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false);
                return(NullType.Value);
            };

            return(getCmd);
        }
        /// <summary>
        /// Implementation for the SetProperties method.
        /// </summary>
        /// <param name="blob">The blob.</param>
        /// <param name="attributes">The attributes.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies any additional options for the request.</param>
        /// <returns>
        /// A <see cref="RESTCommand{T}" /> that sets the properties.
        /// </returns>
        internal static RESTCommand <NullType> SetPropertiesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options)
        {
            RESTCommand <NullType> putCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.Uri);

            putCmd.ApplyRequestOptions(options);
            putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.SetProperties(uri, serverTimeout, attributes.Properties, accessCondition, ctx);
            putCmd.SetHeaders           = (r, ctx) => BlobHttpWebRequestFactory.AddMetadata(r, attributes.Metadata);
            putCmd.SignRequest          = blob.ServiceClient.AuthenticationHandler.SignRequest;
            putCmd.PreProcessResponse   = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex, ctx);
                CloudBlobSharedImpl.ParseSizeAndLastModified(attributes, resp);
                return(NullType.Value);
            };

            return(putCmd);
        }
Example #6
0
        /// <summary>
        /// Implementation for the SetProperties method.
        /// </summary>
        /// <param name="blob">The blob.</param>
        /// <param name="attributes">The attributes.</param>
        /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the condition that must be met in order for the request to proceed. If <c>null</c>, no condition is used.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param>
        /// <returns>
        /// A <see cref="RESTCommand{T}"/> that sets the properties.
        /// </returns>
        internal static RESTCommand <NullType> SetPropertiesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options)
        {
            RESTCommand <NullType> putCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(putCmd);
            putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, useVersionHeader, ctx) => BlobHttpWebRequestFactory.SetProperties(uri, serverTimeout, attributes.Properties, accessCondition, useVersionHeader, ctx);
            putCmd.SetHeaders           = (r, ctx) => BlobHttpWebRequestFactory.AddMetadata(r, attributes.Metadata);
            putCmd.SignRequest          = blob.ServiceClient.AuthenticationHandler.SignRequest;
            putCmd.PreProcessResponse   = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex);
                CloudBlobSharedImpl.UpdateETagLMTLengthAndSequenceNumber(attributes, resp, false);
                return(NullType.Value);
            };

            return(putCmd);
        }
Example #7
0
        /// <summary>
        /// Implements the FetchAttributes method. The attributes are updated immediately.
        /// </summary>
        /// <param name="blob">The blob object that is calling this method.</param>
        /// <param name="attributes">The blob's attributes.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> that fetches the attributes.</returns>
        internal static RESTCommand <NullType> FetchAttributesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options)
        {
            RESTCommand <NullType> getCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(getCmd);
            getCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary;
            getCmd.Handler             = blob.ServiceClient.AuthenticationHandler;
            getCmd.BuildClient         = HttpClientFactory.BuildHttpClient;
            getCmd.BuildRequest        = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.GetProperties(uri, serverTimeout, attributes.SnapshotTime, accessCondition, cnt, ctx);
            getCmd.PreProcessResponse  = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex);
                CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false);
                return(NullType.Value);
            };

            return(getCmd);
        }
Example #8
0
        /// <summary>
        /// Implements the FetchAttributes method. The attributes are updated immediately.
        /// </summary>
        /// <param name="blobUri">The URI of the blob.</param>
        /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> that fetches the attributes.</returns>
        private RESTCommand <ICloudBlob> GetBlobReferenceImpl(Uri blobUri, AccessCondition accessCondition, BlobRequestOptions options)
        {
            // If the blob Uri contains SAS credentials, we need to use those
            // credentials instead of this service client's stored credentials.
            StorageCredentials parsedCredentials;
            DateTimeOffset?    parsedSnapshot;

            blobUri = NavigationHelper.ParseBlobQueryAndVerify(blobUri, out parsedCredentials, out parsedSnapshot);
            CloudBlobClient client = parsedCredentials != null ? new CloudBlobClient(this.BaseUri, parsedCredentials) : this;

            RESTCommand <ICloudBlob> getCmd = new RESTCommand <ICloudBlob>(client.Credentials, blobUri);

            getCmd.ApplyRequestOptions(options);
            getCmd.Handler            = client.AuthenticationHandler;
            getCmd.BuildClient        = HttpClientFactory.BuildHttpClient;
            getCmd.BuildRequest       = (cmd, cnt, ctx) => BlobHttpRequestMessageFactory.GetProperties(cmd.Uri, cmd.ServerTimeoutInSeconds, parsedSnapshot, accessCondition, cnt, ctx);
            getCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex, ctx);

                BlobAttributes attributes = new BlobAttributes()
                {
                    Uri          = blobUri,
                    SnapshotTime = parsedSnapshot,
                };

                CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false);

                switch (attributes.Properties.BlobType)
                {
                case BlobType.BlockBlob:
                    return(new CloudBlockBlob(attributes, client));

                case BlobType.PageBlob:
                    return(new CloudPageBlob(attributes, client));

                default:
                    throw new InvalidOperationException();
                }
            };

            return(getCmd);
        }
        /// <summary>
        /// Implementation for the SetProperties method.
        /// </summary>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> that sets the metadata.</returns>
        internal static RESTCommand <NullType> SetPropertiesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options)
        {
            RESTCommand <NullType> putCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.Uri);

            putCmd.ApplyRequestOptions(options);
            putCmd.Handler      = blob.ServiceClient.AuthenticationHandler;
            putCmd.BuildClient  = HttpClientFactory.BuildHttpClient;
            putCmd.BuildRequest = (cmd, cnt, ctx) =>
            {
                HttpRequestMessage msg = BlobHttpRequestMessageFactory.SetProperties(cmd.Uri, cmd.ServerTimeoutInSeconds, attributes.Properties, accessCondition, cnt, ctx);
                BlobHttpRequestMessageFactory.AddMetadata(msg, attributes.Metadata);
                return(msg);
            };
            putCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex, ctx);
                CloudBlobSharedImpl.ParseSizeAndLastModified(attributes, resp);
                return(NullType.Value);
            };

            return(putCmd);
        }
Example #10
0
        /// <summary>
        /// Implementation for the SetProperties method.
        /// </summary>
        /// <param name="blob">The blob object that is calling this method.</param>
        /// <param name="attributes">The blob's attributes.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> that sets the metadata.</returns>
        internal static RESTCommand <NullType> SetPropertiesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options)
        {
            RESTCommand <NullType> putCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(putCmd);
            putCmd.Handler      = blob.ServiceClient.AuthenticationHandler;
            putCmd.BuildClient  = HttpClientFactory.BuildHttpClient;
            putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) =>
            {
                HttpRequestMessage msg = BlobHttpRequestMessageFactory.SetProperties(uri, serverTimeout, attributes.Properties, accessCondition, cnt, ctx);
                BlobHttpRequestMessageFactory.AddMetadata(msg, attributes.Metadata);
                return(msg);
            };
            putCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex);
                CloudBlobSharedImpl.UpdateETagLMTAndSequenceNumber(attributes, resp);
                return(NullType.Value);
            };

            return(putCmd);
        }
Example #11
0
        /// <summary>
        /// Generates a <see cref="RESTCommand{T}"/> for releasing a lease.
        /// </summary>
        /// <param name="blob">The blob.</param>
        /// <param name="attributes">The attributes.</param>
        /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the condition that must be met in order for the request to proceed. If <c>null</c>, no condition is used.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param>
        /// <returns>
        /// A <see cref="RESTCommand{T}"/> implementing the release lease operation.
        /// </returns>
        /// <exception cref="System.ArgumentException">accessCondition</exception>
        internal static RESTCommand <NullType> ReleaseLeaseImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options)
        {
            CommonUtility.AssertNotNull("accessCondition", accessCondition);
            if (accessCondition.LeaseId == null)
            {
                throw new ArgumentException(SR.MissingLeaseIDReleasing, "accessCondition");
            }

            RESTCommand <NullType> putCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(putCmd);
            putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, useVersionHeader, ctx) => BlobHttpWebRequestFactory.Lease(uri, serverTimeout, LeaseAction.Release, null /* proposedLeaseId */, null /* leaseDuration */, null /* leaseBreakPeriod */, accessCondition, useVersionHeader, ctx);
            putCmd.SignRequest          = blob.ServiceClient.AuthenticationHandler.SignRequest;
            putCmd.PreProcessResponse   = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex);
                CloudBlobSharedImpl.UpdateETagLMTLengthAndSequenceNumber(attributes, resp, false);
                return(NullType.Value);
            };

            return(putCmd);
        }
Example #12
0
        /// <summary>
        /// Implementation for the Exists method.
        /// </summary>
        /// <param name="blob">The blob.</param>
        /// <param name="attributes">The attributes.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param>
        /// <param name="primaryOnly">If <c>true</c>, the command will be executed against the primary location.</param>
        /// <returns>
        /// A <see cref="RESTCommand{T}"/> that checks existence.
        /// </returns>
        internal static RESTCommand <bool> ExistsImpl(ICloudBlob blob, BlobAttributes attributes, BlobRequestOptions options, bool primaryOnly)
        {
            RESTCommand <bool> getCmd = new RESTCommand <bool>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(getCmd);
            getCmd.CommandLocationMode  = primaryOnly ? CommandLocationMode.PrimaryOnly : CommandLocationMode.PrimaryOrSecondary;
            getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, useVersionHeader, ctx) => BlobHttpWebRequestFactory.GetProperties(uri, serverTimeout, attributes.SnapshotTime, null /* accessCondition */, useVersionHeader, ctx);
            getCmd.SignRequest          = blob.ServiceClient.AuthenticationHandler.SignRequest;
            getCmd.PreProcessResponse   = (cmd, resp, ex, ctx) =>
            {
                if (resp.StatusCode == HttpStatusCode.NotFound)
                {
                    return(false);
                }

                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, true, cmd, ex);
                CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false);
                return(true);
            };

            return(getCmd);
        }
Example #13
0
        /// <summary>
        /// Implements the Exists method. The attributes are updated immediately.
        /// </summary>
        /// <param name="blob">The blob object that is calling this method.</param>
        /// <param name="attributes">The blob's attributes.</param>
        /// <param name="options">An object that specifies additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> that checks existence.</returns>
        internal static RESTCommand <bool> ExistsImpl(ICloudBlob blob, BlobAttributes attributes, BlobRequestOptions options)
        {
            RESTCommand <bool> getCmd = new RESTCommand <bool>(blob.ServiceClient.Credentials, attributes.Uri);

            getCmd.ApplyRequestOptions(options);
            getCmd.Handler            = blob.ServiceClient.AuthenticationHandler;
            getCmd.BuildClient        = HttpClientFactory.BuildHttpClient;
            getCmd.BuildRequest       = (cmd, cnt, ctx) => BlobHttpRequestMessageFactory.GetProperties(cmd.Uri, cmd.ServerTimeoutInSeconds, attributes.SnapshotTime, null /* accessCondition */, cnt, ctx);
            getCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                if (resp.StatusCode == HttpStatusCode.NotFound)
                {
                    return(false);
                }

                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, true, cmd, ex);
                CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false);
                return(true);
            };

            return(getCmd);
        }
Example #14
0
        /// <summary>
        /// Generates a <see cref="RESTCommand"/> for changing a lease ID.
        /// </summary>
        /// <param name="blob">The blob object that is calling this method.</param>
        /// <param name="attributes">The blob's attributes.</param>
        /// <param name="proposedLeaseId">The proposed new lease ID.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> implementing the change lease ID operation.</returns>
        internal static RESTCommand <string> ChangeLeaseImpl(ICloudBlob blob, BlobAttributes attributes, string proposedLeaseId, AccessCondition accessCondition, BlobRequestOptions options)
        {
            CommonUtility.AssertNotNull("accessCondition", accessCondition);
            CommonUtility.AssertNotNull("proposedLeaseId", proposedLeaseId);
            if (accessCondition.LeaseId == null)
            {
                throw new ArgumentException(SR.MissingLeaseIDChanging, "accessCondition");
            }

            RESTCommand <string> putCmd = new RESTCommand <string>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(putCmd);
            putCmd.Handler            = blob.ServiceClient.AuthenticationHandler;
            putCmd.BuildClient        = HttpClientFactory.BuildHttpClient;
            putCmd.BuildRequest       = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.Lease(uri, serverTimeout, LeaseAction.Change, proposedLeaseId, null /* leaseDuration */, null /* leaseBreakPeriod */, accessCondition, cnt, ctx);
            putCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex);
                CloudBlobSharedImpl.UpdateETagLMTAndSequenceNumber(attributes, resp);
                return(BlobHttpResponseParsers.GetLeaseId(resp));
            };

            return(putCmd);
        }
        /// <summary>
        /// Implements getting the stream without specifying a range.
        /// </summary>
        /// <param name="blob">The blob.</param>
        /// <param name="attributes">The attributes.</param>
        /// <param name="destStream">The destination stream.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies any additional options for the request.</param>
        /// <returns>
        /// A <see cref="RESTCommand{T}" /> that gets the stream.
        /// </returns>
        internal static RESTCommand <NullType> GetBlobImpl(ICloudBlob blob, BlobAttributes attributes, Stream destStream, long?offset, long?length, AccessCondition accessCondition, BlobRequestOptions options)
        {
            string          lockedETag            = null;
            AccessCondition lockedAccessCondition = null;

            bool   isRangeGet             = offset.HasValue;
            bool   arePropertiesPopulated = false;
            string storedMD5 = null;

            long startingOffset = offset.HasValue ? offset.Value : 0;
            long?startingLength = length;

            RESTCommand <NullType> getCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.Uri);

            getCmd.ApplyRequestOptions(options);
            getCmd.RetrieveResponseStream        = true;
            getCmd.DestinationStream             = destStream;
            getCmd.CalculateMd5ForResponseStream = !options.DisableContentMD5Validation.Value;
            getCmd.BuildRequestDelegate          = (uri, builder, serverTimeout, ctx) =>
                                                   BlobHttpWebRequestFactory.Get(uri, serverTimeout, attributes.SnapshotTime, offset, length, options.UseTransactionalMD5.Value, accessCondition, ctx);
            getCmd.SignRequest    = blob.ServiceClient.AuthenticationHandler.SignRequest;
            getCmd.RecoveryAction = (cmd, ex, ctx) =>
            {
                if ((lockedAccessCondition == null) && !string.IsNullOrEmpty(lockedETag))
                {
                    lockedAccessCondition = AccessCondition.GenerateIfMatchCondition(lockedETag);
                    if (accessCondition != null)
                    {
                        lockedAccessCondition.LeaseId = accessCondition.LeaseId;
                    }
                }

                if (cmd.StreamCopyState != null)
                {
                    offset = startingOffset + cmd.StreamCopyState.Length;
                    if (startingLength.HasValue)
                    {
                        length = startingLength.Value - cmd.StreamCopyState.Length;
                    }
                }

                getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, context) =>
                                              BlobHttpWebRequestFactory.Get(uri, serverTimeout, attributes.SnapshotTime, offset, length, options.UseTransactionalMD5.Value && !arePropertiesPopulated, lockedAccessCondition ?? accessCondition, context);
            };

            getCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(offset.HasValue ? HttpStatusCode.PartialContent : HttpStatusCode.OK, resp, NullType.Value, cmd, ex, ctx);

                if (!arePropertiesPopulated)
                {
                    CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, isRangeGet);
                    storedMD5 = resp.Headers[HttpResponseHeader.ContentMd5];

                    if (!options.DisableContentMD5Validation.Value &&
                        options.UseTransactionalMD5.Value &&
                        string.IsNullOrEmpty(storedMD5))
                    {
                        throw new StorageException(
                                  cmd.CurrentResult,
                                  SR.MD5NotPresentError,
                                  null)
                              {
                                  IsRetryable = false
                              };
                    }

                    lockedETag             = attributes.Properties.ETag;
                    arePropertiesPopulated = true;
                }

                return(NullType.Value);
            };

            getCmd.PostProcessResponse = (cmd, resp, ex, ctx) =>
            {
                long validateLength = startingLength.HasValue ? startingLength.Value : (attributes.Properties.Length - startingOffset);
                HttpResponseParsers.ValidateResponseStreamMd5AndLength(validateLength, storedMD5, cmd, cmd.StreamCopyState);
                return(NullType.Value);
            };

            return(getCmd);
        }
Example #16
0
        /// <summary>
        /// Implements getting the blob.
        /// </summary>
        /// <param name="blob">The blob object that is calling this method.</param>
        /// <param name="attributes">The blob's attributes.</param>
        /// <param name="destStream">The target stream.</param>
        /// <param name="offset">The offset at which to begin downloading the blob, in bytes.</param>
        /// <param name="length">The length of the data to download from the blob, in bytes.</param>
        /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
        /// <param name="options">An object that specifies additional options for the request.</param>
        /// <returns>A <see cref="SynchronousTask"/> that gets the stream.</returns>
        internal static RESTCommand <NullType> GetBlobImpl(ICloudBlob blob, BlobAttributes attributes, Stream destStream, long?offset, long?length, AccessCondition accessCondition, BlobRequestOptions options)
        {
            string          lockedETag            = null;
            AccessCondition lockedAccessCondition = null;

            bool   isRangeGet             = offset.HasValue;
            bool   arePropertiesPopulated = false;
            string storedMD5 = null;

            long startingOffset = offset.HasValue ? offset.Value : 0;
            long?startingLength = length;
            long?validateLength = null;

            RESTCommand <NullType> getCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.StorageUri);

            options.ApplyToStorageCommand(getCmd);
            getCmd.CommandLocationMode           = CommandLocationMode.PrimaryOrSecondary;
            getCmd.RetrieveResponseStream        = true;
            getCmd.DestinationStream             = destStream;
            getCmd.CalculateMd5ForResponseStream = !options.DisableContentMD5Validation.Value;
            getCmd.Handler        = blob.ServiceClient.AuthenticationHandler;
            getCmd.BuildClient    = HttpClientFactory.BuildHttpClient;
            getCmd.BuildRequest   = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.Get(uri, serverTimeout, attributes.SnapshotTime, offset, length, options.UseTransactionalMD5.Value, accessCondition, cnt, ctx);
            getCmd.RecoveryAction = (cmd, ex, ctx) =>
            {
                if ((lockedAccessCondition == null) && !string.IsNullOrEmpty(lockedETag))
                {
                    lockedAccessCondition = AccessCondition.GenerateIfMatchCondition(lockedETag);
                    if (accessCondition != null)
                    {
                        lockedAccessCondition.LeaseId = accessCondition.LeaseId;
                    }
                }

                if (cmd.StreamCopyState != null)
                {
                    offset = startingOffset + cmd.StreamCopyState.Length;
                    if (startingLength.HasValue)
                    {
                        length = startingLength.Value - cmd.StreamCopyState.Length;
                    }
                }

                getCmd.BuildRequest = (command, uri, builder, cnt, serverTimeout, context) => BlobHttpRequestMessageFactory.Get(uri, serverTimeout, attributes.SnapshotTime, offset, length, options.UseTransactionalMD5.Value && !arePropertiesPopulated, lockedAccessCondition ?? accessCondition, cnt, context);
            };

            getCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(offset.HasValue ? HttpStatusCode.PartialContent : HttpStatusCode.OK, resp, NullType.Value, cmd, ex);

                if (!arePropertiesPopulated)
                {
                    CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, isRangeGet);

                    if (resp.Content.Headers.ContentMD5 != null)
                    {
                        storedMD5 = Convert.ToBase64String(resp.Content.Headers.ContentMD5);
                    }

                    if (!options.DisableContentMD5Validation.Value &&
                        options.UseTransactionalMD5.Value &&
                        string.IsNullOrEmpty(storedMD5))
                    {
                        throw new StorageException(
                                  cmd.CurrentResult,
                                  SR.MD5NotPresentError,
                                  null)
                              {
                                  IsRetryable = false
                              };
                    }

                    // If the download fails and Get Blob needs to resume the download, going to the
                    // same storage location is important to prevent a possible ETag mismatch.
                    getCmd.CommandLocationMode = cmd.CurrentResult.TargetLocation == StorageLocation.Primary ? CommandLocationMode.PrimaryOnly : CommandLocationMode.SecondaryOnly;
                    lockedETag     = attributes.Properties.ETag;
                    validateLength = resp.Content.Headers.ContentLength;

                    arePropertiesPopulated = true;
                }

                return(NullType.Value);
            };

            getCmd.PostProcessResponse = (cmd, resp, ctx) =>
            {
                HttpResponseParsers.ValidateResponseStreamMd5AndLength(validateLength, storedMD5, cmd);
                return(Task.FromResult(NullType.Value));
            };

            return(getCmd);
        }