IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  Linux | Open source  >

洗練されたPerl: Perl と Amazon クラウド、第 3 回

画像をアップロードし、コメントを作成、編集、削除する

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません

ダウンロード

原文はこちら

原文はこちら


レベル: 中級

Teodor Zlatanov, Programmer, Gold Software Systems

2009年 6月 14日

この 5 回からなる連載では、Amazon の S3 (Simple Storage Service) と SimpleDB を利用した単純な写真共有 Web サイトを、Perl と Apache を使用して構築します。この第 3 回目では、この写真共有 Web サイトと SimpleDB とのやり取りを説明し、アップロードされるファイルの SimpleDB レコードを URL を使って作成する方法を学びます。また、ある写真に特定のユーザーが書き込んだコメントを SimpleDB レコードとして作成、編集、削除する方法も学びます。

前回の記事からしばらく時間が経ちました。前回までの内容は以下のとおりです。

  • 第 1 回」では S3 と SimpleDB のアーキテクチャーを説明し、またその使い方を実用的な例をとおして学びました。
  • 第 2 回」では、Web ページから HTML フォームを使ってファイルを S3 にアップロードし、サーバーの負荷を最小にする方法を説明しました。
この連載を最大限に活用するために

この連載を読むためには、HTTP と HTML に関する初心者レベルの知識と、JavaScript と Perl (Apache の mod_perl プロセスの内部で使われます) に関する中級レベルの知識が必要です。また、リレーショナル・データベースやディスク・ストレージ、ネットワークなどの知識があると役に立ちます。この連載は回を追うごとに技術的なレベルが高くなるため、そうしたトピックの知識が必要な場合には「参考文献」セクションを参照してください。

ではいよいよ、この写真共有サイトと Amazon の SimpleDB とのやり取りに入りましょう。ここでは、アップロードされるファイル用の SimpleDB レコードを適切な URL を使って作成する方法、また、ある写真に特定のユーザーが書き込んだコメントを SimpleDB レコードとして作成、編集、削除する方法を学びます。(この連載では SimpleDB を Google の BigTable と比較したり、CouchDB のようなスタンドアロンのソリューションと比較したりするわけではないことを忘れないでください。)

前回までの記事と同じように、ドメイン名として share.lifelogs.com を使います。

何よりもまず、データベースの構造

第 1 回で説明したように、テーブルの構造をリスト 1 のように設定しました。


リスト 1. 第 1 回で説明したテーブルの構造

share_photos:
"http://developer.amazonwebservices.com/connect/images/amazon/logo_aws.gif" 
{ user: "ted", name: "Amazon Logo"}

"http://images.share.lifelogs.com/funny.jpg" 
{ user: "bob", name: "Funny Picture",  s3bucket: "images.share.lifelogs.com" }

share_users:
"ted" { given: "Ted", family: "Zlatanov" }
"bob" { given: "Bob", family: "Leech" }

share_comments:
"random-string"
{ 
 url: "http://images.share.lifelogs.com/funny.jpg",
 comment: "Ha ha", 
 posted_when: "2009-03-01T19:00:00+05" 
}

"random-string2"
{ 
 user: "ted",
 url: "http://developer.amazonwebservices.com/connect/images/amazon/logo_aws.gif", 
 comment: "No it doesn't", 
 posted_when: "2009-03-01T20:00:01+05" 
}

"random-string3"
{ 
 url: "http://developer.amazonwebservices.com/connect/images/amazon/logo_aws.gif", 
 comment: "No it doesn't", 
 reply_to: "random-string2", 
 posted_when: "2009-03-01T20:00:01+05" 
}

このバージョンの構造では、1 つのコメント構造の中の 1 つのスレッドに、すべてのコメントを保存することができます。しかしこれでは、2 人のユーザーが同じスレッドで同時にコメントの削除や編集ができてしまう、という危険性があります。

