2012-02-06 75 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