From 5ef1605f0a2afc0baed14bad60a5b44450ba7fbc Mon Sep 17 00:00:00 2001
From: "Shawn O. Pearce"
Date: Sun, 18 May 2008 16:56:29 -0400
Subject: [PATCH] Refactor WindowCache to allow dynamic changes in
configuration
We want to allow applications to alter the WindowCache configuration
on the fly, such as in IDEs when the user changes our parameters and
expects the IDE to respond immediately to the modification.
This means we cannot safely access our window size data from outside
of WindowCache, as the ids for windows can change when the size of a
window is modified by the caller. Instead we must work with the full
file position anytime we want data, which forces us into using a 64
bit value where we had been using only a 32 bit window id.
Signed-off-by: Shawn O. Pearce
---
.../src/org/spearce/jgit/lib/ByteArrayWindow.java | 9 +-
.../src/org/spearce/jgit/lib/ByteBufferWindow.java | 5 +-
.../src/org/spearce/jgit/lib/ByteWindow.java | 80 ++++++++++++-
.../src/org/spearce/jgit/lib/WindowCache.java | 133 +++++++++++++++------
.../src/org/spearce/jgit/lib/WindowCursor.java | 48 ++++----
.../src/org/spearce/jgit/lib/WindowedFile.java | 48 ++------
6 files changed, 218 insertions(+), 105 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ByteArrayWindow.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ByteArrayWindow.java
index aa2797d6..a9e8dbcf 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ByteArrayWindow.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ByteArrayWindow.java
@@ -28,14 +28,17 @@ final class ByteArrayWindow extends ByteWindow {
*
* @param o
* the WindowedFile providing data access
+ * @param p
+ * the file offset.
* @param d
* an id provided by the WindowedFile. See
- * {@link WindowCache#get(WindowCursor, WindowedFile, int)}.
+ * {@link WindowCache#get(WindowCursor, WindowedFile, long)}.
* @param b
* byte array for storage
*/
- ByteArrayWindow(final WindowedFile o, final int d, final byte[] b) {
- super(o, d, b, b.length);
+ ByteArrayWindow(final WindowedFile o, final long p, final int d,
+ final byte[] b) {
+ super(o, p, d, b, b.length);
}
int copy(final byte[] array, final int p, final byte[] b, final int o, int n) {
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ByteBufferWindow.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ByteBufferWindow.java
index 40f85430..a2273f10 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ByteBufferWindow.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ByteBufferWindow.java
@@ -32,12 +32,13 @@ final class ByteBufferWindow extends ByteWindow {
* @See ByteWindow
*
* @param o The WindowedFile
+ * @param p the file offset.
* @param d Window id
* @param b ByteBuffer storage
*/
- ByteBufferWindow(final WindowedFile o, final int d,
+ ByteBufferWindow(final WindowedFile o, final long p, final int d,
final ByteBuffer b) {
- super(o, d, b, b.capacity());
+ super(o, p, d, b, b.capacity());
}
final int copy(final ByteBuffer buffer, final int p, final byte[] b,
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ByteWindow.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ByteWindow.java
index 9d098deb..abd93517 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ByteWindow.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ByteWindow.java
@@ -30,7 +30,8 @@ import java.util.zip.Inflater;
* bytes from a window is very inexpensive.
*
*
- * @param type of object reference used to manage the window data.
+ * @param
+ * type of object reference used to manage the window data.
*/
abstract class ByteWindow extends SoftReference {
final WindowedFile provider;
@@ -41,25 +42,61 @@ abstract class ByteWindow extends SoftReference {
int lastAccessed;
+ final long start;
+
+ final long end;
+
/**
* Constructor for ByteWindow.
*
* @param o
* the WindowedFile providing data access
+ * @param pos
+ * the position in the file the data comes from.
* @param d
* an id provided by the WindowedFile. See
- * {@link WindowCache#get(WindowCursor, WindowedFile, int)}.
+ * {@link WindowCache#get(WindowCursor, WindowedFile, long)}.
* @param ref
* the object value required to perform data access.
* @param sz
* the total number of bytes in this window.
*/
@SuppressWarnings("unchecked")
- ByteWindow(final WindowedFile o, final int d, final T ref, final int sz) {
- super(ref, (ReferenceQueue)WindowCache.clearedWindowQueue);
+ ByteWindow(final WindowedFile o, final long pos, final int d, final T ref,
+ final int sz) {
+ super(ref, (ReferenceQueue) WindowCache.clearedWindowQueue);
provider = o;
size = sz;
id = d;
+ start = pos;
+ end = start + size;
+ }
+
+ final boolean contains(final WindowedFile neededFile, final long neededPos) {
+ return provider == neededFile && start <= neededPos && neededPos < end;
+ }
+
+ /**
+ * Copy bytes from the window to a caller supplied buffer.
+ *
+ * @param ref
+ * the object value required to perform data access.
+ * @param pos
+ * offset within the file to start copying from.
+ * @param dstbuf
+ * destination buffer to copy into.
+ * @param dstoff
+ * offset within dstbuf to start copying into.
+ * @param cnt
+ * number of bytes to copy. This value may exceed the number of
+ * bytes remaining in the window starting at offset
+ * pos.
+ * @return number of bytes actually copied; this may be less than
+ * cnt if cnt exceeded the number of
+ * bytes available.
+ */
+ final int copy(T ref, long pos, byte[] dstbuf, int dstoff, int cnt) {
+ return copy(ref, (int) (pos - start), dstbuf, dstoff, cnt);
}
/**
@@ -106,8 +143,39 @@ abstract class ByteWindow extends SoftReference {
* another window's data must still be supplied as input to finish
* decompression.
* @throws DataFormatException
- * the inflater encountered an invalid chunk of data. Data stream
- * corruption is likely.
+ * the inflater encountered an invalid chunk of data. Data
+ * stream corruption is likely.
+ */
+ final int inflate(T ref, long pos, byte[] dstbuf, int dstoff, Inflater inf)
+ throws DataFormatException {
+ return inflate(ref, (int) (pos - start), dstbuf, dstoff, inf);
+ }
+
+ /**
+ * Pump bytes into the supplied inflater as input.
+ *
+ * @param ref
+ * the object value required to perform data access.
+ * @param pos
+ * offset within the window to start supplying input from.
+ * @param dstbuf
+ * destination buffer the inflater should output decompressed
+ * data to.
+ * @param dstoff
+ * current offset within dstbuf to inflate into.
+ * @param inf
+ * the inflater to feed input to. The caller is responsible for
+ * initializing the inflater as multiple windows may need to
+ * supply data to the same inflater to completely decompress
+ * something.
+ * @return updated dstoff based on the number of bytes
+ * successfully copied into dstbuf by
+ * inf. If the inflater is not yet finished then
+ * another window's data must still be supplied as input to finish
+ * decompression.
+ * @throws DataFormatException
+ * the inflater encountered an invalid chunk of data. Data
+ * stream corruption is likely.
*/
abstract int inflate(T ref, int pos, byte[] dstbuf, int dstoff, Inflater inf)
throws DataFormatException;
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
index fbb07849..1377c727 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/WindowCache.java
@@ -36,19 +36,17 @@ public class WindowCache {
return Integer.numberOfTrailingZeros(newSize);
}
- private static final int maxByteCount;
+ private static int maxByteCount;
- static final int sz;
+ private static int windowSize;
- static final int szb;
+ private static int windowSizeShift;
- static final int szm;
-
- static final boolean mmap;
+ static boolean mmap;
static final ReferenceQueue> clearedWindowQueue;
- private static final ByteWindow[] windows;
+ private static ByteWindow[] windows;
private static int openWindowCount;
@@ -58,11 +56,10 @@ public class WindowCache {
static {
maxByteCount = 10 * MB;
- szb = bits(8 * KB);
- sz = 1 << szb;
- szm = (1 << szb) - 1;
+ windowSizeShift = bits(8 * KB);
+ windowSize = 1 << windowSizeShift;
mmap = false;
- windows = new ByteWindow[maxByteCount / sz];
+ windows = new ByteWindow[maxByteCount / windowSize];
clearedWindowQueue = new ReferenceQueue