flockをもう少しテスト

Copyright(C) 25Feb2014 coskx TNCT

はじめに

flockを使用することで,ファイルアクセスの排他制御ができることがわかった。前のページの例では書き込みのみ制御した。書き込みと読み出しが絡んだ場合でも,独立に作業の待ち行列に並んで,先着受付順に作業が行われることを確かめよう。
前ページの例では,ファイル書き出し直後に同じファイルの読み出しを行なったが,書き込み時にのみflockを使ったため,その直後に読み出しをしようとして,他のスレッドが排他制御を行っていたため,読み出しが出来ずに終了していた。
ここでのテストではファイル操作時には必ずflockをかけて,排他制御および作業可能になるまで待つ(flockがやってくれる)という動作を行う。作 業状況を観察するため,ファイル書き込みには20秒(sleepを使う)かけ,読み込みには2秒(sleepを使う)かけることにする。
テストは,3つのブラウザ(IE,Chrome,SeaMonkey)を立ち上げ,数秒おきに作業を要求する。作業が終わると,ブラウザには,作業開始, 書き込み開始,書き込み終了,読み出し開始,読み出し終了,作業終了の各時刻が表示され,どのような順番に作業が進んだかがわかる。


1.テストに用いたphpファイル



ファイル書き込み・読み出しPHPサンプル
<?php
//////////   ここからphpメイン   ///////////////////////

$pagetoshow=0;
$msg="";
$msg2="";
$fname="flocktest2.txt";
$nLines=0;

$work_begin="work begin at ".date('h:i:s')."<br>\n";
//ここで受け取った文字列を20秒かけて保存する。
if(isset($_POST['ikeike_write'])) {
    $pagetoshow=1;
    $requestmsg="accepted message ".date('h:i:s')."\r\n";
    if (($fp=fopen($fname, "a")) !== false ) { //ファイルのオープン
        if (flock($fp, LOCK_EX)==true) { //ファイルのロック 他のスレッドが使用中の場合は待たされる
            $write_begin="write begin at ".date('h:i:s')."<br>\n";
            $msg.=$fname."のオープンとロックに成功しました。<br>";
            fprintf($fp,$requestmsg);
            fprintf($fp,"-- opened and locked %s\r\n",date('h:i:s')); //時刻の書き出し
            sleep(20); //ファイルをオープンしたまま20秒何もしない(動作確認のため)
            fprintf($fp,"-- %s\r\n",$_POST['mytext']);
            fprintf($fp,"-- will be unlocked and closed %s\r\n",date('h:i:s')); //時刻の書き出し
            fflush($fp); //バッファに残っているものを書き出す
            flock($fp, LOCK_UN); //ロック解除
            $msg.=$fname."をアンロックして,クローズしました。<br>";
            $write_end="write end at ".date('h:i:s')."<br>\n";
        } else { //ここには来ない
            $msg.="** error ファイル".$fname."のロックに失敗しました。<br>";
        }
        fclose($fp); //ファイルのクローズ
    } else {
        $msg.="** error ファイル".$fname."のオープンに失敗しました。<br>";
    }

    sleep(1);
    //再読出
    if (($fp=fopen($fname, "r")) !== false ) { //ファイルのオープン
        flock($fp, LOCK_EX);
        $read_begin="read begin at ".date('h:i:s')."<br>\n";
        $i=0;
        while (($lines[$i]=fgets($fp)) !== false) $i++;
        $nLines=$i;
        sleep(2); //ファイルをオープンしたまま2秒何もしない(動作確認のため)
        flock($fp, LOCK_UN); //ロック解除
        $read_end="read end at ".date('h:i:s')."<br>\n";
        fclose($fp); //ファイルのクローズ
        if ($nLines==0) {
            $msg2.="** error ファイル".$fname."の再読出オープンは成功しましたが,何も読み出せませんでした。<br>";
        }
    } else {
        $msg2.="** error ファイル".$fname."の再読出オープンに失敗しました。<br>";
    }
    $work_end="work end at ".date('h:i:s')."<br>\n";
}

?>

<html>
<body>
<h1>flockによる排他的ファイル書き込みのテスト</h1>

<?php if ($pagetoshow==0) {?>
    <p>
    なにか文字列を書いて,送信ボタンを押すと,20秒後に書き込みが終了します。
    それまでそのまま待ってください。
    </p>
    <form method="post">
    <input type="text" name="mytext">
    <input type="submit" name="ikeike_write" value="送信">
    </form>
<?php } else {
    print $msg . "<br>\n";
    if ($nLines==0) {
        print $msg2 . "<br>\n";
    } else {
        print "現在の".$fname."の内容は以下のとおりです<br>";
        foreach($lines as $str) {
            print $str."<br>\n";
        }
    }
    print "-----------------------------------<br>\n";
    print $work_begin."\n";
    print $write_begin."\n";
    print $write_end."\n";
    print $read_begin."\n";
    print $read_end."\n";
    print $work_end."\n";
} ?>