第 1 回で説明したとおり、この構造は容易に変更することができます。SimpleDB の大きなメリットの 1 つは柔軟性なので、それを活用することにしましょう。「愚かな首尾一貫性は狭い心が化けた物である」と Emerson は言っています。もちろん彼は、「私は引用が大嫌いだ」とも言っています。無駄に超越した一貫性は忘れましょう。

私は、SimpleDB 用の Scratchpad がそれほど便利ではなく、コードから直接呼び出しを行った方が便利だと思いましたが、皆さんはこの Scratchpad を好むかもしれません。この SimpleDB 用の Scratchpad についての URL は「参考文献」セクションを参照してください。また、SimpleDB 用の管理ツールがいくつかあるので、それを購入する方法もあり、Firefox 用の無料の管理ツールを使う方法もあり、あるいは typica シェルを使ってみることもできます。すべて「参考文献」セクションで紹介していますので、好きなものを選んで管理を行ってください。




上に戻る


画像のアップロードと修正

まず、SimpleDB では 1 つのキーに対して複数の値が許容されることに注意してください。そのため、私が説明する画像の URL、あるいはコメントのテキストは、1 つの値ではなく配列であっても構いません。ここではこの機能を使わず、1 つのキーに 1 つの値という単純な構成にします。

では画像の更新を始めましょう。アップロードを行うたびに、コードを実行して新しい画像を share_photos テーブルに追加します。そのために、「第 2 回」で説明した S3 のアップロード・フォームを、ここで作成するコードに接続します。

とりあえず、画像を追加するための簡単なスクリプトを作成しましょう。ユーザー名、URL、画像の名前、そしてオプションとして S3 のバケット名が指定されます。S3 のバケットは単にテーブルの 1 つのフィールドにすぎず、画像を表示したり使用したりするためには URL で充分です。ただし、その URL に画像が既に存在する場合にはアップロードを拒否したいものですが、拒否できるのでしょうか。

分散型データ・ストアの問題は、たった今データ・ストアに置いたデータが、まだネットワークの端まで到達していない可能性があることです。これは日本からヨーロッパに電話をかける場合に似ています (あるいは、ネットワークや音声信号に遅延がある状態で何かをする場合に似ています)。つまり一言言うたびにわずかな遅延があり、相手はそれに応答するのです。言葉が途切れないように話し続けることもできますが、そうすると、こちらの言葉と相手の応答が重なってしまい、重要な会議の進行役のような思いをする羽目になります。つまり遅延は強引に話を進めるにはちょうどよいのですが、礼儀にかなった会話をするには困りものなのです。

それと同じように、SimpleDB システムにデータを格納する場合、データがデータ・センターに到着するまでに少し間があります。さて、以下は Amazon によって確認されたわけではありませんが、データ・センターに向けて送られたデータは Runu 系 (ベテルギウスから 3 パーセク (約 10 光年) 進んだところで、左に向けて進むと見えてきます) では銀河意識の一部となって、銀河意識とつながるナメクジのような存在の生活もろとも改善されるそうです。つまり SimpleDB を使うたびに、Runu 系のナメクジのような存在に貢献していることになります。そして皆さんは、この記事がためにならないと思うことでしょう。

いずれにせよ、銀河意識が改善されるのと並行して、データが稼働し始め、クエリーによってそのデータが確認されるようになります。しかし、そのようになる前にクエリーを実行すると、銀河意識が改善されないばかりか、古いデータを取得してしまうことになります。つまり DB2 のような標準的なデータベースを扱う場合ほど単純ではありません。標準的なデータベースでは ACID の性質があるため、データが稼働し始めると、データベースがトランザクションをコミットすれば、そのトランザクションは確実にコミットされます。SimpleDB や他の「最終的には一貫性のある」データベースの場合には、この不確実性を我慢するしかありません。

