* Make unwrapCorrupt Check Suppressed Ex. (#41889) * As discussed in #24800 we want to check for suppressed corruption indicating exceptions here as well to more reliably categorize corruption related exceptions * Closes #24800, 41201
This commit is contained in:
parent
adb3574af8
commit
00d665540a
|
@ -175,12 +175,42 @@ public final class ExceptionsHelper {
|
|||
return first;
|
||||
}
|
||||
|
||||
private static final List<Class<? extends IOException>> CORRUPTION_EXCEPTIONS =
|
||||
Arrays.asList(CorruptIndexException.class, IndexFormatTooOldException.class, IndexFormatTooNewException.class);
|
||||
|
||||
/**
|
||||
* Looks at the given Throwable's and its cause(s) as well as any suppressed exceptions on the Throwable as well as its causes
|
||||
* and returns the first corruption indicating exception (as defined by {@link #CORRUPTION_EXCEPTIONS}) it finds.
|
||||
* @param t Throwable
|
||||
* @return Corruption indicating exception if one is found, otherwise {@code null}
|
||||
*/
|
||||
public static IOException unwrapCorruption(Throwable t) {
|
||||
return (IOException) unwrap(t, CorruptIndexException.class,
|
||||
IndexFormatTooOldException.class,
|
||||
IndexFormatTooNewException.class);
|
||||
if (t != null) {
|
||||
do {
|
||||
for (Class<?> clazz : CORRUPTION_EXCEPTIONS) {
|
||||
if (clazz.isInstance(t)) {
|
||||
return (IOException) t;
|
||||
}
|
||||
}
|
||||
for (Throwable suppressed : t.getSuppressed()) {
|
||||
IOException corruptionException = unwrapCorruption(suppressed);
|
||||
if (corruptionException != null) {
|
||||
return corruptionException;
|
||||
}
|
||||
}
|
||||
} while ((t = t.getCause()) != null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks at the given Throwable and its cause(s) and returns the first Throwable that is of one of the given classes or {@code null}
|
||||
* if no matching Throwable is found. Unlike {@link #unwrapCorruption} this method does only check the given Throwable and its causes
|
||||
* but does not look at any suppressed exceptions.
|
||||
* @param t Throwable
|
||||
* @param clazzes Classes to look for
|
||||
* @return Matching Throwable if one is found, otherwise {@code null}
|
||||
*/
|
||||
public static Throwable unwrap(Throwable t, Class<?>... clazzes) {
|
||||
if (t != null) {
|
||||
do {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.elasticsearch.action.OriginalIndices;
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.action.search.ShardSearchFailure;
|
||||
|
@ -183,4 +184,31 @@ public class ExceptionsHelperTests extends ESTestCase {
|
|||
ShardOperationFailedException[] groupBy = ExceptionsHelper.groupBy(failures);
|
||||
assertThat(groupBy.length, equalTo(2));
|
||||
}
|
||||
|
||||
public void testUnwrapCorruption() {
|
||||
final Throwable corruptIndexException = new CorruptIndexException("corrupt", "resource");
|
||||
assertThat(ExceptionsHelper.unwrapCorruption(corruptIndexException), equalTo(corruptIndexException));
|
||||
|
||||
final Throwable corruptionAsCause = new RuntimeException(corruptIndexException);
|
||||
assertThat(ExceptionsHelper.unwrapCorruption(corruptionAsCause), equalTo(corruptIndexException));
|
||||
|
||||
final Throwable corruptionSuppressed = new RuntimeException();
|
||||
corruptionSuppressed.addSuppressed(corruptIndexException);
|
||||
assertThat(ExceptionsHelper.unwrapCorruption(corruptionSuppressed), equalTo(corruptIndexException));
|
||||
|
||||
final Throwable corruptionSuppressedOnCause = new RuntimeException(new RuntimeException());
|
||||
corruptionSuppressedOnCause.getCause().addSuppressed(corruptIndexException);
|
||||
assertThat(ExceptionsHelper.unwrapCorruption(corruptionSuppressedOnCause), equalTo(corruptIndexException));
|
||||
|
||||
final Throwable corruptionCauseOnSuppressed = new RuntimeException();
|
||||
corruptionCauseOnSuppressed.addSuppressed(new RuntimeException(corruptIndexException));
|
||||
assertThat(ExceptionsHelper.unwrapCorruption(corruptionCauseOnSuppressed), equalTo(corruptIndexException));
|
||||
|
||||
assertThat(ExceptionsHelper.unwrapCorruption(new RuntimeException()), nullValue());
|
||||
assertThat(ExceptionsHelper.unwrapCorruption(new RuntimeException(new RuntimeException())), nullValue());
|
||||
|
||||
final Throwable withSuppressedException = new RuntimeException();
|
||||
withSuppressedException.addSuppressed(new RuntimeException());
|
||||
assertThat(ExceptionsHelper.unwrapCorruption(withSuppressedException), nullValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -440,10 +440,12 @@ public class RecoverySourceHandlerTests extends ESTestCase {
|
|||
handler.sendFiles(store, metas.toArray(new StoreFileMetaData[0]), () -> 0);
|
||||
fail("exception index");
|
||||
} catch (RuntimeException ex) {
|
||||
assertNull(ExceptionsHelper.unwrapCorruption(ex));
|
||||
final IOException unwrappedCorruption = ExceptionsHelper.unwrapCorruption(ex);
|
||||
if (throwCorruptedIndexException) {
|
||||
assertNotNull(unwrappedCorruption);
|
||||
assertEquals(ex.getMessage(), "[File corruption occurred on recovery but checksums are ok]");
|
||||
} else {
|
||||
assertNull(unwrappedCorruption);
|
||||
assertEquals(ex.getMessage(), "boom");
|
||||
}
|
||||
} catch (CorruptIndexException ex) {
|
||||
|
|
Loading…
Reference in New Issue