diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/JythonTopLevelDataSetHandler.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/JythonTopLevelDataSetHandler.java index 8cdf1a25e98b5cbcef3b40490d44c373919b9bf3..379e6ff5fb3220cc6ae1c8b22a611b1b37ff302b 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/JythonTopLevelDataSetHandler.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/JythonTopLevelDataSetHandler.java @@ -79,6 +79,11 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends */ POST_REGISTRATION_FUNCTION_NAME("post_metadata_registration", 1), + /** + * The name of the function to define to hook into the transaction rollback mechanism. + */ + ROLLBACK_PRE_REGISTRATION_FUNCTION_NAME("rollback_pre_registration", 2), + /** * The name of the function called when secondary transactions, DynamicTransactionQuery * objects, fail. @@ -313,22 +318,35 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends DataSetStorageAlgorithmRunner<T> algorithmRunner, Throwable ex) { PythonInterpreter interpreter = getInterpreterFromService(service); + PyFunction function = tryJythonFunction(interpreter, - JythonHookFunction.ROLLBACK_TRANSACTION_FUNCTION_NAME); + JythonHookFunction.ROLLBACK_PRE_REGISTRATION_FUNCTION_NAME); + if (null != function) { - invokeRollbackTransactionFunction(function, service, transaction, algorithmRunner, ex); + invokeTransactionFunctionWithContext(function, service, transaction, ex); } else if (shouldUseOldJythonHookFunctions()) { - // No Rollback transaction function was called, see if the rollback service function was - // defined, and call it. function = tryJythonFunction(interpreter, - JythonHookFunction.ROLLBACK_SERVICE_FUNCTION_NAME); + JythonHookFunction.ROLLBACK_TRANSACTION_FUNCTION_NAME); if (null != function) { - invokeRollbackServiceFunction(function, service, ex); + invokeRollbackTransactionFunction(function, service, transaction, algorithmRunner, + ex); + } else + { + // No Rollback transaction function was called, see if the rollback service function + // was + // defined, and call it. + function = + tryJythonFunction(interpreter, + JythonHookFunction.ROLLBACK_SERVICE_FUNCTION_NAME); + if (null != function) + { + invokeRollbackServiceFunction(function, service, ex); + } } } } @@ -432,9 +450,17 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends } private void invokeTransactionFunctionWithContext(PyFunction function, - DataSetRegistrationService<T> service, DataSetRegistrationTransaction<T> transaction) + DataSetRegistrationService<T> service, DataSetRegistrationTransaction<T> transaction, + Object... additionalArgs) { - invokeFuncion(service, function, transaction.getTransactionPersistentMap()); + if (additionalArgs.length > 0) + { + invokeFuncion(service, function, transaction.getTransactionPersistentMap(), + additionalArgs); + } else + { + invokeFuncion(service, function, transaction.getTransactionPersistentMap()); + } } private void invokeDidEncounterSecondaryTransactionErrorsFunction(PyFunction function, diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/JythonTopLevelDataSetRegistratorTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/JythonTopLevelDataSetRegistratorTest.java index 179d550299dc7a85156d7099abdc77bd3ee3ede0..f5adff2df4cee49da34ca4e957b97437b9d5f456 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/JythonTopLevelDataSetRegistratorTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/JythonTopLevelDataSetRegistratorTest.java @@ -643,9 +643,10 @@ public class JythonTopLevelDataSetRegistratorTest extends AbstractJythonDataSetH Throwable t = isErrorCausedByUnexpectedInvocation(exception); if (t != null) { - throw new RuntimeException("Extracted unexpected invocation error "+t.getMessage(), t); + throw new RuntimeException("Extracted unexpected invocation error " + + t.getMessage(), t); } - + if (testCase.exceptionAcceptor != null) { assertTrue("Exception " + exception + "was not accepted by validator", @@ -797,6 +798,7 @@ public class JythonTopLevelDataSetRegistratorTest extends AbstractJythonDataSetH } else if (testCase.failurePoint .compareTo(TestCaseParameters.FailurePoint.DURING_VALIDATION) <= 0) { + assertFalse(handler.getExpectations().didPreRegistrationRollbackHappen); assertFalse(handler.getExpectations().didRollbackServiceFunctionRun); assertFalse(handler.getExpectations().didTransactionRollbackHappen); assertFalse(handler.getExpectations().didRollbackTransactionFunctionRunHappen); @@ -809,8 +811,9 @@ public class JythonTopLevelDataSetRegistratorTest extends AbstractJythonDataSetH } else { assertFalse(handler.getExpectations().didRollbackServiceFunctionRun); + assertTrue(handler.getExpectations().didPreRegistrationRollbackHappen); + assertFalse(handler.getExpectations().didRollbackTransactionFunctionRunHappen); assertTrue(handler.getExpectations().didTransactionRollbackHappen); - assertTrue(handler.getExpectations().didRollbackTransactionFunctionRunHappen); assertTrue(handler.getExpectations().didPreRegistrationFunctionRunHappen); assertFalse(handler.getExpectations().didPostRegistrationFunctionRunHappen); diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/TestingDataSetHandlerExpectations.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/TestingDataSetHandlerExpectations.java index db95b9773b784f40b44d9f46b90d74d800e6c6c0..0c9194e2b0dac9d234376ac868268ba0827a0992 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/TestingDataSetHandlerExpectations.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/TestingDataSetHandlerExpectations.java @@ -36,10 +36,11 @@ public class TestingDataSetHandlerExpectations protected boolean didServiceRollbackHappen = false; + protected boolean didPreRegistrationRollbackHappen = false; + protected String registrationContextError; - public boolean isShouldRegistrationFail() { return shouldRegistrationFail; @@ -88,6 +89,9 @@ public class TestingDataSetHandlerExpectations readBoolean(interpreter, "didPostStorageFunctionRunHappen"); didSecondaryTransactionErrorNotificationHappen = readBoolean(interpreter, "didSecondaryTransactionErrorNotificationHappen"); + didPreRegistrationRollbackHappen = + readBoolean(interpreter, "didPreRegistrationRollbackHappen"); + registrationContextError = interpreter.get("contextTestFailed", String.class); } diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/all-hooks.py b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/all-hooks.py index 97cddf7a1ae26f9c59fc54987772c2df71fa4c6a..330495c24cfe5a63d8842f4f13b900e52c23be6b 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/all-hooks.py +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/all-hooks.py @@ -2,6 +2,10 @@ def rollback_transaction(service, transaction, algorithmRunner, throwable): global didTransactionRollbackHappen didTransactionRollbackHappen = True +def rollback_pre_registration(context, throwable): + global didPreRegistrationRollbackHappen + didPreRegistrationRollbackHappen = True + def commit_transaction(service, transaction): global didTransactionCommitHappen didTransactionCommitHappen = True