読者です 読者をやめる 読者になる 読者になる

はじめての Windows Azure Drive

はじめに

Azure Storage Services が提供する Drive は、System.IO 名前空間のクラスを使ってファイルの書き込みや読み込みができるということなので、ちょっと試してみた。

…Development Storage で、だけど。Windows Azure のアカウントも無ければ、金もないので、本番環境では試せていない。

準備

Windows Azure Cloud Service プロジェクトを新規に作成して、ServiceDefinition.csdef ファイルに Drive の設定を記述。

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="DriveSample"
                   xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
    <WebRole name="WebRole1">
        <InputEndpoints>
            <InputEndpoint name="HttpIn" protocol="http" port="80" />
        </InputEndpoints>

        <LocalResources>
            <!-- Drive で使うキャッシュのサイズを記述 -->
            <LocalStorage name="DriveSampleCache"
                          cleanOnRoleRecycle="false"
                          sizeInMB="100"/>
        </LocalResources>
        
        <ConfigurationSettings>
            <Setting name="DiagnosticsConnectionString" />
        </ConfigurationSettings>
    </WebRole>
</ServiceDefinition>

Drive を使ってみる

ファイルの書き込みと読み込みを行うサンプル。

WebRole の Default.aspx に TextBox と Button を貼り付けただけの簡単なサンプル。TextBox に入力された文字列を Drive 内のファイルに書き込んだり、Drive 内のファイルを読み込んで TextBox に表示したりする。

using System;
using System.IO;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;

namespace WebRole1
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        const int DRIVE_SIZE = 64;
        const int CACHE_SIZE = 25;
        const string LOCAL_RESOURCE_NAME = "DriveSampleCache";
        const string FILE_NAME = "hoge.txt";
        const string CONTAINER_ADDRESS = "drives";
        const string PAGE_BLOB_ADDRESS = "mydrive.vhd";

        protected void _writeButton_Click(object sender, EventArgs e)
        {
            // アカウント取得
            // とりあえず開発用のアカウントを使う
            var account = CloudStorageAccount.DevelopmentStorageAccount;

            // Drive の初期化
            // .cscfg ファイルに書いた情報を使う
            var localCache = RoleEnvironment.GetLocalResource(LOCAL_RESOURCE_NAME);
            CloudDrive.InitializeCache(localCache.RootPath, localCache.MaximumSizeInMegabytes);

            // Drive 用の Blob コンテナを作成
            var blobClient = account.CreateCloudBlobClient();
            var blobContainer = blobClient.GetContainerReference(CONTAINER_ADDRESS);
            blobContainer.CreateIfNotExist();

            // Drive のクライアントを作成
            var drive = account.CreateCloudDrive(
                blobContainer.GetPageBlobReference(PAGE_BLOB_ADDRESS)
                .Uri.ToString());

            // Drive を作成
            // 既に作成済みかどうか判断する方法があればいいのに
            try
            {
                drive.Create(DRIVE_SIZE);
            }
            catch (CloudDriveException)
            {
            }

            // Drive をマウントする
            // マウントで取得したドライブレターを使って色々できる
            var driveLetter = drive.Mount(CACHE_SIZE, DriveMountOptions.None);

            // 渡された文字列をファイルに書き込む
            // System.IO 名前空間のクラスが使える
            using (var writer = new StreamWriter(driveLetter + "//" + FILE_NAME))
            {
                writer.Write(this._textBox.Text);
            }
        }

        protected void _readButton_Click(object sender, EventArgs e)
        {
            // アカウント取得
            // とりあえず開発用のアカウントを使う
            var account = CloudStorageAccount.DevelopmentStorageAccount;

            // Drive の初期化
            var localCache = RoleEnvironment.GetLocalResource(LOCAL_RESOURCE_NAME);
            CloudDrive.InitializeCache(localCache.RootPath, localCache.MaximumSizeInMegabytes);

            // Page Blob の URI を取得するために Blob コンテナを取得
            var blobClient = account.CreateCloudBlobClient();
            var blobContainer = blobClient.GetContainerReference(CONTAINER_ADDRESS);

            // Drive のクライアントを作成
            var drive = account.CreateCloudDrive(
                blobContainer.GetPageBlobReference(PAGE_BLOB_ADDRESS)
                .Uri.ToString());

            // Drive をマウントする
            var driveLetter = drive.Mount(CACHE_SIZE, DriveMountOptions.None);

            // Drive に保存されているファイルの内容を読み込む
            using (var reader = new StreamReader(driveLetter + "//" + FILE_NAME))
            {
                this._textBox.Text = reader.ReadToEnd();
            }
        }
    }
}

Drive のマウントが面倒だな

既存の ASP.NET 製 Web サービスがファイルシステムにアクセスするような場合、Drive を使えばすんなり移行できると思っていたけど、Drive をマウントする処理を追加しなければいけないな。