locked
Create Snapshot returns URI of Base Blob - not SnapShot RRS feed

  • Question

  • So I'm using Snapshot to create a History of changes

     

     

                'Get a reference to a blob, which may or may not exist.

                Dim blob As CloudBlob = BlobContainer.GetBlobReference(ObjectID.ToString & "." & Key)

     

                'Upload content to the blob, which will create the blob if it does not already exist.

                blob.UploadFromStream(ms)

                Dim r = blob.CreateSnapshot()

                Return r.Properties.ETag

    (At this point r.URI is the same as the bob.uri)
    However, if I later want to retrieve the snapshot - I need the snapshot URI, not the base blob.)
    which means later I need:
                If Not Snapshot Is Nothing Then
                    Dim MyToken As Microsoft.WindowsAzure.StorageClient.ResultContinuation = Nothing
                    Dim MyOptions As New Microsoft.WindowsAzure.StorageClient.BlobRequestOptions
                    MyOptions.BlobListingDetails = BlobListingDetails.Snapshots
                    MyOptions.UseFlatBlobListing = True
                    Dim res = BlobContainer.ListBlobsSegmented(1000, MyToken, MyOptions)
                    Do
                        For Each b In res.Results
                            If b.Uri.OriginalString.Contains(ProjectID.ToString) Then
                                blob = CType(b, CloudBlob)
                                If blob.Properties.ETag = Snapshot Then
                                    ' Console.WriteLine(b.Uri.OriginalString)
                                    Exit Do
                                End If
                                '                            Console.WriteLine(b.Uri.OriginalString)
                            End If
                        Next
                        If res.HasMoreResults Or res.ContinuationToken IsNot Nothing Then
                            res = res.GetNext()
                        Else
                            Exit Do
                        End If
                    Loop
                End If
    But this is hugely wasteful and slow.
    How can I retrieve a Snapshot without enumerating all files in the container/directory?
    BG

     

    Sunday, September 18, 2011 6:31 PM

Answers

  • Yes Ben, my code just gives you the uri as a string that you can share with the module that wants to reference it. From there on, you can use GetBlobReference as you mentioned to get reference to the CloudBlob reference. Once you get the reference to CloudBlob instance, you can use DownloadXXX method to download the data.

    About blob does not exist - can you check the request Uri and can you tell using your (favorite) storage explorer that the blob exists? A fiddler/netmon trace to also compare the names will be good.

    Thanks,
    Jai

     

    Friday, September 23, 2011 5:14 PM

