簡易掲示板の作成
cgiの応用例として、ごく簡単な掲示板を作ってみます。何回かに分けて説明します。この掲示板は最低限の機能で作ったもので、スパム対策など実用化に必要な機能が組み込まれていませんので、このcgiをそのまま掲示板としてお使いになることはお勧めできません。ご注意ください。データの保存
今までのcgiでは、リクエストからのデータに対して何らかの応答をするだけでした。例えば、式を送られてきたらその答えを返す、文字列を送られてきたらその文字コードを返す、という具合でした。サーバにデータを保存できれば、もっとcgiの応用が広がります。例えば掲示板です。それまでに送られてきた投稿をサーバに保管しておいて、リクエストがあったら投稿を表示します。投稿を溜めておけるというのがポイントで、そのおかげでコミュニケーション・ツールとして機能するわけです。
ロック
サーバ内でファイルの読み書きをする場合は、ファイルのロックが必要です。サーバに対しては多数のクライアントがほぼ同時にアクセスする可能性があります。すると、cgiスクリプトは1つですけれども、アクセス毎にcgiが起動されるので、同じスクリプトが同時平行で複数動くことが有り得るわけです。このような複数の実行スクリプトのそれぞれをプロセスと言います。保存用のファイルの読み書きが同時に複数のプロセスによって行われる可能性があるのです。これを制御しなければ、読んでる途中に書き込まれたり、書き込みが複数ぶつかったり、そのためにファイルが破壊されることもあります。ここでいうファイルの破壊というのは、ファイルの中身がめちゃくちゃになってしまうということです。物理的にディスクが壊れてしまうようなことはありません。そういうことを避けるためには、ロックを使います。あるプロセスがファイルにアクセスするときは、ロックをします。すると他のプロセスはそのファイルにアクセスするのに制限がかかります。あるときは読み込みはできるが、書き込みはできない、別のロックの時は読み書き全部できない、というようにロックされます。今回はflock関数を使いました。
flock ファイルハンドル, ロックの種類;ファイルをオープンして、ファイルハンドルを作成してから、flockを使います。ロックの種類は
LOCK_SH 1 共有ロック。他のプロセスは読み込みできるが書き込みできない LOCK_EX 2 排他的ロック。他のプロセスは読み書きできない LOCK_NB 4 ノン・ブロック。これはLOCK_SH, LOCK_EXとともに用いる。もしも対象のファイルがロックされていた場合、待たずに戻ってくる。 LOCK_UN 8 ロックを解除するLOCK_SH, LOCK_EXだけで使うとブロックモードになります。もしも対象のファイルがロックされていれば、ロックが解除されるまで待ちます。LOCK_SH+LOCK_NB, LOCK_EX+LOCK_NBの場合はノン・ブロックになります。今回はブロックモードで十分です。
open FH, "+<$DATAFILE"; # ">$DATAFILE"とするとファイルが空になって問題が生じる恐れあり flock FH, LOCK_EX; # ファイルの排他的ロック @data = <FH>; #データの読み込み (何かdataに対して作業をする) truncate(FH, 0); seek(FH, 0, 0); # ファイルサイズを0にして、書込のポイントを先頭にする print FH @data; # 書き込みする close FH;これがflockを使う場合の例です。ファイルを全部読み込み、加工して、ファイルを全部書き直しする、というパターンです。排他的ロックを使わなければなりません。