C++ 用 Windows Azure ストレージ クライアント ライブラリのプレビュー版をリリース


このポストは、12 月 20 日に Windows Azure Storage Team が投稿した Windows Azure Storage Client Library for C++ Preview の翻訳です。

マイクロソフトは、C++ 用 Windows Azure ストレージ クライアント ライブラリを新たにリリースしました。現時点ではプレビュー リリースですので、このライブラリは本番環境のコードでは使用しないでください。また、一般提供版のインターフェイスの改良および変更に活用するため、皆様にお試しいただき、フィードバックをお寄せいただけますと幸いです。この記事では、ライブラリの概要について説明します。

Windows Azure ストレージについての詳細は、「SOSP 論文 - Windows Azure Storage: 強力な一貫性を持つ高可用性クラウド ストレージ サービス (英語)」を参照してください。

エミュレーターについての案内

このライブラリでは 2013-08-15 REST バージョンを使用していますが、このバージョンはまだストレージ エミュレーターではサポートされていません。Windows Azure ストレージ エミュレーターの更新版が来月中にリリースされる予定です。こちらでは、新機能が完全にサポートされます。現行バージョンのストレージ エミュレーターで開発を行うと、暫定的に Bad Request エラーが返されます。新しいエミュレーターのリリースまでは、2013-08-15 REST バージョンの新機能を使用するには Windows Azure ストレージ アカウントで開発、テストを行う必要があります。

サポート対象のプラットフォーム

今回のリリースでは、Visual Studio 2012 (v110) と Visual Studio 2013 (v120) の両方のプラットフォームのツールセットで、x64 と x86 のバージョンを提供します。このため、パッケージには次の 8 個のビルドが含まれています。

  1. リリース、x64、v120
  2. デバッグ、x64、v120
  3. リリース、Win32、v120
  4. デバッグ、Win32、v120
  5. リリース、x64、v110
  6. デバッグ、x64、v110
  7. リリース、Win32、v110
  8. デバッグ、Win32、v110

配布場所

このライブラリは NuGet (英語) からダウンロードできます。また、完全なソース コードは GitHub (英語) で入手できます。NuGet パッケージは CoApp ツール (英語) を使用して作成されており、次の 3 つのパッケージで構成されています。

  • wastorage.0.2.0-preview.nupkg: このパッケージには、アプリケーションの開発に必要な、ヘッダーと LIB ファイルが含まれています。ユーザーはこのパッケージをインストールする必要があり、これには redist パッケージとの依存関係が設定されているため、自動的に redist パッケージが NuGet から自動的にインストールされます。
  • wastorage.redist.0.2.0-preview.nupkg: このパッケージには、アプリケーションの実行と再配布に必要な DLL ファイルが含まれています。
  • wastorage.symbols.0.2.0-preview.nupkg: このパッケージには、各 DLL ファイルに対応したシンボルが含まれています。オプションのパッケージです。

パッケージは C++ REST SDK (英語) とも依存関係があり、こちらも自動的に NuGet からインストールされます。C++ REST SDK (コードネーム “Casablanca”) (英語) は、クライアントとサーバー間のクラウドベースの通信をネイティブ コードで実行するためのマイクロソフトのプロジェクトであり、非同期 C++ バインディングを HTTP、JSON、および URI に提供することで、複数のプラットフォームでネイティブ コードから REST サービスへのアクセスをサポートしています。Windows Azure ストレージ クライアント ライブラリではこれを使用して、Windows Azure ストレージ BLOB、キュー、およびテーブルの各サービスと通信しています。

使用可能な機能

ここでは、REST API と直接通信するのではなく Windows Azure ストレージ クライアント ライブラリを使用することによって実現される機能について、概要を説明します。

  • Windows Azure ストレージ REST API 2013-08-15 バージョン全体を簡単に使用可能な形で実装
  • 特定の要求が失敗したときの再試行に指数または線形のバック オフ アルゴリズムを使用する再試行ポリシーを導入
  • 認証モデルを合理化し、共有鍵と共有認証署名の両方をサポート
  • 操作コンテキストと ETW のログを使用して、要求の詳細と結果を確認
  • BLOB のサイズや種類を問わず、ユーザーの構成に応じてブロックまたはページ単位で BLOB を並列アップロード
  • 特定のアップロード用またはダウンロード用 API に対応していなくても BLOB の読み取りおよび書き込みが可能な BLOB ストリーム
  • BLOB のアップロード用とダウンロード用のすべての API で MD5 を完全にサポート
  • 2013 年 11 月に新たに Windows Azure ストレージでのサポートが開始された JSON (英語) を使用したテーブル層
  • エンティティ グループ トランザクションがテーブル サービスでサポートされ、1 つのトランザクションで複数の操作が可能に

読み取りアクセス地理冗長ストレージのサポート

