diff 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
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgDataFile.java	Mon Aug 05 12:45:36 2013 +0200
+++ b/src/org/tmatesoft/hg/repo/HgDataFile.java	Mon Aug 05 17:42:10 2013 +0200
@@ -63,7 +63,12 @@
 	// slashes, unix-style?
 	// repo location agnostic, just to give info to user, not to access real storage
 	private final Path path;
-	private Metadata metadata; // get initialized on first access to file content.
+	/*
+	 * Get initialized on first access to file content.
+	 * We read metadata starting from rev 0 always, so that Metadata#lastRevisionRead()
+	 * shows the region of file history [0..lastRevisionRead] we know metadata for
+	 */
+	private Metadata metadata;
 	
 	/*package-local*/HgDataFile(HgRepository hgRepo, Path filePath, RevlogStream content) {
 		super(hgRepo, content, false);
@@ -477,12 +482,17 @@
 	}
 	
 	private void checkAndRecordMetadata(int localRev) throws HgRuntimeException {
+		int startRev;
 		if (metadata == null) {
 			metadata = new Metadata(getRepo());
+			startRev = 0; // read from the very beginning with one shot - likely isCopy(localRev-i) will be of interest, too
+		} else {
+			startRev = metadata.lastRevisionRead() + 1;
 		}
+		assert localRev >= startRev; // callers of this method ensure that metadata has been checked beforehand
 		// use MetadataInspector without delegate to process metadata only
 		RevlogStream.Inspector insp = new MetadataInspector(metadata, null);
-		super.content.iterate(localRev, localRev, true, insp);
+		super.content.iterate(startRev, localRev, true, insp);
 	}
 
 	private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector {
@@ -501,17 +511,16 @@
 
 		public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgRuntimeException {
 			try {
-				if (metadata.tryRead(revisionNumber, data)) {
-					// da is in prepared state (i.e. we consumed all bytes up to metadata end).
-					// However, it's not safe to assume delegate won't call da.reset() for some reason,
-					// and we need to ensure predictable result.
+				final boolean gotMetadata = metadata.tryRead(revisionNumber, data);
+				if (delegate != null) {
 					data.reset();
-					int offset = metadata.dataOffset(revisionNumber);
-					data = new FilterDataAccess(data, offset, data.length() - offset);
-				} else {
-					data.reset();
-				}
-				if (delegate != null) {
+					if (gotMetadata) {
+						// da is in prepared state (i.e. we consumed all bytes up to metadata end).
+						// However, it's not safe to assume delegate won't call da.reset() for some reason,
+						// and we need to ensure predictable result.
+						int offset = metadata.dataOffset(revisionNumber);
+						data = new FilterDataAccess(data, offset, data.length() - offset);
+					}
 					delegate.next(revisionNumber, actualLen, baseRevision, linkRevision, parent1Revision, parent2Revision, nodeid, data);
 				}
 			} catch (IOException ex) {