Azureの小ネタ (改)

~Azureネタを中心に、色々とその他の技術的なことなどを~

Uncommitted な BLOB

Block Blobは、Put Blockでデータを転送したあとの、Put Block Listによってコミットされますが、転送が中断され、Put Block Listされなかったものは、どこに行ってしまうのでしょうか?

それらは、Uncommitted blobとなって、宙ぶらりんの状態になります。

MSDNから引用すると以下のあたりの部分でしょうか。

存在しない BLOB に対して Put Block を呼び出した場合、コンテンツ サイズが 0 の新しいブロック BLOB が作成されます。この BLOB は、include=uncommittedblobs オプションを指定して List Blobs 操作を実行すると列挙されます。新規 BLOB に対して Put Block List を呼び出すまで、アップロードしたブロックはコミットされません。この方法で作成した BLOB は 1 週間サーバーに保持されます。この期間にブロックを追加またはコミットしなかった BLOB はガベージ コレクションされます。

UncommittedなBlob 一覧は、Get Block List (REST API)で取得することができますが、これに対応するStorage Client APIは用意されているような、用意されていないような感じです。

というのも、CloudBlockBlobクラスのメソッドとしては用意されていないので、REST APIをラップしたBlobHttpWebRequestFactory.GetBlockListメソッドを利用する必要があります。

さらに、Uncommittedなものを取得するためには、ちゃんと署名が必要なので、色々と試行錯誤してしまいました。LINQ Padで実行した断片を残しておきます。

BlockListingFilterで、Committed/Uncommitted/All の3種類をフィルタできます。また、SharedKeyAuthenticationHandler.SignRequestメソッドで署名します。

   var name = "アカウント";
   var keu  = "ストレージアカウントキー";
   
   var creds = new StorageCredentials(name, key);
   var account = new CloudStorageAccount(creds, false);

   ...

   var req = BlobHttpWebRequestFactory.GetBlockList(
        new Uri("http://XXXXX.blob.core.windows.net/hoge/hoge.bin"), 
        90, 
        null, 
        BlockListingFilter.All, AccessCondition.GenerateEmptyCondition(), 
        new OperationContext());
        
    var can = Microsoft.WindowsAzure.Storage.Core.Auth.SharedKeyCanonicalizer.Instance;
    
    var skh = new Microsoft.WindowsAzure.Storage.Auth.Protocol.SharedKeyAuthenticationHandler(
                can, creds, creds.AccountName);

    skh.SignRequest(req, new OperationContext());
    
    var res = req.GetResponse();

    new StreamReader(res.GetResponseStream()).ReadToEnd().Dump();

補足

ちなみに、CloudBlockBlob.Exists()してもFalseとなります。ListBlobs(blobListingDetails : BlobListingDetails.UncommittedBlobs); とやると一覧に含まれます。

補足2

キチント調べてみたら、メソッドがありました。CloudBlockBlob.DownloadBlockList です。GetBlockListからメソッド名を類推して探していたので、見つけ損ねたようです。 :-) 以上。