5

10000以上のファイルを一度に削除しようとしています。たとえば、すべてを一度に削除するか、すべてをそのままにしておく必要があります。

もちろん、明らかな答えは、すべてのファイルを一時ディレクトリに移動し、成功したときに再帰的に削除することですが、これにより、必要なI/Oの量​​が2倍になります。

1)削除する必要のあるファイルがわからない、2)ファイルを頻繁に編集する必要があるため、圧縮は機能しません。

I / Oコストを削減するのに役立つものはありますか?どのプラットフォームでもかまいません。

編集:停電はいつでも発生する可能性があると仮定しましょう。

4

9 に答える 9

13

Kibbeeは正しいです:あなたはトランザクションを探しています。ただし、必要がなければ、データベースや特別なファイルシステム機能に依存する必要はありません。トランザクションの本質は次のとおりです。

  1. 削除するファイルをリストした特別なファイル(「ログ」と呼ばれることもあります)にレコードを書き込みます。
  2. このレコードが安全に書き込まれたら、ファイルが実際に削除されたかのようにアプリケーションが動作することを確認してください。
  3. 後で、トランザクションレコードで指定されたファイルの削除を開始します。
  4. すべてのファイルが削除されたら、トランザクションレコードを削除します。

手順(1)の後はいつでも、アプリケーションを再起動でき、論理的に削除されたファイルは、最終的にすべてなくなるまで削除され続けることに注意してください。

このパスをそれほど遠くまで追求するべきではないことに注意してください。そうしないと、実際のトランザクションシステムを再実装し始めます。ただし、必要な単純なトランザクションがごくわずかである場合は、独自のアプローチを使用できる場合があります。

于 2009-10-26T00:40:51.880 に答える
6

* nixでは、単一のファイルシステム内でのファイルの移動は非常に低コストの操作であり、新しい名前へのハードリンクを作成してから元のファイルのリンクを解除することで機能します。ファイル時間も変更されません。

ファイルを単一のディレクトリに移動できる場合は、そのディレクトリの名前を変更して、真のアトミック操作として邪魔にならないようにし、後でファイル(およびディレクトリ)を低速で非アトミックな方法で削除できます。

データベースだけが必要ではありませんか?それらはすべて、トランザクションのコミットとロールバックが組み込まれています。

于 2009-10-26T00:33:42.037 に答える
5

あなたが本当に探しているのは、取引をする能力だと思います。ディスクは一度に1つのセクターしか書き込むことができないため、一度に1つのファイルしか削除できません。必要なのは、削除の1つが正常に行われなかった場合に、以前の削除をロールバックする機能です。このようなタスクは通常、データベース用に予約されています。ファイルシステムがトランザクションを実行できるかどうかは、使用しているファイルシステムとOSによって異なります。Windows VistaのNTFSは、トランザクションNTFSをサポートしています。それがどのように機能するかはよくわかりませんが、役に立つかもしれません。

また、 Windows用のシャドウコピーと呼ばれるものがあります。これは、Linuxの世界ではLVMスナップショットと呼ばれています。基本的には、ある時点でのディスクのスナップショットです。削除を実行する直前にスナップショットを作成し、正常に実行されない場合は、スナップショットからファイルをコピーして戻すことができます。VBScriptでWMIを使用してシャドウコピーを作成しましたが、C /C++にも同様のAPIが存在すると確信しています。

シャドウコピーとLVMスナップソットについての1つのこと。パーティション全体の作業。したがって、1つのディレクトリだけのスナップショットを撮ることはできません。ただし、ディスク全体のスナップショットを作成するのにかかる時間はわずか数秒です。したがって、スナップショットを作成します。ファイルを削除し、失敗した場合は、スナップショットからファイルをコピーして戻します。これは遅くなりますが、ロールバックを計画している頻度によっては、許容できる場合があります。もう1つのアイデアは、スナップショット全体を復元することです。これは、ディスク全体のすべての変更をロールバックするため、適切な場合とそうでない場合があります。OSやその他の重要なファイルがそこにある場合は良くありません。このパーティションに削除するファイルのみが含まれている場合は、スナップショット全体をより簡単かつ迅速に回復できます。

于 2009-10-26T00:32:36.577 に答える
2

ファイルを移動する代わりに、一時ディレクトリにシンボリックリンクを作成します。その後、問題がなければ、ファイルを削除します。または、どこかにファイルのリストを作成してから削除します。

于 2009-10-26T00:31:48.637 に答える
2

削除するパス名のリストを作成し、このリストをファイルに書き込んで、to_be_deleted.logファイルがディスク(fsync())にヒットしていることを確認してから、削除を開始することはできません。すべての削除が完了したら、to_be_deleted.logトランザクションログを削除します。

アプリケーションを起動すると、が存在するかどうかを確認し、存在するto_be_deleted.log場合は、そのファイルの削除を再生します(「存在しない」エラーは無視します)。

于 2009-10-26T00:39:03.730 に答える
2

あなたの質問に対する基本的な答えは「いいえ」です。より複雑な答えは、これにはファイルシステムからのサポートが必要であり、その種のサポートを備えているファイルシステムはほとんどないということです。どうやら NT には、これをサポートするトランザクション FS があります。Linux 用の BtrFS もこれをサポートする可能性があります。

直接のサポートがない場合は、ハードリンク、移動、削除オプションが最適だと思います。

于 2009-10-26T01:03:14.663 に答える
1

コピーしてから削除する方法は、これを行うためのほぼ標準的な方法だと思います。追加のI/Oを許容できないという事実を知っていますか?

私は自分自身をファイルシステムでのエクスポートとは見なしませんが、トランザクションを実行するための実装では、最初に必要なすべてのアクションを実行しようとし、次に戻ってそれらのアクションをコミットする必要があると思います。IEは、非アトミックに実行するよりも多くのI/Oを実行することを避けられません。

于 2009-10-26T00:36:07.303 に答える
1

ファイルに到達するための抽象化レイヤー(データベースなど)はありますか?(ソフトウェアがファイルシステムに直接接続される場合、私の提案は適用されません)。

ファイルを削除する条件が「正しい」場合は、抽象化レイヤーで状態を「削除済み」に変更し、バックグラウンドジョブを開始して、ファイルシステムからファイルを「実際に」削除します。

もちろん、この提案はファイルの開閉に一定のコストがかかりますが、シンボリックリンクの作成などのI/Oを節約できます。

于 2009-10-26T00:37:32.980 に答える
1

Windows Vista 以降では、Transactional NTFSは必要なことを行う必要があります。

HANDLE txn = CreateTransaction(NULL, 0, 0, 0, 0, NULL /* or timeout */, TEXT("Deleting stuff"));
if (txn == INVALID_HANDLE_VALUE) {
  /* explode */
}
if (!DeleteFileTransacted(filename, txn)) {
  RollbackTransaction(txn); // You saw nothing.
  CloseHandle(txn);
  die_horribly();
}
if (!CommitTransaction(txn)) {
  CloseHandle(txn);
  die_horribly();
}
CloseHandle(txn);
于 2009-10-26T00:50:57.787 に答える