PERL、CGIで、ファイルロックした時って・・・

[上に] [前に] [次に]
マフィン 1999/09/28(火) 02:14:33
CGIを始めました。考えればわかるかもしれませんが、
諸先輩に甘えさせていただきます。

さて、カウンタなどを作るとき、本で読んだらファイルのロック
というのをしますよね。同時に二人が書きこんだらファイルが消えて
しまうかもしれないからとのことです。当然チャットなどでもこの
ロックをしますが、これってロックしちゃうと単に後からきた人は
その時は書きこめないんでしょうか? もう一回フォームを送り直す
んでしょうか?
チャトしてて書きこめなかったことなんかあった記憶がないんですが・・・
教えて。



if (!&lock_file(TXT)) {
         close(TXT);
         &print_error("ファイル $txtfile 操作で衝突が起きました。<BR>更新リンクを押してください。");
     }

# ロック
sub lock_file {
    local(*FILE) = @_;
    if ($uselock) {
        eval("flock(FILE, 2)"); # 2=LOCK_EX
        if ($@) {
            # flock が使えない場合、ここに来る。
            return 0;
        }
    }
    return 1;
}

# アンロック
sub unlock_file {
    local(*FILE) = @_;
    if ($uselock) {
        eval("flock(FILE, 8)"); # 8=LOCK_UN
    }
}

1999/09/28(火) 02:27:06
ロックしてる書き込みが終わるまで処理を待つって事では?
アンロックされたら書き込めるようになると。
だから送り直すことはない。
と思う。

ふじ 1999/09/28(火) 03:19:18
上記のソースを見る限りでは、ロックに失敗したら即
>ファイル $txtfile 操作で衝突が起きました。<BR>更新リンクを押してください。
というメッセージを出力するようです。

ロックが成功するまで待つには、例えば

for(1..5){
if(&lock_file){
書き込み処理
$success = 1;
last;
}else{
sleep 1;
}
}

if($success){
成功
}else{
失敗
}

のようにして成功するまで間隔を空けて数回トライするような
コーディングをする必要があります。

>ロックしてる書き込みが終わるまで処理を待つって事では?
上記のソースを見る限り、そのような処理はしてませんね。

>チャトしてて書きこめなかったことなんかあった記憶がないんですが・・・
これはたまたまでしょう。上記のソースでは、書き込めずに
再送を求めるメッセージが出ることはありえますよ。

1999/09/28(火) 04:36:33
http://www.tohoho-web.com/wwwperl2.htm#flock
>ブロックモードでは、自分がロックをかけることが
>できる状態になるまでプログラムが一時停止する。
って書いてあったので、待機するのかと思ってました。
違ったんですね・・(-_-;勉強になりました。

なえ 1999/09/28(火) 08:59:59
flock(FILE, 2)なら、ロック解除されるまで待ちます。
ループ処理をする必要はありません。
それとファイルをクローズすれば自動的にロック解除されるのでロック解除のルーチンは要りません。

それと、ちょっとコードにミスあります。
>eval("flock(FILE, 2)"); # 2=LOCK_EX
>if ($@) {
># flock が使えない場合、ここに来る。
>return 0;
>}
eval関数は実行時エラーや文法エラーの時のみ、$@にエラーコードをセットします。
よってこのままでは、ファイルロックに失敗しても1を返しちゃうと思います。

なえ 1999/09/28(火) 09:22:38
追伸です;

flock関数が使えるかどうかは、サーバー管理者に聞くなりダミーの処理を流せばCGI設置前に分かりますので、
flockが使えるかどうかで処理を分岐させる必要は無いと思います。
おそらくWin98マシンでテストして、それからサーバーに載せて本番で動かすのに、
いちいちコードを書き換えないで済むようにevalを使ってるのだと思いますが、
その場合のコードは次のようになります。
if (eval("flock(FILE, 2)")){
  return(1);
}
else{
  return(0);
}

もちろんここまでの話はflockが使えると仮定した場合の話ですので、
もしも使えないならば、ダミーファイルやシンボリックリンクを利用して、擬似的なファイルロック関数を自作する事になります。
その場合は、ふじさんのようにループをさせる必要が出てきますし、ロック解除のルーチンもちゃんと必要になってきます。

あと、もう一言。
ファイルロックに関しては今までにも何度か発言されていますので、
それを検索してみて見つからなかったり、それでも分からなかった時に質問しましょうね。

ふじ 1999/09/28(火) 11:11:02
>なえさん
フォローありがとうございます。
#flockはあんまり使わないんで勘違いしてました(^^;;

>ダミーファイルやシンボリックリンクを利用して、
ダミーファイルではなくてディレクトリの方が良いですよね。
#ファイルは作成時に重複存在チェックをしない(で成功する)けど、
#ディレクトリは作成できずに失敗しますから。

1999/09/28(火) 23:34:08
>なえさん
ありがとうございます。
フォローがなかったら僕も勘違いするところでした(^^;
鵜呑みにするのは良くないですね。
専用の命令なのに待たなかったらブロックモードの意味ないですもんね。
お恥ずかしい。本当に勉強になりました。

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