changeset 606:5daa42067e7c

Avoid mmap files when only few bytes are to be read
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 07 May 2013 14:16:35 +0200
parents c56edf42be64
children 66f1cc23b906
files src/org/tmatesoft/hg/internal/DataAccessProvider.java src/org/tmatesoft/hg/internal/DirstateReader.java src/org/tmatesoft/hg/internal/RevlogStream.java src/org/tmatesoft/hg/repo/HgBundle.java
diffstat 4 files changed, 21 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/internal/DataAccessProvider.java	Mon May 06 20:28:21 2013 +0200
+++ b/src/org/tmatesoft/hg/internal/DataAccessProvider.java	Tue May 07 14:16:35 2013 +0200
@@ -84,14 +84,14 @@
 		return mapioBoundary == 0 ? Integer.MAX_VALUE : mapioBoundary;
 	}
 
-	public DataAccess createReader(File f) {
+	public DataAccess createReader(File f, boolean shortRead) {
 		if (!f.exists()) {
 			return new DataAccess();
 		}
 		try {
 			FileChannel fc = new FileInputStream(f).getChannel();
 			long flen = fc.size();
-			if (flen > mapioMagicBoundary) {
+			if (!shortRead && flen > mapioMagicBoundary) {
 				// TESTS: bufLen of 1024 was used to test MemMapFileAccess
 				return new MemoryMapFileAccess(fc, flen, mapioBufSize, context.getLog());
 			} else {
--- a/src/org/tmatesoft/hg/internal/DirstateReader.java	Mon May 06 20:28:21 2013 +0200
+++ b/src/org/tmatesoft/hg/internal/DirstateReader.java	Tue May 07 14:16:35 2013 +0200
@@ -66,7 +66,7 @@
 		if (dirstateFile == null || !dirstateFile.exists()) {
 			return;
 		}
-		DataAccess da = repo.getDataAccess().createReader(dirstateFile);
+		DataAccess da = repo.getDataAccess().createReader(dirstateFile, false);
 		try {
 			if (da.isEmpty()) {
 				return;
@@ -142,7 +142,7 @@
 		if (dirstateFile == null || !dirstateFile.exists()) {
 			return new Pair<Nodeid,Nodeid>(NULL, NULL);
 		}
-		DataAccess da = internalRepo.getDataAccess().createReader(dirstateFile);
+		DataAccess da = internalRepo.getDataAccess().createReader(dirstateFile, false);
 		try {
 			if (da.isEmpty()) {
 				return new Pair<Nodeid,Nodeid>(NULL, NULL);
--- a/src/org/tmatesoft/hg/internal/RevlogStream.java	Mon May 06 20:28:21 2013 +0200
+++ b/src/org/tmatesoft/hg/internal/RevlogStream.java	Tue May 07 14:16:35 2013 +0200
@@ -77,14 +77,18 @@
 		this.indexFile = indexFile;
 	}
 
-	/*package*/ DataAccess getIndexStream() {
-		// FIXME [1.1] must supply a hint that I'll need really few bytes of data (perhaps, at some offset) 
-		// to avoid mmap files when only few bytes are to be read (i.e. #dataLength())
-		return dataAccess.createReader(indexFile);
+	/**
+	 * @param shortRead pass <code>true</code> to indicate intention to read few revisions only (as opposed to reading most of/complete revlog)
+	 * @return never <code>null</code>, empty {@link DataAccess} if no stream is available
+	 */
+	/*package*/ DataAccess getIndexStream(boolean shortRead) {
+		// shortRead hint helps  to avoid mmap files when only 
+		// few bytes are to be read (i.e. #dataLength())
+		return dataAccess.createReader(indexFile, shortRead);
 	}
 
 	/*package*/ DataAccess getDataStream() {
-		return dataAccess.createReader(getDataFile());
+		return dataAccess.createReader(getDataFile(), false);
 	}
 	
 	/*package*/ DataSerializer getIndexStreamWriter() {
@@ -147,7 +151,7 @@
 		// XXX in fact, use of iterate() instead of this implementation may be quite reasonable.
 		//
 		revisionIndex = checkRevisionIndex(revisionIndex);
-		DataAccess daIndex = getIndexStream();
+		DataAccess daIndex = getIndexStream(true);
 		try {
 			int recordOffset = getIndexOffsetInt(revisionIndex);
 			daIndex.seek(recordOffset + 12); // 6+2+4
@@ -168,7 +172,7 @@
 	 */
 	public byte[] nodeid(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException {
 		revisionIndex = checkRevisionIndex(revisionIndex);
-		DataAccess daIndex = getIndexStream();
+		DataAccess daIndex = getIndexStream(true);
 		try {
 			int recordOffset = getIndexOffsetInt(revisionIndex);
 			daIndex.seek(recordOffset + 32);
@@ -190,7 +194,7 @@
 	 */
 	public int linkRevision(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException {
 		revisionIndex = checkRevisionIndex(revisionIndex);
-		DataAccess daIndex = getIndexStream();
+		DataAccess daIndex = getIndexStream(true);
 		try {
 			int recordOffset = getIndexOffsetInt(revisionIndex);
 			daIndex.seek(recordOffset + 20);
@@ -226,7 +230,7 @@
 	public int findRevisionIndex(Nodeid nodeid) throws HgInvalidControlFileException {
 		// XXX this one may be implemented with iterate() once there's mechanism to stop iterations
 		final int indexSize = revisionCount();
-		DataAccess daIndex = getIndexStream();
+		DataAccess daIndex = getIndexStream(false);
 		try {
 			byte[] nodeidBuf = new byte[20];
 			for (int i = 0; i < indexSize; i++) {
@@ -255,7 +259,7 @@
 		if (revisionCount() == 0) {
 			return 0;
 		}
-		DataAccess daIndex = getIndexStream();
+		DataAccess daIndex = getIndexStream(true);
 		int lastRev = revisionCount() - 1;
 		try {
 			int recordOffset = getIndexOffsetInt(lastRev);
@@ -421,7 +425,7 @@
 		if (outlineCached()) {
 			return;
 		}
-		DataAccess da = getIndexStream();
+		DataAccess da = getIndexStream(false);
 		try {
 			if (da.isEmpty()) {
 				// do not fail with exception if stream is empty, it's likely intentional
@@ -551,7 +555,7 @@
 		}
 		
 		public void start(int totalWork, CachedRevision cachedRevision) {
-			daIndex = getIndexStream();
+			daIndex = getIndexStream(totalWork <= 10);
 			if (needData && !inline) {
 				daData = getDataStream();
 			}
--- a/src/org/tmatesoft/hg/repo/HgBundle.java	Mon May 06 20:28:21 2013 +0200
+++ b/src/org/tmatesoft/hg/repo/HgBundle.java	Tue May 07 14:16:35 2013 +0200
@@ -60,7 +60,7 @@
 	}
 
 	private DataAccess getDataStream() throws IOException {
-		DataAccess da = accessProvider.createReader(bundleFile);
+		DataAccess da = accessProvider.createReader(bundleFile, false);
 		byte[] signature = new byte[6];
 		if (da.length() > 6) {
 			da.readBytes(signature, 0, 6);