transaction: add atomic groups to transaction logic
authorHenrik Stuart <hg@hstuart.dk>
Mon, 11 May 2009 21:12:40 +0200
changeset 8363 c8e81f557da7
parent 8362 bbc74c05b8a4
child 8364 fa901423ac23
transaction: add atomic groups to transaction logic When performing a strip operation on a repository, it is vital that all the truncations are performed, or that none of them are. This is done by adding support for writing a number of entries in a single operation. Co-contributor: Sune Foldager <cryo@cyanite.org>
mercurial/repair.py
mercurial/transaction.py
--- a/mercurial/repair.py	Tue May 12 11:15:54 2009 +0200
+++ b/mercurial/repair.py	Mon May 11 21:12:40 2009 +0200
@@ -125,10 +125,12 @@
     tr = repo.transaction()
     offset = len(tr.entries)
 
+    tr.startgroup()
     cl.strip(striprev, tr)
     mfst.strip(striprev, tr)
     for f in fs:
         f.strip(striprev, tr)
+    tr.endgroup()
 
     try:
         for i in xrange(offset, len(tr.entries)):
--- a/mercurial/transaction.py	Tue May 12 11:15:54 2009 +0200
+++ b/mercurial/transaction.py	Mon May 11 21:12:40 2009 +0200
@@ -51,6 +51,7 @@
         self.entries = []
         self.map = {}
         self.journal = journal
+        self._queue = []
 
         self.file = open(self.journal, "w")
         if createmode is not None:
@@ -62,8 +63,25 @@
             self.file.close()
 
     @active
+    def startgroup(self):
+        self._queue.append([])
+
+    @active
+    def endgroup(self):
+        q = self._queue.pop()
+        d = ''.join(['%s\0%d\n' % (x[0], x[1]) for x in q])
+        self.entries.extend(q)
+        self.file.write(d)
+        self.file.flush()
+
+    @active
     def add(self, file, offset, data=None):
         if file in self.map: return
+
+        if self._queue:
+            self._queue[-1].append((file, offset, data))
+            return
+
         self.entries.append((file, offset, data))
         self.map[file] = len(self.entries) - 1
         # add enough data to the journal to do the truncate
@@ -78,6 +96,11 @@
 
     @active
     def replace(self, file, offset, data=None):
+        '''
+        replace can only replace already committed entries
+        that are not pending in the queue
+        '''
+
         if file not in self.map:
             raise KeyError(file)
         index = self.map[file]