--- a/hgext3rd/evolve/stablerange.py Wed Nov 22 13:44:44 2017 +0100
+++ b/hgext3rd/evolve/stablerange.py Wed Nov 22 15:05:15 2017 +0100
@@ -249,8 +249,6 @@
# The point up to which we have data in cache
self._tiprev = None
self._tipnode = None
- # cache the 'depth' of a changeset, the size of '::rev'
- self._depthcache = {}
# cache the standard stable subranges or a range
self._subrangescache = {}
# To slices merge, we need to walk their descendant in reverse stable
@@ -273,6 +271,7 @@
def warmup(self, repo, upto=None):
"""warm the cache up"""
repo = repo.unfiltered()
+ repo.depthcache.update(repo)
cl = repo.changelog
# subrange should be warmed from head to range to be able to benefit
# from revsfromrange cache. otherwise each merge will trigger its own
@@ -340,38 +339,7 @@
duration)
def depthrev(self, repo, rev):
- repo = repo.unfiltered()
- cl = repo.changelog
- depth = self._getdepth
- nullrev = nodemod.nullrev
- stack = [rev]
- while stack:
- revdepth = None
- current = stack[-1]
- revdepth = depth(current)
- if revdepth is not None:
- stack.pop()
- continue
- p1, p2 = self._parents(current, cl.parentrevs)
- if p1 == nullrev:
- # root case
- revdepth = 1
- elif p2 == nullrev:
- # linear commit case
- parentdepth = depth(p1)
- if parentdepth is None:
- stack.append(p1)
- else:
- revdepth = parentdepth + 1
- else:
- # merge case
- revdepth = self._depthmerge(cl, current, p1, p2, stack)
- if revdepth is not None:
- self._setdepth(current, revdepth)
- stack.pop()
- # actual_depth = len(list(cl.ancestors([rev], inclusive=True)))
- # assert revdepth == actual_depth, (rev, revdepth, actual_depth)
- return revdepth
+ return repo.depthcache.get(rev)
def rangelength(self, repo, rangeid):
headrev, index = rangeid[0], rangeid[1]
@@ -417,18 +385,6 @@
self._parentscache[rev] = parents
return parents
- def _getdepth(self, rev):
- """utility function used to access the depth cache
-
- This mostly exist to help the on disk persistence."""
- return self._depthcache.get(rev)
-
- def _setdepth(self, rev, value):
- """utility function used to set the depth cache
-
- This mostly exist to help the on disk persistence."""
- self._depthcache[rev] = value
-
def _getsub(self, rev):
"""utility function used to access the subranges cache
@@ -491,63 +447,18 @@
expected = len(revs) - 1
# Since we do warmup properly, we can expect the cache to be hot
# for everythin under the merge we investigate
- cache = self._depthcache
+ cache = repo.depthcache
# note: we cannot do a binary search because element under the
# inherited point might have mismatching depth because of inner
# branching.
for rev in i:
- if cache[rev] == expected:
+ if cache.get(rev) == expected:
break
expected -= 1
value = (expected - 1, rev)
self._inheritancecache[merge] = value
return value
- def _depthmerge(self, cl, rev, p1, p2, stack):
- # sub method to simplify the main 'depthrev' one
- revdepth = None
- depth = self._getdepth
- depth_p1 = depth(p1)
- depth_p2 = depth(p2)
- missingparent = False
- if depth_p1 is None:
- stack.append(p1)
- missingparent = True
- if depth_p2 is None:
- stack.append(p2)
- missingparent = True
- if missingparent:
- return None
- # computin depth of a merge
- # XXX the common ancestors heads could be cached
- ancnodes = cl.commonancestorsheads(cl.node(p1), cl.node(p2))
- ancrevs = [cl.rev(a) for a in ancnodes]
- anyunkown = False
- ancdepth = []
- for r in ancrevs:
- d = depth(r)
- if d is None:
- anyunkown = True
- stack.append(r)
- ancdepth.append((r, d))
- if anyunkown:
- return None
- if not ancrevs:
- # unrelated branch, (no common root)
- revdepth = depth_p1 + depth_p2 + 1
- elif len(ancrevs) == 1:
- # one unique branch point:
- # we can compute depth without any walk
- depth_anc = ancdepth[0][1]
- revdepth = depth_p1 + (depth_p2 - depth_anc) + 1
- else:
- # multiple ancestors, we pick one that is
- # * the deepest (less changeset outside of it),
- # * lowest revs because more chance to have descendant of other "above"
- anc, revdepth = max(ancdepth, key=lambda x: (x[1], -x[0]))
- revdepth += len(cl.findmissingrevs(common=[anc], heads=[rev]))
- return revdepth
-
def _subranges(self, repo, rangeid):
if self.rangelength(repo, rangeid) == 1:
return []
@@ -706,7 +617,6 @@
tiprev INTEGER NOT NULL,
tipnode BLOB NOT NULL
);""",
- "CREATE TABLE depth(rev INTEGER NOT NULL PRIMARY KEY, depth INTEGER NOT NULL);",
"""CREATE TABLE range(rev INTEGER NOT NULL,
idx INTEGER NOT NULL,
PRIMARY KEY(rev, idx));""",
@@ -721,19 +631,15 @@
);""",
"CREATE INDEX subranges_index ON subranges (suprev, supidx);",
"CREATE INDEX range_index ON range (rev, idx);",
- "CREATE INDEX depth_index ON depth (rev);"
]
_newmeta = "INSERT INTO meta (schemaversion, tiprev, tipnode) VALUES (?,?,?);"
_updatemeta = "UPDATE meta SET tiprev = ?, tipnode = ?;"
-_updatedepth = "INSERT INTO depth(rev, depth) VALUES (?,?);"
_updaterange = "INSERT INTO range(rev, idx) VALUES (?,?);"
_updatesubranges = """INSERT
INTO subranges(listidx, suprev, supidx, subrev, subidx)
VALUES (?,?,?,?,?);"""
_queryexist = "SELECT name FROM sqlite_master WHERE type='table' AND name='meta';"
_querymeta = "SELECT schemaversion, tiprev, tipnode FROM meta;"
-_querydepth = "SELECT depth FROM depth WHERE rev = ?;"
-_batchdepth = "SELECT rev, depth FROM depth;"
_queryrange = "SELECT * FROM range WHERE (rev = ? AND idx = ?);"
_querysubranges = """SELECT subrev, subidx
FROM subranges
@@ -742,7 +648,7 @@
class sqlstablerange(stablerange):
- _schemaversion = 0
+ _schemaversion = 1
def __init__(self, repo):
lrusize = repo.ui.configint('experimental', 'obshashrange.lru-size',
@@ -753,9 +659,7 @@
self._cl = repo.unfiltered().changelog # (okay to keep an old one)
self._ondisktiprev = None
self._ondisktipnode = None
- self._unsaveddepth = {}
self._unsavedsubranges = {}
- self._fulldepth = False
def warmup(self, repo, upto=None):
self._con # make sure the data base is loaded
@@ -776,22 +680,6 @@
repo.ui.warn('(cache will not be saved)\n')
super(sqlstablerange, self).warmup(repo, upto)
- def _getdepth(self, rev):
- cache = self._depthcache
- if rev not in cache and rev <= self._ondisktiprev and self._con is not None:
- value = None
- result = self._con.execute(_querydepth, (rev,)).fetchone()
- if result is not None:
- value = result[0]
- # in memory caching of the value
- cache[rev] = value
- return cache.get(rev)
-
- def _setdepth(self, rev, depth):
- assert rev not in self._unsaveddepth
- self._unsaveddepth[rev] = depth
- super(sqlstablerange, self)._setdepth(rev, depth)
-
def _getsub(self, rangeid):
cache = self._subrangescache
if rangeid not in cache and rangeid[0] <= self._ondisktiprev and self._con is not None:
@@ -808,10 +696,6 @@
self._unsavedsubranges[rangeid] = value
super(sqlstablerange, self)._setsub(rangeid, value)
- def _inheritancepoint(self, *args, **kwargs):
- self._loaddepth()
- return super(sqlstablerange, self)._inheritancepoint(*args, **kwargs)
-
def _db(self):
try:
util.makedirs(self._vfs.dirname(self._path))
@@ -847,7 +731,8 @@
def _save(self, repo):
repo = repo.unfiltered()
- if not (self._unsavedsubranges or self._unsaveddepth):
+ repo.depthcache.save(repo)
+ if not self._unsavedsubranges:
return # no new data
if self._con is None:
@@ -886,26 +771,12 @@
]
con.execute(_updatemeta, meta)
- self._savedepth(con, repo)
self._saverange(con, repo)
con.commit()
self._ondisktiprev = self._tiprev
self._ondisktipnode = self._tipnode
- self._unsaveddepth.clear()
self._unsavedsubranges.clear()
- def _savedepth(self, con, repo):
- repo = repo.unfiltered()
- data = self._unsaveddepth.items()
- con.executemany(_updatedepth, data)
-
- def _loaddepth(self):
- """batch load all data about depth"""
- if not (self._fulldepth or self._con is None):
- result = self._con.execute(_batchdepth)
- self._depthcache.update(result.fetchall())
- self._fulldepth = True
-
def _saverange(self, con, repo):
repo = repo.unfiltered()
data = []