]> source.dussan.org Git - jgit.git/commitdiff
Enforce max memory for DeltaWindow. 85/9385/3
authorColby Ranger <cranger@google.com>
Thu, 27 Dec 2012 16:48:39 +0000 (08:48 -0800)
committerColby Ranger <cranger@google.com>
Thu, 27 Dec 2012 17:23:30 +0000 (09:23 -0800)
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

org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindow.java

index c51cafcbf2be2f04bd2307f6e61d23ed26ea4e92..b440774bc6e879c78b5ddcc004ed3b68b7c17500 100644 (file)
@@ -164,6 +164,14 @@ class DeltaWindow {
                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 @@ class DeltaWindow {
                        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 @@ class DeltaWindow {
                        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 @@ class DeltaWindow {
                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());