- ベストアンサー
mkdirでのファイルロック
以前にも質問したのですが間違って締めきってしまったので再度質問します。CGI初心者なのですがmkdirを使ってファイルロックをかけたいのですがどうすればいいのかわかりません。たぶん、下記の部分というのはなんとなくわかりました。 分かる方よろしくお願いします。 #### メッセージ番号設定 #### sub getnumber { open(COUNTER,"$countfile") || &error('カウントファイルが開けない'); $this_num = <COUNTER>; close(COUNTER); $this_num++; open(COUNTER,">$countfile") || &error('カウントファイルに書きこめない'); print COUNTER "$this_num"; close(COUNTER); if( length($this_num) == 1 ){ $this_num ="000000" . $this_num;} elsif( length($this_num) == 2 ){ $this_num ="00000" . $this_num; } elsif( length($this_num) == 3 ){ $this_num ="0000" . $this_num; } elsif( length($this_num) == 4 ){ $this_num ="000" . $this_num; } elsif( length($this_num) == 5 ){ $this_num ="00" . $this_num; } elsif( length($this_num) == 6 ){ $this_num ="0" . $this_num; } } #### データファイルへ入力 #### sub inputDB { $datafile = "$predatadir/userdata01.csv"; open(DB,">>$datafile") || &error('データファイルに書きこめない'); print DB "$yourname,$email\n"; close(DB); }
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
#1です。 おそらく修正なさったプログラムで大丈夫だと思います。が、素人判断ですので、他の方からの回答をしばらくお待ちになるか、あるいは思い切って実践に移して様子をみるか、最終的にはご自分で判断なさって下さい。実践に移す場合は、念のため少なくともデータファイルだけは(できれば全てのファイルの)バックアップをとっておくとよいと思います。 以下、気づいた点を書きます。あくまでも素人の意見なので、参考程度に受け取って下さい。 ・ロックはファイル出力時は必要ですが、入力時は不要かもしれません。つまり、プログラムのはじめの方、カウンタのファイルをリードするところでは、ロックはなくても良さそうです。 ・「userdata01.csv」はおそらくカウンタのファイルに比べてとても大きいと思われますが、あまり大きすぎてその処理に時間がかかると、その処理のきっかけとなるアクセスをした人が、途中でブラウザの「中止」を押した場合、ロック状態のままになったり、ファイルが壊れたりする不具合があるかもしれません。(心配しすぎかも!?) それから、余計なお節介ですが、$this_numが6桁以下の場合、頭に0をつけて7桁にするif-elsif-...のところは、次のようにすれば1行で済みます。 $this_num = sprintf("%07d", $this_num); 長くなってしまいすみません。では。
その他の回答 (2)
- zebedeer
- ベストアンサー率66% (80/121)
修正版でもカウンタが重複することがあります。 (データが飛ばなければ良いなら問題ないですけど) 基本的にファイルロックをかける場合、データを読み込むときから書き込むときまでロックをかけ続けます。 なので、今回の場合、カウンターファイルを読み込んでからデータファイルへ書き出すまでロックをかけ続けます。 #追記なのでCSVファイルの処理時間はそれほどかかりません。 あと、気になる点として、下の3点くらいかな? 1、下の方も仰っていますが、デットロック時の処理が無い 2、普通ロックに失敗した場合はsleepしてretryしますが、いきなりexitしていいの? 3、unlockに失敗したときの処理は? (unlockに失敗しても不用意にrmdirしないこと!)
参考URLをご覧ください。mkdirによる方法も載っています。すでにご存知でしたらすみません。
補足
ありがとうございます。 教えていただいたURLを参考にして作ってみたのですが、カウントファイルの操作時、データファイルへの出力時に、 ファイルロックの処理というとこんなかんじでいいのでしょうか? #### メッセージ番号設定 ##### sub getnumber { #ディレクトリの作成ができなかったらあきらめる if(!mkdir($lockdir,0755)){ exit(1); } #ディレクトリの作成ができたらカウントファイルを開く処理 open(COUNTER,"$countfile") || &error('カウントファイルが開けない'); $this_num = <COUNTER>; close(COUNTER); #lockdirを消す rmdir($lockdir); $this_num++; #ディレクトリの作成ができなかったらあきらめる if(!mkdir($lockdir,0755)){ exit(1); } #ディレクトリの作成ができたらカウントファイルに書き込む処理 open(COUNTER,">$countfile") || &error('カウントファイルに書きこめない'); print COUNTER "$this_num"; close(COUNTER); #lockdirを消す rmdir($lockdir); if( length($this_num) == 1 ){ $this_num ="000000" . $this_num;} elsif( length($this_num) == 2 ){ $this_num ="00000" . $this_num; } elsif( length($this_num) == 3 ){ $this_num ="0000" . $this_num; } elsif( length($this_num) == 4 ){ $this_num ="000" . $this_num; } elsif( length($this_num) == 5 ){ $this_num ="00" . $this_num; } elsif( length($this_num) == 6 ){ $this_num ="0" . $this_num; } } #### データファイルへ入力 #### sub inputDB { $datafile = "$predatadir/userdata01.csv"; #ディレクトリの作成ができなかったらあきらめる if(!mkdir($lockdir,0755)){ exit(1); } open(DB,">>$datafile") || &error('データファイルに書きこめない'); print DB "$yourname,$email\n"; close(DB); #lockdirを消す rmdir($lockdir); }