排他処理について教えてください

このQ&Aのポイント
  • 排他処理について教えてください。
  • 現在、ガンダムカルトQQQ(MIDI-CG-SOFT-総合サイト)【http://ha1.seikyou.ne.jp/home/jun/】様よりフリーで配布されている「QQQ MEMBERS ver1.00」を使用してメンバー管理を行なっています。しかし、このスクリプトには排他処理が入っていなかった為、ディスカバリーシステム【http://www.dscvsys.com/Perl.htm#filelock】様のページを参考にrenameを使った排他処理を作成しましたが、どこに排他処理をかけていいかわからず、かなり悩んでいます。
  • 尚、ファイル構成は以下の通りです。 cgi-bin  |  ├member.cgi  ├jcode.pl  └lockdir    └lockfile(拡張子無しテキストファイル)
回答を見る
  • ベストアンサー

排他処理について教えてください。

現在、ガンダムカルトQQQ(MIDI-CG-SOFT-総合サイト)【http://ha1.seikyou.ne.jp/home/jun/】様よりフリーで配布されている「QQQ MEMBERS ver1.00」を使用してメンバー管理を行なっています。 しかし、このスクリプトには排他処理が入っていなかった為、ディスカバリーシステム【http://www.dscvsys.com/Perl.htm#filelock】様のページを参考にrenameを使った排他処理を作成しましたが、どこに排他処理をかけていいかわからず、かなり悩んでいます。 *排他処理はディスカバリーシステム様の記述をそのまんま使用しています。 尚、ファイル構成は以下の通りです。 cgi-bin  |  ├member.cgi  ├jcode.pl  └lockdir    └lockfile(拡張子無しテキストファイル) 大変申し訳ありませんがご教授宜しくお願い致します。

  • CGI
  • 回答数1
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
  • lahalito
  • ベストアンサー率48% (31/64)
回答No.1

利用されているソースも何も見ていないので詳細は分かりませんが、とりあえず、改良したいソースファイルの中から、以下の2つを調べてみてください。 (1) 排他制御したい対象ファイルは何か? (2) そのファイルに対して書き込み処理を行っている箇所はどこか? 調べたら、書き込みを開始する前に「ロック」して、書き込みが完了したら「ロック解除」してあげれば良いと思います。 なお大抵の場合、読み込みに対しては排他制御は不要です。

perl_beginner
質問者

補足

