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 <spearce@spearce.org>
This commit is contained in:
parent
a3945d1bc8
commit
e6bd689d2c
|
@ -47,9 +47,11 @@
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import org.eclipse.jgit.JGitText;
|
||||
import org.eclipse.jgit.errors.LargeObjectException;
|
||||
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
|
||||
import org.eclipse.jgit.junit.TestRepository;
|
||||
|
@ -133,7 +135,9 @@ public void testWhole_LargeObject() throws Exception {
|
|||
ol.getCachedBytes();
|
||||
fail("Should have thrown LargeObjectException");
|
||||
} catch (LargeObjectException tooBig) {
|
||||
assertEquals(id.name(), tooBig.getMessage());
|
||||
assertEquals(MessageFormat.format(
|
||||
JGitText.get().largeObjectException, id.name()), tooBig
|
||||
.getMessage());
|
||||
}
|
||||
|
||||
ObjectStream in = ol.openStream();
|
||||
|
@ -257,7 +261,9 @@ public void testDelta_LargeObjectChain() throws Exception {
|
|||
ol.getCachedBytes();
|
||||
fail("Should have thrown LargeObjectException");
|
||||
} catch (LargeObjectException tooBig) {
|
||||
assertEquals(id3.name(), tooBig.getMessage());
|
||||
assertEquals(MessageFormat.format(
|
||||
JGitText.get().largeObjectException, id3.name()), tooBig
|
||||
.getMessage());
|
||||
}
|
||||
|
||||
ObjectStream in = ol.openStream();
|
||||
|
@ -313,7 +319,9 @@ public void testDelta_LargeInstructionStream() throws Exception {
|
|||
ol.getCachedBytes();
|
||||
fail("Should have thrown LargeObjectException");
|
||||
} catch (LargeObjectException tooBig) {
|
||||
assertEquals(id3.name(), tooBig.getMessage());
|
||||
assertEquals(MessageFormat.format(
|
||||
JGitText.get().largeObjectException, id3.name()), tooBig
|
||||
.getMessage());
|
||||
}
|
||||
|
||||
ObjectStream in = ol.openStream();
|
||||
|
|
|
@ -135,7 +135,9 @@ public void testStandardFormat_LargeObject() throws Exception {
|
|||
ol.getCachedBytes();
|
||||
fail("Should have thrown LargeObjectException");
|
||||
} catch (LargeObjectException tooBig) {
|
||||
assertEquals(id.name(), tooBig.getMessage());
|
||||
assertEquals(MessageFormat.format(
|
||||
JGitText.get().largeObjectException, id.name()), tooBig
|
||||
.getMessage());
|
||||
}
|
||||
|
||||
ObjectStream in = ol.openStream();
|
||||
|
@ -416,7 +418,9 @@ public void testPackFormat_LargeObject() throws Exception {
|
|||
ol.getCachedBytes();
|
||||
fail("Should have thrown LargeObjectException");
|
||||
} catch (LargeObjectException tooBig) {
|
||||
assertEquals(id.name(), tooBig.getMessage());
|
||||
assertEquals(MessageFormat.format(
|
||||
JGitText.get().largeObjectException, id.name()), tooBig
|
||||
.getMessage());
|
||||
}
|
||||
|
||||
ObjectStream in = ol.openStream();
|
||||
|
|
|
@ -216,6 +216,10 @@ invalidWildcards=Invalid wildcards {0}
|
|||
invalidWindowSize=Invalid window size
|
||||
isAStaticFlagAndHasNorevWalkInstance={0} is a static flag and has no RevWalk instance
|
||||
kNotInRange=k {0} not in {1} - {2}
|
||||
largeObjectException={0} exceeds size limit
|
||||
largeObjectOutOfMemory=Out of memory loading {0}
|
||||
largeObjectExceedsByteArray=Object {0} exceeds 2 GiB byte array limit
|
||||
largeObjectExceedsLimit=Object {0} exceeds {1} limit, actual size is {2}
|
||||
lengthExceedsMaximumArraySize=Length exceeds maximum array size
|
||||
listingAlternates=Listing alternates
|
||||
localObjectsIncomplete=Local objects incomplete.
|
||||
|
@ -374,6 +378,7 @@ unexpectedReportLine=unexpected report line: {0}
|
|||
unknownDIRCVersion=Unknown DIRC version {0}
|
||||
unknownHost=unknown host
|
||||
unknownIndexVersionOrCorruptIndex=Unknown index version (or corrupt index): {0}
|
||||
unknownObject=unknown object
|
||||
unknownObjectType=Unknown object type {0}.
|
||||
unknownRepositoryFormat2=Unknown repository format "{0}"; expected "0".
|
||||
unknownRepositoryFormat=Unknown repository format
|
||||
|
|
|
@ -276,6 +276,10 @@ public static JGitText get() {
|
|||
/***/ 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 static JGitText get() {
|
|||
/***/ public String unknownDIRCVersion;
|
||||
/***/ public String unknownHost;
|
||||
/***/ public String unknownIndexVersionOrCorruptIndex;
|
||||
/***/ public String unknownObject;
|
||||
/***/ public String unknownObjectType;
|
||||
/***/ public String unknownRepositoryFormat2;
|
||||
/***/ public String unknownRepositoryFormat;
|
||||
|
|
|
@ -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 ObjectId getObjectId() {
|
|||
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 void setObjectId(AnyObjectId id) {
|
|||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ public final byte[] getBytes(int sizeLimit) throws LargeObjectException,
|
|||
try {
|
||||
return cloneArray(cached);
|
||||
} catch (OutOfMemoryError tooBig) {
|
||||
throw new LargeObjectException();
|
||||
throw new LargeObjectException.OutOfMemory(tooBig);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,14 +195,17 @@ public byte[] getCachedBytes(int sizeLimit) throws LargeObjectException,
|
|||
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);
|
||||
|
|
|
@ -157,7 +157,9 @@ public byte[] getCachedBytes() throws LargeObjectException {
|
|||
try {
|
||||
throw new LargeObjectException(getObjectId());
|
||||
} catch (IOException cannotObtainId) {
|
||||
throw new LargeObjectException();
|
||||
LargeObjectException err = new LargeObjectException();
|
||||
err.initCause(cannotObtainId);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,9 @@ public byte[] getCachedBytes() throws LargeObjectException {
|
|||
try {
|
||||
throw new LargeObjectException(getObjectId());
|
||||
} catch (IOException cannotObtainId) {
|
||||
throw new LargeObjectException();
|
||||
LargeObjectException err = new LargeObjectException();
|
||||
err.initCause(cannotObtainId);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,8 +125,12 @@ static ObjectLoader open(InputStream in, File path, AnyObjectId id,
|
|||
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 @@ static ObjectLoader open(InputStream in, File path, AnyObjectId id,
|
|||
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);
|
||||
|
|
|
@ -424,8 +424,9 @@ private DeltaIndex index(DeltaWindowEntry ent)
|
|||
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)
|
||||
|
|
Loading…
Reference in New Issue