原子删除大量文件

Gyö*_*sek 5 c c++ io file atomic

我试图一次删除10000多个文件,原子地,例如,所有文件都需要立即删除,或者都需要留在原地.

当然,显而易见的答案是将所有文件移动到一个临时目录中,并在成功时以递归方式删除它,但这会使所需的I/O量翻倍.

压缩不起作用,因为1)我不知道哪些文件需要删除,2)文件需要经常编辑.

有什么可以帮助降低I/O成本吗?任何平台都可以.

编辑:我们假设任何时候都可能发生停电.

Dal*_*und 13

Kibbee是正确的:你正在寻找交易.但是,如果您不想要,则无需依赖数据库或特殊文件系统功能.交易的本质是:

  1. 将记录写入一个特殊文件(通常称为"日志"),列出要删除的文件.
  2. 一旦安全地写入此记录,请确保您的应用程序的行为就像文件实际已被删除一样.
  3. 稍后,开始删除事务记录中指定的文件.
  4. 删除所有文件后,删除事务记录.

请注意,在步骤(1)之后的任何时间,您都可以重新启动应用程序,它将继续删除逻辑删除的文件,直到它们最终全部消失.

请注意,您不应该走很远的路:否则您将开始重新实现真正的交易系统.但是,如果您只需要很少的简单事务,则可以接受自己的方法.


Dig*_*oss 6

在*nix上,在单个文件系统中移动文件是一种成本非常低的操作,它通过建立新名称的硬链接然后取消链接原始文件来工作.它甚至不会改变任何文件时间.

如果您可以将文件移动到单个目录中,那么您可以重命名该目录以使其成为真正的原子操作,然后以较慢的非原子方式删除文件(和目录).

你确定你不只是想要一个数据库吗?它们都内置了事务提交和回滚.

  • @ralu:所有交易系统都做的是记录意图,并在做任何无法逆转的事情之前识别和协调不归点.我试图调出一种删除文件的事务方法.它有更多的开销,而不仅仅是用'unlink(2)`来削减,但这是交易的代价.不过,我应该这么说. (2认同)

Kib*_*bee 5

我认为你真正想要的是能够进行交易.由于光盘一次只能写一个扇区,因此一次只能删除一个扇区.您需要的是,如果其中一个删除未成功发生,则可以回滚先前的删除.像这样的任务通常保留给数据库.文件系统是否可以执行事务取决于您使用的文件系统和操作系统.Windows Vista上的NTFS支持Transactional NTFS.我不太确定它的工作原理,但它可能很有用.

此外,还有一种称为Windows的卷影副本,在Linux世界中称为LVM快照.基本上它是一个时间点的光盘快照.您可以在执行删除之前直接拍摄快照,如果没有成功,则将文件复制回快照.我在VBScript中使用WMI创建了卷影副本,我确信C/C++也存在类似的api.

关于Shadow Copy和LVM Snapsots的一件事.关于整个分区的工作.因此,您无法仅拍摄单个目录的快照.但是,拍摄整个磁盘的快照只需几秒钟.所以你会拍一张快照.删除文件,如果不成功,则将文件复制回快照.这将是缓慢的,但取决于您计划回滚的频率,这可能是可以接受的.另一个想法是恢复整个快照.这可能会或可能不会很好,因为它会回滚整个磁盘上的所有更改.如果您的操作系统或其他重要文件位于那里,那就不好了.如果此分区仅包含要删除的文件,则恢复整个快照可能更容易,更快捷.