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) {