mkdirのロック機能について

[上に] [前に] [次に]
るみ 1999/10/19(火) 14:36:33
とほほ掲示板のロック機能についてですが、

#
# File lock
#
foreach $i ( 1, 2, 3, 4, 5, 6 ) {
if (mkdir("lock/wwwboard.loc", 0755)) {
last;
} elsif ($i == 1) {
($mtime) = (stat("lock/wwwboard.loc"))[9];
if ($mtime < time() - 600) {
rmdir("lock/wwwboard.loc");
}
} elsif ($i < 6) {
sleep(2);
} else {
print "Content-type: text/html\n";
print "\n";
print "<HTML>\n";
print "<HEAD>\n";
print "<TITLE>掲示板</TITLE>\n";
print "</HEAD>\n";
print "<BODY>\n";
print "<H1>掲示板</H1>\n";
print "<HR>\n";
print "只今、掲示板が混雑しております。しばらくお待ちの上、";
print "再度アクセスお願いします。\n";
print "<HR>\n";
print "</BODY>\n";
print "</HTML>\n";
exit(1);
}
}

は以下のような動作をしているのでしょうか?

「lockディレクトリの下にパーミッション755のwwwboard.locを作成し、
 それができなければ配列が1に等しいとき(?)$mtimeにwwwboard.locの
 最終更新時刻を得、もし最終更新時刻が600秒より少なければ(?)
 wwwboard.locを削除する。
 又は配列が6より小さければ2秒間待つか、
 『只今、掲示板が混雑しております。〜』のエラーメッセージを出す。」

しかしこれがどうしてロックの機能を果たすのかが分かりません。
ディレクトリを作ることがどうしてロックになるのかと…
../199908/99080221.htm

> こうすると、存在チェックとロックファイル(ディレクトリ)の作成が
> 同時に行える(既に同じ名前のディレクトリがある場合は、
> mkdir が失敗する)ので、普通のファイルを作成する方法よりは
> 確実なロックになります。
> #UNIXでもWindowsでも使えます。
という記述がありましたが、やっぱりなんでロックファイルの作成イコール
ロック機能になるのか分かりませんでした。

このサイトのPerlとCGIの説明を読んだり、ラウンジで検索しましたが
この程度しか分かりませんでした。どなたかこんな未熟者にも分かるような
解説をお願いします m(__)m

マン蔵 1999/10/19(火) 17:14:32
動作的には、
ロック用のディレクトリを作成してみる。
失敗した場合
・1回目なら
 ロック用のディレクトリが作成してから600秒超える場合は、
 何らかの障害で処理が止まった可能性を考慮してロック用のディレクトリを削除しとく。
・2〜5回目なら
 2秒間待ってみる。
・6回目以上なら
 エラーメッセージを出す。
って、動作になります。

>ロックファイルの作成イコールロック機能になるのか分かりませんでした。
ファイルのロックには、flock がありますが、
>flock()をサポートしていないシステムもあり、無理に使用するとperlが異常終了する。
http://www.tohoho-web.com/wwwperl2.htm#flock
と書いているように、どこの環境(サーバやperlのバージョンなど)でも動くように
するには結構面倒な作業になります。
その点、ディレクトリの作成はほとんどの環境で動作可能なので使われているのだと思います。
(もちろん、すべての環境でOKって訳ではないでしょうけど・・・。)

原理的には、
1.ロック用ディレクトリを作成する。
2.書き込み処理を実行する。
3.ロック用ディレクトリを削除する。
としておけば、もし他の人が書き込み中ならロック用ディレクトリが存在するはず。
だから、『ロック用ディレクトリを作成しようとして失敗したなら書き込み中だ!』
と解釈するわけです。

もちろん、ディレクトリを作成出来るようにパーミッションを設定しないと
常に作成に失敗し、『まだ書き込み中なの!?』って事になりますけどね。