lahalitoさん、早速のご回答有難うございます。 lahalitoさんが教えてくれた(1)と(2)について 調べたところ、以下の様な状態でした。 どちらもサブルーチンで呼び出されており、 プログラムの処理工程は大体わかるのですが、 どこに排他制御を掛けていいかわからず試行錯誤しております。ソースが長くなり大変申し訳ありません。ご面倒かと思いますが、またご教授いただけないでしょうか? 宜しくお願いします。 (1)排他制御したい対象ファイル #************************************************ # 初期変数設定 #************************************************ sub setup{ $cgi_file ='member.cgi'; #このファイル名 #$id = $ENV{'REMOTE_HOST'}; $id = $ENV{'REMOTE_ADDR'}; $log_head = 'member'; #ログの頭文字 $log_foot = 'cgi'; #ログの拡張子 $log_dir = 'member'; $CH_S_NUM{$log_max}=' selected'; @c_list=("A","B","C","D","E","F"); @p_list=("G","H","I","J","K","L","N","M","O","P" ); } (2) そのファイルに対して書き込み処理を行っている箇所はどこか? #************************************************ # ログ書き込み # #ロック開始関数 #$lfi = &fileLock"lockfile") || die 'ビジー!'; # #ロック解除関数 #&fileUnlock($lfi); #************************************************ sub log_write{ $FORM{'phone'} =~ s/\r/<br>/g; if($FORM{'re_art'} ne ""){ local(@files)=&dir_list($log_head,$log_foot,$log_dir); foreach $file(@files){ open(DB,"$log_dir/$log_head$file\.$log_foot"); local(@lines) = <DB>; close(DB); @write_log=(); foreach(@lines){ $_=~ s/\n//g; if($_ eq ''){last;} local($date,$update,$art,$name,$email,$owner,$phone,$pass,$work,$cat,$id,$place,$etc) = split(/<>/,$_); if($FORM{'re_art'} eq $art){ if($FORM{'del'} eq ""){ $phone =join("<>",$FORM{date},$ttime,$FORM{'re_art'},$FORM{'name'},$FORM{'email'},$FORM{'owner'},$FORM{'phone'},$FORM{'pass'},$FORM{'work'},$FORM{'cat'},$id,$FORM{'place'},$FORM{'etc'},"\n"); push(@write_log,$phone); } $flag=1; }else{push(@write_log,"$_\n");} } if($flag eq 1){ open(DB,">$log_dir/$log_head$file.$log_foot"); print DB @write_log; close(DB); last; } } if($flag ne 1){ &header('エラー'); print '<h2>おしらせ</h2><i><b>記事が見つけられませんでした。</b></i><p>'; &html; &footer; exit; } }else{ # 記録ファイルを読み出しオープンして、配列<@lines>に格納する local($file,$num)=&active_log; open(DB,"$log_dir/$log_head$file\.$log_foot"); local(@lines) = <DB>; close(DB); $phone =join("<>",$date_now,$ttime,$num,$FORM{'name'},$FORM{'email'},$FORM{'owner'},$FORM{'phone'},$FORM{'pass'},$FORM{'work'},$FORM{'cat'},$id,$FORM{'place'},$FORM{'etc'},"\n"); push(@lines,$phone); # 記録ファイルを上書きオープンして、配列<@new>を書き出す open(DB,">$log_dir/$log_head$file.$log_foot"); print DB @lines; close(DB); chmod 0666,"$log_dir/$log_head$file.$log_foot"; } }

