【Perl】ファイルロック(排他処理)について語ろう
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
02/06/23 10:18ID:eY2l+Gw10111nobodyさん
02/07/01 02:27ID:???おまえも気づけYO!
0112nobodyさん
02/07/01 22:52ID:???http://tako.2ch.net/test/read.cgi?bbs=perl&key=963036704&st=33
0113nobodyさん
02/07/02 12:38ID:3nOaRL0G0114nobodyさん
02/07/02 17:44ID:???http://natto.2ch.net/perl/kako/963/963036704.html
0115nobodyさん
02/07/04 16:41ID:???・・・と煽ろうと思ったら,レベルの低いスレだったのね.失礼.
0116Hideki ◆wtRzKEV2
02/07/09 09:11ID:???3秒で消し去るのって問題ありでしょうか?
とほほとか見て作ってみたんですけど指摘があればお願いします。
(my $mode, my $file, @_) = @_;
while(!mkdir("$file.lock", 0755))
{
sleep(1);
rmdir "$file.lock" if(time - (stat "$file.lock")[9] > 3);
}
open(DATA, "$mode$file");
print DATA @_;
close DATA;
return rmdir "$file.lock";
0117Hideki ◆wtRzKEV2
02/07/09 09:12ID:???0118nobodyさん
02/07/09 09:31ID:zyHRUAZm始めて裁判見てきたけど、ひろゆきって2chでの中傷について、「おいらは第三者だもんねー」ってな主張してたけど、裁判官に一喝されてた。
どうもひろゆきが企業の中傷を禁止してないことと、削除依頼を自分の意思で突っぱねたことで、当事者と判断されてる感じ。
でも裁判官も他の掲示板と2chは同じには扱っていないみたいだったから、他の掲示板には影響ないと思うけど。
それにしても、ひろゆきの顔はイベント板のタイトルに使ってる写真と全然違うのに驚いた。
あの写真は「勝負写真」なんだろうけど、あれじゃ詐欺だよ。
実物は深海魚みたいな顔だった。
0120Hideki ◆wtRzKEV2
02/07/09 18:23ID:upY+9e5f0121nobodyさん
02/07/09 18:54ID:???指摘する前に質問させてくれ。
これはソースの一部分か? どうみても独立したソースじゃないよな。
なぜファイルロックにmkdirが有効なのか理解できてるのか?
0122Hideki ◆wtRzKEV2
02/07/09 20:00ID:upY+9e5fみたいに渡す構成です。
mkdirを使えば
-> OS処理なので2つのプロセスが両方とも実行ができない。(Windows, UNIXで使える)
-> mkdir以下のコードはひとつのプロセスが実行する保証が得られる
-> mkdirできない間(rmdirが実行されるまで)は他のプロセスは待つ
-> mkdirできれば、ファイルを書きに行く。
-> もし異常終了か何かでロックディレクトリーが残っていれば3秒以上経った物は不正なロックとして強制削除。ファイルを書きに行く。
という構成で書いたのですが、どこら辺が話にならないのでしょうか?説明お願いします。
0123nobodyさん
02/07/09 20:14ID:???ファイルロックを実行して、目的のファイルデータを読み書きするのに要する
時間は処理の混み具合によっては3秒以上かかる可能性もある。もし3秒以上
処理にかかったら他のプロセスにデータを壊される可能性あり。
ファイルロック以外の部分でも書き込み途中でシステムがダウンしたらデータが
壊れる可能性もある。
0124Hideki ◆wtRzKEV2
02/07/09 20:56ID:???秒数で攻めたらいたちごっこですね。
壊す危険を冒すよりは、書き込みを中止する方がいいかもしれませんね。
> 途中でシステムがダウンしたら
そりゃopen後書き込む前に刺さりゃー、何のロックしても無駄ってヤツだ。
0125nobodyさん
02/07/09 22:36ID:???Hideki ◆wtRzKEV2 を叩くスレはここ?
0127nobodyさん
02/07/09 23:05ID:???そう思うならそれで良い、どれだけデータの安全と整合性を保障したいかだから。
そう言う人が秒間50アクセスのDBを管理するなんて事も珍しいでしょうし。
取り合えず
statの取得とrmdirがシステムコールレベルでアトミックになされる保障は
何処にも無い。
消そうとするロックディレクトリが正常かどうかの判断が出来ていない。
よって
>rmdir "$file.lock" if(time - (stat "$file.lock")[9] > 3);
この行は有っても無くても同じ
0128nobodyさん
02/07/09 23:07ID:???基本的に動作と確認が一発で出来る様な
アトミックなシステムコールを使わなきゃ駄目です。
ifで調べてから、動作なんてその間一万年掛かるかも知れないし
0129Hideki ◆wtRzKEV2
02/07/10 00:11ID:???0130nobodyさん
02/07/10 00:16ID:???0131Hideki ◆wtRzKEV2
02/07/10 00:22ID:???同次元の突込みが無いので自分のためのスクリプトしては問題は無いと思った。
つーか、てめーはだれだ!ププッじゃねぇぞ、コルゥァ!
>> 途中でシステムがダウンしたら
>そりゃopen後書き込む前に刺さりゃー、何のロックしても無駄ってヤツだ。
この考え方からしてまだまだだよな。元データを壊さない工夫がないって言い
たかったのに…。
0133Hideki ◆wtRzKEV2
02/07/10 00:35ID:???そうです。まだまだこれからです。まだ若いので。
おおー。まだいるんか。
も1つヒントというか助言だが、mkdir より symlink または rename が
いいと思うぞ。なぜかと言うと mkdir より軽いからだ。なぜ軽いかというと
ファイルシステムを勉強すればわかる。
ただし、symlink は環境によっては使えないから rename を使ったほうがい
いということだ。
最後に、プロは完璧に近いものをストックとしていくつかもっているけど
ここじゃ披露する気にはなれないということを言っておこう。
0135nobodyさん
02/07/10 00:49ID:???0136nobodyさん
02/07/10 00:49ID:???0137nobodyさん
02/07/10 00:49ID:???0138nobodyさん
02/07/10 00:50ID:???0139nobodyさん
02/07/10 00:53ID:???http://www2q.biglobe.ne.jp/~terra/cgi/lockfile.htm
ユーモアのあるページだなぁ。この人は基本的な関数の実行結果の真偽を
使うことも知らないのか…。
こういうページが氾濫しては…。
0141nobodyさん
02/07/10 02:06ID:???dat 落ち前に読んでおけ
http://pc.2ch.net/test/read.cgi/sec/1025671013/349-
0142nobodyさん
02/07/10 02:35ID:???0144nobodyさん
02/07/10 03:04ID:???ブログラマにはギャグセンスも必要っと φ(。。) メモメモ
0146nobodyさん
02/07/10 10:54ID:???(゚Д゚)ハァ? >>142が言ってるのはファイルに直接アクセスなんかしないで
排他処理が元からきちっと実装されてるDBMS使えってことだろ。
まあDBMSが使えるサーバなんて限られてるしこのスレ的にはスレ違いだとは思うが。
0147nobodyさん
02/07/10 15:23ID:???MySQLやらPostgreSQLが〜となるとたしかにアレだろうけど、
BerkleyDB とかなら OS 標準で入っていることも非常に多いし、
Perl からでも使えるしナー。
0148115
02/07/10 16:43ID:???> テーブルの真中には大きなスパゲティの皿が置いてあります.
> またN本のフォークがあって哲学者と哲学者の席の間に置いてあります.
> 哲学者は思索を続けていますが,お腹がすくと両側のフォークを取って
> スパゲティを食べます.お腹が一杯になると食べるのを止めてフォークを返します.
> 哲学者は紳士ですから,お腹が空いていても両方のフォークが手に入るまでは待ちます.
これか。このスレとは微妙に方向性が違うような。
0152nobodyさん
02/07/10 18:38ID:???MySQL が BerkleyDB の機能を使ってトランザクションを実現
しているくらいなのに、lock やってないわけなかろ。いつの
version の話してるの?
http://www.sleepycat.com/docs/reftoc.html
http://www.sleepycat.com/docs/ref/lock/intro.html
見て出直してこい。ちなみにこの document は 4.0.14 のだけど、
3.x のころからしっかり lock subsystem がある。
0153nobodyさん
02/07/10 21:53ID:???OS標準で入ってるつーと
http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/db/README?rev=1.1&content-type=text/x-cvsweb-markup
とかVer 1だろ。
perlのDB_Fileで2や3も使えるけど、インターフェースは1でサポートされてる部分しか使えねーはずだが。
0154nobodyさん
02/07/11 02:02ID:???http://search.cpan.org/search?dist=BerkeleyDB
使えば?
あと、FreeBSD では完全に標準な状態ではたしかにそうだけど、ふつう
ports で 3.x が入ってくるし、Debian でも完全に標準では 2.x でふつう
3.x、RedHat では完全に標準で 3.x が入る
0155nobodyさん
02/07/11 04:50ID:???それなら車輪の再発明は止めて最初からDBMSを使うべきというのは
反論しようのない正論。しかも、リソースのありかまで教えてくれているし。
ただ、こういう極めて的確な回答があると、この手のスレはつまらなくなるね…。
0157nobodyさん
02/07/11 09:23ID:???0158nobodyさん
02/07/11 11:11ID:???0159nobodyさん
02/07/11 16:21ID:???0160nobodyさん
02/07/11 21:02ID:???0161nobodyさん
02/07/12 18:11ID:???# 排他処理をしたいです。
# ローカル環境(WindowsMe+Apache+Cygwin付属のPerl)では成功するのですが、
# サーバで実行するときには、必ず失敗します(エラー表示部が実行されます)。
# もし落ち度がありましたらご教授ください。以下要所の抜粋です。
sub create_lock {
my ($lockfile, $retry) = @_;
while (!mkdir($lockfile, 0755)) {
if (--$retry <= 0) {
return undef;
}
sleep(1);
}
return 1;
}
sub remove_lock {
my ($lockfile) = @_;
rmdir($lockfile);
}
#上記関数の利用例
my $lock_handle = &create_lock("./lockfile", 5);
if (not $lock_handle) {
&print_error($resource{writedatafailed});
}
#ここで処理する
&remove_lock($dir_lock);
0162nobodyさん
02/07/12 19:10ID:???ディレクトリに書き込み権限がない。
既にロックされている(./lockfileが存在する)。
のどちらか。
&create_lock("./lockfile", 5);
と
&remove_lock($dir_lock);
のファイル名が…
0163nobodyさん
02/07/12 19:38ID:???ご指摘ありがとうございます。(;ワ;)
今夜さっそくディレクトリの書き込み権限のチェックをしてみます。
えーと、下の $dir_lock は貼り付け時に直し忘れました(^^;)
混乱させてしまったようで、すみません。
あとでまた結果報告しにきます。
0165nobodyさん
02/07/18 03:33ID:???open(OUT, "+< outfile.txt");
flock(OUT, 2);
truncate(OUT, 0);
seek(OUT, 0, 0);
print OUT "........";
close(OUT);
の欠点を教えてください。
お願いします。
0167nobodyさん
02/07/18 13:34ID:???0169nobodyさん
02/07/18 14:56ID:???flock(OUT, 2);
seek(OUT, 0, 0);
print OUT "........";
truncate(OUT, tell(OUT));
close(OUT);
書き込みが終わってからtruncate()したほうが安全でちょっと速いみたい。
truncate(FILE, tell(FILE)) : 56 wallclock secs ( 8.21 usr + 39.26 sys = 47.47 CPU) @ 210.67/s (n=10000)
truncate(FILE, 0) 60 wallclock secs ( 8.43 usr + 42.72 sys = 51.15 CPU) @ 195.49/s (n=10000)
0170nobodyさん
02/07/18 15:36ID:???正確にはsyswriteするか$|=1してバッファ使わない様にした方が良いけど
0171nobodyさん
02/07/18 15:38ID:???前提が変なのに何をどうしたいのやら
0172nobodyさん
02/07/18 15:41ID:???0173fusianasan
02/07/18 16:45ID:???だれに言ってるんだ? わたしの記憶が確かなら>>170に定数って書いてるYO!
0174nobodyさん
02/07/18 17:11ID:???( > v<)ノ タマンネー♪
0175nobodyさん
02/07/18 17:30ID:???0177nobodyさん
02/07/18 17:42ID:???0178nobodyさん
02/07/18 19:10ID:???0179nobodyさん
02/07/18 23:34ID:???0180nobodyさん
02/07/18 23:43ID:???漢字で書いたら一緒だけど。
ま、もう当分この板はこんな調子でしょ・・・。
0181nobodyさん
02/07/19 01:05ID:???0183nobodyさん
02/07/19 02:38ID:???他のプロセスとの関係とかあります?
0184nobodyさん
02/07/19 02:45ID:???>>1参照。
どんな環境でもつかえてっていうのが、このスレの主題。
flockは環境によってはつかえない。
flockつかえるなら、それでいい。
0185行番号でるかな
02/07/19 03:00ID:???01 open FH,"<./hoge";
02 my @hoge = <FH>;
03 close FH;
04 # @hogeを加工、比較的重い作業
05 open FH "+<./hoge";
06 flock (FH,2);
07 # 書き込み
2行目で配列に全部読み込んでいる、hogeの内容全部がオンメモリな状態。
今10個のプロセスが一斉に読み込みを行ったとする。
つまり10個のプロセス全てが同じ内容の@hogeを得る。
全てのプロセスが完了した時のhogeの内容はどれか一つの
プロセスの内容しか反映されて居ないだろう。
0186183
02/07/19 03:17ID:???どこかのサイトに読み込みオープンでもflockすべきだと
書いてあったのが気になっていたんですが、
そういう場合のことだったんですね。
ありがとうございました。
0187nobodyさん
02/07/19 14:05ID:???0188nobodyさん
02/07/19 15:23ID:H65klWUwこれじゃだめか?
0189nobodyさん
02/07/19 15:44ID:???まあ、可能性ははるかに低くなると思うが。
0191nobodyさん
02/07/19 19:14ID:g9uMB3Mk同じtimeでも唯一のプロセスしかロックできないから大丈夫でない?
1秒内にロックを解除しないままプロセスが死んだ時ってこと?
0192nobodyさん
02/07/20 21:32ID:???0193nobodyさん
02/07/25 16:40ID:Ong5dr5a1.ユニークなファイル名を作り書き込み。
2.指定のファイル名にrename
にしときなさいってこった。
0195nobodyさん
02/07/26 01:04ID:???書き込み中のプロセス事故死に対応して100点。
0197nobodyさん
02/07/26 03:55ID:???sub unlock{
省略
}
この構文の意味がわからんから教えてくれ
unlock関数とif文が何で一緒になってるんだ?
0198nobodyさん
02/07/26 05:36ID:???ちょっと聞いた奥さん教えてくれ!
ぷぷぷ
0200nobodyさん
02/07/26 11:19ID:???読み込み処理のときにはしなくてもいいんですか?
0202nobodyさん
02/07/26 13:35ID:NvB7dZaP=
if($lockkey) {
&unlock;
}
0204nobodyさん
02/07/28 16:44ID:???それでもタイムアウトまでは待つのでは?
あ、正常な処理中にタイムアウトを超えてしまった場合が問題なのかな?
完璧を追求するのなら。
0205nobodyさん
02/07/29 14:41ID:???0206nobodyさん
02/07/29 14:47ID:???0208nobodyさん
02/07/29 15:15ID:???のページでロックの仕方が紹介されていたので使わせてもらおうと思いました。
で、「古いロックファイル(ディレクトリ)の削除」の項目にある、
$retry = 5; # リトライ回数セット
while (!mkdir($lockdir, 0755)) { # 作成。出来なければ待つ
if (--$retry <= 0) { # 5回ダメなら
if (mkdir($lockdir2, 0755)) { # ロックを消すための排他
if ((-M $lockdir) * 86400 > 600) { # 作成時間が10分以上前なら
# ロック入れ替え
rename($lockdir2, $lockdir) or &error("LOCK ERROR");
last; # 一連の処理へ
}else{ rmdir($lockdir2); } # 部分ロック削除
}
&error("BUSY"); # あきらめる
}
sleep(1); # 1秒待つ
}
一連の処理
rmdir($lockdir); # 削除
とりあえず、これ使っておけば大丈夫なんでしょうか。
2ちゃんねるみたいな同時アクセスが凄い場所でない限り。
■ このスレッドは過去ログ倉庫に格納されています