From 51beee5568b7c44b01240b96c0d4d81e10362fae Mon Sep 17 00:00:00 2001 From: Colby Ranger Date: Thu, 27 Dec 2012 08:48:39 -0800 Subject: [PATCH] Enforce max memory for DeltaWindow. Previously, memory limits were enforced at the start of each iteration of the delta search, based on objects that were currently loaded in memory. However, new objects added to the window may be expanded in a future iteration of the search and thus were not accounted for correctly at the start of the search. To fix this, memory limits are now enforced before each object is loaded. Change-Id: I898ab43e7bf5ee7189831f3a68bb9385ae694b8f --- .../jgit/storage/pack/DeltaWindow.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindow.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindow.java index c51cafcbf..b440774bc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindow.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindow.java @@ -164,6 +164,14 @@ private static long estimateSize(ObjectToPack ent) { return DeltaIndex.estimateIndexSize(ent.getWeight()); } + private static long estimateIndexSize(DeltaWindowEntry ent) { + if (ent.buffer == null) + return estimateSize(ent.object); + + int len = ent.buffer.length; + return DeltaIndex.estimateIndexSize(len) - len; + } + private void clear(DeltaWindowEntry ent) { if (ent.index != null) loaded -= ent.index.getIndexSize(); @@ -420,6 +428,8 @@ private DeltaIndex index(DeltaWindowEntry ent) IOException, LargeObjectException { DeltaIndex idx = ent.index; if (idx == null) { + checkLoadable(ent, estimateIndexSize(ent)); + try { idx = new DeltaIndex(buffer(ent)); } catch (OutOfMemoryError noMemory) { @@ -439,6 +449,8 @@ private byte[] buffer(DeltaWindowEntry ent) throws MissingObjectException, IncorrectObjectTypeException, IOException, LargeObjectException { byte[] buf = ent.buffer; if (buf == null) { + checkLoadable(ent, ent.size()); + buf = PackWriter.buffer(config, reader, ent.object); if (0 < maxMemory) loaded += buf.length; @@ -447,6 +459,18 @@ private byte[] buffer(DeltaWindowEntry ent) throws MissingObjectException, return buf; } + private void checkLoadable(DeltaWindowEntry ent, long need) { + int tail = next(resSlot); + while (maxMemory < loaded + need) { + DeltaWindowEntry cur = window[tail]; + clear(cur); + if (cur == ent) + throw new LargeObjectException.ExceedsLimit( + maxMemory, loaded + need); + tail = next(tail); + } + } + private Deflater deflater() { if (deflater == null) deflater = new Deflater(config.getCompressionLevel());