要するに、画像の更新はそれほど単純ではないのです。指定された URL に画像が既に存在する場合にはアップロードを拒否したいのですが、必ずしもそれが可能とは限りません。例えば、Alice が http://horsey.com/wilbur.png をアップロードし、それと同時に Bob も http://horsey.com/wilbur.png をアップロードしたと考えてみてください。Alice が先にアップロードしたことに Bob が気付かなければ、Bob がアップロードすることで、Alice がアップロードした画像は上書きされてしまいます。ではどうすればよいのでしょう。

皆さんはまず最初に、何が不都合なのか?と尋ねるかもしれません。ユーザーにとっては不都合ですが、それほどにまで大きな問題ではありません。また、こうしたことが起こる可能性が非常に高いわけではありません。とは言え、ユーザーを幸せにしたいものであり、私達が異常に品質を気にする人間である場合には、明らかに欠陥のあるものをリリースしたことを死の床で悔やむかもしれません。

そこで、不幸を墓場まで持ち込まないで済むように、画像用のテーブルの設計を変更することにします (リスト 2)。


リスト 2. テーブルの設計を変更する

share_photos:

"random-string10"
{ url: "http://developer.amazonwebservices.com/connect/images/amazon/logo_aws.gif",
        user: "ted", name: "Amazon Logo"}

"random-string11"
{ url: "http://images.share.lifelogs.com/funny.jpg", user: "bob", name: "Funny Picture",
        s3bucket: "images.share.lifelogs.com" }

これまで見てきた random-string は UUID です。これはまだ完璧ではありませんが、少なくとも URL が同じであっても画像が衝突することはありません。しかしちょっと待ってください。画像のコメントはどうするのでしょう。それは簡単で、単に外部キーを変更すればよいのです (リスト 3)。


リスト 3. 外部キーを変更する

share_comments:

"random-string3"
{ 
 image_id: "random-string10", 
 comment: "No it doesn't", 
 reply_to: "random-string2", 
 posted_when: "2009-03-01T20:00:01+05" 
}

この状態では、同じ URL を持つ複数のエントリーが share_photos の中に存在する可能性があることを認識しておく必要がありますが、それを除けばシステムに問題はないようです。

ここでは、最終的なバージョンのテーブルがどのようになるかを見せようとしているのではなく、私が皆さんと一緒に作業しようとしていることを理解してください。こうすることで SimpleDB の柔軟性を示すことができ、また同時に、作成し、テストし、改善し、そして繰り返すという、アジャイル開発の最高の形を示すことができます。すべてのことを計画するのではなく、次の段階に進むために最低限必要なものだけを計画するのです。そのためには、

  • どのような場合にも、全体としての目標を忘れてはいけません。
  • アーキテクチャーに関する決定を、特定のタスクに固有の決定をするのと同じように軽々しく行ったり、変更したりしてはいけません。

こうしてみると、画像のアップロードは簡単だと思いませんか。指定された URL、画像の名前、ユーザー名を使って新しいエントリーを SimpleDB に追加すればよいだけです。S3 のバケットはオプションです。画像のアップロードには PutAttributes 呼び出しを使います。

画像の変更も同じように容易ですが、ここではとりあえず、名前の変更のみができるようにしましょう。これも PutAttributes を使って行います。




上に戻る


コメントの追加と変更

この前のセクションの share_comments テーブルを参照してください。非常に単純です。コメントを追加するためには、コメントのテキスト、画像の ID、そしてオプションとして親コメントの ID とユーザー名が必要です。コメントの変更では、とりあえずコメントのテキストのみを変更できるようにします。




上に戻る


スタンドアロン・スクリプト

この記事には、先ほど挙げたタスク (画像の追加と変更、コメントの追加と変更) を実行するための、スタンドアロンの Perl スクリプト simple_go.pl を含めてあります (この simple_go.pl スクリプトは、この記事の最後の「ダウンロード」セクションから入手することができます)。このスクリプトはドメインを作成しないので、SimpleDB のドメイン share_photos.share.lifelogs.com と share_comments.share.lifelogs.com を外部で作成する必要があります。これはいずれかの SimpleDB 管理ツールを使えば簡単に作成することができます。--domain スイッチによって、share.lifelogs.com が ($full_domain に保存される) フル・ドメイン名の何か別のものに変更されることに注意してください。

