Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 694:7efabe0cddcf
Speed up (a) file rename history to minimize file reads; (b) file.isCopy(int) to read metadata for few revisions at once (use pattern assumes earlier revisions are likely to be queried, too); (c) HgIgnore.isIgnored by caching matched initial fragments (to substitute more expensive Matcher.matches with cheaper HashMap.contains)
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Mon, 05 Aug 2013 17:42:10 +0200 |
parents | 5050ee565bd1 |
children |
comparison
equal
deleted
inserted
replaced
693:32b0d19e8aba | 694:7efabe0cddcf |
---|---|
61 | 61 |
62 // absolute from repo root? | 62 // absolute from repo root? |
63 // slashes, unix-style? | 63 // slashes, unix-style? |
64 // repo location agnostic, just to give info to user, not to access real storage | 64 // repo location agnostic, just to give info to user, not to access real storage |
65 private final Path path; | 65 private final Path path; |
66 private Metadata metadata; // get initialized on first access to file content. | 66 /* |
67 * Get initialized on first access to file content. | |
68 * We read metadata starting from rev 0 always, so that Metadata#lastRevisionRead() | |
69 * shows the region of file history [0..lastRevisionRead] we know metadata for | |
70 */ | |
71 private Metadata metadata; | |
67 | 72 |
68 /*package-local*/HgDataFile(HgRepository hgRepo, Path filePath, RevlogStream content) { | 73 /*package-local*/HgDataFile(HgRepository hgRepo, Path filePath, RevlogStream content) { |
69 super(hgRepo, content, false); | 74 super(hgRepo, content, false); |
70 path = filePath; | 75 path = filePath; |
71 } | 76 } |
475 sb.append(')'); | 480 sb.append(')'); |
476 return sb.toString(); | 481 return sb.toString(); |
477 } | 482 } |
478 | 483 |
479 private void checkAndRecordMetadata(int localRev) throws HgRuntimeException { | 484 private void checkAndRecordMetadata(int localRev) throws HgRuntimeException { |
485 int startRev; | |
480 if (metadata == null) { | 486 if (metadata == null) { |
481 metadata = new Metadata(getRepo()); | 487 metadata = new Metadata(getRepo()); |
482 } | 488 startRev = 0; // read from the very beginning with one shot - likely isCopy(localRev-i) will be of interest, too |
489 } else { | |
490 startRev = metadata.lastRevisionRead() + 1; | |
491 } | |
492 assert localRev >= startRev; // callers of this method ensure that metadata has been checked beforehand | |
483 // use MetadataInspector without delegate to process metadata only | 493 // use MetadataInspector without delegate to process metadata only |
484 RevlogStream.Inspector insp = new MetadataInspector(metadata, null); | 494 RevlogStream.Inspector insp = new MetadataInspector(metadata, null); |
485 super.content.iterate(localRev, localRev, true, insp); | 495 super.content.iterate(startRev, localRev, true, insp); |
486 } | 496 } |
487 | 497 |
488 private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector { | 498 private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector { |
489 private final Metadata metadata; | 499 private final Metadata metadata; |
490 private final RevlogStream.Inspector delegate; | 500 private final RevlogStream.Inspector delegate; |
499 setCancelSupport(CancelSupport.Factory.get(chain)); | 509 setCancelSupport(CancelSupport.Factory.get(chain)); |
500 } | 510 } |
501 | 511 |
502 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgRuntimeException { | 512 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgRuntimeException { |
503 try { | 513 try { |
504 if (metadata.tryRead(revisionNumber, data)) { | 514 final boolean gotMetadata = metadata.tryRead(revisionNumber, data); |
505 // da is in prepared state (i.e. we consumed all bytes up to metadata end). | 515 if (delegate != null) { |
506 // However, it's not safe to assume delegate won't call da.reset() for some reason, | |
507 // and we need to ensure predictable result. | |
508 data.reset(); | 516 data.reset(); |
509 int offset = metadata.dataOffset(revisionNumber); | 517 if (gotMetadata) { |
510 data = new FilterDataAccess(data, offset, data.length() - offset); | 518 // da is in prepared state (i.e. we consumed all bytes up to metadata end). |
511 } else { | 519 // However, it's not safe to assume delegate won't call da.reset() for some reason, |
512 data.reset(); | 520 // and we need to ensure predictable result. |
513 } | 521 int offset = metadata.dataOffset(revisionNumber); |
514 if (delegate != null) { | 522 data = new FilterDataAccess(data, offset, data.length() - offset); |
523 } | |
515 delegate.next(revisionNumber, actualLen, baseRevision, linkRevision, parent1Revision, parent2Revision, nodeid, data); | 524 delegate.next(revisionNumber, actualLen, baseRevision, linkRevision, parent1Revision, parent2Revision, nodeid, data); |
516 } | 525 } |
517 } catch (IOException ex) { | 526 } catch (IOException ex) { |
518 recordFailure(ex); | 527 recordFailure(ex); |
519 } catch (HgInvalidControlFileException ex) { | 528 } catch (HgInvalidControlFileException ex) { |