##// END OF EJS Templates
branchmap: encapsulate cache updating in the map itself...
Martijn Pieters -
r41764:328ca3b9 default
parent child Browse files
Show More
@@ -2376,13 +2376,18 b' def perfbranchmap(ui, repo, *filternames'
2376 view = repo
2376 view = repo
2377 else:
2377 else:
2378 view = repo.filtered(filtername)
2378 view = repo.filtered(filtername)
2379 if util.safehasattr(view._branchcaches, '_per_filter'):
2380 filtered = view._branchcaches._per_filter
2381 else:
2382 # older versions
2383 filtered = view._branchcaches
2379 def d():
2384 def d():
2380 if clear_revbranch:
2385 if clear_revbranch:
2381 repo.revbranchcache()._clear()
2386 repo.revbranchcache()._clear()
2382 if full:
2387 if full:
2383 view._branchcaches.clear()
2388 view._branchcaches.clear()
2384 else:
2389 else:
2385 view._branchcaches.pop(filtername, None)
2390 filtered.pop(filtername, None)
2386 view.branchmap()
2391 view.branchmap()
2387 return d
2392 return d
2388 # add filter in smaller subset to bigger subset
2393 # add filter in smaller subset to bigger subset
@@ -43,75 +43,89 b" subsettable = {None: 'visible',"
43 'served': 'immutable',
43 'served': 'immutable',
44 'immutable': 'base'}
44 'immutable': 'base'}
45
45
46 def updatecache(repo):
46
47 """Update the cache for the given filtered view on a repository"""
47 class BranchMapCache(object):
48 # This can trigger updates for the caches for subsets of the filtered
48 """Cache mapping"""
49 # view, e.g. when there is no cache for this filtered view or the cache
49 def __init__(self):
50 # is stale.
50 self._per_filter = {}
51
51
52 cl = repo.changelog
52 def __getitem__(self, repo):
53 filtername = repo.filtername
53 self.updatecache(repo)
54 bcache = repo._branchcaches.get(filtername)
54 return self._per_filter[repo.filtername]
55 if bcache is None or not bcache.validfor(repo):
55
56 # cache object missing or cache object stale? Read from disk
56 def updatecache(self, repo):
57 bcache = branchcache.fromfile(repo)
57 """Update the cache for the given filtered view on a repository"""
58 # This can trigger updates for the caches for subsets of the filtered
59 # view, e.g. when there is no cache for this filtered view or the cache
60 # is stale.
58
61
59 revs = []
62 cl = repo.changelog
60 if bcache is None:
63 filtername = repo.filtername
61 # no (fresh) cache available anymore, perhaps we can re-use
64 bcache = self._per_filter.get(filtername)
62 # the cache for a subset, then extend that to add info on missing
65 if bcache is None or not bcache.validfor(repo):
63 # revisions.
66 # cache object missing or cache object stale? Read from disk
64 subsetname = subsettable.get(filtername)
67 bcache = branchcache.fromfile(repo)
65 if subsetname is not None:
66 subset = repo.filtered(subsetname)
67 bcache = subset.branchmap().copy()
68 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs
69 revs.extend(r for r in extrarevs if r <= bcache.tiprev)
70 else:
71 # nothing to fall back on, start empty.
72 bcache = branchcache()
73
68
74 revs.extend(cl.revs(start=bcache.tiprev + 1))
69 revs = []
75 if revs:
70 if bcache is None:
76 bcache.update(repo, revs)
71 # no (fresh) cache available anymore, perhaps we can re-use
72 # the cache for a subset, then extend that to add info on missing
73 # revisions.
74 subsetname = subsettable.get(filtername)
75 if subsetname is not None:
76 subset = repo.filtered(subsetname)
77 bcache = self[subset].copy()
78 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs
79 revs.extend(r for r in extrarevs if r <= bcache.tiprev)
80 else:
81 # nothing to fall back on, start empty.
82 bcache = branchcache()
77
83
78 assert bcache.validfor(repo), filtername
84 revs.extend(cl.revs(start=bcache.tiprev + 1))
79 repo._branchcaches[repo.filtername] = bcache
85 if revs:
86 bcache.update(repo, revs)
80
87
81 def replacecache(repo, bm):
88 assert bcache.validfor(repo), filtername
82 """Replace the branchmap cache for a repo with a branch mapping.
89 self._per_filter[repo.filtername] = bcache
90
91 def replace(self, repo, remotebranchmap):
92 """Replace the branchmap cache for a repo with a branch mapping.
93
94 This is likely only called during clone with a branch map from a
95 remote.
83
96
84 This is likely only called during clone with a branch map from a remote.
97 """
85 """
98 cl = repo.changelog
86 cl = repo.changelog
99 clrev = cl.rev
87 clrev = cl.rev
100 clbranchinfo = cl.branchinfo
88 clbranchinfo = cl.branchinfo
101 rbheads = []
89 rbheads = []
102 closed = []
90 closed = []
103 for bheads in remotebranchmap.itervalues():
91 for bheads in bm.itervalues():
104 rbheads += bheads
92 rbheads.extend(bheads)
105 for h in bheads:
93 for h in bheads:
106 r = clrev(h)
94 r = clrev(h)
107 b, c = clbranchinfo(r)
95 b, c = clbranchinfo(r)
108 if c:
96 if c:
109 closed.append(h)
97 closed.append(h)
98
110
99 if rbheads:
111 if rbheads:
100 rtiprev = max((int(clrev(node))
112 rtiprev = max((int(clrev(node)) for node in rbheads))
101 for node in rbheads))
113 cache = branchcache(
102 cache = branchcache(bm,
114 remotebranchmap, repo[rtiprev].node(), rtiprev,
103 repo[rtiprev].node(),
115 closednodes=closed)
104 rtiprev,
105 closednodes=closed)
106
116
107 # Try to stick it as low as possible
117 # Try to stick it as low as possible
108 # filter above served are unlikely to be fetch from a clone
118 # filter above served are unlikely to be fetch from a clone
109 for candidate in ('base', 'immutable', 'served'):
119 for candidate in ('base', 'immutable', 'served'):
110 rview = repo.filtered(candidate)
120 rview = repo.filtered(candidate)
111 if cache.validfor(rview):
121 if cache.validfor(rview):
112 repo._branchcaches[candidate] = cache
122 self._per_filter[candidate] = cache
113 cache.write(rview)
123 cache.write(rview)
114 break
124 return
125
126 def clear(self):
127 self._per_filter.clear()
128
115
129
116 class branchcache(dict):
130 class branchcache(dict):
117 """A dict like object that hold branches heads cache.
131 """A dict like object that hold branches heads cache.
@@ -992,7 +992,7 b' class localrepository(object):'
992
992
993 self._dirstatevalidatewarned = False
993 self._dirstatevalidatewarned = False
994
994
995 self._branchcaches = {}
995 self._branchcaches = branchmap.BranchMapCache()
996 self._revbranchcache = None
996 self._revbranchcache = None
997 self._filterpats = {}
997 self._filterpats = {}
998 self._datafilters = {}
998 self._datafilters = {}
@@ -1520,8 +1520,7 b' class localrepository(object):'
1520 def branchmap(self):
1520 def branchmap(self):
1521 '''returns a dictionary {branch: [branchheads]} with branchheads
1521 '''returns a dictionary {branch: [branchheads]} with branchheads
1522 ordered by increasing revision number'''
1522 ordered by increasing revision number'''
1523 branchmap.updatecache(self)
1523 return self._branchcaches[self]
1524 return self._branchcaches[self.filtername]
1525
1524
1526 @unfilteredmethod
1525 @unfilteredmethod
1527 def revbranchcache(self):
1526 def revbranchcache(self):
@@ -2073,9 +2072,9 b' class localrepository(object):'
2073 return
2072 return
2074
2073
2075 if tr is None or tr.changes['origrepolen'] < len(self):
2074 if tr is None or tr.changes['origrepolen'] < len(self):
2076 # updating the unfiltered branchmap should refresh all the others,
2075 # accessing the 'ser ved' branchmap should refresh all the others,
2077 self.ui.debug('updating the branch cache\n')
2076 self.ui.debug('updating the branch cache\n')
2078 branchmap.updatecache(self.filtered('served'))
2077 self.filtered('served').branchmap()
2079
2078
2080 if full:
2079 if full:
2081 rbc = self.revbranchcache()
2080 rbc = self.revbranchcache()
@@ -2093,7 +2092,7 b' class localrepository(object):'
2093 # can't use delattr on proxy
2092 # can't use delattr on proxy
2094 del self.__dict__[r'_tagscache']
2093 del self.__dict__[r'_tagscache']
2095
2094
2096 self.unfiltered()._branchcaches.clear()
2095 self._branchcaches.clear()
2097 self.invalidatevolatilesets()
2096 self.invalidatevolatilesets()
2098 self._sparsesignaturecache.clear()
2097 self._sparsesignaturecache.clear()
2099
2098
@@ -13,6 +13,7 b' import errno'
13
13
14 from .i18n import _
14 from .i18n import _
15 from . import (
15 from . import (
16 branchmap,
16 changelog,
17 changelog,
17 error,
18 error,
18 localrepo,
19 localrepo,
@@ -193,7 +194,7 b' class statichttprepository(localrepo.loc'
193 self.changelog = changelog.changelog(self.svfs)
194 self.changelog = changelog.changelog(self.svfs)
194 self._tags = None
195 self._tags = None
195 self.nodetagscache = None
196 self.nodetagscache = None
196 self._branchcaches = {}
197 self._branchcaches = branchmap.BranchMapCache()
197 self._revbranchcache = None
198 self._revbranchcache = None
198 self.encodepats = None
199 self.encodepats = None
199 self.decodepats = None
200 self.decodepats = None
@@ -13,7 +13,6 b' import struct'
13
13
14 from .i18n import _
14 from .i18n import _
15 from . import (
15 from . import (
16 branchmap,
17 cacheutil,
16 cacheutil,
18 error,
17 error,
19 narrowspec,
18 narrowspec,
@@ -174,7 +173,7 b' def maybeperformlegacystreamclone(pullop'
174 repo._writerequirements()
173 repo._writerequirements()
175
174
176 if rbranchmap:
175 if rbranchmap:
177 branchmap.replacecache(repo, rbranchmap)
176 repo._branchcaches.replace(repo, rbranchmap)
178
177
179 repo.invalidate()
178 repo.invalidate()
180
179
General Comments 0
You need to be logged in to leave comments. Login now