transaction: change the on disk format for backupentries
authorPierre-Yves David <pierre-yves.david@fb.com>
Wed, 05 Nov 2014 01:52:46 +0000
changeset 23309 7eb520f5efe4
parent 23308 dadcd40b62d8
child 23310 5bd1f6572db0
transaction: change the on disk format for backupentries We need to store new data to improve the current transaction logic: - location: We want to generate and backup file outside of the 'store' (eg: bookmarks, or various cache files). This requires knowing and preserving where each file is located. The value of this new field is a string. It will be used as a key for a vfs mapping. - cache: We would like to handle cache file in the transaction code. This Will help to have cache consistent with the repository state and avoid performance issue on big repository like Mozilla. However, failure to handle cache file should not result in a transaction failure. We add a new field that carry this information. The value is boolean, A True value mean any error while handling this file can be ignored. Those two mechanisms are not implemented yet, but they are now persisted in the on disk file. Support for new mechanisms is coming in later changeset. We update the file format now and will introduce the new features in later changeset. The format version is set to 0 until we actually support the new feature. This will prevent misunderstanding between incomplete and final client. Support for reading both version 1 and (future) version 2 could be achieved (using default value when reading version 1) but has not been seen as necessary for now.
mercurial/transaction.py
--- a/mercurial/transaction.py	Thu Nov 13 15:47:15 2014 -0500
+++ b/mercurial/transaction.py	Wed Nov 05 01:52:46 2014 +0000
@@ -15,7 +15,7 @@
 import errno
 import error, util
 
-version = 1
+version = 0
 
 def active(func):
     def _active(self, *args, **kwds):
@@ -43,7 +43,7 @@
                     raise
 
     backupfiles = []
-    for f, b in backupentries:
+    for l, f, b, c in backupentries:
         if f and b:
             filepath = opener.join(f)
             backuppath = opener.join(b)
@@ -99,9 +99,10 @@
         self.hookargs = {}
         self.file = opener.open(self.journal, "w")
 
-        # a list of ('path', 'backuppath') entries.
+        # a list of ('location', 'path', 'backuppath', cache) entries.
         # if 'backuppath' is empty, no file existed at backup time
         # if 'path' is empty, this is a temporary transaction file
+        # (location, and cache are current unused)
         self._backupentries = []
         self._backupmap = {}
         self._backupjournal = "%s.backupfiles" % journal
@@ -193,13 +194,13 @@
         else:
             backupfile = ''
 
-        self._addbackupentry((file, backupfile))
+        self._addbackupentry(('', file, backupfile, False))
 
     def _addbackupentry(self, entry):
         """register a new backup entry and write it to disk"""
         self._backupentries.append(entry)
         self._backupmap[file] = len(self._backupentries) - 1
-        self._backupsfile.write("%s\0%s\n" % entry)
+        self._backupsfile.write("%s\0%s\0%s\0%d\n" % entry)
         self._backupsfile.flush()
 
     @active
@@ -209,7 +210,7 @@
         Such file will be delete when the transaction exit (on both failure and
         success).
         """
-        self._addbackupentry(('', tmpfile))
+        self._addbackupentry(('', '', tmpfile, False))
 
     @active
     def addfilegenerator(self, genid, filenames, genfunc, order=0, vfs=None):
@@ -355,7 +356,7 @@
         self.file.close()
         self._backupsfile.close()
         # cleanup temporary files
-        for f, b in self._backupentries:
+        for _l, f, b, _c in self._backupentries:
             if not f and b and self.opener.exists(b):
                 self.opener.unlink(b)
         self.entries = []
@@ -365,7 +366,7 @@
             self.opener.unlink(self.journal)
         if self.opener.isfile(self._backupjournal):
             self.opener.unlink(self._backupjournal)
-            for _f, b in self._backupentries:
+            for _l, _f, b, _c in self._backupentries:
                 if b and self.opener.exists(b):
                     self.opener.unlink(b)
         self._backupentries = []
@@ -447,10 +448,10 @@
                     if line:
                         # Shave off the trailing newline
                         line = line[:-1]
-                        f, b = line.split('\0')
-                        backupentries.append((f, b))
+                        l, f, b, c = line.split('\0')
+                        backupentries.append((l, f, b, bool(c)))
             else:
-                report(_("journal was created by a newer version of "
+                report(_("journal was created by a different version of "
                          "Mercurial"))
 
     _playback(file, report, opener, entries, backupentries)