Stream Position Not Reset on Retries in PageBlob WritePages API

Stream Position Not Reset on Retries in PageBlob WritePages API

  • Comments 2

 The issue is resolved in the Windows Azure SDK  1.3 release which can be downloaded here.

We recently came across a bug in the StorageClient library in which WritePages fails on retries because the stream is not reset to the beginning before a retry is attempted. This results in the StorageClient reading from incorrect position and hence causing WritePages to fail on retries.

The workaround is to implement a custom retry on which we reset the stream to the start before we invoke WritePages. We have taken note of this bug and it will be fixed in the next release of StorageClient library. Until then, Andrew Edwards, an architect in Storage team, has provided a workaround which can be used to implement WritePages with retries. The workaround saves the selected retry option and sets the retry policy to “None”. It then implements its own retry mechanism using the policy set. But before issuing a request, it rewinds the stream position to the beginning ensures that WritePages will read from the correct stream position.

This solution should also be used in the VHD upload code provided in blog “Using Windows Azure Page Blobs and How to Efficiently Upload and Download Page Blobs”. Please replace pageBlob.WritePages with the call to the below static method to get around the bug mentioned in this post.

Jai Haridas

 

static void WritePages(CloudPageBlob pageBlob, MemoryStream memoryStream, long offset)
{
        CloudBlobClient client = pageBlob.ServiceClient;
        RetryPolicy savedPolicy = client.RetryPolicy;
        client.RetryPolicy = RetryPolicies.NoRetry();

        int retryCount = 0;

        for (;;)
        {
            TimeSpan delay = TimeSpan.FromMilliseconds(-1);

            // pageBlob.WritePages doesn't do this for retries
            memoryStream.Seek(0, SeekOrigin.Begin);

            try
            {
                pageBlob.WritePages(memoryStream, offset);
                break;
            }
            catch (TimeoutException e)
            {
                bool shouldRetry = savedPolicy != null ? 
                    savedPolicy()(retryCount++, e, out delay) : false;
                if (!shouldRetry)
                {
                    throw;
                }
            }
            catch (StorageServerException e)
            {
                bool shouldRetry = savedPolicy != null ? 
                    savedPolicy()(retryCount++, e, out delay) : false;
                if (!shouldRetry)
                {
                    throw;
                }
            }

            if (delay > TimeSpan.Zero)
            {
                System.Threading.Thread.Sleep(delay);
            }
        }

        client.RetryPolicy = savedPolicy;
}

Leave a Comment
  • Please add 1 and 1 and type the answer here:
  • Post
  • Now that 1.4 has been released, is this fixed?

  • @Chris, Yes this is fixed in sdk 1.4.

Page 1 of 1 (2 items)