obscache: Only access the new obsmarkers for marker update
authorPierre-Yves David <pierre-yves.david@octobus.net>
Wed, 03 May 2017 21:47:06 +0200
changeset 2328 7ccacaa38782
parent 2327 6b751daad348
child 2329 3bb8382fc4cb
obscache: Only access the new obsmarkers for marker update Since we know what what is the part of the file with "new" markers we can just access these. If the cache was up to date before the transaction, we'll re-parse data we just wrote. See the inline comment for details. This is good enough for now.
hgext3rd/evolve/obscache.py
--- a/hgext3rd/evolve/obscache.py	Wed May 03 20:56:26 2017 +0200
+++ b/hgext3rd/evolve/obscache.py	Wed May 03 21:47:06 2017 +0200
@@ -13,6 +13,7 @@
 import errno
 
 from mercurial import (
+    error,
     localrepo,
     obsolete,
     phases,
@@ -20,6 +21,8 @@
     util,
 )
 
+from mercurial.i18n import _
+
 from . import (
     exthelper,
 )
@@ -160,6 +163,31 @@
 
     return True, startrev, startidx
 
+
+# XXX copied as is from Mercurial 4.2 and added the "offset" parameters
+@util.nogc
+def _readmarkers(data, offset=None):
+    """Read and enumerate markers from raw data"""
+    off = 0
+    diskversion = struct.unpack('>B', data[off:off + 1])[0]
+    if offset is None:
+        off += 1
+    else:
+        assert 1 <= offset
+        off = offset
+    if diskversion not in obsolete.formats:
+        raise error.Abort(_('parsing obsolete marker: unknown version %r')
+                          % diskversion)
+    return diskversion, obsolete.formats[diskversion][0](data, off)
+
+def markersfrom(obsstore, byteoffset, firstmarker):
+    if '_all' in vars(obsstore):
+        # if the data are in memory, just use that
+        return obsstore._all[firstmarker:]
+    else:
+        obsdata = obsstore.svfs.tryread('obsstore')
+        return _readmarkers(obsdata, byteoffset)[1]
+
 class obscache(object):
     """cache the "does a rev" is the precursors of some obsmarkers data
 
@@ -258,23 +286,10 @@
 
         # process the new obsmarkers
         if startidx is not None:
-            markers = repo.obsstore._all
-            # Note:
-            #
-            #   There are no actually needs to load the full obsstore here,
-            #   since we only read the latest ones.  We do it for simplicity in
-            #   the first implementation. Loading the full obsstore has a
-            #   performance cost and should go away in this case too. We have
-            #   two simples options for that:
-            #
-            #   1) provide and API to start reading markers from a byte offset
-            #      (we have that data in the cache key)
-            #
-            #   2) directly update the cache at a lower level, in the code
-            #      responsible for adding a markers.
-            #
-            #   Option 2 is probably a bit more invasive, but more solid on the long run
-            markers = [markers[i] for i in xrange(startidx, len(repo.obsstore))]
+            if startidx == 0: # all markers
+                markers = repo.obsstore._all
+            else:
+                markers = markersfrom(repo.obsstore, self._cachekey[3], startidx)
             self._updatemarkers(repo, markers)
 
         self._cachekey = getcachekey(repo)