comparison mercurial/revlog.py @ 8314:57a41c08feab

revlog: preread revlog .i file Smaller revlogs can be read with a single read, do it on open.
author Matt Mackall <mpm@selenic.com>
date Thu, 07 May 2009 19:39:45 -0500
parents b87a50b7125c
children c8493310ad9b
comparison
equal deleted inserted replaced
8313:b695392491e7 8314:57a41c08feab
28 REVLOGNG = 1 28 REVLOGNG = 1
29 REVLOGNGINLINEDATA = (1 << 16) 29 REVLOGNGINLINEDATA = (1 << 16)
30 REVLOG_DEFAULT_FLAGS = REVLOGNGINLINEDATA 30 REVLOG_DEFAULT_FLAGS = REVLOGNGINLINEDATA
31 REVLOG_DEFAULT_FORMAT = REVLOGNG 31 REVLOG_DEFAULT_FORMAT = REVLOGNG
32 REVLOG_DEFAULT_VERSION = REVLOG_DEFAULT_FORMAT | REVLOG_DEFAULT_FLAGS 32 REVLOG_DEFAULT_VERSION = REVLOG_DEFAULT_FORMAT | REVLOG_DEFAULT_FLAGS
33
34 _prereadsize = 1048576
33 35
34 RevlogError = error.RevlogError 36 RevlogError = error.RevlogError
35 LookupError = error.LookupError 37 LookupError = error.LookupError
36 38
37 def getoffset(q): 39 def getoffset(q):
313 315
314 class revlogoldio(object): 316 class revlogoldio(object):
315 def __init__(self): 317 def __init__(self):
316 self.size = struct.calcsize(indexformatv0) 318 self.size = struct.calcsize(indexformatv0)
317 319
318 def parseindex(self, fp, inline): 320 def parseindex(self, fp, data, inline):
319 s = self.size 321 s = self.size
320 index = [] 322 index = []
321 nodemap = {nullid: nullrev} 323 nodemap = {nullid: nullrev}
322 n = off = 0 324 n = off = 0
323 data = fp.read() 325 if len(data) < _prereadsize:
326 data += fp.read() # read the rest
324 l = len(data) 327 l = len(data)
325 while off + s <= l: 328 while off + s <= l:
326 cur = data[off:off + s] 329 cur = data[off:off + s]
327 off += s 330 off += s
328 e = _unpack(indexformatv0, cur) 331 e = _unpack(indexformatv0, cur)
356 359
357 class revlogio(object): 360 class revlogio(object):
358 def __init__(self): 361 def __init__(self):
359 self.size = struct.calcsize(indexformatng) 362 self.size = struct.calcsize(indexformatng)
360 363
361 def parseindex(self, fp, inline): 364 def parseindex(self, fp, data, inline):
362 try: 365 try:
363 size = util.fstat(fp).st_size 366 size = len(data)
367 if size == _prereadsize:
368 size = util.fstat(fp).st_size
364 except AttributeError: 369 except AttributeError:
365 size = 0 370 size = 0
366 371
367 if util.openhardlinks() and not inline and size > 1000000: 372 if util.openhardlinks() and not inline and size > _prereadsize:
368 # big index, let's parse it on demand 373 # big index, let's parse it on demand
369 parser = lazyparser(fp, size) 374 parser = lazyparser(fp, size)
370 index = lazyindex(parser) 375 index = lazyindex(parser)
371 nodemap = lazymap(parser) 376 nodemap = lazymap(parser)
372 e = list(index[0]) 377 e = list(index[0])
373 type = gettype(e[0]) 378 type = gettype(e[0])
374 e[0] = offset_type(0, type) 379 e[0] = offset_type(0, type)
375 index[0] = e 380 index[0] = e
376 return index, nodemap, None 381 return index, nodemap, None
377 382
378 data = fp.read()
379 # call the C implementation to parse the index data 383 # call the C implementation to parse the index data
380 index, nodemap, cache = parsers.parse_index(data, inline) 384 index, nodemap, cache = parsers.parse_index(data, inline)
381 return index, nodemap, cache 385 return index, nodemap, cache
382 386
383 def packentry(self, entry, node, version, rev): 387 def packentry(self, entry, node, version, rev):
430 if hasattr(opener, "defversion"): 434 if hasattr(opener, "defversion"):
431 v = opener.defversion 435 v = opener.defversion
432 if v & REVLOGNG: 436 if v & REVLOGNG:
433 v |= REVLOGNGINLINEDATA 437 v |= REVLOGNGINLINEDATA
434 438
435 i = "" 439 i = ''
436 try: 440 try:
437 f = self.opener(self.indexfile) 441 f = self.opener(self.indexfile)
438 i = f.read(4) 442 i = f.read(_prereadsize)
439 f.seek(0)
440 if len(i) > 0: 443 if len(i) > 0:
441 v = struct.unpack(versionformat, i)[0] 444 v = struct.unpack(versionformat, i[:4])[0]
442 except IOError, inst: 445 except IOError, inst:
443 if inst.errno != errno.ENOENT: 446 if inst.errno != errno.ENOENT:
444 raise 447 raise
445 448
446 self.version = v 449 self.version = v
460 self._io = revlogio() 463 self._io = revlogio()
461 if self.version == REVLOGV0: 464 if self.version == REVLOGV0:
462 self._io = revlogoldio() 465 self._io = revlogoldio()
463 if i: 466 if i:
464 try: 467 try:
465 d = self._io.parseindex(f, self._inline) 468 d = self._io.parseindex(f, i, self._inline)
466 except (ValueError, IndexError), e: 469 except (ValueError, IndexError), e:
467 raise RevlogError(_("index %s is corrupted") % (self.indexfile)) 470 raise RevlogError(_("index %s is corrupted") % (self.indexfile))
468 self.index, self.nodemap, self._chunkcache = d 471 self.index, self.nodemap, self._chunkcache = d
469 472
470 # add the magic null revision at -1 (if it hasn't been done already) 473 # add the magic null revision at -1 (if it hasn't been done already)