[PATCH 1 of 6] transaction: ensure journal is committed to file system

Henrik Stuart hg at hstuart.dk
Tue Apr 21 12:33:20 CDT 2009


# HG changeset patch
# User Henrik Stuart <hg at hstuart.dk>
# Date 1240218938 -7200
# Node ID 092a6d08bc115c771c1c51947cc463b34f5fe097
# Parent  18710802cd4943834441c37420286a98b9a9bba5
transaction: ensure journal is committed to file system

Without the fsync that ensures the journal is written to the underlying
file system, the transaction caller may believe that the journal is
committed, but it may subsequently be lost if the actual writing to the
file system fails, e.g. since the disk is full. Thus, an incomplete
transaction log may exist on the disk, possibly corrupting state on a
subsequent hg recover, or leaving irrelevant data in revlogs.

Co-contributor: Sune Foldager <cryo at cyanite.org>

diff -r 18710802cd49 -r 092a6d08bc11 mercurial/transaction.py
--- a/mercurial/transaction.py	Tue Apr 21 16:02:59 2009 +0200
+++ b/mercurial/transaction.py	Mon Apr 20 11:15:38 2009 +0200
@@ -39,9 +39,14 @@
         if file in self.map: return
         self.entries.append((file, offset, data))
         self.map[file] = len(self.entries) - 1
+        self._write("%s\0%d\n" % (file, offset))
+
+    def _write(self, data):
         # add enough data to the journal to do the truncate
-        self.file.write("%s\0%d\n" % (file, offset))
+        self.file.write(data)
         self.file.flush()
+        # ensure journal is synced to file system
+        os.fsync(self.file.fileno())
 
     def find(self, file):
         if file in self.map:
@@ -53,8 +58,7 @@
             raise KeyError(file)
         index = self.map[file]
         self.entries[index] = (file, offset, data)
-        self.file.write("%s\0%d\n" % (file, offset))
-        self.file.flush()
+        self._write("%s\0%d\n" % (file, offset))
 
     def nest(self):
         self.count += 1


More information about the Mercurial-devel mailing list