このスクリプトは CPAN の Data::UUID モジュールを使って新しい一意の識別子を生成します。

また、このスクリプトはエラー処理が雑であり、すぐに die() を選択しようとします。これは怠惰で卑しむべきことであり、記事を書いているプログラマーが堕落していることを世界に示したい場合以外は、こうしたことをすべきではありません。

そんなスクリプトへようこそ。

最後のタスクは、SELECT 文を送信し、項目を削除することです。この実装は単純で、後でこれらのタスクが必要になるため、ここではその実装方法を説明します。

画像を一覧表示するためには、リスト 4 に示すように、スクリプトを呼び出します。


リスト 4. 画像を一覧表示する

./simple_go.pl -l -i --ak=accesskey --sk=secretkey

ここで 1 つ注意をしておきます。このスクリプトを実行するマシンが他の人に使われていないことを確認してください。他の人がそのマシンを使っている場合、その人達はプロセスの一覧を見て、皆さんの Amazon の秘密鍵を知ることができてしまいます。同様に、シェルの中で履歴を保持していると、秘密鍵も履歴ファイルの中に残ってしまいます。適切な方法としては、ファイル名を渡し、そのファイルからパスワードを取得することです。しかしここでは単純にするために、そうした実装はしてありません。

コメントを一覧表示するためには次のようにします。


リスト 5. コメントを一覧表示する

./simple_go.pl -l -c --ak=accesskey --sk=secretkey

ここまでは非常に簡単です。このスクリプトは内部で $service->select() メソッドを呼び出し、その結果を解析し、show_list() を使ってデータを出力します。すべての動作はキーが 1 つの値しか持たないという前提で行われます (put() メソッドで Replace=true と指定していることに注意してください)。そのため、これは汎用の SimpleDB スクリプトではありません。

汎用の SimpleDB スクリプトを作成しない理由は、それが必要ないからです。まず、簡単なソリューションで解決しましょう。複数の値が必要な場合には、このスクリプトを後で変更するか、あるいは単に新しいコードを作成すればよいのです。このスクリプトは、この Web サイトのデータベース構造を作成するための練習なのです。

従って、このスクリプトを実際のサイトで使おうとはしないでください (このスクリプトは、単に system() を呼び出してエラーをログ・ファイルに記録しているだけです)。確かにこれは数百行のコードであり、実際に動作しますが、このスクリプトのプロトタイプはすべて惜しげなく廃棄しなくてはいけません。そうすることで真のプログラムを作成できるのです。たとえインデントが空白 1 つで行き当たりばったりの (まあ、良く言えば「創造的な」) レイアウトに少しばかり愛着が湧いてきたとしても、このスクリプトを例外扱いしないようにしましょう。

スクリプトに戻りましょう。新しい画像の作成は簡単です (バケットはオプションです)。


リスト 6. 新しい画像を作成する

./simple_go.pl -i --ak=accesskey --sk=secretkey -u ted --url="any url"
  --name="any name you like" --bucket=mybucket

画像の名前を編集します (-l -i によって、25EC17B8-0F6B-11DE-A1A1-944E07F9DEC1 という ID が得られます)。これによって、一意の UUID を持つ画像が作成されます。


リスト 7. 一意の UUID を持つ新しい画像を作成する

./simple_go.pl -i --ak=accesskey --sk=secretkey --name="new name"
  --id=25EC17B8-0F6B-11DE-A1A1-944E07F9DEC1

同様に、コメントの作成も簡単です (userrefcommentid はオプションです)。


リスト 8. コメントを作成する

./simple_go.pl -c --ak=accesskey --sk=secretkey -u ted --refimageid="any image ID"
  --text="the text" --refcommentid='any comment ID'

