obsolete: obsstore.add now takes a list of markers.
authorPierre-Yves.David@ens-lyon.org
Fri, 13 Jul 2012 22:15:11 +0200
changeset 17220 bdac214a4705
parent 17219 494a970f68de
child 17221 988974c2a4bf
obsolete: obsstore.add now takes a list of markers. This allow efficient IO and it greatly simplify the merging of markers.
mercurial/obsolete.py
--- a/mercurial/obsolete.py	Thu Jul 12 19:58:07 2012 +0200
+++ b/mercurial/obsolete.py	Fri Jul 13 22:15:11 2012 +0200
@@ -164,8 +164,7 @@
         self.sopener = sopener
         data = sopener.tryread('obsstore')
         if data:
-            for marker in _readmarkers(data):
-                self._load(marker)
+            self._load(_readmarkers(data))
 
     def __iter__(self):
         return iter(self._all)
@@ -188,11 +187,15 @@
             if len(succ) != 20:
                 raise ValueError(succ)
         marker = (str(prec), tuple(succs), int(flag), encodemeta(metadata))
-        self.add(transaction, marker)
+        self.add(transaction, [marker])
+
+    def add(self, transaction, markers):
+        """Add new markers to the store
 
-    def add(self, transaction, marker):
-        """Add a new marker to the store"""
-        if marker not in self._all:
+        Take care of filtering duplicate.
+        Return the number of new marker."""
+        new = [m for m in markers if m not in self._all]
+        if new:
             f = self.sopener('obsstore', 'ab')
             try:
                 # Whether the file's current position is at the begin or at
@@ -204,29 +207,26 @@
                 offset = f.tell()
                 transaction.add('obsstore', offset)
                 # offset == 0: new file - add the version header
-                for bytes in _encodemarkers([marker], offset == 0):
+                for bytes in _encodemarkers(new, offset == 0):
                     f.write(bytes)
             finally:
                 # XXX: f.close() == filecache invalidation == obsstore rebuilt.
                 # call 'filecacheentry.refresh()'  here
                 f.close()
-            self._load(marker)
+            self._load(new)
+        return len(new)
 
     def mergemarkers(self, transation, data):
-        other = _readmarkers(data)
-        local = set(self._all)
-        new = [m for m in other if m not in local]
-        for marker in new:
-            # XXX: N marker == N x (open, write, close)
-            # we should write them all at once
-            self.add(transation, marker)
+        markers = _readmarkers(data)
+        self.add(transation, markers)
 
-    def _load(self, marker):
-        self._all.append(marker)
-        pre, sucs = marker[:2]
-        self.precursors.setdefault(pre, set()).add(marker)
-        for suc in sucs:
-            self.successors.setdefault(suc, set()).add(marker)
+    def _load(self, markers):
+        for mark in markers:
+            self._all.append(mark)
+            pre, sucs = mark[:2]
+            self.precursors.setdefault(pre, set()).add(mark)
+            for suc in sucs:
+                self.successors.setdefault(suc, set()).add(mark)
 
 def _encodemarkers(markers, addheader=False):
     # Kept separate from flushmarkers(), it will be reused for