関連するQ&A

  • 排他処理について

    あるシステムの、(CGIアプリケーションの)ログファイルの機能ですが、 ログのサイズが指定のサイズに達したとき、 バックアップファイルとしてリネームし、また新たにファイルを作成する...という処理があります。 (1)ファイルのサイズは CFile::GetStatus( FileName,fs ) で、 で、fs.m_size を取得しています。 (2)fs.m_size >= (指定のサイズ)になったときに 拡張子を .bakに切り替え(rename)ています。 ・・・ということで、同じ処理で2つのログファイルができ、.bakは指定のファイルサイズ程度で 残っているはずだったのですが。。。 複数プロセスが同時に動くことがあり、排他がかかっていないため、 複数プロセスで、ファイルサイズが指定のサイズをオーバーしたと判断し、 続けて(!?)リネーム処理が行われ、 .bakファイルも小さなファイルになってしまう事が発生しました。 これを防ぐには、排他が不可欠とはわかるのですが システムに一番影響なく、訂正するにはどのような方法があるか アドバイスしていただけないでしょうか。 かなりアクセスの多いシステムなのであまり、重たくなるような修正はできないのです。 ファイルサイズがオーバーしたときに overflg用のファイルを作成しておき、 ・そのファイルがあったら他のプロセスは何もしないで普通に書き込む  (書き込む時には排他がかかっています) ・そのファイルが無かったら、普通にファイルに書き込む  (ファイルサイズは多少オーバーしても問題はありません) ・renameが終わったら、そのoverflg用ファイルを削除する のようなことを考えたのですが、実用的でしょうか? よろしくお願いします。

  • 排他処理

    こんにちは。 定期的にperlスクリプトを動かしてファイルを作成し、http(Apache)でそのファイルを参照するシステムを作成中です。 このとき、作成中の中途半端なファイルを読まないようにしたいのですが、 どのようにするのがよいでしょうか? CGIスクリプトで掲示板等のファイルにアクセスする際の排他制御についてなら、いろいろと情報もあるのですが、今回のようなケースについてはどうも情報が見つかりませんでした。 単純にテンポラリファイルを作って最後にrenameするだけでもよさそうなのですが、どの程度確実なものでしょうか。 あるいはapacheの設定でなにかうまい方法があるのでしょうか? どなたかご存知でしたら、ご教示願います。 OSはSolarisです。よろしくお願いします。

    • 締切済み
    • CGI
  • 排他処理について

    http://www.tryhp.net/lock.htm このサイトの排他処理を参考に組んでいるのですが、 「7.完成」のソース、「#ロックされていなければロックする」以降に出てくる$tmpfileについての質問です。 この変数$tmpfileにはテンポラリ用にこちらで用意したファイル名が入っているということでしょうか? リネームするのであれば rename($tmp_dummy,$datafile); かなと考えていたのですが…。 ソース上部でも$tmpfileのテンポラリを作成していないので不思議です。 意図が読めずに困っております。お知恵を拝借したいと思います。

    • ベストアンサー
    • Perl
  • セッションデータの排他処理

    セッションデータを更新するようなケースで、簡単に排他処理をする方法はないでしょうか。 現在はCGI::Sessionを使っていますが、このfileドライバは、読み込み時にflock⇒開放⇒書き込み時にflock、というように一度開放してしまいます。他の付属ドライバは調べていませんが同じかもしれません。 CGI::Sessionオブジェクトが存在する間はずっとロックしておいて欲しいのです。(と言うより普通に考えればそうであるべきな気がしますが) やはりそのための、たとえばIDごとにわざわざロックファイルを作るとかの処理が必要なのでしょうか。あるいは、ドライバを自分で書くとか。 常套手段的な、それともすでにそういうドライバをご存知でしたら教えてください。 また、セッションデータを更新するなんて珍しくもないと思うんですが、CGI::Sessionが対応してない理由とか、皆さんはどうしているのかも、気になります。

  • batファイルにおけるファイルの排他チェック

    いつも助けてもらっています。 バッチファイルにて、 あるファイルの排他チェックは出来ますか? このバッチファイルは、システムを立ち上げてて 自動で処理を開始するのですが、 その処理で使用するファイルを 他のソフトで開かれている場合には、 処理を実行しないように制御を掛けたいためです。 インターネットで調べてみましたが、 うまく調べられなかったです。 OSは2000とXPです。 よろしくお願いいたします。

  • File::Findモジュールの例外処理

    サーバー内の入り組んだ階層の中にある全てのhtmlファイルをEUCコードに一括 変換処理したいと考えています。 但し、あるひとつのディレクトリ内とそのディレクト以下の階層にあるhtmlファイルは 処理したくありません。 require "jcode.pl"; use File::Find; find(\&fileProc, './public_html'); sub fileProc { my $fname = $_; return unless -f $_; #### ここに例外処理を書けばいいと思うのですが・・・ return unless /\.html$/; open IN, $fname; open TMP, ">$fname.temptemp"; # 存在しないファイル名 while (<IN>) { &jcode'convert(*_,'euc'); print TMP; } close IN; close TMP; rename "$fname.temptemp", $fname or warn "cannot rename $fname because $! \n"; } どう書けばいいのかよろしくご教授ください。

    • ベストアンサー
    • Perl
  • ファイルの排他について

    はじめまして。 初心者ですが、今非常に困っております。 RandomAccessFileを使用して、ファイルの排他をしたいのですが・・・。具体的に言うと、AがAAA.xmlをOPEN中にBがAAA.xmlをOPENしようとするとAがOPEN中なので、例外処理に飛ばしたいのです。いくら試みても例外処理に飛びません。 <例>(java version "1.3.1.05") try { raf = new RandomAccessFile("AAA.xml","rw"); // OPEN raf.writeBytes(111); // WRITE1 raf.writeBytes(222); // WRITE2 raf.writeBytes(333); // WRITE3 raf.writeBytes(444); // WRITE4 raf.writeBytes(555); // WRITE5 raf.close(); // CLOSE } catch(IOException e) { // 排他制御に失敗. リトライしたい System.out.println("別のプロセス?が使用中") }  心当たりのある方がいらしゃいましたら、ご協力お願い致します。

  • Accessの排他制御をどのように行うべきか

    いつもお世話になっております。 Windows2000 Access2002、またはAccess2000にて、 複数のPCで、サーバにおいてあるmdbファイルを使用するシステムを開発する場合、 (例えば、スタンドアロンで使用していたシステムを複数のPCで使用することになったと仮定します。 また予算の都合上、Oracle、SQL Serverなどは使えないものとし、各PCにAccessがインストールされます。 ) 排他制御を行うために、Accessで排他モードで開いて使用するという対応というのは、問題ないのでしょうか。 データが破損する可能性があるということをよく耳にするのですが、 過去に上記の対応を行われた方がいらっしゃいましたら、その後の運用で問題は発生しなかったか(ファイルが壊れる事はないのか)、 過去に壊れた事象をお持ちの方がいらっしゃいましたら、どのように対応されたのか、 別の対応方法をとられていらっしゃる方は、その対応方法を ご教授いただけないでしょうか。 プログラムでデータの破損を退避できるのであれば、上の対応と併せて開発できそうな気はするのですが、、 ご回答、よろしくお願いいたします。

  • 排他ロックが掛かっているファイルを読み込む

    排他ロックが掛かっている(別のプロセスが使用している) テキストファイルを読み込みたいのですが、 System.IO.FileStreamを実行した後に、IOExceptionエラーが発生し、 読み込みができません。 System.IO.FileStreamにはこだわってませんので、 排他ロックが掛かっているテキストファイルを読み込む方法を ご存知の方は、ご教授頂けませんでしょうか。 宜しくお願いします。 <ソースコード> 'ファイルパス wFullPath = "\\XXX.XXX.XXX.XXX\TEXT\TEST.TXT" (XXX.XXX.XXX.XXX:IPアドレス) 'ファイルを開く Dim fs As New System.IO.FileStream(wFullPath, _ System.IO.FileMode.Open, _ System.IO.FileAccess.ReadWrite, _ System.IO.FileShare.ReadWrite) 'FileStreamを基にしたStringReaderのインスタンスを作成 Dim enc As System.Text.Encoding = _ System.Text.Encoding.GetEncoding("shift_jis") Dim sr As New System.IO.StreamReader(fs, enc) 'ファイルの内容をすべて読み込む Dim s As String = sr.ReadToEnd() <開発環境> 言語:VB.NET Microsoft Visual Studio 2008 Microsoft .NET Framework Version 3.5 SP1

  • Perlの多重起動を禁止したい

    main_01.plというプログラムがあります。 これは10分毎にバッチファイルから起動の命令が下ります。ただしプログラムの処理によっては10分以上かかることがあります。 この時、main_01.pl がすでに起動していた場合、main_01.pl はすぐに exit; になるように組みたいのです。僕が考えた方法は、あるテキストファイルにロックをかけ、そのファイルがロック中であるならばプログラムは処理を行わずすぐに終了する、といった感じです。 =============================== # タイムアウト処理 my $timeout = 5; # 排他処理 my $lockfile="lock.txt"; # 多重起動停止 (ここに $lockfile が書き込めなかったらmain_01.plは別に起動していることになるので起動しない。) # 排他処理開始 open(LOCK,"$lockfile"); flock(LOCK,2); # 処理開始 eval { # タイムアウト local $SIG{ALRM} = sub { die "alarm\n" }; alarm( $timeout ); # プログラムスタート print "\n◆スタート\n\n"; sleep(4); # プログラム終了 print "\n◆終わりました。\n\n"; }; # タイムアウト処理 if ( $@ ) { # タイムアウト print "\nタイムアウトしました。TIMEOUT= $timeout \n"; } else { # タイムアウトせずに正常終了 print "\n正常終了しました。\n"; } # 排他処理終了 close(LOCK); exit;

    • ベストアンサー
    • Perl

専門家に質問してみよう