この場合も、コメントの ID は一意の UUID です。コメントのテキストの編集も上と同様の方法で行います (-l -c によって 4BE2EA0A-0F6B-11DE-976B-A542FC6BD07C という ID が得られます)。


リスト 9. 一意の UUID を持つコメントを作成する

./simple_go.pl -c --ak=accesskey --sk=secretkey --text="the text"
  --id=4BE2EA0A-0F6B-11DE-976B-A542FC6BD07C

そして、画像やコメントの削除も上と同様の方法で行います。


リスト 10. 画像やコメントを削除する

./simple_go.pl --delete -i --ak=accesskey --sk=secretkey
  --id=25EC17B8-0F6B-11DE-A1A1-944E07F9DEC1
./simple_go.pl --delete -c --ak=accesskey --sk=secretkey
  --id=4BE2EA0A-0F6B-11DE-976B-A542FC6BD07C




上に戻る


まとめ

今回は、この連載で構築している写真共有サイトの基礎となる SimpleDB データベースでの、画像とコメントの作成、編集、そして削除の方法を説明しました。

ここではスキーマを (大まかに) 作成し、画像とコメントの追加、一覧表示、変更、削除を行うツールを実装しました。そして、画像とコメントの両方の主キーとして UUID を使用することで、2 人のユーザーが画像用の同じ URL を同時にアップロードするという起こりにくいシナリオを防止しました。

また、1 つのキーに対して 1 つの値しか使わないようにしました。これは、それ以上のことが現在のスキーマでは必要なく、またここでは単純さを目標にしているためです。この欠点については、後でコードの中で対処する必要があるかもしれませんが、ここではこれで我慢することにします。

第 4 回では、すべてを組み合わせ、mod_perl による Web サイトを作り上げます。





上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
Sample script for this articlesimple_go.zip4KBHTTP
ダウンロード形式について


参考文献

学ぶために

製品や技術を入手するために
  • Javascript Scratchpad for Amazon SimpleDB は、HTML と JavaScript による単純なアプリケーションであり、これを利用すると、何もコードを作成せずに Amazon SimpleDB の API を使用することができます。

  • Google の typica シェルは、Amazon の SQS、EC2、SimpleDB、そしてDevPay LS といった Web サービスにアクセスするための、単純でスレッドセーフな API です。この API は QUERY インターフェースを使用しており、またこれらのサービスに対する Amazon の SOAP クライアントの中にあるメソッドに従ってメソッドをパターン化しています。

  • Open Source Simple DB Firefox Plugin: SDB Tool は Firefox ベースの無料の SimpleDB 管理ツールです。

  • この SimpleDB モジュールによって Amazon::SimpleDB を簡単に使えるようになります。私はここからヒントを得ました。

  • 以下の最新技術を (価格情報と共に) 入手してください。
  • CPAN (Comprehensive Perl Archive Network) サイトには膨大な数のモジュールとモジュールのドキュメントが用意されています。

  • Firefox 用の便利な S3 管理ユーティリティー・アドオン、S3Fox (Amazon S3 Firefox Organizer) を入手してください。

  • developerWorks から直接ダウンロードできる IBM ソフトウェアの試用版を使用して皆さんの次期 Linux 開発プロジェクトを構築してください。


議論するために
  • My developerWorks community に参加してください。個人プロファイルとカスタムのホームページを利用することで、皆さんの関心事項に合わせて developerWorks を調整することができ、また他の developerWorks ユーザーとやり取りすることができます。


著者について

photo- teodor zlatanov

Teodor Zlatanov は 1999年にボストン大学 (Boston University) でコンピューター工学の修士号を取得しています。彼は 1992年からプログラマーとして働いており、Perl、Java、C、C++ を使ってきています。彼が関心を持っている領域は、オープンソースによるテキスト構文解析、データベース・アーキテクチャー、ユーザー・インターフェース、UNIX システム管理などです。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



 


 


不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


    日本IBMについて プライバシー お問い合わせ