All replies

  • So I'm using Snapshot to create a History of changes

     

                'Get a reference to a blob, which may or may not exist.

                Dim blob As CloudBlob = BlobContainer.GetBlobReference(ObjectID.ToString & "." & Key)

     

                'Upload content to the blob, which will create the blob if it does not already exist.

                blob.UploadFromStream(ms)

                Dim r = blob.CreateSnapshot()

                Return r.Properties.ETag

    (At this point r.URI is the same as the bob.uri)
    However, if I later want to retrieve the snapshot - I need the snapshot URI, not the base blob.)
    which means later I need:
                If Not Snapshot Is Nothing Then
                    Dim MyToken As Microsoft.WindowsAzure.StorageClient.ResultContinuation = Nothing
                    Dim MyOptions As New Microsoft.WindowsAzure.StorageClient.BlobRequestOptions
                    MyOptions.BlobListingDetails = BlobListingDetails.Snapshots
                    MyOptions.UseFlatBlobListing = True
                    Dim res = BlobContainer.ListBlobsSegmented(1000, MyToken, MyOptions)
                    Do
                        For Each b In res.Results
                            If b.Uri.OriginalString.Contains(ProjectID.ToString) Then
                                blob = CType(b, CloudBlob)
                                If blob.Properties.ETag = Snapshot Then
                                    ' Console.WriteLine(b.Uri.OriginalString)
                                    Exit Do
                                End If
                                '                            Console.WriteLine(b.Uri.OriginalString)
                            End If
                        Next
                        If res.HasMoreResults Or res.ContinuationToken IsNot Nothing Then
                            res = res.GetNext()
                        Else
                            Exit Do
                        End If
                    Loop
                End If
    But this is hugely wasteful and slow.
    How can I retrieve a Snapshot without enumerating all files in the container/directory?
    BG

    Sunday, September 18, 2011 6:31 PM
  • The following is documented:

    -- When you create a snapshot, the blob's Snapshot property returns a DateTime value that uniquely identifies the snapshot relative to its base blob. You can use this value to perform further operations on the snapshot. Note that this DateTime value is opaque.

    Sunday, September 18, 2011 6:52 PM
    Answerer
  • You don't need to make additional requests to storage to build the URI of the snapshot if you already have a reference to the snapshot. The SnapshotTime property will be non-null. To generate the full URI for the snapshot, you can build it from the base URI and add the appropriate query string. I agree that the CloudBlob class should have some method that returns this for you, but until this happens, this is what I use.

    var snapshot = blob.CreateSnapshot();
    var uri = Microsoft.WindowsAzure.StorageClient.Protocol.BlobRequest.Get(snapshot.Uri, 0, snapshot.SnapshotTime.Value, null).Address.AbsoluteUri;
    
    

     

    Monday, September 19, 2011 3:08 AM
  • Hi Ben,

     Yes, this is a known little quirk since the snapshot timestamp is stored as a property rather than reflecting it in the Uri. We will take your feedback for an easy way to retrieve the snapshot Uri via the blob instance as a feature request. Btw, the blob instance returned in CreateSnapshot can be used to retrieve the snapshot but looks like you want to save the Uri and later call it (maybe not even within the same process). In absence of such a property, you can provide an extension method that formulates the snapshot Uri (see below) OR use the above method that Fernando has provided that relies on the protocol layer which returns the HttpWebRequest for accessing the blob.

    Example (please test it :)):

                string uri = string.Format("{0}?snapshot={1}&timeout={2}",
                    snapshotBlob.Uri.AbsoluteUri,
                    snapshotBlob.SnapshotTime.Value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffff'Z'", CultureInfo.InvariantCulture),
                    timeout.TotalSeconds);
    
    

    Thanks,

    jai

    Tuesday, September 20, 2011 3:50 PM
  • Nope.

     

    All of this will create a uri - but it doesn't return a blob.

    the uri isn't worth much without a blob from which to recover same.

     

                    If IsDate(Snapshot) Then

                        '                    Dim b = Microsoft.WindowsAzure.StorageClient.Protocol.BlobRequest.Get(blob.Uri, 0, CDate(Snapshot), Nothing)

                        Dim d As String = CDate(Snapshot).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffff'Z'", Globalization.CultureInfo.InvariantCulture)

                        Dim b As String = String.Format("{0}?snapshot={1}&timeout={2}", blob.Uri.AbsoluteUri, d, 50)

                        blob = CloudBlobClient.GetBlobReference(b)

     

    Thursday, September 22, 2011 5:50 PM
  • Web Web everywhere and not a one example of a snapshot blob being recalled on demand.

     

    Thursday, September 22, 2011 6:04 PM
  • This return error Blob does't exist.

     

    Friday, September 23, 2011 5:08 PM
  • Yes Ben, my code just gives you the uri as a string that you can share with the module that wants to reference it. From there on, you can use GetBlobReference as you mentioned to get reference to the CloudBlob reference. Once you get the reference to CloudBlob instance, you can use DownloadXXX method to download the data.

    About blob does not exist - can you check the request Uri and can you tell using your (favorite) storage explorer that the blob exists? A fiddler/netmon trace to also compare the names will be good.

    Thanks,
    Jai

     

    Friday, September 23, 2011 5:14 PM