Mercurial > hg4j
diff src/org/tmatesoft/hg/internal/RevlogStream.java @ 158:b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Wed, 09 Mar 2011 13:16:37 +0100 |
parents | d5268ca7715b |
children | 71ddbf8603e8 |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/internal/RevlogStream.java Wed Mar 09 05:22:17 2011 +0100 +++ b/src/org/tmatesoft/hg/internal/RevlogStream.java Wed Mar 09 13:16:37 2011 +0100 @@ -26,6 +26,7 @@ import java.util.LinkedList; import java.util.List; +import org.tmatesoft.hg.core.HgBadStateException; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgRepository; @@ -77,7 +78,7 @@ revision = indexSize - 1; } try { - int recordOffset = inline ? (int) index.get(revision).offset : revision * REVLOGV1_RECORD_SIZE; + int recordOffset = inline ? index.get(revision).getIntOffset() : revision * REVLOGV1_RECORD_SIZE; daIndex.seek(recordOffset + 12); // 6+2+4 int actualLen = daIndex.readInt(); return actualLen; @@ -99,7 +100,7 @@ } DataAccess daIndex = getIndexStream(); try { - int recordOffset = inline ? (int) index.get(revision).offset : revision * REVLOGV1_RECORD_SIZE; + int recordOffset = inline ? index.get(revision).getIntOffset() : revision * REVLOGV1_RECORD_SIZE; daIndex.seek(recordOffset + 32); byte[] rv = new byte[20]; daIndex.readBytes(rv, 0, 20); @@ -122,7 +123,7 @@ } DataAccess daIndex = getIndexStream(); try { - int recordOffset = inline ? (int) index.get(revision).offset : revision * REVLOGV1_RECORD_SIZE; + int recordOffset = inline ? index.get(revision).getIntOffset() : revision * REVLOGV1_RECORD_SIZE; daIndex.seek(recordOffset + 20); int linkRev = daIndex.readInt(); return linkRev; @@ -208,11 +209,11 @@ i = start; } - daIndex.seek(inline ? index.get(i).offset : i * REVLOGV1_RECORD_SIZE); + daIndex.seek(inline ? index.get(i).getIntOffset() : i * REVLOGV1_RECORD_SIZE); for (; i <= end; i++ ) { if (inline && needData) { // inspector reading data (though FilterDataAccess) may have affected index position - daIndex.seek(index.get(i).offset); + daIndex.seek(index.get(i).getIntOffset()); } long l = daIndex.readLong(); // 0 @SuppressWarnings("unused") @@ -231,7 +232,7 @@ DataAccess userDataAccess = null; if (needData) { final byte firstByte; - long streamOffset = index.get(i).offset; + int streamOffset = index.get(i).getIntOffset(); DataAccess streamDataAccess; if (inline) { streamDataAccess = daIndex; @@ -240,9 +241,10 @@ streamDataAccess = daData; daData.seek(streamOffset); } + final boolean patchToPrevious = baseRevision != i; // XXX not sure if this is the right way to detect a patch firstByte = streamDataAccess.readByte(); if (firstByte == 0x78 /* 'x' */) { - userDataAccess = new InflaterDataAccess(streamDataAccess, streamOffset, compressedLen); + userDataAccess = new InflaterDataAccess(streamDataAccess, streamOffset, compressedLen, patchToPrevious ? -1 : actualLen); } else if (firstByte == 0x75 /* 'u' */) { userDataAccess = new FilterDataAccess(streamDataAccess, streamOffset+1, compressedLen-1); } else { @@ -251,7 +253,7 @@ userDataAccess = new FilterDataAccess(streamDataAccess, streamOffset, compressedLen); } // XXX - if (baseRevision != i) { // XXX not sure if this is the right way to detect a patch + if (patchToPrevious) { // this is a patch LinkedList<PatchRecord> patches = new LinkedList<PatchRecord>(); while (!userDataAccess.isEmpty()) { @@ -281,7 +283,7 @@ } } } catch (IOException ex) { - throw new IllegalStateException(ex); // FIXME need better handling + throw new HgBadStateException(ex); // FIXME need better handling } finally { daIndex.done(); if (daData != null) { @@ -345,14 +347,23 @@ // perhaps, package-local or protected, if anyone else from low-level needs them // XXX think over if we should keep offset in case of separate data file - we read the field anyway. Perhaps, distinct entry classes for Inline and non-inline indexes? private static class IndexEntry { - public final long offset; // for separate .i and .d - copy of index record entry, for inline index - actual offset of the record in the .i file (record entry + revision * record size)) + private final int/*long*/ offset; // for separate .i and .d - copy of index record entry, for inline index - actual offset of the record in the .i file (record entry + revision * record size)) //public final int length; // data past fixed record (need to decide whether including header size or not), and whether length is of compressed data or not public final int baseRevision; public IndexEntry(long o, int baseRev) { - offset = o; + offset = (int) o; + // Index file stores offsets as long, but since DataAccess doesn't support long length() and others yet, + // no reason to operate with long offsets + if (o != offset) { + throw new HgBadStateException("Data too big, offset didn't fit to sizeof(int)"); + } baseRevision = baseRev; } + + public int getIntOffset() { + return offset; + } } // mpatch.c : apply() @@ -360,7 +371,7 @@ public/*for HgBundle; until moved to better place*/static byte[] apply(DataAccess baseRevisionContent, int outcomeLen, List<PatchRecord> patch) throws IOException { int last = 0, destIndex = 0; if (outcomeLen == -1) { - outcomeLen = (int) baseRevisionContent.length(); + outcomeLen = baseRevisionContent.length(); for (PatchRecord pr : patch) { outcomeLen += pr.start - last + pr.len; last = pr.end;