diff src/org/tmatesoft/hg/internal/RevlogStream.java @ 354:5f9073eabf06

Propagate errors with exceptions up to a end client
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 01 Dec 2011 05:21:40 +0100
parents 8da7ade36c57
children 189dc6dc1c3e
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/internal/RevlogStream.java	Thu Dec 01 03:05:28 2011 +0100
+++ b/src/org/tmatesoft/hg/internal/RevlogStream.java	Thu Dec 01 05:21:40 2011 +0100
@@ -24,6 +24,7 @@
 import java.util.zip.Inflater;
 
 import org.tmatesoft.hg.core.HgBadStateException;
+import org.tmatesoft.hg.core.HgInvalidControlFileException;
 import org.tmatesoft.hg.core.HgInvalidRevisionException;
 import org.tmatesoft.hg.core.Nodeid;
 import org.tmatesoft.hg.repo.HgInternals;
@@ -80,50 +81,43 @@
 	}
 	
 	/**
-	 * @throws HgBadStateException if internal read operation failed
+	 * @throws HgInvalidControlFileException if attempt to read index file failed
+	 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog
 	 */
-	public int dataLength(int revision) {
+	public int dataLength(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException {
 		// XXX in fact, use of iterate() instead of this implementation may be quite reasonable.
 		//
-		final int indexSize = revisionCount();
+		revisionIndex = checkRevisionIndex(revisionIndex);
 		DataAccess daIndex = getIndexStream();
-		if (revision == TIP) {
-			revision = indexSize - 1;
-		}
 		try {
-			int recordOffset = getIndexOffsetInt(revision);
+			int recordOffset = getIndexOffsetInt(revisionIndex);
 			daIndex.seek(recordOffset + 12); // 6+2+4
 			int actualLen = daIndex.readInt();
 			return actualLen; 
 		} catch (IOException ex) {
-			ex.printStackTrace(); // log error. FIXME better handling
-			throw new HgBadStateException(ex);
+			throw new HgInvalidControlFileException(null, ex, indexFile);
 		} finally {
 			daIndex.done();
 		}
 	}
 	
 	/**
-	 * @throws HgBadStateException if internal read operation failed
+	 * Read nodeid at given index
+	 * 
+	 * @throws HgInvalidControlFileException if attempt to read index file failed
+	 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog
 	 */
-	public byte[] nodeid(int revision) throws HgInvalidRevisionException {
-		final int indexSize = revisionCount();
-		if (revision == TIP) {
-			revision = indexSize - 1;
-		}
-		if (revision < 0 || revision >= indexSize) {
-			throw new HgInvalidRevisionException(revision).setRevisionIndex(revision, 0, indexSize);
-		}
+	public byte[] nodeid(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException {
+		revisionIndex = checkRevisionIndex(revisionIndex);
 		DataAccess daIndex = getIndexStream();
 		try {
-			int recordOffset = getIndexOffsetInt(revision);
+			int recordOffset = getIndexOffsetInt(revisionIndex);
 			daIndex.seek(recordOffset + 32);
 			byte[] rv = new byte[20];
 			daIndex.readBytes(rv, 0, 20);
 			return rv;
 		} catch (IOException ex) {
-			ex.printStackTrace();
-			throw new HgBadStateException();
+			throw new HgInvalidControlFileException(null, ex, indexFile);
 		} finally {
 			daIndex.done();
 		}
@@ -131,25 +125,20 @@
 
 	/**
 	 * Get link field from the index record.
-	 * @throws HgBadStateException if internal read operation failed
+	 * 
+	 * @throws HgInvalidControlFileException if attempt to read index file failed
+	 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog
 	 */
-	public int linkRevision(int revision) {
-		final int last = revisionCount() - 1;
-		if (revision == TIP) {
-			revision = last;
-		}
-		if (revision < 0 || revision > last) {
-			throw new IllegalArgumentException(Integer.toString(revision));
-		}
+	public int linkRevision(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException {
+		revisionIndex = checkRevisionIndex(revisionIndex);
 		DataAccess daIndex = getIndexStream();
 		try {
-			int recordOffset = getIndexOffsetInt(revision);
+			int recordOffset = getIndexOffsetInt(revisionIndex);
 			daIndex.seek(recordOffset + 20);
 			int linkRev = daIndex.readInt();
 			return linkRev;
 		} catch (IOException ex) {
-			ex.printStackTrace();
-			throw new HgBadStateException();
+			throw new HgInvalidControlFileException(null, ex, indexFile);
 		} finally {
 			daIndex.done();
 		}
@@ -161,8 +150,9 @@
 	// Unlike its counterpart, {@link Revlog#getLocalRevisionNumber()}, doesn't fail with exception if node not found,
 	/**
 	 * @return integer in [0..revisionCount()) or {@link HgRepository#BAD_REVISION} if not found
+	 * @throws HgInvalidControlFileException if attempt to read index file failed
 	 */
-	public int findLocalRevisionNumber(Nodeid nodeid) {
+	public int findLocalRevisionNumber(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();
@@ -179,8 +169,7 @@
 				daIndex.skip(inline ? 12 + compressedLen : 12);
 			}
 		} catch (IOException ex) {
-			ex.printStackTrace(); // log error. FIXME better handling. Perhaps, shall return BAD_REVISION here as well?
-			throw new IllegalStateException(ex);
+			throw new HgInvalidControlFileException("Failed", ex, indexFile).setRevision(nodeid);
 		} finally {
 			daIndex.done();
 		}
@@ -267,10 +256,23 @@
 	}
 
 	/**
+	 * @param revisionIndex shall be valid index, [0..baseRevisions.length-1]. 
+	 * It's advised to use {@link #checkRevisionIndex(int)} to ensure argument is correct. 
 	 * @return  offset of the revision's record in the index (.i) stream
 	 */
-	private int getIndexOffsetInt(int revision) {
-		return inline ? indexRecordOffset[revision] : revision * REVLOGV1_RECORD_SIZE;
+	private int getIndexOffsetInt(int revisionIndex) {
+		return inline ? indexRecordOffset[revisionIndex] : revisionIndex * REVLOGV1_RECORD_SIZE;
+	}
+	
+	private int checkRevisionIndex(int revisionIndex) throws HgInvalidRevisionException {
+		final int last = revisionCount() - 1;
+		if (revisionIndex == TIP) {
+			revisionIndex = last;
+		}
+		if (revisionIndex < 0 || revisionIndex > last) {
+			throw new HgInvalidRevisionException(revisionIndex).setRevisionIndex(revisionIndex, 0, last);
+		}
+		return revisionIndex;
 	}
 
 	private void initOutline() {