2012-02-01 3 views
3

多くの一般的なファイルシステムではアトミック操作は提供されていませんが、アトミックにファイルを書き込むことは特定のシナリオでは非常に重要です。私はこの問題の解決策を思いつきました。非トランザクションファイルシステムでのアトミックファイル書き込みの実装

Iは、以下の仮定を行った:

  • 使用中のファイルシステムは、(例えば、NTFS)iノード・レベルでアトミック操作をサポートします。これは、の削除がアトミックであることを意味します。
  • プログラム自体がファイルにアクセスします。
  • プログラムのインスタンスは一度に1つしかなく、シングルスレッドで動作します。
  • 簡単にするために、ファイル内容全体が毎回書き込まれます(つまり、切り捨て - 書き込み)。

これは、次のような問題があります。ファイルを書き込んでいるうちに、プログラムが中断され、書き込むコンテンツの一部だけが残ってしまう可能性があります。

は、私は次のプロセスを提案:

  1. は一時ファイルに新しいコンテンツを書く
  2. 移動元のファイルを一時的な場所へオリジナルバックアップ
  3. 移動オリジナル
  4. バックアップ

バックアップを削除ファイルは、(例えば、彼らは異なっ前置することができ、または同じボリューム上の別のディレクトリにすることができる)オリジナルファイルと区別されています。同時に、その名前は対応するオリジナルに直接マッピングする必要があります(たとえば、同じファイル名を使用するなど)。

しかし、この操作はまだアトミックではありません。プロセスは、ステップ1、2、3または4中断することができる:

  1. 潜在的に不完全新規を残します。
  2. 移動はアトミックですが、ターゲットファイルが失われています。 新しいバックアップが存在し、完了です。
  3. 移動はアトミックですが、使用されていませんバックアップです。 オリジナルは、に置き換えられました。新しい内容
  4. 削除はアトミックです。

前提条件2と3を前提として、クラッシュ後にプログラムを再起動する必要があります。起動プロセスの間に、それはこれらの回復のチェックを実行する必要があります。

  • 新が存在するが、バックアップが、我々はそれが不完全になる可能性があるので新しいを削除する手順1で以降に墜落していない場合。
  • が存在し、バックアップは、あまりにも、私たちはバックアップが存在しますが、手順3で続行した後は、あまりにも、私たちがクラッシュしていない場合は、ステップ2は、ステップ3
  • を続行した後、墜落しない場合

リカバリプロセス自体は、アトミック操作のみを使用しているため、中断後に中断したところでそのまま続行されます。

私は、このアイデアが1つのプログラムのアトミック書き込みを保証すると考えています。

  • 同じプログラムの複数のインスタンスを使用する場合、現在進行中のファイル書き込みで他のプログラムに干渉することがあります。
  • 通常は書き込むだけの書き込みをしない外部プログラムは通常正しい結果を得ますが、同時に要求されたエントリに書き込み操作があると、間違ってエントリが見つからないことがあります。

これらの問題(前の前提条件で除外されています)は、使用ポリシー(たとえば、他のインスタンスを確認し、他のユーザーへのディレクトリアクセスを拒否する)によって解決できます。

最後に、私の質問:それは意味があるのでしょうか、それともプロセスに欠陥がありますか?このアプローチが実際に使用されないようにする問題はありますか?

+0

私はこれにいくつかのC#コードを書いていますが、私は要求に応じて追加することができましたが、質問はすでに1マイルほどです。 – mafu

答えて

3

あなたのステップをさらに簡素化することができます。

  1. 一時ファイルに新しいコンテンツを書く新
  2. は、起動時にオリジナル

から

  • 移動の新しいオリジナルのファイルを削除します。
    1. オリジナルが存在しない場合はNe手順3の前にプロセスが中断された場合は、「新規」を「オリジナル」に移動します。
    2. オリジナルと新規の両方が存在する場合、手順2の前にプロセスが中断され、新規を削除します。

    私は設定ファイルの管理にこれを使用していますが、このプロセスから問題が発生したことはありません。

  • +0

    -facepalm-あなたが正しくている – mafu

    +1

    指定した動作が順番に行われると仮定します。すべてのファイルシステムがそれを保証するわけではありません。 – CodesInChaos

    +0

    @CodeInChaos:それはちょっと悪いことです:(私はステップ間でfsバッファをフラッシュしなければならないのですか?そしてあなたの思考を続けて、私はフラッシュ要求を無視するハードディスクを聞いた... – mafu

    4

    あなたが想定する必要があり一つだけ、ファイルの名前を変更することはアトミック操作です

    したがって、次のステップは、(少なくとも、OSなどのUNIX上の)補正を確保しますがあり

    1. 一時ファイルに新しいコンテンツを書きます新
    2. は、アプリケーションがクラッシュした場合は再起動したときには、古いコンテンツを取得または新しい

    に元の名前にこの道を、一時ファイルの名前を変更します余分なコードを必要とせずに

    +0

    これは、 – mafu

    +0

    @mafutrct:名前を変更すると、上書きすることができます(少なくともUnixでは)。 –

    +0

    警告:メタデータがコミットされる前にデータブロックがディスクに書き込まれることを保証しないファイルシステムもあります。一時ファイルを書き込んだ後、名前を変更する前に 'fdatasync()'やそれに相当するものを呼び出さなければならないかもしれません。 –

    関連する問題