comparison mercurial/revlog.py @ 13275:68da048b4c88

revlog: incrementally build node cache with linear searches This avoids needing to prime the cache for operations like verify which visit most or all of the index.
author Matt Mackall <mpm@selenic.com>
date Tue, 18 Jan 2011 15:55:46 -0600
parents fff12b3d953a
children ba6a63339f7c
comparison
equal deleted inserted replaced
13274:57d433f632b7 13275:68da048b4c88
174 self.size = struct.calcsize(indexformatng) 174 self.size = struct.calcsize(indexformatng)
175 175
176 def parseindex(self, data, inline): 176 def parseindex(self, data, inline):
177 # call the C implementation to parse the index data 177 # call the C implementation to parse the index data
178 index, cache = parsers.parse_index2(data, inline) 178 index, cache = parsers.parse_index2(data, inline)
179 nodemap = None 179 return index, None, cache
180 if not data:
181 nodemap = {nullid: nullrev}
182 return index, nodemap, cache
183 180
184 def packentry(self, entry, node, version, rev): 181 def packentry(self, entry, node, version, rev):
185 p = _pack(indexformatng, *entry) 182 p = _pack(indexformatng, *entry)
186 if rev == 0: 183 if rev == 0:
187 p = _pack(versionformat, version) + p[4:] 184 p = _pack(versionformat, version) + p[4:]
226 self._chunkcache = (0, '') 223 self._chunkcache = (0, '')
227 self.index = [] 224 self.index = []
228 self._shallowroot = shallowroot 225 self._shallowroot = shallowroot
229 self._parentdelta = 0 226 self._parentdelta = 0
230 self._pcache = {} 227 self._pcache = {}
228 self._nodecache = {nullid: nullrev}
229 self._nodepos = None
231 230
232 v = REVLOG_DEFAULT_VERSION 231 v = REVLOG_DEFAULT_VERSION
233 if hasattr(opener, 'options') and 'defversion' in opener.options: 232 if hasattr(opener, 'options') and 'defversion' in opener.options:
234 v = opener.options['defversion'] 233 v = opener.options['defversion']
235 if v & REVLOGNG: 234 if v & REVLOGNG:
272 d = self._io.parseindex(i, self._inline) 271 d = self._io.parseindex(i, self._inline)
273 except (ValueError, IndexError): 272 except (ValueError, IndexError):
274 raise RevlogError(_("index %s is corrupted") % (self.indexfile)) 273 raise RevlogError(_("index %s is corrupted") % (self.indexfile))
275 self.index, nodemap, self._chunkcache = d 274 self.index, nodemap, self._chunkcache = d
276 if nodemap is not None: 275 if nodemap is not None:
277 self.nodemap = nodemap 276 self.nodemap = self._nodecache = nodemap
278 self.rev = self._revmap
279 if not self._chunkcache: 277 if not self._chunkcache:
280 self._chunkclear() 278 self._chunkclear()
281
282 @util.propertycache
283 def nodemap(self):
284 n = {nullid: nullrev}
285 i = self.index
286 for r in xrange(len(i) - 1):
287 n[i[r][7]] = r
288 self.rev = self._revmap
289 return n
290 279
291 def tip(self): 280 def tip(self):
292 return self.node(len(self.index) - 2) 281 return self.node(len(self.index) - 2)
293 def __len__(self): 282 def __len__(self):
294 return len(self.index) - 1 283 return len(self.index) - 1
295 def __iter__(self): 284 def __iter__(self):
296 for i in xrange(len(self)): 285 for i in xrange(len(self)):
297 yield i 286 yield i
298 def _revmap(self, node): 287
288 @util.propertycache
289 def nodemap(self):
290 n = self.rev(self.node(0))
291 return self._nodecache
292
293 def rev(self, node):
299 try: 294 try:
300 return self.nodemap[node] 295 return self._nodecache[node]
301 except KeyError: 296 except KeyError:
297 n = self._nodecache
298 if node in n:
299 return n[node]
300 i = self.index
301 p = self._nodepos
302 if p is None:
303 p = len(i) - 2
304 for r in xrange(p, -1, -1):
305 v = i[r][7]
306 n[v] = r
307 if v == node:
308 self._nodepos = r - 1
309 return r
302 raise LookupError(node, self.indexfile, _('no node')) 310 raise LookupError(node, self.indexfile, _('no node'))
303 311
304 def rev(self, node):
305 if node == nullid:
306 return nullrev
307 i = self.index
308 for r in xrange(len(i) - 2, -1, -1):
309 if i[r][7] == node:
310 return r
311 raise LookupError(node, self.indexfile, _('no node'))
312 def node(self, rev): 312 def node(self, rev):
313 return self.index[rev][7] 313 return self.index[rev][7]
314 def linkrev(self, rev): 314 def linkrev(self, rev):
315 return self.index[rev][4] 315 return self.index[rev][4]
316 def parents(self, node): 316 def parents(self, node):