diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/JythonTopLevelDataSetHandlerV2.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/JythonTopLevelDataSetHandlerV2.java index 1dc810d763b82f82832a44c4ded4c906098675af..aadcbdfb1d2e85ac5ec5fe00ad2d0505b095c538 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/JythonTopLevelDataSetHandlerV2.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v2/JythonTopLevelDataSetHandlerV2.java @@ -17,6 +17,7 @@ package ch.systemsx.cisd.etlserver.registrator.api.v2; import java.io.File; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -35,6 +36,7 @@ import ch.systemsx.cisd.etlserver.TopLevelDataSetRegistratorGlobalState; import ch.systemsx.cisd.etlserver.registrator.DataSetFile; import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationPersistentMap; import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationService; +import ch.systemsx.cisd.etlserver.registrator.DataSetStorageAlgorithm; import ch.systemsx.cisd.etlserver.registrator.DataSetStorageAlgorithmRunner; import ch.systemsx.cisd.etlserver.registrator.DataSetStorageAlgorithmRunner.IPrePostRegistrationHook; import ch.systemsx.cisd.etlserver.registrator.DataSetStorageAlgorithmRunner.IRollbackDelegate; @@ -42,6 +44,7 @@ import ch.systemsx.cisd.etlserver.registrator.DataSetStorageRollbacker; import ch.systemsx.cisd.etlserver.registrator.IDataSetOnErrorActionDecision.ErrorType; import ch.systemsx.cisd.etlserver.registrator.MarkerFileUtility; import ch.systemsx.cisd.etlserver.registrator.api.v1.impl.AbstractTransactionState; +import ch.systemsx.cisd.etlserver.registrator.api.v1.impl.RollbackStack; import ch.systemsx.cisd.etlserver.registrator.api.v1.impl.RollbackStack.IRollbackStackDelegate; import ch.systemsx.cisd.etlserver.registrator.recovery.AbstractRecoveryState; import ch.systemsx.cisd.etlserver.registrator.recovery.DataSetStoragePrecommitRecoveryState; @@ -329,11 +332,16 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend } }; + ArrayList<DataSetStorageAlgorithm<T>> dataSetStorageAlgorithms = + recoveryState.getDataSetStorageAlgorithms(state); + + RollbackStack rollbackStack = recoveryState.getRollbackStack(); + DataSetStorageAlgorithmRunner<T> runner = new DataSetStorageAlgorithmRunner<T>(recoveryState.getIncomingDataSetFile(), // incoming - recoveryState.getDataSetStorageAlgorithms(state), // algorithms + dataSetStorageAlgorithms, // algorithms rollbackDelegate, // rollback delegate, - recoveryState.getRollbackStack(), // rollbackstack + rollbackStack, // rollbackstack logger, // registrationLogger state.getGlobalState().getOpenBisService(), // openBisService hookAdaptor, // the hooks @@ -375,9 +383,9 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend new AbstractTransactionState.LiveTransactionRollbackDelegate(state .getGlobalState().getStagingDir()); - recoveryState.getRollbackStack().setLockedState(false); + rollbackStack.setLockedState(false); - recoveryState.getRollbackStack().rollbackAll(rollbackStackDelegate); + rollbackStack.rollbackAll(rollbackStackDelegate); UnstoreDataAction action = state.getOnErrorActionDecision().computeUndoAction( ErrorType.OPENBIS_REGISTRATION_FAILURE, null); @@ -395,6 +403,7 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend hookAdaptor.executePreRegistrationRollback(persistentMapHolder, null); + finishRegistration(dataSetStorageAlgorithms, rollbackStack); } else { @@ -424,6 +433,10 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend shouldStopRecovery = true; logger.registerSuccess(); + + // do the actions performed when the registration comes into terminal state. + finishRegistration(dataSetStorageAlgorithms, rollbackStack); + } } } catch (Throwable error) @@ -446,6 +459,18 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend } + private void finishRegistration(ArrayList<DataSetStorageAlgorithm<T>> dataSetStorageAlgorithms, + RollbackStack rollbackStack) + { + System.out.println("finish him"); + for (DataSetStorageAlgorithm<T> algorithm : dataSetStorageAlgorithms) + { + System.out.println("finish him " + algorithm.getStagingFile()); + algorithm.getStagingFile().delete(); + } + rollbackStack.discard(); + } + /** * Create an adaptor that offers access to the recovery hook functions. */ diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/JythonDropboxRecoveryTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/JythonDropboxRecoveryTest.java index 3c4fbfb6fd856c3de986a9d713fa890cbda2cfab..c9a592e5737c231bb9c77b4ec636576141b66b81 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/JythonDropboxRecoveryTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/JythonDropboxRecoveryTest.java @@ -277,14 +277,11 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest assertNoOriginalMarkerFileExists(); assertNoRecoveryMarkerFile(); - assertDirEmpty(stagingDirectory); - assertJythonHooks("pre_metadata_registration", "rollback_pre_registration"); - // FIXME: this check is commented out because of a bug! - // assertDirEmpty(precommitDirectory); - // assert there is no recovery file - // rolllback requirementes + assertDirEmptyOrContainsEmptyDirs(precommitDirectory); + + assertNoRecoveryMarkerFile(); } private void assertJythonHooks(String... messages) @@ -318,8 +315,7 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest // item in store assertStorageProcess(atomicatOperationDetails.recordedObject(), DATA_SET_CODE, "sub_data_set_1", 0); - // FIXME: this is commented out to cover the bug! beware - // assertDirEmpty(stagingDirectory); + assertDirEmpty(precommitDirectory); assertNoOriginalMarkerFileExists(); @@ -330,10 +326,8 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest break; case RECOVERY_ROLLED_BACK: assertDataSetNotStoredProcess(DATA_SET_CODE); - assertDirEmpty(stagingDirectory); - // FIXME: this is commented out to cover the bug! beware - // assertDirEmpty(precommitDirectory); + assertDirEmptyOrContainsEmptyDirs(precommitDirectory); assertNoOriginalMarkerFileExists(); assertNoRecoveryMarkerFile(); @@ -404,6 +398,21 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest assertEquals(contents, "[]", Arrays.asList(file.list()).toString()); } + private void assertDirEmptyOrContainsEmptyDirs(File file) + { + for (String s : file.list()) + { + File subFile = new File(file, s); + if (subFile.isFile()) + { + fail("Directory " + file + " is not empty! It contains a file" + s); + } else if (subFile.isDirectory()) + { + assertDirEmptyOrContainsEmptyDirs(subFile); + } + } + } + private void assertOriginalMarkerFileExists() { assertTrue( @@ -499,7 +508,7 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest context.checking(new StorageErrorExpectations(atomicatOperationDetails)); handleAndMakeRecoverableImmediately(testCase); - + JythonHookTestTool.assertMessagesInWorkingDirectory(workingDirectory, "pre_metadata_registration", "post_metadata_registration"); @@ -508,23 +517,25 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest assertOriginalMarkerFileExists(); makeFileSystemAvailable(workingDirectory); - + // this recovery should succeed handler.handle(markerFile); assertStorageProcess(atomicatOperationDetails.recordedObject(), DATA_SET_CODE, "sub_data_set_1", 0); - + assertNoOriginalMarkerFileExists(); assertNoRecoveryMarkerFile(); + assertDirEmpty(precommitDirectory); + // // // item in store // // JythonHookTestTool.assertMessagesInWorkingDirectory(workingDirectory, "post_storage"); } - + // INFO: test with recovery from error in storage confirmed @Test public void testRecoveryFailureAtStorageConfirmed() @@ -566,6 +577,8 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest assertNoOriginalMarkerFileExists(); assertNoRecoveryMarkerFile(); + assertDirEmpty(precommitDirectory); + // // // item in store // @@ -651,6 +664,8 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest assertNoOriginalMarkerFileExists(); assertNoRecoveryMarkerFile(); + assertDirEmpty(precommitDirectory); + JythonHookTestTool.assertMessagesInWorkingDirectory(workingDirectory, "post_storage"); } @@ -731,14 +746,13 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest { initialExpectations(); registerDataSetsAndMakeFileSystemUnavailable(); - + // the recovery should happen here setStorageConfirmed(false); } } - class BasicRecoveryTestExpectations extends AbstractExpectations { final RecoveryTestCase testCase; @@ -909,7 +923,8 @@ public class JythonDropboxRecoveryTest extends AbstractJythonDataSetHandlerTest one(openBisService).drawANewUniqueID(); will(returnValue(new Long(1))); one(openBisService).performEntityOperations(with(atomicatOperationDetails)); - will(doAll(makeFileSystemUnavailableAction(), returnValue(new AtomicEntityOperationResult()))); + will(doAll(makeFileSystemUnavailableAction(), + returnValue(new AtomicEntityOperationResult()))); } /**