Browse Source

Allow TemporaryBuffer.Heap to allocate smaller than 8 KiB

If the heap limit was set to something smaller than 8 KiB, we were
still allocating the full 8 KiB block size, and accepting up to
the amount we allocated by.  Instead actually put a hard cap on
the limit.

Change-Id: Id1da26fde2102e76510b1da4ede8493928a981cc
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
stable-0.9
Shawn O. Pearce 15 years ago
parent
commit
97311cd3e0
  1. 14
      org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java
  2. 33
      org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java

14
org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java

@ -255,7 +255,7 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
}
public void testUsingHiddenDeltaBaseFails() throws Exception {
final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
packHeader(pack, 1);
pack.write((Constants.OBJ_REF_DELTA) << 4 | 4);
b.copyRawTo(pack);
@ -297,13 +297,13 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
// But don't include it in the pack.
//
final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
packHeader(pack, 2);
copy(pack, src.open(N));
copy(pack,src.open(s.parseBody(N).getTree()));
digest(pack);
final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(256);
final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
final PacketLineOut inPckLine = new PacketLineOut(inBuf);
inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
+ "refs/heads/s" + '\0'
@ -339,13 +339,13 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
// But don't include it in the pack.
//
final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
packHeader(pack, 2);
copy(pack, src.open(N));
copy(pack,src.open(s.parseBody(N).getTree()));
digest(pack);
final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(256);
final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
final PacketLineOut inPckLine = new PacketLineOut(inBuf);
inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
+ "refs/heads/s" + '\0'
@ -379,12 +379,12 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
// Don't include the tree in the pack.
//
final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
packHeader(pack, 1);
copy(pack, src.open(N));
digest(pack);
final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(256);
final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
final PacketLineOut inPckLine = new PacketLineOut(inBuf);
inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
+ "refs/heads/s" + '\0'

33
org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java

@ -126,7 +126,7 @@ public abstract class TemporaryBuffer extends OutputStream {
blocks.add(s);
}
final int n = Math.min(Block.SZ - s.count, len);
final int n = Math.min(s.buffer.length - s.count, len);
System.arraycopy(b, off, s.buffer, s.count, n);
s.count += n;
len -= n;
@ -171,7 +171,7 @@ public abstract class TemporaryBuffer extends OutputStream {
blocks.add(s);
}
final int n = in.read(s.buffer, s.count, Block.SZ - s.count);
int n = in.read(s.buffer, s.count, s.buffer.length - s.count);
if (n < 1)
return;
s.count += n;
@ -192,8 +192,12 @@ public abstract class TemporaryBuffer extends OutputStream {
* @return total length of the buffer, in bytes.
*/
public long length() {
return inCoreLength();
}
private long inCoreLength() {
final Block last = last();
return ((long) blocks.size()) * Block.SZ - (Block.SZ - last.count);
return ((long) blocks.size() - 1) * Block.SZ + last.count;
}
/**
@ -251,8 +255,13 @@ public abstract class TemporaryBuffer extends OutputStream {
if (overflow != null) {
destroy();
}
blocks = new ArrayList<Block>(inCoreLimit / Block.SZ);
blocks.add(new Block());
if (inCoreLimit < Block.SZ) {
blocks = new ArrayList<Block>(1);
blocks.add(new Block(inCoreLimit));
} else {
blocks = new ArrayList<Block>(inCoreLimit / Block.SZ);
blocks.add(new Block());
}
}
/**
@ -270,7 +279,7 @@ public abstract class TemporaryBuffer extends OutputStream {
}
private boolean reachedInCoreLimit() throws IOException {
if (blocks.size() * Block.SZ < inCoreLimit)
if (inCoreLength() < inCoreLimit)
return false;
switchToOverflow();
@ -444,12 +453,20 @@ public abstract class TemporaryBuffer extends OutputStream {
static class Block {
static final int SZ = 8 * 1024;
final byte[] buffer = new byte[SZ];
final byte[] buffer;
int count;
Block() {
buffer = new byte[SZ];
}
Block(int sz) {
buffer = new byte[sz];
}
boolean isFull() {
return count == SZ;
return count == buffer.length;
}
}
}

Loading…
Cancel
Save