1

これは、ファイルのr/wロックとリンク解除の重複ではないことに注意してください。(違い-プラットフォーム。ロックや削除などのファイルの操作はまったく異なるセマンティクスを持っているため、結果は異なります)。

次の問題があります。各セッションデータがセッションIDで名前が付けられた単純なファイルに保存されるファイルシステムベースのセッションストレージを作成したいと思います。

次のAPIが必要です:write(sid,data,timeout)、、ここread(sid,data,timeout)remove(sid) sid ==ファイル名、また、すべてのタイムアウトセッションを削除する可能性のあるある種のGCが必要です。

単一のプロセスで作業する場合は非常に簡単な作業ですが、複数のプロセスで作業する場合や共有フォルダーで作業する場合でも、絶対に簡単ではありません。

私が考えた最も簡単な解決策は次のとおりです。

write/read:
   hanlde=CreateFile
   LockFile(handle)
   read/write data
   UnlockFile(handle)
   CloseHanlde(handle)

GC (for each file in directory)
   hanlde=CreateFile
   LockFile(handle)
   check if timeout occured
     DeleteFile
   UnlockFile(handle)
   CloseHanlde(handle)

しかし、AFIAK私はDeleteFile開いたロックされたファイルを呼び出すことができません(ファイルロックが必須ではなく、開いたファイルに対してリンク解除が許可されているUnixとは異なります。

しかしDeleteFile、ロックループの外に置くと、悪いシナリオが発生する可能性があります

GC - CreateFile/LockFile/Unlock/CloseHandle,
write - oCreateFile/LockFile/WriteUpdatedData/Unlock/CloseHandle
GC - DeleteFile

誰かがそのような問題がどのように解決されるかについての考えを持っていますか?ファイルロックとファイル削除を組み合わせたり、ファイルアトミック(Win32)で操作したりできるトリックはありますか?

ノート:

  • データベースを使いたくない、
  • NT5.01以降のWin32APIのソリューションを探しています

ありがとう。

4

3 に答える 3

2

これがどのように機能するのか、私にはよくわかりません。ただし、別のプロセスによって開かれているファイルを削除することは可能です。ファイルを作成するプロセスは、CreateFile() の dwShareMode 引数に FILE_SHARE_DELETE フラグを使用する必要があります。その後の DeleteFile() 呼び出しは成功します。ファイルの最後のハンドルが閉じられるまで、ファイルは実際にはファイル システムから削除されません。

于 2009-12-19T16:41:01.167 に答える
1

現在、レコードがタイムアウトしているかどうかを GC が判断できるようにするデータがレコードに含まれています。そのハウスキーピング情報を「TooLateWeAlreadyTimedItOut」フラグで拡張するのはどうですか。

 GC sets TooLateWeAlreadyTimedItOut = true
 Release lock
    <== writer comes in here, sees the "TooLate" flag and so does not write
 GC deletes

つまり、一種の楽観的ロック アプローチを使用しています。これには Writer での追加の複雑さが必要ですが、OS 固有の問題に依存することはなくなりました。

この場合に何が起こるかはわかりません:

 GC checks timeout
 GC deletes
 Writer attempts write, and finds no file ...

このケースで計画したことは、「TooLate」ケースでも使用できます

追加するために編集:

このシーケンスが発生するのは有効であるとあなたは言いました:

 GC Deletes
 (Very slightly later) Writer attempts a write, sees no file, creates a new one

ライターは、「tooLate」フラグをこの場合と同一のものとして扱うことができます。別の名前で新しいファイルを作成し、名前の末尾にバージョン番号を使用します。セッション ファイルを初めて開くときは、ディレクトリ検索が必要ですが、その後、セッションに最新の名前を隠しておくことができます。

これは、特定のセッションに対して Writer スレッドが 1 つしか存在できないこと、またはファイルを作成する 2 つの Writer スレッド間で仲介できることを前提としていますが、単純な GC/Writer ケースが機能するには、これが当てはまる必要があります。

于 2009-12-19T14:25:48.177 に答える
0

Windows の場合、CreateFile にFILE_FLAG_DELETE_ON_CLOSEオプションを使用できます。これにより、ハンドルを閉じるとファイルが削除されます。しかし、これがあなたのセマンティクスを満たしているかどうかはわかりません (なぜなら、delete-on-close 属性をクリアできるとは思えないからです。

ここに別の考えがあります。削除する前にファイルの名前を変更するのはどうですか? ファイルを削除することを決定した後、書き込みが行われるウィンドウを閉じることはできませんが、削除する前にファイルの名前を変更するとどうなりますか? その後、書き込みが発生すると、セッション ファイルが存在しないことがわかり、再作成されます。

心に留めておくべき重要なことは、問題のウィンドウを閉じることはできないということです。私見には2つの解決策があります:

  1. 言及されたdjnaのようなフラグを追加するか、
  2. ミューテックスという名前のセッションごとに取得する必要があります。これには、セッションでの書き込みをシリアル化するという不幸な副作用があります。

TooLate フラグを持つことのマイナス面は何ですか? つまり、時期尚早にファイルを削除すると何が問題になるのでしょうか? 結局のところ、システムは存在しないファイルに対処する必要があります...

于 2009-12-19T15:59:08.210 に答える