ファイルのロック解除と削除を 1 回の操作で実行
-
20-09-2019 - |
質問
複製ではありませんのでご注意ください ファイルの読み取り/書き込みのロックとリンク解除. 。(違いはプラットフォームです。ロックや削除などのファイル操作はセマンティクスがまったく異なるため、解決方法も異なります)。
次の問題があります。ファイルシステムベースのセッションストレージを作成したいと考えています。各セッションデータは、セッション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
Opeded Locked File(ファイルロックが必須ではなく、開いたファイルにUnlinkが許可されているUNIXとは異なります。
しかし、私が置いた場合 DeleteFile
ロックループの外では悪いシナリオが発生する可能性があります
GC - CreateFile/LockFile/Unlock/CloseHandle,
write - oCreateFile/LockFile/WriteUpdatedData/Unlock/CloseHandle
GC - DeleteFile
そのような問題をどのように解決できるか誰かが考えていますか?ファイルロックとファイルの削除を組み合わせたり、ファイルAtomic(Win32)で操作を行うことを可能にするトリックはありますか?
ノート:
- データベースは使いたくないのですが、
- NT 5.01 以降の Win32 API のソリューションを探しています
ありがとう。
解決
私は本当にこれが動作するようになっているか理解していません。しかし、別のプロセスによって開かれたのファイルを削除することも可能です。ファイルを作成するプロセス)(のCreateFileのdwShareMode引数にFILE_SHARE_DELETEフラグを使用しなければなりません。その後のDeleteFileを()の呼び出しが成功します。その上で最後のハンドルが閉じられるまで、ファイルが実際にファイルシステムから削除されません。
他のヒント
あなたは、現在のレコードがタイムアウトしている場合、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-specifcしわに依存しないです。
私は明確ではないんだ場合に何が起こるか:
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」フラグを扱うことができます。それはちょうど別の名前で、の新しいのファイルは、その名の末尾の一部としてバージョン番号を使用して作成されます。セッションファイルを最初に開くと、ディレクトリ検索が必要ですが、あなたはセッションで最新の名前を隠しておくことができます。
これは特定のセッションのための1つのライター・スレッドがあり得ること、あるいは我々は、ファイルを作成する2つのライタースレッド間で仲介することができるが、それが動作するようにあなたのシンプルなGC /ライターの場合も同様でなければならないことを前提としていない。
Windows の場合は、 FILE_FLAG_DELETE_ON_CLOSE CreateFile のオプション - ハンドルを閉じるときにファイルが削除されます。しかし、これがあなたのセマンティクスを満たしているかどうかはわかりません(delete-on-close属性をクリアできるとは思えないためです)。
ここで別の考えがあります。ファイルを削除する前に名前を変更してみてはどうでしょうか?ファイルを削除すると決めた後は、書き込みが行われるウィンドウを閉じることはできませんが、削除する前にファイルの名前を変更したらどうなるでしょうか?その後、書き込みが行われると、セッション ファイルが存在しないことが確認され、セッション ファイルが再作成されます。
留意すべき重要な点は、問題のウィンドウを単純に閉じることはできないということです。私見ですが、解決策は 2 つあります。
- djna のようなフラグを追加するか、
- セッションごとに名前付き mutex を取得する必要がありますが、これにはセッションでの書き込みがシリアル化されるという残念な副作用があります。
TooLate フラグを持つことの欠点は何ですか?言い換えれば、ファイルを途中で削除すると何が問題になるのでしょうか?結局のところ、システムはファイルが存在しないことに対処する必要があります...