複数人からのログファイルの書き込みについて

解決


おかぽん  2013-11-22 02:37:59  No: 45608

あるプログラムの動作ログを取ることになりました。
起動時、終了時、保存時、削除時等のタイミングで、処理日時、PC名、ユーザー名、動作情報を
ネットワーク上の共有フォルダにあるログファイルに書き込みます。
一人が操作するだけでは、それほど頻繁に書き込みしませんが、複数人がこのプログラムを
起動し、一つのログファイルを更新します。
こういう場合、AssignFile、Append、Writeln、Flush、CloseFileを使う方がいいのでしょうか?
それとも、TFileStreamをfmShareDenyWriteで開いて、排他制御して使うほうがいいのでしょうか?

単独で書き込みするログ出力は経験ありますが、複数人が書き込む場合は経験がないので、
よければ経験談など、アドバイスをお願いします。
ようするに複数人から同時更新される(された)場合を心配しています。

念のため環境はWindows7+(まだ)Delphi5 です。


Quest  2013-11-22 08:50:53  No: 45609

複数人からではなく、1台のPCで複数のプロセスから
テキストベースのログファイルに書き込む処理を作ったことがありますが
その時は1台のPC限定だったので、Mutexを使って排他制御して
ファイルの書き込み自体はAssignFile、Append、Writelnを使いました。
おかぽんさんの場合は、複数のPCからアクセスする共有ファイルなので
TFileStreamなどで排他制御するのが王道だと思います。


おかぽん  2013-11-23 02:03:36  No: 45610

Questさん、レスありがとうございます。

> TFileStreamなどで排他制御するのが王道だと思います。
ということで、以下のようなコードでテストプログラムを作成しました。
別PCで起動し、タイマーで適当なログを書き出し、自PCでは
Delphi上でブレークしたところ、別PC側では、タイムアウトで
終了してくれました。
fmShareDenyWrite がどのような仕組みなのかよくわかりませんが。

FFileName: ログファイル名
FTimeOut: タイムアウト時間(ミリ秒)

細かいエラートラップとか、チェックは割愛
function WriteLogStream(aLog: String): String;
var
  startcount: Cardinal;
  stream: TFileStream;
begin
  Result := '';
  startcount := GetTickCount;
  while True do begin
    try
      if FileExists(FFileName) then begin
        stream := TFileStream.Create(FFileName, fmOpenReadWrite or fmShareDenyWrite);
      end
      else begin
        stream := TFileStream.Create(FFileName, fmCreate or fmShareDenyWrite);
      end;
      try
        stream.Position := stream.Size;
        stream.Write(PChar(aLog)^, Length(aLog));
      finally
        stream.Free;
      end;
      Break;
    except
      Sleep(100);
    end;
    if (GetTickCount - startcount) >= FTimeOut then Break;
  end;
end;

あとは、実際の運用環境で、エラーなくストレスなく、書き込みできるか試してみます。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加