今回のリリースでは、セカンダリ拠点に存在するストレージ アカウント データへの読み取りアクセスが完全にサポートされました。この機能を使用するには、管理ポータルから特定のストレージ アカウントに対して有効化する必要があります。読み取りアクセス地理冗長ストレージの詳細については、こちらのページを参照してください。

使用方法

NuGet パッケージをインストールすると、使用する必要があるヘッダー ファイルはすべて “was” (Windows Azure Storage の略) という名前のフォルダーに格納されます。このフォルダー内にあるヘッダー ファイルのうち、次のものは特に重要です。

  • blob.h: BLOB サービスに関連するすべての型の宣言に使用します。
  • queue.h: キュー サービスに関連するすべての型の宣言に使用します。
  • table.h: テーブル サービスに関連するすべての型の宣言に使用します。
  • storage_account.h: cloud_storage_account 型を宣言します。この型を使用すると、アカウント名と鍵の組み合わせ、または接続文字列を使用してサービスのクライアント オブジェクトを簡単に作成できます。
  • retry_policies.h: すべての操作で使用可能な再試行ポリシーを個別に宣言します。

これらを使用する際は、まず、使用するヘッダーをインクルードします。

#include "was/storage_account.h"

#include "was/queue.h"

#include "was/table.h"

#include "was/blob.h"

ここでは、cloud_storage_account オブジェクトを作成することにします。これは、後述のコードでサービスのクライアント オブジェクトを作成する際に必要です。この例では接続の安全性を考慮して https を使用しますが、アプリケーションのデバッグを行う際には http を使用すると非常に便利です。

wa::storage::cloud_storage_account storage_account = wa::storage::cloud_storage_account::parse(U("AccountName=<account_name>;AccountKey=<account_key>;DefaultEndpointsProtocol=https"));

BLOB

ここでは、まず BLOB コンテナーを作成します。さらに、「何らかのテキスト」を追加して、それをダウンロードし、最後にコンテナー内のすべての BLOB をリスト表示します。

// BLOB コンテナーを作成

wa::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client();

wa::storage::cloud_blob_container container = blob_client.get_container_reference(U("mycontainer"));

container.create_if_not_exists();

// BLOB をアップロード

wa::storage::cloud_block_blob blob1 = container.get_block_blob_reference(U("myblob"));

blob1.upload_text(U("some text"));

// BLOB をダウンロード

wa::storage::cloud_block_blob blob2 = container.get_block_blob_reference(U("myblob"));

utility::string_t text = blob2.download_text();

// BLOB をリスト表示

wa::storage::blob_result_segment blobs = container.list_blobs_segmented(wa::storage::blob_continuation_token());

テーブル

次に示すサンプルでは、まずテーブルを作成し、異なる型のプロパティを複数持つエンティティを挿入し、最後にそのエンティティを取得します。取得操作の最初に、ポイント クエリを実行して特定のエンティティを取得します。このクエリ操作では、PartitionKey が “partition” と等しく、RowKey が “m” 以上のすべてのエンティティに対してクエリを実行します。これにより、最終的に、サンプルで挿入した元のエンティティが取得されます。

Windows Azure テーブルについての詳細は、「テーブル サービス データ モデルについて」および「Windows Azure テーブルの活用方法 (英語)」の記事を参照してください。

// テーブルを作成

wa::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

wa::storage::cloud_table table = table_client.get_table_reference(U("mytable"));

table.create_if_not_exists();

// テーブル エンティティを挿入

wa::storage::table_entity entity(U("partition"), U("row"));

entity.properties().insert(wa::storage::table_entity::property_type(U("PropertyA"), wa::storage::table_entity_property(U("some string"))));

entity.properties().insert(wa::storage::table_entity::property_type(U("PropertyB"), wa::storage::table_entity_property(utility::datetime::utc_now())));

entity.properties().insert(wa::storage::table_entity::property_type(U("PropertyC"), wa::storage::table_entity_property(utility::new_uuid())));

wa::storage::table_operation operation1 = wa::storage::table_operation::insert_or_replace_entity(entity);

wa::storage::table_result table_result = table.execute(operation1);

// テーブル エンティティを取得

wa::storage::table_operation operation2 = wa::storage::table_operation::retrieve_entity(U("partition"), U("row"));

wa::storage::table_result result = table.execute(operation2);

// テーブル エンティティのクエリを実行

wa::storage::table_query query;

query.set_filter_string(wa::storage::table_query::combine_filter_conditions(

wa::storage::table_query::generate_filter_condition(U("PartitionKey"), wa::storage::query_comparison_operator::equal, U("partition")),

wa::storage::query_logical_operator::and,

wa::storage::table_query::generate_filter_condition(U("RowKey"), wa::storage::query_comparison_operator::greater_than_or_equal, U("m"))));

std::vector<wa::storage::table_entity> results = table.execute_query(query);

キュー

