- 1 名前:nobodyさん [02/06/23 10:18 ID:eY2l+Gw1]
- どんな環境でも使えて、軽くて、頑丈なロックを考えようじゃありません
- 756 名前:nobodyさん [04/11/12 07:07:11 ID:djvAfFkI]
- >>747
レイフォース >>>> 越えられない壁 >>>> レイヤーセクション
- 757 名前:752 mailto:sage [04/11/13 13:06:05 ID:???]
- 調べてみたところ、
・NFS Version4なら、ロック機構が組み込まれているので問題が無い(flock(2)でok?) ・NLM(Network Lock Manager)プロトコルに対応したサーバとクライアントならば、 fcntl(2)で対応可能。(ただし、一部のシステムで信頼が無いかも) ・それ以外はロックファイルを作るのが一般的 という感じらしいことが分かりました。 ありがとうございました。
- 758 名前:nobodyさん [04/11/13 15:51:42 ID:6imth/Ie]
- >756
レイストーム >>> レイフォース >>> レイクライシス
- 759 名前:nobodyさん mailto:sage [04/11/14 12:08:06 ID:???]
- レイフォース=ガンロック >> php >> perl >> レイヤーセクション >> レイストーム / レイクライシス
- 760 名前:nobodyさん mailto:sage [04/11/15 01:32:31 ID:???]
- なんか、SIMPLE1500のTHEダブルシューティングが欲しくなってきたw
- 761 名前:nobodyさん [04/11/18 09:27:07 ID:upfr9/ei]
- >>760
それなに?
- 762 名前:nobodyさん [04/11/18 10:10:24 ID:3NzX+MnA]
- 俺もレイ・フォースは好きだったな
懐かしい
- 763 名前:nobodyさん [04/11/18 19:52:46 ID:GLzLqJbZ]
- >>762 同意。
- 764 名前:nobodyさん mailto:sage [04/11/18 20:49:35 ID:???]
- おめーらロックすんぞ
- 765 名前:nobodyさん [04/11/27 15:36:14 ID:o5xdYnQz]
- ファイルロックって読み込むときは必要無いの?
- 766 名前:nobodyさん mailto:sage [04/11/27 15:54:59 ID:???]
- ロックするべ?
- 767 名前:nobodyさん mailto:sage [04/11/27 17:40:53 ID:???]
- >>765
書き込みが行われず中身が固定のファイルなら不要
- 768 名前:nobodyさん mailto:sage [04/12/04 12:35:02 ID:???]
- 質問しに来たらすでに同じ質問してる人がいた。
>>765-767 サンクス 過去ログは見るもんだ。
- 769 名前:nobodyさん mailto:sage [04/12/04 19:37:01 ID:???]
- それは過去ログって言わないけどな
- 770 名前:nobodyさん mailto:sage [04/12/20 07:41:20 ID:???]
- 追記モードのやつを読むときはいらないんじゃないの?
壊れてる可能性のあるところってバッティングしているときのだけでしょ?
- 771 名前:nobodyさん [04/12/20 14:13:21 ID:sskqg6P0]
- phpとperlでflock関数でファイルロックをしてますが
現在1つのスクリプト中に複数の箇所でファイルロックを使ってます。 これらのファイルロックを全てやめて代わりに、 スクリプトの一番最初でダミーのファイルにロックをかけて スクリプトの一番最後でロックを解除するようにして他のプロセスが スクリプトを実行しているときはスクリプトの実行自体を順番待ちさせて 同時に複数のプロセスがファイルへの書き込みをできないように 変えようと思いますが、何か問題あるでしょうか? 1つ気になるのは、もしスクリプトの途中でexit関数等でスクリプトの実行が終了した場合は 自動的にダミーファイルのロックが解除されファイルも自動的にcloseされますか?
- 772 名前:nobodyさん mailto:sage [04/12/20 15:14:56 ID:???]
- >>770
追記であろうがなかろうが書き込みはロックした上で行われるのなら 読み込みだけのときはロック不要。
- 773 名前:nobodyさん mailto:sage [04/12/20 15:30:20 ID:???]
- >>771
プロセスが死ねばロックは解除される。 先頭と末尾でロックと解除をするようにするのはいいが、 パフォーマンス低下は明らか。
- 774 名前:nobodyさん mailto:sage [04/12/20 16:09:04 ID:???]
- mod_perl や mod_php のときって
スクリプトの実行が終了してもプロセスは死なないと思うけど mod_* がスクリプト中の flock の後始末を面倒見てくれるんですよね?
- 775 名前:nobodyさん mailto:sage [04/12/20 20:09:18 ID:???]
- >>770
二つ以上のプロセスが同時に追記したら、データが混じる可能性があるし。 >>772 勧告ロックはそうはいかない。 >>774 PHPは面倒みてくれるけど、mod_perlのファイルハンドルは無理。 だから、IO::File,FileHandleモジュールなどを使う。 perl.apache.org/docs/1.0/guide/porting.html#Filehandlers_and_locks_leakages
- 776 名前:770 mailto:sage [04/12/20 21:19:18 ID:???]
- >>772
ロックしなくて読んでいいのは、追記モードのときだけではないの? 上書きモードだと一旦中身が空になるわけで、そのときロックしないで 読んでしまったらだめだよね? 読み込んで、それをそのまま出力しておしまいな 2ch の read.cgi みたいなやつならそういうアプローチもいいだろうけど、読んだデータ を処理に利用する場合はだめと思う。 >>775 >>770 のやつ 「書込時にちゃんとロックする前提で」っていうのが抜けてた。スマソ
- 777 名前:771 [04/12/20 21:25:49 ID:sskqg6P0]
- >>773
回答ありがとうございます。 やっぱパフォーマンスの問題になりますか…
- 778 名前:nobodyさん mailto:sage [04/12/20 21:25:58 ID:???]
- >>776
ロックして書き込み中は読み込もうとしてもアクセスできないだろ。
- 779 名前:nobodyさん mailto:sage [04/12/20 22:28:54 ID:???]
- >>776
追記モードでも、書き込み途中の中途半端なデータを読む可能性を考えればダメでは?
- 780 名前:nobodyさん mailto:sage [04/12/20 23:16:39 ID:???]
- >>778 なこたぁない。。
>>779 そだね けちろん: 読み込みデータがハンパでもいいタイプのシステムなら ロックは無用。読み込みデータがその後のデータに関わってくるのなら ロック白
- 781 名前:nobodyさん mailto:sage [04/12/20 23:47:40 ID:???]
- >>778
ロックの掛け方による >>779 例えば固定長なら書込み途中のデータを見分けて使わない機構とかできそうな予感がするな? >>780 そのけつろんは読みの場合限定ってことで
- 782 名前:nobodyさん mailto:sage [04/12/21 06:25:34 ID:???]
- >>778
アドバイザリロックはいくらでもロックを無視できる。
- 783 名前: [05/02/02 14:16:34 ID:hfbAK0ph]
-
- 784 名前:nobodyさん mailto:sage [05/02/26 07:20:55 ID:???]
- ロック状態を保持するデーモン作る
- 785 名前:nobodyさん [2005/03/27(日) 21:58:07 ID:frr01O3q]
- それ最強
- 786 名前:nobodyさん [2005/03/28(月) 02:50:20 ID:QWQNdIyl]
- ユーザ名とロックIDを引数にしてロック状態の設定、解除、状態取得を行えるCGIサービスを誰かやって!
もちろん無料で( ̄ε ̄@)」 lock.service.jp/lock.cgi&user=xxx?id=1?timeout=60 lock.service.jp/status.cgi&user=xxx?id=1 # <html><body>OK</body></html> # <html><body>NG</body></html> lock.service.jp/unlock.cgi&user=xxx?id=1 こんな奴
- 787 名前:nobodyさん mailto:sage [2005/03/28(月) 03:17:29 ID:???]
- >>786
実在のドメインを例示に使うなと何度(ry
- 788 名前:nobodyさん mailto:sage [2005/03/28(月) 03:50:52 ID:???]
- ( ̄ε ̄@)
- 789 名前:nobodyさん [2005/03/30(水) 16:45:20 ID:0SN1W7SJ]
- 二つ以上のファイルをflockしても問題ないんですか?
flock(FH, 2); flock(FH2, 2);
- 790 名前:nobodyさん mailto:sage [2005/03/30(水) 17:17:26 ID:???]
- >>789
ないよ。 # デッドロックには気を付けてね。
- 791 名前:nobodyさん mailto:sage [2005/03/30(水) 18:55:15 ID:???]
- To: lock@xxxx.xx.xx
Subject: Lock user=xxxx pass=xxxx timeout=60 lock-id=1 ========== Subject: Unlock ========== Subject: Status こんな感じのメールでロック状態を管理してくれるサービスきぼんw
- 792 名前:nobodyさん mailto:sage [2005/03/30(水) 19:01:47 ID:???]
- 伝書鳩 (ry
- 793 名前:nobodyさん mailto:sage [2005/03/31(木) 04:46:07 ID:???]
- >>792
それだ! To: lock@xxxx.xx.xx Subject: Lock user=xxxx pass=xxxx timeout=60 lock-id=1 ======= ↓ 登録してある住所にlock-id確認コードを郵送 ↓ 登録ページからlock-id確認コードを入力
- 794 名前:789 mailto:sage [2005/03/31(木) 09:19:53 ID:???]
- thnx>>790
- 795 名前:nobodyさん mailto:sage [2005/04/02(土) 05:31:48 ID:???]
- rename $0 $0.tmp
perl $0.tmp rename $0.tmp $0
- 796 名前:nobodyさん [2005/04/04(月) 15:59:12 ID:UmDaQFM/]
- >>795
すげw
- 797 名前:nobodyさん mailto:age [2005/04/08(金) 17:32:31 ID:???]
- ごめん、>>795のどこがすげwのか、解説してください?
- 798 名前:nobodyさん mailto:sage [2005/04/08(金) 19:48:39 ID:???]
- 自信をリネームとかできんのかな
- 799 名前:nobodyさん mailto:sage [2005/04/08(金) 21:23:04 ID:???]
- リネームに失敗しても、他のプロセスがリネームしてるヤツがあれば実行する罠
- 800 名前:nobodyさん mailto:sage [2005/04/08(金) 23:18:53 ID:???]
- 書き込みの最中に死んだりするとデータ全部消えて無くなるな。仕方ないか。
- 801 名前:nobodyさん mailto:sage [2005/04/09(土) 19:52:50 ID:???]
- >>800
ゆーあーばか
- 802 名前:nobodyさん [2005/06/06(月) 21:34:45 ID:nLjgLi0T]
- sub create_lock {
for ($i = 0; $i < 10; $i++) {#10回繰り返す return if link($0, $lock);#link関数でロックファイルが作成できれば終了 sleep(1);#作れない場合は1秒スリープしてから再挑戦 } print "BUSY";#10回以内にロックできない場合はBUSYと表示 exit;#スクリプト終了 } ↑だとうまくいくのに、↓だとうまくいかないのは何ででしょうか? ↓ですとsleepを5回繰り返した後&error("BUSY")の処理をします。 sub create_lock { local($retry) = 5; # 1分以上古いロックは削除する if (-e $lockfile) { local($mtime) = (stat($lockfile))[9]; if ($mtime < time - 60) { &unlock; } } while (!mkdir($lockfile, 0755)) { if (--$retry <= 0) { &error("BUSY");#5回以内にロックできない場合はBUSYと表示 } sleep(1); } exit; }
- 803 名前:nobodyさん mailto:なかな [2005/06/06(月) 21:38:25 ID:???]
- あかさたなはまやらわあかさたなはまやらわあかさたなはまやらわあかさたなはまやらわあかさたなはまやりわあかさたなはまやらわあかさたなはまやらわあかさたなはまやらを
- 804 名前:nobodyさん [2005/06/06(月) 23:11:37 ID:pBVz6jtY]
- >>802
よくわからんがmkdirに成功するとwhileループを抜けてすぐ exitするからじゃないか? それ以外にも古いロックを削除するあたりが突っ込みどころ ありそうだが、サブルーチンunlockがどういうものか示されて ない以上は疑惑レベルだな。
- 805 名前:nobodyさん [2005/06/07(火) 11:44:43 ID:Jzx4SwvB]
- なぜこれでロックがかかるのでしょうか?
フォルダを作って消してるだけのような気がするんですけど。 ↓ &createlock();#mkdirでロックファイルを作成する open(FILE,"+<$logfile"); 〜(処理)〜 close(FILE); &unlock;#rmdirでロックファイルを削除する
- 806 名前:nobodyさん mailto:sage [2005/06/07(火) 12:33:20 ID:???]
- createlock と unlock の中身がわからないとなんとも・・・。
- 807 名前:nobodyさん mailto:sage [2005/06/07(火) 15:11:06 ID:???]
- サーバー環境によって使えたり使えなかったりする関数の一覧みたいなのって
WEBに転がってませんかね? 環境 A B C flock × ○ ○ mkdir ○ ○ ○ こんな感じの一覧表みたいなのがあればいいな
- 808 名前:nobodyさん mailto:sage [2005/06/07(火) 18:06:21 ID:???]
- >>804
802です。お答えありがとうございました。 ごめんなさい、勘違いしてました。ちゃんとロックできました。 ところで、質問ですけども、 sub create_lock { local($retry) = 5; if (-e $lockfile) { local($mtime) = (stat($lockfile))[9]; # ←この部分の[9] if ($mtime < time - 60) { &unlock; } } while (!mkdir($lockfile, 0755)) { if (--$retry <= 0) { &error("BUSY"); } sleep(1); } exit; } ↑の文章の local($mtime) = (stat($lockfile))[9]; 特に[9]の意味が分からないのですが、この文章は何を意味するのでしょうか?
- 809 名前:nobodyさん mailto:sage [2005/06/07(火) 19:19:30 ID:???]
- >>808
statはファイルの様々な情報を長いリストにして返す関数で、その9番目の 要素であるところのファイル更新時間だけ欲しいから[9]で取り出してると いうことだな。詳しくはperldoc -f statでもしてくれ。
- 810 名前:nobodyさん mailto:sage [2005/06/07(火) 20:02:25 ID:???]
- >>809
ありがとうございました。理解できました。
- 811 名前:nobodyさん mailto:sage [2005/06/07(火) 20:15:05 ID:???]
- >>809
前から疑問に思っていたんだが、 > 9番目 0から始まっているから、この場合10番目なのはみんな知っていると思うけど、9番目といってもいいのかな? どういう言い方が正しいのか教えて。
- 812 名前:nobodyさん mailto:sage [2005/06/07(火) 20:59:09 ID:???]
- 9番目の要素(ninth element)、0番目の要素(zeroth element)でいいと思うけど、
9番の要素、0番の要素の方がすっきりする?
- 813 名前:nobodyさん mailto:sage [2005/06/07(火) 22:14:04 ID:???]
- 質問です。かの有名なperlメモで以下のように書きました。
my_flockのサブルーチンの中で、戻り値を「\%lfh」のようにリファレンスで返す理由がわかりません。どなたか教えてください $lfh = my_flock() or die 'Busy!'; open(FILE,"+<$logfile"); chop($count = <FILE>); $count++; seek(FILE,0,0); print FILE "$count\n"; close(FILE); my_funlock($lfh); sub my_flock { my %lfh = (dir => './lockdir/', basename => 'lockfile', timeout => 60, trytime => 5, @_); $lfh{path} = $lfh{dir} . $lfh{basename}; for (my $i = 0; $i < $lfh{trytime}; $i++, sleep 1) { return \%lfh if (rename($lfh{path}, $lfh{current} = $lfh{path} . time)); } # ■↑戻り値がなぜ\%lfh? opendir(LOCKDIR, $lfh{dir}); my @filelist = readdir(LOCKDIR); closedir(LOCKDIR); foreach (@filelist) { if (/^$lfh{basename}(\d+)/) { return \%lfh if (time - $1 > $lfh{timeout} and rename($lfh{dir} . $_, $lfh{current} = $lfh{path} . time)); last; # ■↑戻り値がなぜ\%lfh? } } undef; } sub my_funlock { rename($_[0]->{current}, $_[0]->{path}); }
- 814 名前:nobodyさん mailto:sage [2005/06/07(火) 22:35:39 ID:???]
- my_funlockで$lfh{current}と$lfh{path}の2つの値を使いたい
ので、この作者は(他にもいろいろ方法は考えられるがたまたま) その2つの値が入ったハッシュのリファレンスを返すという方法 を選択した、というところだろうか。
- 815 名前:nobodyさん [2005/06/08(水) 00:31:21 ID:HPDd28CP]
- >>813
戻り値無しで if (rename($lfh{path}, $lfh{current} = $lfh{path} . time)); return; とやっても同じ
- 816 名前:nobodyさん mailto:sage [2005/06/08(水) 12:02:28 ID:???]
- ここのカウンター広告ないし最高だよ。
www.eucaly.net/ www.eucaly.net/ www.eucaly.net/ www.eucaly.net/ www.eucaly.net/ www.eucaly.net/ www.eucaly.net/ www.eucaly.net/ www.eucaly.net/ www.eucaly.net/
- 817 名前:nobodyさん [2005/06/08(水) 12:12:58 ID:???]
- >>815
違うような・・・
- 818 名前:nobodyさん [2005/06/08(水) 13:04:42 ID:???]
- >>814
お答えありがとうございました。 何かの弾みで「./lockdir/lockfile」の名前が変わってしまうことってありますか? その場合ってエラーを返すしかないのでしょうか?
- 819 名前:nobodyさん [2005/07/02(土) 23:42:28 ID:MoVRWRYG]
- PHPで掲示板のログファイルを読み込んで配列に入れるのに
file()を使ってたんですが、これはロックされてないですよね? fopenしてflockに変更した方がいいですか?
- 820 名前:nobodyさん mailto:sage [2005/07/03(日) 19:24:42 ID:???]
- >>819
スレタイを声を出して100回読んでみなさい。
- 821 名前:nobodyさん mailto:sage [2005/07/06(水) 15:38:22 ID:???]
- ファイルロック(排他処理)について語ろう
- 822 名前:nobodyさん mailto:sage [2005/07/06(水) 20:01:43 ID:???]
- ファイルロック(排他処理)について語ろう
- 823 名前:nobodyさん mailto:sage [2005/07/07(木) 11:51:39 ID:???]
- file関数は読み込みしかしないからロックも何もない
- 824 名前:nobodyさん [2005/07/11(月) 12:06:06 ID:LOhIsGf7]
- open LOCK, ">hogehoge";
flock LOCK, 2; 処理; ↑のようにLOCKをしっぱなしで、closeをしないとどうなりますか? 一連の処理が終了したら、LOCKは自動解除されるんでしょうか?
- 825 名前:nobodyさん mailto:sage [2005/07/11(月) 15:42:12 ID:???]
- PGが終了すればファイルハンドルは閉じられる。
- 826 名前:nobodyさん mailto:sage [2005/07/11(月) 16:23:12 ID:???]
- ファイルロック難しいお
- 827 名前:nobodyさん [2005/09/29(木) 15:27:47 ID:6eWvRT5D]
- エクセルでテンポラリがリネームに失敗するのは排他処理に失敗したこと
による可能性はありますか?
- 828 名前:nobodyさん mailto:sage [2005/09/30(金) 17:50:44 ID:???]
- ロック用ファイル1に時刻書き込み
↓ ロックファイル1に時刻がなかったらロック用ファイル2を開いてロック(あったら待機) ↓ 一時ファイルに書き込み ↓ 読み込み用ファイルに内容をコピー ↓ ロック用ファイル2を閉じる ↓ ロック用ファイル1を空にする 最強、破損なし。 時刻は異常があった時に現在時刻と比較して無限待機させない用。
- 829 名前:nobodyさん mailto:sage [2005/09/30(金) 18:31:16 ID:???]
- >>828
「1に時刻書き込み」してから「1に時刻がなかったら」をチェックするのは変じゃない?
- 830 名前:nobodyさん mailto:sage [2005/09/30(金) 21:17:53 ID:???]
- それよりロック用ファイル1のロックはどうするんだ
- 831 名前:nobodyさん mailto:sage [2005/09/30(金) 21:28:52 ID:???]
- 「破損なし」なのは「ロック用ファイル2」をロックしてるからだけで、
本質的には目新しいアイディアがひとつも無いどころか 単に無駄なことしてるだけに思えるのは気のせいですかそうですか。
- 832 名前:nobodyさん [2005/10/09(日) 23:29:44 ID:nlo5+ZWx BE:169416465-##]
- >>828
はなしにならんな。 あきれたよ。もう実家に帰る!
- 833 名前:nobodyさん [2005/12/08(木) 21:09:42 ID:pHM0ErCM]
- perlを始めて3ヶ月位ですが、ファイルロックに
ついて自分なりに色々と試行錯誤した結果、以下の ようなルーチンを作りました。 flockが使える事が前提ですが、何か欠点や改良点が あれば指摘して頂けるとありがたいです。 filelock.pl package filelock; our %_lock; sub END { foreach my $file ( keys %_lock ) { close( $_lock{$file}{'handle'} ); unlink( $_lock{$file}{'name'} ); if( $_lock{$file}{'tmp'} ) { rename( $_lock{$file}{'tmp'}, $file ); } } } sub readOpen { my ( $file ) = @_; my ( $handle ); _append( $file ); if( !open( $handle, "<$file" )) { return undef; } return $handle; }
- 834 名前:nobodyさん [2005/12/08(木) 21:10:10 ID:pHM0ErCM]
- sub writeOpen {
my ( $file ) = @_; my ( $handle ); _append( $file ); if( !$_lock{$file}{'tmp'} ) { $_lock{$file}{'tmp'} = $file; $_lock{$file}{'tmp'} =~ s/(.*)\.(.*)/$1\.tmp/; } if( !open( $handle, ">$_lock{$file}{'tmp'}" )) { return undef; } return $handle; } sub _append { my ( $file ) = @_; if( $_lock{$file} ) { return; } $_lock{$file}{'name'} = $file; $_lock{$file}{'name'} =~ s/(.*)\.(.*)/$1\.lck/; open( $_lock{$file}{'handle'}, ">$_lock{$file}{'name'}" ); my $count = 0; while( !flock( $_lock{$file}{'handle'}, 2 )) { sleep( 1 ); if( $count++ > 10 ) { print '[error]Sarver Busy.'; exit; } } } 1;
- 835 名前:nobodyさん [2005/12/08(木) 21:14:40 ID:pHM0ErCM]
- ちなみに、使い方は下記のように使います。
require './filelock.pl'; $file = filelock::readOpen( "count.dat" ); $data = <$file>; close( $file ); $data = $data + 1; $file = filelock::writeOpen( "count.dat" ); print $file $data; close( $file );
- 836 名前:nobodyさん mailto:sage [2005/12/08(木) 23:57:56 ID:???]
- 普通にflock使えばいいのにと野暮な突っ込み。
斜め読みしただけだから適当に。 ノンブロッキングロックじゃないと、whileループ内は無駄。 test.txtとtest.datが同じファイルと見なされる。 ロックを解除してるところがない? サンプルスクリプトはロックが壊れる典型。
- 837 名前:nobodyさん mailto:sage [2005/12/09(金) 00:42:03 ID:???]
- >>836
解答ありがとうございます。 >ノンブロッキングロックじゃないと、whileループ内は無駄。 そうですね。2(LOCK_EX)ではなくて2|4(LOCK_EX|LOCK_NB) とすればokですね。 >test.txtとtest.datが同じファイルと見なされる。 まぁ、これは仕様という事で…(^^; >ロックを解除してるところがない? ENDの中のcloseで解除しているつもりなのですが closeではロックは自動的解除されないのでしょうか? >サンプルスクリプトはロックが壊れる典型。 どういう場合にロックが壊れるのでしょうか? ご掲示頂けるとありがたいです。
- 838 名前:nobodyさん mailto:sage [2005/12/09(金) 03:18:54 ID:???]
- >>837
ENDブロックは、スクリプトの処理の最後で処理されるので、 自動でアンロックさせたいのなら、返すファイルハンドルをオブジェクトにして、 DESTROYブロックを使ってアンロックさせる。 ついでにcloseも再定義。 ロックについては web.archive.org/web/20040216083853/www98.sakura.ne.jp/~jun/perl/flock.html
- 839 名前:833 mailto:sage [2005/12/09(金) 03:47:51 ID:???]
- >>838
意図的にENDブロックに書いています。オブジェクトを作ってDEST ROYブロックでアンロックする方法も考えたのですが… hoge01.pl read "data01.dat" read "data02.dat" -> hoge02.pl write"data01.dat" write"data02.dat" -> hoge03.pl write"data03.dat" end ↑こんな感じで読み書きしたい場合、ファイルアクセスする可能 性のある所全てでオブジェクトを保持していないといけないので、 意図的にグローバルに情報を置いて、スクリプトの終わりでEND ブロック内で一括に処理したのです。 ところで、"closeも再定義"って何ですか?
- 840 名前:nobodyさん mailto:sage [2005/12/09(金) 12:08:16 ID:???]
- closeの再定義と言ったのは、closeのオーバーライドすること。
closeでロックの開放をするのなら、自前のcloseを書いて、 そこで必要な操作を行ってから、CORE::closeを呼び出すという感じで。 と、考えていたのだけど、 どうも考え方が違ってたっぽいか。
- 841 名前:833 mailto:sage [2005/12/09(金) 15:36:13 ID:???]
- ちょっと、皆さんが勘違いしているっぽいので詳細を書きます。
readOpen 戻り値 : ファイルハンドル 機能 : 指定されたファイルの拡張子をlckに変えたファイルを flockして指定されたファイルをオープン。flockが10秒以上で きない場合は異常終了。 writeOpen 戻り値 : ファイルハンドル 機能 : 指定されたファイルの拡張子をlckに変えたファイルを flockして指定されたファイルの拡張子をtmpに変えたファイル をオープン。flockが10秒以上できない場合は異常終了。 END 機能 : readOpen,writeOpenでロックされたファイル(*.lck)を close。writeOpenで返したのファイル(ハンドル)を元の名前に リネーム。(*.tmp→*.元の拡張子) 引き続き、何か欠点や改良点があれば指摘して頂けるとありがたいです。
- 842 名前:nobodyさん mailto:sage [2005/12/09(金) 16:10:37 ID:???]
- >>841
致命的にやばい点: ENDの中でlockファイルをcloseした時点でflockは外れるので、 その後のunlockとtmpファイルのrenameがロックなしで行われる。 改善した方がいい点: readしかしない場合でも排他的にロックしてしまうのは嬉しくない。 ENDが実行されるまでロック状態が持続するので、ロックの保持 期間が長くなりそうだしdaemon的プログラムだとどうすんの? tmpの書き込み中に問題がでて取りやめたいときの手段がない (やろうと思えば%filelock::_lockいじる手はあるが...) リトライ回数が尽きたときにいきなりexitするのは汎用性がない。 せめてdieにしとけばevalでトラップする余地があるのだが。
- 843 名前:833 mailto:sage [2005/12/09(金) 17:26:00 ID:???]
- >unlockとtmpファイルのrenameがロックなしで行われる。
そうですね。renameは一番最初にやるとして、その後にunlink→ closeでしょうか?closeの前にunlinkってできるのでしょうか? >readしかしない場合でも排他的にロックしてしまうのは嬉しくない。 ここでは省略しましたが、 unlockFile( $filename ) 機能 : 強制的に指定されたファイルのロックを解除する。 というルーチンがあります。自分は、デフォルトは「最後まで排 他的にロック」。オプションで「指定したファイルのロックを解除」 っていう感じで考えてます。この方が間違いが無いと思うので。 >tmpの書き込み中に問題がでて取りやめたいときの手段 そうですね。これは、abortLockみたいなルーチンを作って最後の ENDブロックの中でrenameしないようにすれば良いんじゃないで しょうか? >リトライ回数が尽きたときにいきなりexitするのは汎用性がない。 if( $count++ > 10 ) { die "flock busy" } こんな感じで良いですかね? まだまだ経験が浅いので、先輩諸氏からの助言は為になります。 他にも欠点や改良点があれば指摘して頂けるとありがたいです。
- 844 名前:nobodyさん mailto:sage [2005/12/09(金) 21:41:26 ID:???]
- >>843
「ファイルを変更する(可能性がある)場合に排他ロック、読むだけで済む場合は共有ロック」 というのはひとつのセオリーだけれども、なぜそれがセオリーなのか、そもそもファイルロックとは何なのかを調べるなどして考えてみましょう。 >readしかしない場合でも排他的にロックしてしまうのは嬉しくない。 という >>842 の指摘にはまったく同意で、デメリットはいくらも思いつくけれど残念ながらメリットはひとつも思い浮かびません。 見境なしに排他ロックというのではファイルロックの魅力が半減以下です。 またファイルを利用している、いないに関わらずロックを離さないというのはお行儀が今ひとつ。各プロセスの実行時間が充分に短く、また起動頻度が比較的低ければ問題は出づらいでしょうけれど、少なくとも誰かに勧めることができるやり方じゃないですね。
- 845 名前:833 mailto:sage [2005/12/09(金) 22:03:55 ID:???]
- 色々な意見を参考に作り直してみました。
前作にあったバグ(read→write→readした時に*.tmpファイルから 読まない)も修正しています。 open パラメータ:通常のopenと一緒だけど使えるのは'>'と'<'のみ。 戻り値:ファイルハンドル 機能:指定されたファイルの拡張子をlckに変えたファイルを flockして指定されたファイルをオープン。flockが10秒以上で きない場合は異常終了。 close パラメータ:openで得られたファイルハンドルとオプション。 機能 : 指定されたファイルハンドルを閉じます。オプションで 1を指定するとロックを解除して書き込みがある場合はリネーム して反映。2を指定するとロックを解除して書き込みがある場合 は*.tmpファイルを削除(つまり書き込みをキャンセル) END 機能 : *.lckをclose&unlink。*.tmpがある場合は、元のファイ ル名にリネーム。 package filelock; our %_FileList; our %_HandleList; sub END { foreach my $filename ( keys %_FileList ) { if( $_FileList{$filename}{'temp'} ) { rename( $_FileList{$filename}{'temp'}, $filename ) } unlink( $_FileList{$filename}{'lock'} ); close( $_FileList{$filename}{'handle'} ); } }
- 846 名前:833 mailto:sage [2005/12/09(金) 22:05:50 ID:???]
- sub open {
my ( $filename ) = @_; my ( $handle, $tempfile, $mode ); if( $filename =~ /^>.*/ ) { $filename =~ s/^>(.*)/$1/; $mode = 2 } elsif( $filename =~ /^<.*/ ) { $filename =~ s/^<(.*)/$1/; $mode = 1 } else { return undef; } if( $mode == 1 && !( -e $filename )) { return undef } if( !$_FileList{$filename} ) { my $lockname = $filename; $lockname =~ s/(.*)\.(.*)/$1\.lck/; open( $handle, ">$lockname" ); my $count = 0; while( !flock( $handle, ( 2 | 4 ))) { sleep( 1 ); if( $count++ > 10 ) { die "flock busy" } } $_FileList{$filename}{'lock'} = $lockname; $_FileList{$filename}{'handle'} = $handle; } $tempfile = $filename; if( $mode == 1 ) { if( $_FileList{$filename}{'temp'} ) { $tempfile = $_FileList{$filename}{'temp'} } if( !open( $handle, "<$tempfile" )) { die "file open error(read)" } } elsif( $mode == 2 ) { if( $_FileList{$filename}{'temp'} ) { $tempfile = $_FileList{$filename}{'temp'} } else { $tempfile =~ s/(.*)\.(.*)/$1\.tmp/; $_FileList{$filename}{'temp'} = $tempfile; } if( !open( $handle, ">$tempfile" )) { die "file open error(write)" }
- 847 名前:833 mailto:sage [2005/12/09(金) 22:07:31 ID:???]
- }
$_HandleList{$handle} = $filename; return $handle; } sub close { my ( $handle, $option ) = @_; if( $option && ( $option == 1 || $option == 2 )) { close( $handle ); my $filename = $_HandleList{$handle}; if( $_FileList{$filename}{'temp'} && $option == 1 ) { rename( $_FileList{$filename}{'temp'}, $filename ) } elsif( $_FileList{$filename}{'temp'} && $option == 2 ) { unlink( $_FileList{$filename}{'temp'} ) } unlink( $_FileList{$filename}{'lock'} ); close( $_FileList{$filename}{'handle'} ); delete( $_FileList{$filename} ); delete( $_HandleList{$handle} ); } else { close( $handle ); delete( $_HandleList{$handle} ); } } 1; 例: require './filelock.pl'; $file = filelock::open( "<count.dat" ); $data = <$file>; filelock::close( $file ); $data = $data + 1; $file = filelock::open( ">count.dat" ); print $file $data; filelock::close( $file, 1 );
- 848 名前:nobodyさん mailto:sage [2005/12/11(日) 11:36:06 ID:???]
- わぁ。。 もっとシンプルなやり方あるのにぃ〜
- 849 名前:nobodyさん mailto:sage [2005/12/11(日) 15:20:09 ID:???]
- my ( $filename ) = @_; まで読んだ。
- 850 名前:nobodyさん mailto:sage [2005/12/11(日) 23:38:47 ID:???]
- どうせ>>848は、「じゃあ、そのやり方を書いてみろ」
と言ったところで、その案に穴があるか、書けないか どっちかだろ?…という訳で、とりあえず >>848 じ ゃ あ 、 そ の や り 方 を 書 い て み ろ
- 851 名前:nobodyさん mailto:sage [2005/12/12(月) 10:42:51 ID:???]
- unlinkしてからcloseもだめです。
(Aが正常にロックを取得した状態から) B: open A: unlink C: open A: close B: flock(成功する) C: flock(成功する) flockを使うときはロックファイルは一度作ったら消さないのが わかりやすい。 どうしても削除したければ、その操作をするためのロックを 別にするとかややこしいことをする羽目になる。
- 852 名前:nobodyさん mailto:sage [2005/12/12(月) 21:10:57 ID:???]
- >>851
ん?Aがロックした状態なんだよね? B: open -> Aがロック中なので開けない A: unlink -> 自分がロック中なので削除できる C: open -> Aがロック中なので開けない A: close -> 自分のロックを外す B: flock(成功する) -> Bがロック C: flock(成功する) -> Bがロック中なので開けない…のでわ?
- 853 名前:nobodyさん mailto:sage [2005/12/12(月) 21:21:39 ID:???]
- >>852
flockによるロック中でもopenはできるのでBはopenできるし、 Aが削除した後はそのファイルは存在しないんだから、 Cは新たに同じ名前の別のファイルを作ってopenできる。 そしてことのきBとCがそれぞれロックファイルだと思って 開いたファイルは実は別のものになるというのが問題 なのです。
- 854 名前:nobodyさん mailto:sage [2005/12/12(月) 22:29:46 ID:???]
- >>853
削除したらロックが外れるのは初耳だ。 つちの環境だと open -> unlink -> sleep(10) -> close で、sleep(10)の間はflockできないんだが…。 >flockによるロック中でもopenはできるので >>833(845)のソースではopenする前にflockの 確認してると思うけど、そりゃ、perlが内部で flock処理に入ったタイミングで他プロセスが openしたらできるかもしれないが、そしたら flock自体意味無しって事になるぞ?
- 855 名前:nobodyさん mailto:sage [2005/12/12(月) 22:33:12 ID:???]
- 正:うちの環境
誤:つちの環境 とりあえず>>853は>>833(845)のソースを実際に実行して 穴があってから発言したら? "俺予想"だけで発言しても意味無いよ。
- 856 名前:nobodyさん mailto:sage [2005/12/12(月) 22:39:11 ID:???]
- >>854
削除したらロックがはずれるのではなくて、同じ名前のロック ファイルを別に作れてしまう。sleep(10)の間にロックファイルを openしようとしたら存在しないので新しいファイルが作られてしまう から、当然flockもできるでしょ。 > openする前にflockの 確認してると思うけど flockはopenした後のファイルハンドルに対する操作 だから、openしてないのにできるわけないよ。ロックファイルの openと操作したいファイルのopenを混同してない?
|

|