Mercurial > public > mercurial-scm > hg
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) |