HierarchicalMicroScheduler no longer attempts to wrap exceptions

-- This behavior, which isn't obviously valuable at all, continued to grab and rethrow exceptions in the HMS that, if run without NT, would show up as more meaningful errors.  Now HMS simply checks whether the throwable it received on error was a RuntimeException.  If so, it is stored and rethrow without wrapping later.  If it isn't, only in this case is the exception wrapped in a ReviewedStingException.
-- Added a QC walker ErrorThrowingWalker that will throw a UserException, ReviewedStingException, and NullPointerException from map as specified on the command line
-- Added IT that ensures that all three types are thrown properly (i.e., you catch a NullPointerException when you ask for one to be thrown) with and without threading enabled.
-- I believe this will finally put to rest all of these annoying HMS captures.
This commit is contained in:
Mark DePristo 2012-03-23 11:27:10 -04:00
parent ab288354e9
commit ff26f2bf68
3 changed files with 126 additions and 9 deletions

View File

@ -47,7 +47,7 @@ public class HierarchicalMicroScheduler extends MicroScheduler implements Hierar
/** /**
* An exception that's occurred in this traversal. If null, no exception has occurred. * An exception that's occurred in this traversal. If null, no exception has occurred.
*/ */
private Throwable error = null; private RuntimeException error = null;
/** /**
* Queue of incoming shards. * Queue of incoming shards.
@ -345,22 +345,22 @@ public class HierarchicalMicroScheduler extends MicroScheduler implements Hierar
return error != null; return error != null;
} }
private synchronized StingException getTraversalError() { private synchronized RuntimeException getTraversalError() {
if(!hasTraversalErrorOccurred()) if(!hasTraversalErrorOccurred())
throw new ReviewedStingException("User has attempted to retrieve a traversal error when none exists"); throw new ReviewedStingException("User has attempted to retrieve a traversal error when none exists");
return error;
// If the error is already a StingException, pass it along as is. Otherwise, wrap it.
if(error instanceof StingException)
return (StingException)error;
else
return new ReviewedStingException("An error occurred during the traversal.",error);
} }
/** /**
* Allows other threads to notify of an error during traversal. * Allows other threads to notify of an error during traversal.
*/ */
protected synchronized void notifyOfTraversalError(Throwable error) { protected synchronized void notifyOfTraversalError(Throwable error) {
this.error = error; // If the error is already a Runtime, pass it along as is. Otherwise, wrap it.
if (error instanceof RuntimeException)
this.error = (RuntimeException)error;
else
this.error = new ReviewedStingException("An error occurred during the traversal.", error);
} }

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2011, The Broad Institute
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.broadinstitute.sting.gatk.walkers.qc;
import org.broadinstitute.sting.commandline.Input;
import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker;
import org.broadinstitute.sting.gatk.walkers.RodWalker;
import org.broadinstitute.sting.gatk.walkers.TreeReducible;
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;
import org.broadinstitute.sting.utils.exceptions.UserException;
/**
* a walker that simply throws errors. Allows us to test that the engine is behaving as expected with error handling
*/
public class ErrorThrowingWalker extends RodWalker<Integer,Integer> implements TreeReducible<Integer> {
@Input(fullName="exception", shortName = "E", doc="Java class of exception to throw", required=true)
public String exceptionToThrow;
//
// Template code to allow us to build the walker, doesn't actually do anything
//
@Override
public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
if ( exceptionToThrow.equals("UserException") ) {
throw new UserException("UserException");
} else if ( exceptionToThrow.equals("NullPointerException") ) {
throw new NullPointerException();
} else if ( exceptionToThrow.equals("ReviewedStingException") ) {
throw new ReviewedStingException("ReviewedStingException");
} else {
throw new UserException.BadArgumentValue("exception", "exception isn't a recognized value " + exceptionToThrow);
}
}
@Override
public Integer reduceInit() {
return 0;
}
@Override
public Integer reduce(Integer value, Integer sum) {
return value + sum;
}
public Integer treeReduce(final Integer lhs, final Integer rhs) {
return lhs + rhs;
}
}

View File

@ -25,9 +25,13 @@
package org.broadinstitute.sting.gatk; package org.broadinstitute.sting.gatk;
import org.broadinstitute.sting.WalkerTest; import org.broadinstitute.sting.WalkerTest;
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;
import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.exceptions.UserException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.Arrays;
/** /**
* *
*/ */
@ -73,4 +77,45 @@ public class EngineFeaturesIntegrationTest extends WalkerTest {
@Test() private void testMissingInterval() { @Test() private void testMissingInterval() {
testMissingFile("missing interval", "-T UnifiedGenotyper -L missing.interval_list -I " + b37GoodBAM); testMissingFile("missing interval", "-T UnifiedGenotyper -L missing.interval_list -I " + b37GoodBAM);
} }
// --------------------------------------------------------------------------------
//
// Test that our exceptions are coming back as we expect
//
// --------------------------------------------------------------------------------
private class EngineErrorHandlingTestProvider extends TestDataProvider {
Class expectedException;
boolean multiThreaded;
public EngineErrorHandlingTestProvider(Class exceptedException, final boolean multiThreaded) {
super(EngineErrorHandlingTestProvider.class);
this.expectedException = exceptedException;
this.multiThreaded = multiThreaded;
setName(String.format("Engine error handling: expected %s, is-multithreaded %b", exceptedException, multiThreaded));
}
}
@DataProvider(name = "EngineErrorHandlingTestProvider")
public Object[][] makeEngineErrorHandlingTestProvider() {
for ( final boolean multiThreaded : Arrays.asList(true, false)) {
new EngineErrorHandlingTestProvider(NullPointerException.class, multiThreaded);
new EngineErrorHandlingTestProvider(UserException.class, multiThreaded);
new EngineErrorHandlingTestProvider(ReviewedStingException.class, multiThreaded);
}
return EngineErrorHandlingTestProvider.getTests(EngineErrorHandlingTestProvider.class);
}
//
// Loop over errors to throw, make sure they are the errors we get back from the engine, regardless of NT type
//
@Test(dataProvider = "EngineErrorHandlingTestProvider")
public void testEngineErrorHandlingTestProvider(EngineErrorHandlingTestProvider cfg) {
final String root = "-T ErrorThrowing -R " + b37KGReference;
final String args = root + (cfg.multiThreaded ? " -nt 2" : "") + " -E " + cfg.expectedException.getSimpleName();
WalkerTestSpec spec = new WalkerTestSpec(args, 0, cfg.expectedException);
executeTest(cfg.toString(), spec);
}
} }