</body>
</html>




2.テストの方法


3つのブラウザ(IE,Chrome,SeaMonkey)を立ち上げた。

実行時最初のブラウザ表示

flockによる排他的ファイル書き込みのテスト

なにか文字列を書いて,送信ボタンを押すと,20秒後に書き込みが終了します。 それまでそのまま待ってください。



各ブラウザに,それぞれ「Hello from IE 」「Hello from Chrome 」「Hello from SeaMonkey」を入力し,順番に送信ボタンを押した。





3.実行結果



3つのブラウザの実行結果は約1分後に次々に表示された。

IEの結果表示

flockによる排他的ファイル書き込みのテスト

flocktest2.txtのオープンとロックに成功しました。
flocktest2.txtをアンロックして,クローズしました。

現在のflocktest2.txtの内容は以下のとおりです
accepted message 05:01:57
-- opened and locked 05:01:57
-- Hello from IE
-- will be unlocked and closed 05:02:17
accepted message 05:01:59
-- opened and locked 05:02:17
-- Hello from Chrome
-- will be unlocked and closed 05:02:37
accepted message 05:02:01
-- opened and locked 05:02:37
-- Hello from SeaMonkey
-- will be unlocked and closed 05:02:57

-----------------------------------
work begin at 05:01:57
write begin at 05:01:57
write end at 05:02:17
read begin at 05:02:57
read end at 05:02:59
work end at 05:02:59
Chromeの結果表示

flockによる排他的ファイル書き込みのテスト

flocktest2.txtのオープンとロックに成功しました。
flocktest2.txtをアンロックして,クローズしました。

現在のflocktest2.txtの内容は以下のとおりです
accepted message 05:01:57 
-- opened and locked 05:01:57 
-- Hello from IE 
-- will be unlocked and closed 05:02:17 
accepted message 05:01:59 
-- opened and locked 05:02:17 
-- Hello from Chrome 
-- will be unlocked and closed 05:02:37 
accepted message 05:02:01 
-- opened and locked 05:02:37 
-- Hello from SeaMonkey 
-- will be unlocked and closed 05:02:57 

-----------------------------------
work begin at 05:01:59
write begin at 05:02:17
write end at 05:02:37
read begin at 05:02:59
read end at 05:03:01
work end at 05:03:01
SeaMonkeyの結果表示

flockによる排他的ファイル書き込みのテスト

flocktest2.txtのオープンとロックに成功しました。
flocktest2.txtをアンロックして,クローズしました。

現在のflocktest2.txtの内容は以下のとおりです
accepted message 05:01:57
-- opened and locked 05:01:57
-- Hello from IE
-- will be unlocked and closed 05:02:17
accepted message 05:01:59
-- opened and locked 05:02:17
-- Hello from Chrome
-- will be unlocked and closed 05:02:37
accepted message 05:02:01
-- opened and locked 05:02:37
-- Hello from SeaMonkey
-- will be unlocked and closed 05:02:57

-----------------------------------
work begin at 05:02:01
write begin at 05:02:37
write end at 05:02:57
read begin at 05:03:01
read end at 05:03:03
work end at 05:03:03

実行結果を見ると,IEの書き込み作業,Chromeの書き込み作業,SeaMonkeyの書き込み作業の後,IEの読み出し作業,Chromeの読み出し作業,SeaMonkeyの読み出し作業の順で行われている。3つのブラウザ共に,読みだしたファイルの内容(ブラウザに表示されている)は3つのブラウザからの書き込みが終了した時点のものである。

実行結果の時刻を見ると詳細な作業順がわかる。
最初に
IEの書き込み作業が始まる。
その作業中に,
Chromeの書き込み作業,SeaMonkeyの書き込み作業が待ち行列に入る。
IEの書き込み作業が終わると,Chromeの書き込み作業が始まる。
その作業中に,待ち行列は
SeaMonkeyの書き込み作業のみになるが,すぐにあとからIEの読み出し作業が待ち行列に加わり,待ち行列はSeaMonkeyの書き込み作業,IEの読み出し作業となる。
Chromeの書き込み作業が終わると,SeaMonkeyの書き込み作業が始まる。
その作業中に,待ち行列はIEの読み出し作業のみになるが,すぐにあとからChromeの読み出し作業が待ち行列に加わり,待ち行列はIEの読み出し作業,Chromeの読み出し作業となる。
SeaMonkeyの書き込み作業が終わると,IEの読み出し作業が始まる。
その作業中に,待ち行列はChromeの読み出し作業のみになるが,すぐにあとからSeaMonkey読み出し作業が待ち行列に加わり,待ち行列はChromeの読み出し作業,SeaMonkey読み出し作業となる。
IEの読み出し作業が終わると,Chromeの読み出し作業が始まる。
その作業中に,待ち行列はSeaMonkey読み出し作業のみになる
Chromeの読み出し作業終わると,SeaMonkeyの読み出し作業が始まる。
ここで
待ち行列は空になる。