最後のサンプルでは、まずキューを作成し、メッセージを追加し、そのメッセージを取得して、最後にこれを更新します。

// キューを作成

wa::storage::cloud_queue_client queue_client = storage_account.create_cloud_queue_client();

wa::storage::cloud_queue queue = queue_client.get_queue_reference(U("myqueue"));

queue.create_if_not_exists();

// キューにメッセージを追加

wa::storage::cloud_queue_message message1(U("mymessage"));

queue.add_message(message1);

// キューのメッセージを取得

wa::storage::cloud_queue_message message2 = queue.get_message();

// キューのメッセージを更新

message2.set_content(U("changedmessage"));

queue.update_message(message2, std::chrono::seconds(30), true);

デバッグ方法

何らかの問題が発生した場合、呼び出しのいずれかから例外が発生したことが通知されます。この例外は wa::storage::storage_exception という型で、発生した問題に関する詳細な情報を含んでいます。次のコードをご覧ください。

try

{

blob1.download_attributes();

}

catch (const wa::storage::storage_exception& e)

{

std::cout << "例外: " << e.what() << std::endl;

ucout << U("開始時刻: ") << e.result().start_time().to_string() << U("終了時刻: ") << e.result().end_time().to_string() << U(" の要求で、HTTP ステータス コード ") << e.result().http_status_code() << U(" が返されました。サーバーから報告された要求 ID : ") << e.result().service_request_id() << std::endl;

}

存在しない BLOB で実行しようとした場合、このコードでは次のような文字列が記録されます。

例外: The specified blob does not exist.

開始時刻: Fri, 13 Dec 2013 18:31:11 GMT、終了時刻: Fri, 13 Dec 2013 18:31:11 GMT の要求で、HTTP ステータス コード 404 が返されました。サーバーから報告された要求 ID: 5de65ae4-9a71-4b1d-9c99-cc4225e714c6

このライブラリでは wa::storage::operation_context という型も提供されています。これはすべての API をサポートしていて、操作中の処理内容を詳細に取得できます。これに関して、次のコードで説明します。

wa::storage::operation_context context;

context.set_sending_request([] (web::http::http_request& request, wa::storage::operation_context)

{

ucout << U("次の宛先に要求を送信中: ") << request.request_uri().to_string() << std::endl;

});

context.set_response_received([] (web::http::http_request&, const web::http::http_response& response, wa::storage::operation_context)

{ ucout << U("理由メッセージ: ") << response.reason_phrase() << std::endl;

});

try

{

blob1.download_attributes(wa::storage::access_condition(), wa::storage::blob_request_options(), context);

}

catch (const wa::storage::storage_exception& e)

{

std::cout << "例外: " << e.what() << std::endl;

}

ucout << U("この操作で ") << context.request_results().size() << U(" 個の要求が実行されました。最後の要求のステータス コード: ") << context.request_results().back().http_status_code() << std::endl;

先ほどと同様に、存在しない BLOB で実行しようとした場合、このコードでは次のような文字列が記録されます。

次の宛先に要求を送信中: http://myaccount.blob.core.windows.net/mycontainer/myblob?timeout=90

理由メッセージ: The specified blob does not exist.

例外: The specified blob does not exist.

この操作で 1 個の要求が実行されました。最後の要求のステータス コード: 404

サンプル

マイクロソフトは、GitHub でサンプル プロジェクトを配布 (英語) しています。各抽象化ストレージのセットアップと実行の際にお役立てください。またその他に、主要なシナリオのサンプルが複数用意されています。サンプル プロジェクトはすべて “samples” という名前のフォルダーに格納されます。

Visual Studio の場合、サンプル ソリューションのファイル名は “Microsoft.WindowsAzure.Storage.Samples.sln” です。Microsoft.WindowsAzure.Storage.SamplesCommon プロジェクトの samples_common.h ファイルで、ユーザーのストレージ アカウントの認証情報を更新します。ソリューション エクスプローラーのウィンドウに移動し、実行するサンプル プロジェクト (Microsoft.WindowsAzure.Storage.BlobsGettingStarted など) を選択します。次に、[Project] メニューで [Set as StartUp Project] を選択 (またはプロジェクトを右クリックしてコンテキスト メニューから同オプションを選択) します。

まとめ

マイクロソフトは皆様からのフィードバックをお待ちしております、ページ下部のコメント欄、フォーラム、または GitHub (英語) までお気軽にお寄せください。また、不具合を発見した場合は、GitHub まで報告していただくと、後から解決策が確認できます。

Serdar Ozler、Mike Fisher、Joe Giardino

参照資料

ソース コード (GitHub、英語)

バイナリ ファイル (NuGet、英語)

Windows Azure ストレージのリリース - CORS、JSON、分単位メトリックなど各種機能の導入

Windows Azure テーブル: JSON の紹介 (英語)

Comments (0)

Skip to main content