simplify exception reading / writing - now use a named exception for unknonw exceptions

This commit is contained in:
Simon Willnauer 2015-06-29 20:39:04 +02:00
parent fa016a2b09
commit 62d29ff6a4
3 changed files with 84 additions and 45 deletions

View File

@ -65,9 +65,8 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
}
public ElasticsearchException(StreamInput in) throws IOException {
super(in.readOptionalString(), in.readThrowable()); //TODO readOptionalThrowable
super(in.readOptionalString(), in.readThrowable());
readStackTrace(this, in);
}
/**
@ -166,8 +165,7 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
writeStackTraces(this, out);
}
public static ElasticsearchException readException(StreamInput input) throws IOException {
final String name = input.readString();
public static ElasticsearchException readException(StreamInput input, String name) throws IOException {
Constructor<? extends ElasticsearchException> elasticsearchException = MAPPING.get(name);
if (elasticsearchException == null) {
throw new IllegalStateException("unknown exception with name: " + name);
@ -179,18 +177,13 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
}
}
public static void writeException(ElasticsearchException ex, StreamOutput output) throws IOException {
output.writeString(ex.getClass().getName());
ex.writeTo(output);
}
/**
* A base class for exceptions that should carry rest headers
*/
@SuppressWarnings("unchecked")
public static class WithRestHeadersException extends ElasticsearchException implements HasRestHeaders {
private final ImmutableMap<String, List<String>> headers;
private final Map<String, List<String>> headers;
public WithRestHeadersException(String msg, Tuple<String, String[]>... headers) {
super(msg);
@ -202,9 +195,9 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
int numKeys = in.readVInt();
ImmutableMap.Builder<String, List<String>> builder = ImmutableMap.builder();
for (int i = 0; i < numKeys; i++) {
String key = in.readString();
int numValues = in.readVInt();
ArrayList<String> headers = new ArrayList<>(numValues);
final String key = in.readString();
final int numValues = in.readVInt();
final ArrayList<String> headers = new ArrayList<>(numValues);
for (int j = 0; j < numValues; j++) {
headers.add(in.readString());
}
@ -223,12 +216,11 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
for (String v : entry.getValue()) {
out.writeString(v);
}
}
}
@Override
public ImmutableMap<String, List<String>> getHeaders() {
public Map<String, List<String>> getHeaders() {
return headers;
}
@ -236,7 +228,7 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
return Tuple.tuple(name, values);
}
private static ImmutableMap<String, List<String>> headers(Tuple<String, String[]>... headers) {
private static Map<String, List<String>> headers(Tuple<String, String[]>... headers) {
Map<String, List<String>> map = Maps.newHashMap();
for (Tuple<String, String[]> header : headers) {
List<String> list = map.get(header.v1());
@ -353,15 +345,19 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
return ExceptionsHelper.detailedMessage(this).trim();
}
/**
* Deserializes stacktrace elements as well as suppressed exceptions from the given output stream and
* adds it to the given exception.
*/
public static <T extends Throwable> T readStackTrace(T throwable, StreamInput in) throws IOException {
int stackTraceElements = in.readVInt();
final int stackTraceElements = in.readVInt();
StackTraceElement[] stackTrace = new StackTraceElement[stackTraceElements];
for (int i = 0; i < stackTraceElements; i++) {
String declaringClasss = in.readString();
String fielName = in.readString();
String methodName = in.readString();
int lineNumber = in.readVInt();
stackTrace[i] = new StackTraceElement(declaringClasss,methodName, fielName, lineNumber);
final String declaringClasss = in.readString();
final String fileName = in.readString();
final String methodName = in.readString();
final int lineNumber = in.readVInt();
stackTrace[i] = new StackTraceElement(declaringClasss,methodName, fileName, lineNumber);
}
throwable.setStackTrace(stackTrace);
@ -372,6 +368,9 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
return throwable;
}
/**
* Serializes the given exceptions stacktrace elements as well as it's suppressed exceptions to the given output stream.
*/
public static <T extends Throwable> T writeStackTraces(T throwable, StreamOutput out) throws IOException {
StackTraceElement[] stackTrace = throwable.getStackTrace();
out.writeVInt(stackTrace.length);
@ -533,7 +532,8 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
org.elasticsearch.ElasticsearchParseException.class,
org.elasticsearch.action.PrimaryMissingActionException.class,
org.elasticsearch.index.engine.CreateFailedEngineException.class,
org.elasticsearch.index.shard.IllegalIndexShardStateException.class
org.elasticsearch.index.shard.IllegalIndexShardStateException.class,
org.elasticsearch.common.io.stream.StreamInput.NamedException.class
};
Map<String, Constructor<? extends ElasticsearchException>> mapping = new HashMap<>();

View File

@ -39,6 +39,9 @@ import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
import static org.elasticsearch.ElasticsearchException.readException;
import static org.elasticsearch.ElasticsearchException.readStackTrace;
/**
*
*/
@ -486,42 +489,41 @@ public abstract class StreamInput extends InputStream {
int key = readVInt();
switch (key) {
case 0:
return (T) ElasticsearchException.readException(this);
final String name = readString();
return (T) readException(this, name);
case 1:
// this sucks it would be nice to have a better way to construct those?
String msg = readOptionalString();
final int idx = msg.indexOf(" (resource=");
String resource = msg.substring(idx + " (resource=".length(), msg.length()-1);
final String resource = msg.substring(idx + " (resource=".length(), msg.length()-1);
msg = msg.substring(0, idx);
return (T) ElasticsearchException.readStackTrace(new CorruptIndexException(msg, resource, readThrowable()), this); // TODO add a string throwable ctor to this?
return (T) readStackTrace(new CorruptIndexException(msg, resource, readThrowable()), this); // Lucene 5.3 will have getters for all these
case 2:
String itnMessage = readOptionalString();
final String itnMessage = readOptionalString();
readThrowable();
return (T) ElasticsearchException.readStackTrace(new IndexFormatTooNewException(itnMessage, -1, -1, -1), this);
return (T) readStackTrace(new IndexFormatTooNewException(itnMessage, -1, -1, -1), this);
case 3:
String itoMessage = readOptionalString();
final String itoMessage = readOptionalString();
readThrowable();
return (T) ElasticsearchException.readStackTrace(new IndexFormatTooOldException(itoMessage, -1, -1, -1), this);
return (T) readStackTrace(new IndexFormatTooOldException(itoMessage, -1, -1, -1), this);
case 4:
String npeMessage = readOptionalString();
final String npeMessage = readOptionalString();
readThrowable();
return (T) ElasticsearchException.readStackTrace(new NullPointerException(npeMessage), this);
return (T) readStackTrace(new NullPointerException(npeMessage), this);
case 5:
String nfeMessage = readOptionalString();
final String nfeMessage = readOptionalString();
readThrowable();
return (T) ElasticsearchException.readStackTrace(new NumberFormatException(nfeMessage), this);
return (T) readStackTrace(new NumberFormatException(nfeMessage), this);
case 6:
return (T) ElasticsearchException.readStackTrace(new IllegalArgumentException(readOptionalString(), readThrowable()), this);
return (T) readStackTrace(new IllegalArgumentException(readOptionalString(), readThrowable()), this);
case 7:
return (T) ElasticsearchException.readStackTrace(new IllegalStateException(readOptionalString(), readThrowable()), this);
return (T) readStackTrace(new IllegalStateException(readOptionalString(), readThrowable()), this);
case 8:
String eofMessage = readOptionalString();
final String eofMessage = readOptionalString();
readThrowable();
return (T) ElasticsearchException.readStackTrace(new EOFException(eofMessage), this);
return (T) readStackTrace(new EOFException(eofMessage), this);
case 9:
return (T) ElasticsearchException.readStackTrace(new SecurityException(readOptionalString(), readThrowable()), this);
case 10: // unknown -- // C - should we use a dedicated exception
return (T) ElasticsearchException.readStackTrace(new ElasticsearchException(readOptionalString(), readThrowable()), this);
return (T) readStackTrace(new SecurityException(readOptionalString(), readThrowable()), this);
default:
assert false : "no such exception for id: " + key;
}
@ -544,4 +546,33 @@ public abstract class StreamInput extends InputStream {
return new InputStreamStreamInput(new ByteArrayInputStream(bytes, offset, length));
}
public static class NamedException extends ElasticsearchException {
private final String name;
public NamedException(String name, String msg, Throwable cause) {
super(msg, cause);
if (name == null) {
throw new IllegalArgumentException("name must not be null");
}
this.name = name;
}
public NamedException(StreamInput in) throws IOException {
super(in);
name = in.readString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeString(name);
}
@Override
protected String getExceptionName() {
return Strings.toUnderscoreCase(name);
}
}
}

View File

@ -456,9 +456,7 @@ public abstract class StreamOutput extends OutputStream {
} else {
writeBoolean(true);
if (throwable instanceof ElasticsearchException) {
writeVInt(0);
ElasticsearchException.writeException((ElasticsearchException) throwable, this);
return;
} else if (throwable instanceof CorruptIndexException) {
writeVInt(1);
} else if (throwable instanceof IndexFormatTooNewException) {
@ -478,7 +476,17 @@ public abstract class StreamOutput extends OutputStream {
} else if (throwable instanceof SecurityException) {
writeVInt(9);
} else {
writeVInt(10); // unknown
ElasticsearchException ex;
if (throwable instanceof ElasticsearchException) {
ex = (ElasticsearchException) throwable;
} else {
ex = new StreamInput.NamedException(ElasticsearchException.getExceptionName(throwable), throwable.getMessage(), throwable.getCause());
}
writeVInt(0);
writeString(ex.getClass().getName());
ex.writeTo(this);
return;
}
writeOptionalString(throwable.getMessage());
writeThrowable(throwable.getCause());