$fh = dio_open($cntfile,O_RDONRY|O_TRUNC );
dio_fcntl($fh,F_SETLKW,array(”type”=>F_WRLCK));
$result = dio_write($fh,$cnt);
dio_fcntl($fh,F_SETLKW,array(”type”=>F_UNLCK));
dio_close($fh);
排他制御の基本的な流れは
1.オープンする
2.ロックする
3.読み込む
4.書き込む
5.ロック解除する
6.クローズする
となります。
つまり、ご質問にかかれているサンプルの流れで基本的にはよいということになります。
・NFS環境での排他制御について
SolarisのNFS環境とのことですので、排他制御にflock()は使えず、fcntl()を使用する必要があります。
NFSサーバとクライアントがNetwork Lock Manager(NLM)プロトコルに対応していれば、NFS上のファイルに対してもfcntl関数を使って安全に排他制御を行うことができます。
・サンプルソースの記述ミス?
ご質問の例で dio_write()を使っているにもかかわらず
$fh = dio_open($cntfile,O_RDONRY|O_TRUNC );
で、O_RDONRYとなっているのは書き間違いでしょうか。
$fh = dio_open($cntfile,O_RDWR|O_TRUNC );
ですよね。リードオンリーモードで読み込んでいるにもかかわらず、dio_write()しているのでエラーになります。
・ロックする
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
fcntl(fd, F_SETLKW, &lock)
・ロック解除する
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = (off_t) 0;
lock.l_len = (off_t) 0;
fcntl(fd, F_SETLKW, &lock);
php-4.3.10のソース(ext/dio/dio.c)をみてみると
ファイル全体を排他制御する場合、
ロックは
dio_fcntl($fh,F_SETLKW,F_WRLCK);
ロック解除は
dio_fcntl($fh,F_SETLKW,F_UNLCK);
と書くだけでいけそうです。(バージョンにもよると思いますのでご確認ください。)
・各パラメータ
start 省略すると 0
length 省略すると 0
whence 省略すると 0 (SEEK_SET)
は、ファイルのある部分をロックするときに設定します。ファイル全体をロックする場合は、0,0,SEEK_SETを設定します。dio_fcntl()だと省略すればよいです。
type 省略すると 0
は、どのような排他制御をするかを指定します。
F_RDLCK シェアードロック
F_WRLCK 排他ロック
F_UNLCK 上記ふたつのロックを解除
各パラメータの詳細は紹介したURLが詳しいのでそちらを参考にしてください。
・マニュアルの間違い
wenthとあるところは間違っています。dio.cではwhenceとなっていますのでご注意ください。
大変ありがとうございました。
教えていただいた通りに試してみたら、無事作動しているようです。