Sometimes we hit EOFException while reading from a 'DIRC' file with the new DirCache API. This was caused by BufferedInputStream.skip skipping only part of the range we asked it to skip if the range we asked it to skip spanned over the end of the current buffer block. Two skip requests are necessary in this case: one to force the stream to skip to the end of the buffer, and another to skip over data in the source stream before reading the next buffer block into memory. NB.skipFully handles this by abstracting the necessary loop into a utility function, much like NB.readFully handles the necessary read loop to ensure we read a full block of data. DirCacheEntry and DirCache both need to use this routine to skip over the parts of the DIRC file they do not wish to read. Signed-off-by: Shawn O. Pearce <spearce@xxxxxxxxxxx> --- This actually fixes the bug EOFException bug identified by John Franey. .../src/org/spearce/jgit/dircache/DirCache.java | 2 +- .../org/spearce/jgit/dircache/DirCacheEntry.java | 2 +- org.spearce.jgit/src/org/spearce/jgit/util/NB.java | 27 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCache.java b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCache.java index 995942c..76657c4 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCache.java +++ b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCache.java @@ -370,7 +370,7 @@ private void readFrom(final FileInputStream inStream) throws IOException, // a performance optimization. Since we do not // understand it, we can safely skip past it. // - in.skip(NB.decodeInt32(hdr, 4)); + NB.skipFully(in, NB.decodeUInt32(hdr, 4)); } else { // The extension is not an optimization and is // _required_ to understand this index format. diff --git a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java index bcf5596..011bc16 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java +++ b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java @@ -116,7 +116,7 @@ DirCacheEntry(final byte[] sharedInfo, final int infoAt, final int actLen = INFO_LEN + pathLen; final int expLen = (actLen + 8) & ~7; if (actLen != expLen) - in.skip(expLen - actLen); + NB.skipFully(in, expLen - actLen); } /** diff --git a/org.spearce.jgit/src/org/spearce/jgit/util/NB.java b/org.spearce.jgit/src/org/spearce/jgit/util/NB.java index fa13354..759caf5 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/util/NB.java +++ b/org.spearce.jgit/src/org/spearce/jgit/util/NB.java @@ -71,6 +71,33 @@ public static void readFully(final InputStream fd, final byte[] dst, } /** + * Skip an entire region of an input stream. + * <p> + * The input stream's position is moved forward by the number of requested + * bytes, discarding them from the input. This method does not return until + * the exact number of bytes requested has been skipped. + * + * @param fd + * the stream to skip bytes from. + * @param toSkip + * total number of bytes to be discarded. Must be >= 0. + * @throws EOFException + * the stream ended before the requested number of bytes were + * skipped. + * @throws IOException + * there was an error reading from the stream. + */ + public static void skipFully(final InputStream fd, long toSkip) + throws IOException { + while (toSkip > 0) { + final long r = fd.skip(toSkip); + if (r <= 0) + throw new EOFException("Short skip of block"); + toSkip -= r; + } + } + + /** * Compare a 32 bit unsigned integer stored in a 32 bit signed integer. * <p> * This function performs an unsigned compare operation, even though Java -- 1.6.0.87.g2858d -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html