解説になってるかな?(^_^;

るみ 1999/10/19(火) 17:26:41
あっ、という事は、
「誰かが書きこんでいる間はロックファイルが存在する」
「書き込みが終わるとロックファイルを削除する」
「他人が書き込みを始めた時、既にロックファイルが存在すると書きこめない」
「600秒を超えたら書き込みのいかんに関わらずにロックファイルを削除する」
という解釈で合っているでしょうか?

マン蔵 1999/10/19(火) 18:44:39
う〜ん、大体あってますけど・・・。
ちょっと気になるので補足しましょう。

ポイントは、
1.ロック状態であるかどうかの判定にファイルでなくディレクトリを用いる。
2.予期せぬ障害に対する予防策を用意する。
です。

あくまでもロックの制御は『自分はこう言う決まりにする』と決めるだけであって
>「他人が書き込みを始めた時、既にロックファイルが存在すると書きこめない」
と言うのは表現上誤解を生むかと思います。

自分が書き込みを始めようとするときに、他の人が書き込んでいないか確認する。
その確認方法は、
1.ロック状態を示すファイルの存在を確認する。
2.上記が存在するなら、エラー(書き込み中)。
  存在しないなら、自分がロックする(ロックファイルを作成する)。
と考えるのが自然なのですが、上記の方法だと複数の人間が同時に実行した場合に
問題が発生します。1と2で処理が分かれているために起こる問題です。
その辺は、以前の質問でふじさんが説明してます。
(もしここが理解できないようでしたら、もう少し突っ込みますので言ってくださいね。)

そこで、チェックとロックを一度に処理する為にディレクトリを使用するのです。
(あくまでもこれはロックを判定するための物で、掲示板のようなファイルとは違うので注意)


>「600秒を超えたら書き込みのいかんに関わらずにロックファイルを削除する」
この点は、念のために行っておく、と言う感じで、
『掲示板にメッセージと追加(書き込み)するのに10分もかからないだろう。』と判断し、
『ロックし始めてから10分もたってるなら、サーバーが落ちたとかの理由で正常にCGIが終了しなかったかも。』
と決め付けて、『そのままじゃまずいからロックを解除しよう。』と考えているのです。
ですから、もしもっと時間がかかる処理を実行するなら『600秒』では足りないかもしれないし、
その逆もありえます。
その辺は、どのくらい処理に時間がかかるか考えて秒数を変更すればOKです。

るみ 1999/10/20(水) 09:33:23
ちょっと過去ログを調べていて遅れました。すみません。
> ファイルでなくディレクトリを用いる。
ええと、これは
../199908/99080221.htm
でふじさんの発言を拝見しましたが、
「ファイルを作成」だと他プロセスがファイルを上書きしてしまうのに
対し、「ディレクトリの作成」だと同じ名前のディレクトリを
上書きする事はできないという事でしょうか。
ちょっとカン違いしてましたがmkdirってUNIXのコマンドなんですね…
だとするとwwwboard.locというファイルでなくともロック用ディレクトリを
作るだけでもいいんでしょうか。

> あくまでもロックの制御は『自分はこう言う決まりにする』と決めるだけであって
> >「他人が書き込みを始めた時、既にロックファイルが存在すると書きこめない」
> と言うのは表現上誤解を生むかと思います。
なるほど。自分でそういう取り決めを作るという事ですね。

> その辺は、どのくらい処理に時間がかかるか考えて秒数を変更すればOKです。
この辺りはばっちり理解できました!

マン蔵 1999/10/20(水) 14:19:02

別にせかしている訳ではないので気にしなくて良いですよ。
私も出来る範囲でお答えしているだけですから。
(っと自分のレスが遅れた際の予防線!?(^_^;)

まず、wwwboard.loc はファイルではなく、ディレクトリです。
普段はディレクトリに拡張子を付けるないでしょうから、
『拡張子がついている=ファイル』と思われる方も多いので念のため。
(なんとなくこの辺で困惑しているように読み取れたものですから。)

>「ファイルを作成」だと他プロセスがファイルを上書きしてしまうのに
>対し、「ディレクトリの作成」だと同じ名前のディレクトリを
>上書きする事はできないという事でしょうか。
そうですね。
もちろん、同じファイル名で読み込み専用のファイルが存在してたり、
作ろうとするディレクトリのパーミッションによってエラーになりますけどね。
あと、作ろうとするファイル名と同じ名のディレクトリがあったり、
逆に作ろうとするディレクトリ名と同じ名のファイルがあったりすると
エラーになるでしょう。(この辺は試した訳では無いのであしからず。)

ただ、mkdir()はディレクトリを作成できた時にだけ正常でそれ以外の時にエラーになります。
『ファイルを上書きすることはあるだろうけど
 ディレクトリはファイルと違うんだから上書きしないでしょう?
 同名のディレクトリが存在するのに作るのは誤ってるでしょう?
 だからエラーだよね。』
と自分は解釈しています。

この作成と存在チェックが同時に行える点がロック処理(またはロック判定)において重要で、
mkdir()はほとんどの環境で使えるために良く利用されるのです。
(ちなみにUNIXは良くわかりませんがDOSのコマンドにもありますよ。)

だいぶ、イメージが固まってきているようですがどうでしょう。(^_^)

るみ 1999/10/20(水) 15:42:15
[[解決]]
> wwwboard.loc はファイルではなく、ディレクトリです。
えええっそれは知りませんでした!!
すっかりカン違いしてた訳ですね。ほんと、
ここでつまってました(汗)

> 『ファイルを上書きすることはあるだろうけど
>  ディレクトリはファイルと違うんだから上書きしないでしょう?
>  同名のディレクトリが存在するのに作るのは誤ってるでしょう?
>  だからエラーだよね。』

すごく良く分かりました〜!ありがとうございました。
半年位のやっと謎が解けました。うれしい! (^^)
大解決です!

マン蔵 1999/10/20(水) 16:14:57
やはり、wwwboard.loc がファイルだと思われてたんですね。
半年間のもやもやを解決するのに役立てて良かったです。
これですっきり眠れますね。(^_^;)

[上に] [前に] [次に]