summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java85
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java32
3 files changed, 52 insertions, 70 deletions
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
index 6b746e3193..731b4caa83 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
@@ -64,7 +64,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.util.IO;
/**
* Dumps a file over HTTP GET (or its information via HEAD).
@@ -122,7 +121,8 @@ final class FileSender {
String getTailChecksum() throws IOException {
final int n = 20;
final byte[] buf = new byte[n];
- IO.readFully(source.getChannel(), fileLen - n, buf, 0, n);
+ source.seek(fileLen - n);
+ source.readFully(buf, 0, n);
return ObjectId.fromRaw(buf).getName();
}
@@ -140,6 +140,7 @@ final class FileSender {
final OutputStream out = rsp.getOutputStream();
try {
final byte[] buf = new byte[4096];
+ source.seek(pos);
while (pos < end) {
final int r = (int) Math.min(buf.length, end - pos);
final int n = source.read(buf, 0, r);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java
index 8f4e691630..829832e6a5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java
@@ -65,7 +65,6 @@ import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.PackInvalidException;
import org.eclipse.jgit.errors.PackMismatchException;
-import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.NB;
import org.eclipse.jgit.util.RawParseUtils;
@@ -90,6 +89,9 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
private RandomAccessFile fd;
+ /** Serializes reads performed against {@link #fd}. */
+ private final Object readLock = new Object();
+
long length;
private int activeWindows;
@@ -364,9 +366,11 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
try {
if (invalid)
throw new PackInvalidException(packFile);
- fd = new RandomAccessFile(packFile, "r");
- length = fd.length();
- onOpenPack();
+ synchronized (readLock) {
+ fd = new RandomAccessFile(packFile, "r");
+ length = fd.length();
+ onOpenPack();
+ }
} catch (IOException ioe) {
openFail();
throw ioe;
@@ -387,53 +391,61 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
}
private void doClose() {
- if (fd != null) {
- try {
- fd.close();
- } catch (IOException err) {
- // Ignore a close event. We had it open only for reading.
- // There should not be errors related to network buffers
- // not flushed, etc.
+ synchronized (readLock) {
+ if (fd != null) {
+ try {
+ fd.close();
+ } catch (IOException err) {
+ // Ignore a close event. We had it open only for reading.
+ // There should not be errors related to network buffers
+ // not flushed, etc.
+ }
+ fd = null;
}
- fd = null;
}
}
ByteArrayWindow read(final long pos, int size) throws IOException {
- if (length < pos + size)
- size = (int) (length - pos);
- final byte[] buf = new byte[size];
- IO.readFully(fd.getChannel(), pos, buf, 0, size);
- return new ByteArrayWindow(this, pos, buf);
+ synchronized (readLock) {
+ if (length < pos + size)
+ size = (int) (length - pos);
+ final byte[] buf = new byte[size];
+ fd.seek(pos);
+ fd.readFully(buf, 0, size);
+ return new ByteArrayWindow(this, pos, buf);
+ }
}
ByteWindow mmap(final long pos, int size) throws IOException {
- if (length < pos + size)
- size = (int) (length - pos);
+ synchronized (readLock) {
+ if (length < pos + size)
+ size = (int) (length - pos);
- MappedByteBuffer map;
- try {
- map = fd.getChannel().map(MapMode.READ_ONLY, pos, size);
- } catch (IOException ioe1) {
- // The most likely reason this failed is the JVM has run out
- // of virtual memory. We need to discard quickly, and try to
- // force the GC to finalize and release any existing mappings.
- //
- System.gc();
- System.runFinalization();
- map = fd.getChannel().map(MapMode.READ_ONLY, pos, size);
- }
+ MappedByteBuffer map;
+ try {
+ map = fd.getChannel().map(MapMode.READ_ONLY, pos, size);
+ } catch (IOException ioe1) {
+ // The most likely reason this failed is the JVM has run out
+ // of virtual memory. We need to discard quickly, and try to
+ // force the GC to finalize and release any existing mappings.
+ //
+ System.gc();
+ System.runFinalization();
+ map = fd.getChannel().map(MapMode.READ_ONLY, pos, size);
+ }
- if (map.hasArray())
- return new ByteArrayWindow(this, pos, map.array());
- return new ByteBufferWindow(this, pos, map);
+ if (map.hasArray())
+ return new ByteArrayWindow(this, pos, map.array());
+ return new ByteBufferWindow(this, pos, map);
+ }
}
private void onOpenPack() throws IOException {
final PackIndex idx = idx();
final byte[] buf = new byte[20];
- IO.readFully(fd.getChannel(), 0, buf, 0, 12);
+ fd.seek(0);
+ fd.readFully(buf, 0, 12);
if (RawParseUtils.match(buf, 0, Constants.PACK_SIGNATURE) != 4)
throw new IOException(JGitText.get().notAPACKFile);
final long vers = NB.decodeUInt32(buf, 4);
@@ -445,7 +457,8 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
throw new PackMismatchException(MessageFormat.format(
JGitText.get().packObjectCountMismatch, packCnt, idx.getObjectCount(), getPackFile()));
- IO.readFully(fd.getChannel(), length - 20, buf, 0, 20);
+ fd.seek(length - 20);
+ fd.read(buf, 0, 20);
if (!Arrays.equals(buf, packChecksum))
throw new PackMismatchException(MessageFormat.format(
JGitText.get().packObjectCountMismatch
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java
index 1778654203..1f2042d4c2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java
@@ -51,8 +51,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
import java.text.MessageFormat;
import org.eclipse.jgit.JGitText;
@@ -139,36 +137,6 @@ public class IO {
}
/**
- * Read the entire byte array into memory, or throw an exception.
- *
- * @param fd
- * file to read the data from.
- * @param pos
- * position to read from the file at.
- * @param dst
- * buffer that must be fully populated, [off, off+len).
- * @param off
- * position within the buffer to start writing to.
- * @param len
- * number of bytes that must be read.
- * @throws EOFException
- * the stream ended before dst was fully populated.
- * @throws IOException
- * there was an error reading from the stream.
- */
- public static void readFully(final FileChannel fd, long pos,
- final byte[] dst, int off, int len) throws IOException {
- while (len > 0) {
- final int r = fd.read(ByteBuffer.wrap(dst, off, len), pos);
- if (r <= 0)
- throw new EOFException(JGitText.get().shortReadOfBlock);
- pos += r;
- off += r;
- len -= r;
- }
- }
-
- /**
* Skip an entire region of an input stream.
* <p>
* The input stream's position is moved forward by the number of requested