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.
--- 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)