1

私は2つのローカルディレクトリ間の一貫性を維持することを含むアプリケーションに取り組んでいます。具体的には、ディレクトリの1つにあるすべてのファイルが特定の方法で変更されることを除いて、ディレクトリは同一である必要があります(この部分は私の質問にとって重要ではありません)。

実行中、アプリケーションは各パスで発生する変更をリッスンする2つのプロセスを実行し、必要に応じてそれらを同期に戻すための関連操作を実行します。

私の具体的な質問に関して:私は、アプリケーションを開始するときのトリッキーな状況についてのアドバイスを探しています。この時点で、各プロセスは、処理している両方のパスの下にあるすべてのファイル/フォルダーをチェックして、アプリケーションの実行中に何らかの変更があったかどうかを確認する必要があります。(アプリケーションがシャットダウン中に発生したことをOSから通知できないため、すべてのファイル/フォルダーを直接チェックする必要があると想定します。)

各プロセスは、指定されたパスの下にあるすべてのファイル/フォルダーの永続的なデータ構造にアクセス(および維持)します。私は、各ファイルとフォルダーのデータ構造内に次のものを保持する必要があると考えていました。

  • ファイル/フォルダ名;
  • ファイルハッシュ(CRC32);
  • ファイル/フォルダーの最後のmodデータ。と
  • ファイル/フォルダのサイズ。

これらの情報は明らかにファイル/フォルダへの変更をチェックするのに役立ちますが、それらを保存するための最良の方法は何ですか?

アプリケーションの開始状況にアプローチするための賢明な方法の1つは、各プロセスが指定されたパスの下にあるすべてのファイル/フォルダーを再帰的にスキャンし、スキャンされた各ファイルのメタデータをそのデータ構造に格納されているメタデータと比較することです。 。次に、プロセスはデータ構造を反復処理して、パスから削除されたものを探す必要があります。このプロセス中に発生する可能性のあるいくつかのケースは次のとおりです。

  • ファイルが変更されました(ファイル名はデータ構造にありますが、ハッシュは異なります)。
  • 追加されたファイル(データ構造に同一のファイル名またはハッシュが見つかりません);
  • ファイルの名前が変更されました(同じハッシュを持つファイルはデータ構造に存在しますが、同じファイル名ではありません);
  • フォルダが追加されました(データ構造にフォルダ名がありません);
  • フォルダーが削除されました(データ構造内のフォルダー名ですが、パスの下にはありません);
  • フォルダの名前が変更されました(トリッキーなもの)。

では、このタスクに使用するのに最適なデータ構造は何ですか?私の頭の中で、私はある種のソートされた連想配列、たとえば赤黒木を格納fileしてfolderオブジェクトを格納することを考えています。各fileオブジェクトにはnamehashmod-date属性が含まれ、各folderオブジェクトにはnamechildren属性が含まれ、childrenその下にあるすべてのものを含む別の連想配列が格納されます。任意のファイルへのパスを指定します。たとえば、/foo/bar/file.txtルート()から開始し、の親オブジェクトに到達するまでfooチェックします。barfile.txt

私が考えることができるもう1つの方法は、すべてをフラットに格納することです。たとえば、各キーが各ファイル/フォルダーへのフルパスであり、値がfile/folderオブジェクトである赤黒木が1つあります。これはおそらく検索の方が速いでしょうが、とにかくすべての値を反復処理せずに名前が変更されたファイル/フォルダーを検出することはできません。これはコストがかかるように聞こえます。最初のアプローチでは、名前変更の識別には、データ構造のすべてではなく一部のチェックのみが含まれる場合があります。

申し訳ありませんが、上記のアイデアはひどくよく考えられていません。この分野の最先端は何ですか、そしてこれらのタイプの問題へのよく踏まれたアプローチはありますか?

4

1 に答える 1

0

ファイルシステムをモデリングしているので、階層データ構造を使用するのはごく自然なことです。結局のところ、dir1\dir2\foo.txt のファイルと dir3\bar.txt を比較する必要はありませんよね? 追跡しているものとして、ディレクトリ間のファイルの移動については言及していません。

したがって、データ構造は次のようになります。

interface IFSEntry {
  string name
  datetime creationDate
  pure virtual bool Compare(IFSEntry other)
  pure virtual void UpdateFrom(IFSEntry other)
  pure virtual bool WasRenamed(Dictionary<string,IFSEntry> possibleOriginals, out string oldName)
  ...
} 

class File : IFSEntry {
  ...
} 

class Directory : IFSEntry {
  private Dictionary<string,IFSEntry> children;
  ...
}

UpdateFrom と Compare の Directory 実装は、それらの子を再帰します。

ファイルの名前変更は、CRC を比較することで比較的簡単です。両方の場所で変更され、名前が変更されたファイルを見逃す可能性があります。比較を実行する時間がパフォーマンスの問題であることが判明した場合は、CRC ディクショナリを Directory クラスに追加できます。

ディレクトリの移動の場合、子ファイルも変更された場合、あいまいな論理状況になります。ユーザーがその状況で操作するマージ ツールを用意するのが最善です。

ファイルが両方の場所で変更され、競合する変更が発生した場合は、ユーザー向けのマージ戦略も必要です。ドキュメントが一貫性を失っていないことをユーザーの目で確認できるようにするためだけに、これは常に良い考えだと私は主張します。

于 2011-06-30T21:55:50.593 に答える