2012-02-06 74 views
1

我正在尝试在C++中编写一个类,它提供了一种原子追加到文件的方法,即使在停电中写入的情况下也是如此。首先,我将当前文件位置(距离文件开头的64个偏移量,以字节为单位)写入单独的日志文件。然后,我将请求的数据写入日期文件的末尾。最后,我在日志文件中调用ftruncate()(将截断大小设置为0)。ftruncate()是异步的吗?

主要思想是,如果这个类有人要求打开一个非空的日志文件的文件,那么你知道一个写入被中断,你可以从日志文件和fseek读取最后写入的位置到那个地方。你失去了最后的部分写入,但该文件不应该被损坏。

不幸的是,似乎ftruncate()是异步的。实际上,即使我在ftruncate之后调用fflush()和fsync(),我也会看到日志在进行大量写操作时增长到高达数百个字节。它总是最终以0结束,但我期望在任何时候都能看到0或8的大小。

是否有可能使ftruncate完全同步?或者有更好的方式来使用期刊?

+0

呃电源故障? – 2012-02-06 00:57:18

+0

如果在恢复日志期间再次断电,该怎么办? – 2012-02-06 00:59:24

+1

“有没有更好的方式来使用期刊?” - 取决于您的恢复要求。在你的数据文件中写入一些“下一块应该是N字节”的消息将避免需要单独的日志(并且头部重新定位在磁性HDD上很慢),假设在恢复情况下你有时间从开始重新扫描文件 - 沿着块跳转,或者当从文件末尾向后扫描时,可以将这种下一块N字节内容与其他内容区分开。内存映射对日记来说可能更优雅一些。 – 2012-02-06 01:43:44

回答

4

ftruncate()不会更改文件中文件描述符的写入偏移量。如果打开文件并在调用ftruncate()后写入下一个长度,那么发生的情况是文件的偏移量仍在增加。当你写入时,它会将文件的长度重置为偏移量,然后在那里写入字节。

在您拨打ftruncate()之后,您可能想要调用lseek(fd, 0, SEEK_SET),以便下一次写入文件将发生在文件的开头。

+0

像一个魅力工作。 :) 谢谢! – dicroce 2012-02-06 03:54:37

+0

它也适用于我! – amc 2012-10-05 01:56:31