From e6bd689d2c48efb4e6662ffca2fbdbc7570d2db1 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 30 Aug 2010 11:53:25 -0700 Subject: Improve LargeObjectException reporting Use 3 different types of LargeObjectException for the 3 major ways that we can fail to load an object. For each of these use a unique string translation which describes the root cause better than just the ObjectId.name() does. Change-Id: I810c98d5691b74af9fc6cbd46fc9879e35a7bdca Signed-off-by: Shawn O. Pearce --- .../src/org/eclipse/jgit/JGitText.java | 5 ++ .../eclipse/jgit/errors/LargeObjectException.java | 74 +++++++++++++++++++++- .../src/org/eclipse/jgit/lib/ObjectLoader.java | 11 ++-- .../jgit/storage/file/LargePackedDeltaObject.java | 4 +- .../jgit/storage/file/LargePackedWholeObject.java | 4 +- .../eclipse/jgit/storage/file/UnpackedObject.java | 16 +++-- .../org/eclipse/jgit/storage/pack/DeltaWindow.java | 5 +- 7 files changed, 106 insertions(+), 13 deletions(-) (limited to 'org.eclipse.jgit/src/org/eclipse') diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java index fc12e57135..ea40fe8847 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java @@ -276,6 +276,10 @@ public class JGitText extends TranslationBundle { /***/ public String invalidWindowSize; /***/ public String isAStaticFlagAndHasNorevWalkInstance; /***/ public String kNotInRange; + /***/ public String largeObjectException; + /***/ public String largeObjectOutOfMemory; + /***/ public String largeObjectExceedsByteArray; + /***/ public String largeObjectExceedsLimit; /***/ public String lengthExceedsMaximumArraySize; /***/ public String listingAlternates; /***/ public String localObjectsIncomplete; @@ -433,6 +437,7 @@ public class JGitText extends TranslationBundle { /***/ public String unknownDIRCVersion; /***/ public String unknownHost; /***/ public String unknownIndexVersionOrCorruptIndex; + /***/ public String unknownObject; /***/ public String unknownObjectType; /***/ public String unknownRepositoryFormat2; /***/ public String unknownRepositoryFormat; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java index f77aecbb42..a1107dc35f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java @@ -43,6 +43,9 @@ package org.eclipse.jgit.errors; +import java.text.MessageFormat; + +import org.eclipse.jgit.JGitText; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ObjectId; @@ -73,6 +76,13 @@ public class LargeObjectException extends RuntimeException { return objectId; } + /** @return either the hex encoded name of the object, or 'unknown object'. */ + protected String getObjectName() { + if (getObjectId() != null) + return getObjectId().name(); + return JGitText.get().unknownObject; + } + /** * Set the identity of the object, if its not already set. * @@ -86,6 +96,68 @@ public class LargeObjectException extends RuntimeException { @Override public String getMessage() { - return objectId != null ? objectId.name() : getClass().getSimpleName(); + return MessageFormat.format(JGitText.get().largeObjectException, + getObjectName()); + } + + /** An error caused by the JVM being out of heap space. */ + public static class OutOfMemory extends LargeObjectException { + private static final long serialVersionUID = 1L; + + /** + * Construct a wrapper around the original OutOfMemoryError. + * + * @param cause + * the original root cause. + */ + public OutOfMemory(OutOfMemoryError cause) { + initCause(cause); + } + + @Override + public String getMessage() { + return MessageFormat.format(JGitText.get().largeObjectOutOfMemory, + getObjectName()); + } + } + + /** Object size exceeds JVM limit of 2 GiB per byte array. */ + public static class ExceedsByteArrayLimit extends LargeObjectException { + private static final long serialVersionUID = 1L; + + @Override + public String getMessage() { + return MessageFormat + .format(JGitText.get().largeObjectExceedsByteArray, + getObjectName()); + } + } + + /** Object size exceeds the caller's upper limit. */ + public static class ExceedsLimit extends LargeObjectException { + private static final long serialVersionUID = 1L; + + private final long limit; + + private final long size; + + /** + * Construct an exception for a particular size being exceeded. + * + * @param limit + * the limit the caller imposed on the object. + * @param size + * the actual size of the object. + */ + public ExceedsLimit(long limit, long size) { + this.limit = limit; + this.size = size; + } + + @Override + public String getMessage() { + return MessageFormat.format(JGitText.get().largeObjectExceedsLimit, + getObjectName(), limit, size); + } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java index b7e58ea156..0fc3bce65b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java @@ -139,7 +139,7 @@ public abstract class ObjectLoader { try { return cloneArray(cached); } catch (OutOfMemoryError tooBig) { - throw new LargeObjectException(); + throw new LargeObjectException.OutOfMemory(tooBig); } } @@ -195,14 +195,17 @@ public abstract class ObjectLoader { ObjectStream in = openStream(); try { long sz = in.getSize(); - if (sizeLimit < sz || Integer.MAX_VALUE < sz) - throw new LargeObjectException(); + if (sizeLimit < sz) + throw new LargeObjectException.ExceedsLimit(sizeLimit, sz); + + if (Integer.MAX_VALUE < sz) + throw new LargeObjectException.ExceedsByteArrayLimit(); byte[] buf; try { buf = new byte[(int) sz]; } catch (OutOfMemoryError notEnoughHeap) { - throw new LargeObjectException(); + throw new LargeObjectException.OutOfMemory(notEnoughHeap); } IO.readFully(in, buf, 0, buf.length); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedDeltaObject.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedDeltaObject.java index 02e218216d..2b98f107f8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedDeltaObject.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedDeltaObject.java @@ -157,7 +157,9 @@ class LargePackedDeltaObject extends ObjectLoader { try { throw new LargeObjectException(getObjectId()); } catch (IOException cannotObtainId) { - throw new LargeObjectException(); + LargeObjectException err = new LargeObjectException(); + err.initCause(cannotObtainId); + throw err; } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedWholeObject.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedWholeObject.java index 9f5b804ce4..9550be4e1d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedWholeObject.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedWholeObject.java @@ -97,7 +97,9 @@ class LargePackedWholeObject extends ObjectLoader { try { throw new LargeObjectException(getObjectId()); } catch (IOException cannotObtainId) { - throw new LargeObjectException(); + LargeObjectException err = new LargeObjectException(); + err.initCause(cannotObtainId); + throw err; } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java index 78e7b10a7d..4065019dc5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java @@ -125,8 +125,12 @@ public class UnpackedObject { if (hdr[p.value++] != 0) throw new CorruptObjectException(id, JGitText.get().corruptObjectGarbageAfterSize); - if (path == null && Integer.MAX_VALUE < size) - throw new LargeObjectException(id.copy()); + if (path == null && Integer.MAX_VALUE < size) { + LargeObjectException.ExceedsByteArrayLimit e; + e = new LargeObjectException.ExceedsByteArrayLimit(); + e.setObjectId(id); + throw e; + } if (size < wc.getStreamFileThreshold() || path == null) { byte[] data = new byte[(int) size]; int n = avail - p.value; @@ -163,8 +167,12 @@ public class UnpackedObject { JGitText.get().corruptObjectInvalidType); } - if (path == null && Integer.MAX_VALUE < size) - throw new LargeObjectException(id.copy()); + if (path == null && Integer.MAX_VALUE < size) { + LargeObjectException.ExceedsByteArrayLimit e; + e = new LargeObjectException.ExceedsByteArrayLimit(); + e.setObjectId(id); + throw e; + } if (size < wc.getStreamFileThreshold() || path == null) { in.reset(); IO.skipFully(in, p); 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 d5296a03e3..6a71ad7dcf 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 @@ -424,8 +424,9 @@ class DeltaWindow { try { idx = new DeltaIndex(buffer(ent)); } catch (OutOfMemoryError noMemory) { - LargeObjectException e = new LargeObjectException(ent.object); - e.initCause(noMemory); + LargeObjectException.OutOfMemory e; + e = new LargeObjectException.OutOfMemory(noMemory); + e.setObjectId(ent.object); throw e; } if (0 < maxMemory) -- cgit v1.2.3