Beispiel #1
0
        /// <summary>
        /// Implementation method for the ClearPage methods.
        /// </summary>
        /// <param name="startOffset">The start offset. Must be multiples of 512.</param>
        /// <param name="length">Length of the data range to be cleared. Must be multiples of 512.</param>
        /// <param name="options">An object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="TaskSequence"/> that writes the pages.</returns>
        private TaskSequence ClearPageImpl(long startOffset, long length, BlobRequestOptions options)
        {
            CommonUtils.AssertNotNull("options", options);

            if (startOffset < 0 || startOffset % Protocol.Constants.PageSize != 0)
            {
                CommonUtils.ArgumentOutOfRange("startOffset", startOffset);
            }

            if (length <= 0 || length % Protocol.Constants.PageSize != 0)
            {
                CommonUtils.ArgumentOutOfRange("length", length);
            }

            PutPageProperties properties = new PutPageProperties()
            {
                Range     = new PageRange(startOffset, startOffset + length - 1),
                PageWrite = PageWrite.Clear,
            };

            var webRequest = ProtocolHelper.GetWebRequest(
                this.ServiceClient,
                options,
                (timeout) => BlobRequest.PutPage(this.TransformedAddress, timeout, properties, null));

            webRequest.ContentLength = 0;

            // signing request needs Size to be set
            this.ServiceClient.Credentials.SignRequest(webRequest);

            // Get the response
            var responseTask = webRequest.GetResponseAsyncWithTimeout(this.ServiceClient, options.Timeout);

            yield return(responseTask);

            // Parse the response
            using (HttpWebResponse webResponse = responseTask.Result as HttpWebResponse)
            {
                this.ParseSizeAndLastModified(webResponse);
            }
        }
        /// <summary>
        /// Implementation method for the WritePage methods.
        /// </summary>
        /// <param name="pageData">The page data.</param>
        /// <param name="startOffset">The start offset.</param> 
        /// <param name="sourceStreamPosition">The beginning position of the source stream prior to execution, negative if stream is unseekable.</param>
        /// <param name="options">An object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="TaskSequence"/> that writes the pages.</returns>
        private TaskSequence WritePageImpl(Stream pageData, long startOffset, long sourceStreamPosition, BlobRequestOptions options)
        {
            CommonUtils.AssertNotNull("options", options);

            long length = pageData.Length;

            // Logic to rewind stream on a retry
            // HACK : for non seekable streams we need a way to detect the retry iteration so as to only attempt to execute once.
            // The first attempt will have SourceStreamPosition = -1, which means the first iteration on a non seekable stream.
            // The second attempt will have SourceStreamPosition = -2, anything below -1 is considered an abort. Since the Impl method
            // does not have an executino context to be aware of what iteration is used the SourceStreamPosition is utilized as counter to
            // differentiate between the first attempt and a retry.
            if (sourceStreamPosition >= 0 && pageData.CanSeek)
            {
                if (sourceStreamPosition != pageData.Position)
                {
                    pageData.Seek(sourceStreamPosition, 0);
                }
            }
            else if (sourceStreamPosition < -1)
            {
                // TODO : Need to rewrite this to support buffering in XSCL2 so that retries can work on non seekable streams
                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.CannotRetryNonSeekableStreamError));
            }

            if (startOffset % Protocol.Constants.PageSize != 0)
            {
                CommonUtils.ArgumentOutOfRange("startOffset", startOffset);
            }

            // TODO should reuse sourceStreamPoisition when the HACK above is removed, for readability using a new local variable
            long rangeStreamOffset = pageData.CanSeek ? pageData.Position : 0;

            PutPageProperties properties = new PutPageProperties()
            {
                Range = new PageRange(startOffset, startOffset + length - rangeStreamOffset - 1),
                PageWrite = PageWrite.Update,
            };

            if ((1 + properties.Range.EndOffset - properties.Range.StartOffset) % Protocol.Constants.PageSize != 0 ||
                (1 + properties.Range.EndOffset - properties.Range.StartOffset) == 0)
            {
                CommonUtils.ArgumentOutOfRange("pageData", pageData);
            }

            var webRequest = ProtocolHelper.GetWebRequest(
                this.ServiceClient,
                options,
                (timeout) => BlobRequest.PutPage(this.TransformedAddress, timeout, properties, null));

            ////BlobRequest.AddMetadata(webRequest, this.Metadata);

            // Retrieve the stream
            var requestStreamTask = webRequest.GetRequestStreamAsync();
            yield return requestStreamTask;

            // Copy the data
            using (var outputStream = requestStreamTask.Result)
            {
                var copyTask = new InvokeTaskSequenceTask(() => { return pageData.WriteTo(outputStream); });
                yield return copyTask;

                // Materialize any exceptions
                var scratch = copyTask.Result;
            }

            // signing request needs Size to be set
            this.ServiceClient.Credentials.SignRequest(webRequest);

            // Get the response
            var responseTask = webRequest.GetResponseAsyncWithTimeout(this.ServiceClient, options.Timeout);
            yield return responseTask;

            // Parse the response
            using (HttpWebResponse webResponse = responseTask.Result as HttpWebResponse)
            {
                this.ParseSizeAndLastModified(webResponse);
            }
        }
        /// <summary>
        /// Implementation method for the ClearPage methods.
        /// </summary>
        /// <param name="startOffset">The start offset. Must be multiples of 512.</param>
        /// <param name="length">Length of the data range to be cleared. Must be multiples of 512.</param>
        /// <param name="options">An object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="TaskSequence"/> that writes the pages.</returns>
        private TaskSequence ClearPageImpl(long startOffset, long length, BlobRequestOptions options)
        {
            CommonUtils.AssertNotNull("options", options);

            if (startOffset < 0 || startOffset % Protocol.Constants.PageSize != 0)
            {
                CommonUtils.ArgumentOutOfRange("startOffset", startOffset);
            }

            if (length <= 0 || length % Protocol.Constants.PageSize != 0)
            {
                CommonUtils.ArgumentOutOfRange("length", length);
            }

            PutPageProperties properties = new PutPageProperties()
            {
                Range = new PageRange(startOffset, startOffset + length - 1),
                PageWrite = PageWrite.Clear,
            };

            var webRequest = ProtocolHelper.GetWebRequest(
                this.ServiceClient,
                options,
                (timeout) => BlobRequest.PutPage(this.TransformedAddress, timeout, properties, null));

            webRequest.ContentLength = 0;

            // signing request needs Size to be set
            this.ServiceClient.Credentials.SignRequest(webRequest);

            // Get the response
            var responseTask = webRequest.GetResponseAsyncWithTimeout(this.ServiceClient, options.Timeout);
            yield return responseTask;

            // Parse the response
            using (HttpWebResponse webResponse = responseTask.Result as HttpWebResponse)
            {
                this.ParseSizeAndLastModified(webResponse);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Implementation method for the WritePage methods.
        /// </summary>
        /// <param name="pageData">The page data.</param>
        /// <param name="startOffset">The start offset.</param>
        /// <param name="sourceStreamPosition">The beginning position of the source stream prior to execution, negative if stream is unseekable.</param>
        /// <param name="options">An object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="TaskSequence"/> that writes the pages.</returns>
        private TaskSequence WritePageImpl(Stream pageData, long startOffset, long sourceStreamPosition, BlobRequestOptions options)
        {
            CommonUtils.AssertNotNull("options", options);

            long length = pageData.Length;

            // Logic to rewind stream on a retry
            // For non seekable streams we need a way to detect the retry iteration so as to only attempt to execute once.
            // The first attempt will have SourceStreamPosition = -1, which means the first iteration on a non seekable stream.
            // The second attempt will have SourceStreamPosition = -2, anything below -1 is considered an abort. Since the Impl method
            // does not have an execution context to be aware of what iteration is used the SourceStreamPosition is utilized as counter to
            // differentiate between the first attempt and a retry.
            if (sourceStreamPosition >= 0 && pageData.CanSeek)
            {
                if (sourceStreamPosition != pageData.Position)
                {
                    pageData.Seek(sourceStreamPosition, 0);
                }
            }
            else if (sourceStreamPosition < -1)
            {
                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.CannotRetryNonSeekableStreamError));
            }

            if (startOffset % Protocol.Constants.PageSize != 0)
            {
                CommonUtils.ArgumentOutOfRange("startOffset", startOffset);
            }

            long rangeStreamOffset = pageData.CanSeek ? pageData.Position : 0;

            PutPageProperties properties = new PutPageProperties()
            {
                Range     = new PageRange(startOffset, startOffset + length - rangeStreamOffset - 1),
                PageWrite = PageWrite.Update,
            };

            if ((1 + properties.Range.EndOffset - properties.Range.StartOffset) % Protocol.Constants.PageSize != 0 ||
                (1 + properties.Range.EndOffset - properties.Range.StartOffset) == 0)
            {
                CommonUtils.ArgumentOutOfRange("pageData", pageData);
            }

            var webRequest = ProtocolHelper.GetWebRequest(
                this.ServiceClient,
                options,
                (timeout) => BlobRequest.PutPage(this.TransformedAddress, timeout, properties, null));

            ////BlobRequest.AddMetadata(webRequest, this.Metadata);

            // Retrieve the stream
            var requestStreamTask = webRequest.GetRequestStreamAsync();

            yield return(requestStreamTask);

            // Copy the data
            using (var outputStream = requestStreamTask.Result)
            {
                var copyTask = new InvokeTaskSequenceTask(() => { return(pageData.WriteTo(outputStream)); });
                yield return(copyTask);

                // Materialize any exceptions
                var scratch = copyTask.Result;
            }

            // signing request needs Size to be set
            this.ServiceClient.Credentials.SignRequest(webRequest);

            // Get the response
            var responseTask = webRequest.GetResponseAsyncWithTimeout(this.ServiceClient, options.Timeout);

            yield return(responseTask);

            // Parse the response
            using (HttpWebResponse webResponse = responseTask.Result as HttpWebResponse)
            {
                this.ParseSizeAndLastModified(webResponse);
            }
        }