diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithm.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithm.java index 2351fd7d447937f36f5c22cdb59faaaf7a2d146c..9ad70f4b99a20d21594d4e2a3da0f2e1e574b7ef 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithm.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithm.java @@ -61,6 +61,16 @@ public class DataSetRegistrationAlgorithm public void rollback(DataSetRegistrationAlgorithm algorithm, Throwable ex); } + /** + * Interface for code that is run to register a new data set. + * + * @author Chandrasekhar Ramakrishnan + */ + public static interface IDataSetInApplicationServerRegistrator + { + public void registerDataSetInApplicationServer(NewExternalData data) throws Throwable; + } + /** * Object for holding the state necessary for registring a data set. * @@ -150,75 +160,10 @@ public class DataSetRegistrationAlgorithm this.emailSubjectTemplate = EMAIL_SUBJECT_TEMPLATE; } - public String getErrorMessageTemplate() - { - return defaultErrorMessageTemplate; - } - public File getIncomingDataSetFile() { return incomingDataSetFile; } - - public IEncapsulatedOpenBISService getOpenBisService() - { - return openBisService; - } - - public IDelegatedActionWithResult<Boolean> getCleanAftrewardsAction() - { - return cleanAfterwardsAction; - } - - public IPreRegistrationAction getPreRegistrationAction() - { - return preRegistrationAction; - } - - public IPostRegistrationAction getPostRegistrationAction() - { - return postRegistrationAction; - } - - public DataSetInformation getDataSetInformation() - { - return dataSetInformation; - } - - public IDataStoreStrategy getDataStoreStrategy() - { - return dataStoreStrategy; - } - - public ITypeExtractor getTypeExtractor() - { - return typeExtractor; - } - - public IStorageProcessor getStorageProcessor() - { - return storageProcessor; - } - - public DataSetType getDataSetType() - { - return dataSetType; - } - - public File getStoreRoot() - { - return storeRoot; - } - - public IMailClient getMailClient() - { - return mailClient; - } - - public Lock getRegistrationLock() - { - return registrationLock; - } } static private final Logger notificationLog = LogFactory.getLogger(LogCategory.NOTIFY, @@ -239,6 +184,8 @@ public class DataSetRegistrationAlgorithm // Immutable State private final DataSetRegistrationAlgorithmState state; + private final IDataSetInApplicationServerRegistrator applicationServerRegistrator; + private final IRollbackDelegate rollbackDelegate; private final File incomingDataSetFile; @@ -250,14 +197,21 @@ public class DataSetRegistrationAlgorithm private String errorMessageTemplate; - public DataSetRegistrationAlgorithm(DataSetRegistrationAlgorithmState state, + public DataSetRegistrationAlgorithm(final DataSetRegistrationAlgorithmState state, IRollbackDelegate rollbackDelegate) + { + this(state, rollbackDelegate, new DefaultApplicationServerRegistrator(state)); + } + + public DataSetRegistrationAlgorithm(DataSetRegistrationAlgorithmState state, + IRollbackDelegate rollbackDelegate, IDataSetInApplicationServerRegistrator applicationServerRegistrator) { this.state = state; this.rollbackDelegate = rollbackDelegate; incomingDataSetFile = state.incomingDataSetFile; dataSetInformation = state.dataSetInformation; - errorMessageTemplate = state.getErrorMessageTemplate(); + errorMessageTemplate = state.defaultErrorMessageTemplate; + this.applicationServerRegistrator = applicationServerRegistrator; } /** @@ -307,11 +261,9 @@ public class DataSetRegistrationAlgorithm final String errorMessage = "Error when trying to register data set '" + incomingDataSetFile.getName() + "'."; - state.getMailClient() - .sendMessage( - String.format(errorMessage, dataSetInformation - .getExperimentIdentifier().getExperimentCode()), - ex.getMessage(), null, null, userEmailOrNull); + state.mailClient.sendMessage(String.format(errorMessage, dataSetInformation + .getExperimentIdentifier().getExperimentCode()), ex.getMessage(), null, + null, userEmailOrNull); if (state.shouldDeleteUnidentified) { deleted = removeAndLog(errorMessage + " [" + ex.getMessage() + "]"); @@ -329,6 +281,21 @@ public class DataSetRegistrationAlgorithm } } + /** + * This method is only ever called for unidentified data sets. + */ + public final void dealWithUnidentifiedDataSet() + { + final boolean ok = + state.shouldDeleteUnidentified ? (removeAndLog(incomingDataSetFile.getName() + + " could not be identified.")) : FileRenamer.renameAndLog( + incomingDataSetFile, getBaseDirectoryHolder().getTargetFile()); + if (ok) + { + clean(); + } + } + public final File createBaseDirectory(final IDataStoreStrategy strategy, final File baseDir, final DataSetInformation dataSetInfo) { @@ -366,7 +333,7 @@ public class DataSetRegistrationAlgorithm public File getStoreRoot() { - return state.getStoreRoot(); + return state.storeRoot; } /** @@ -385,14 +352,33 @@ public class DataSetRegistrationAlgorithm return state.cleanAfterwardsAction.execute(); } + private static class DefaultApplicationServerRegistrator implements IDataSetInApplicationServerRegistrator + { + private final IEncapsulatedOpenBISService openBisService; + + private final DataSetInformation dataSetInformation; + + DefaultApplicationServerRegistrator(DataSetRegistrationAlgorithmState state) + { + openBisService = state.openBisService; + dataSetInformation = state.dataSetInformation; + } + + public void registerDataSetInApplicationServer(NewExternalData data) throws Throwable + { + openBisService.registerDataSet(dataSetInformation, data); + } + + } + /** - * Contact openBis and register the data set there. Subclasses may override. + * Use the applicationServerRegistrator to register the data set with the app server. * * @throws Throwable */ - protected void registerDataSetInApplicationServer(NewExternalData data) throws Throwable + private void registerDataSetInApplicationServer(NewExternalData data) throws Throwable { - state.getOpenBisService().registerDataSet(dataSetInformation, data); + applicationServerRegistrator.registerDataSetInApplicationServer(data); } private void rollback(Throwable ex) @@ -421,7 +407,7 @@ public class DataSetRegistrationAlgorithm incomingDataSetFile.getAbsolutePath()); File dataFile = getStorageProcessor().storeData(dataSetInformation, getTypeExtractor(), - state.getMailClient(), incomingDataSetFile, + state.mailClient, incomingDataSetFile, baseDirectoryHolder.getBaseDirectory()); if (getOperationLog().isInfoEnabled()) { @@ -438,7 +424,7 @@ public class DataSetRegistrationAlgorithm final BooleanOrUnknown isCompleteFlag = dataSetInformation.getIsCompleteFlag(); // Ensure that we either register the data set and initiate the processing copy or // do none of both. - state.getRegistrationLock().lock(); + state.registrationLock.lock(); try { errorMessageTemplate = DATA_SET_REGISTRATION_FAILURE_TEMPLATE; @@ -447,7 +433,7 @@ public class DataSetRegistrationAlgorithm clean(); } finally { - state.getRegistrationLock().unlock(); + state.registrationLock.unlock(); } getStorageProcessor().commit(incomingDataSetFile, baseDirectoryHolder.getBaseDirectory()); @@ -491,10 +477,9 @@ public class DataSetRegistrationAlgorithm } if (StringUtils.isBlank(email) == false) { - state.getMailClient().sendMessage( - String.format(state.emailSubjectTemplate, dataSetInformation - .getExperimentIdentifier().getExperimentCode()), msg, null, null, - email); + state.mailClient.sendMessage(String.format(state.emailSubjectTemplate, + dataSetInformation.getExperimentIdentifier().getExperimentCode()), msg, + null, null, email); } } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithmRunner.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithmRunner.java index 166572320f251c385da84fe9e3409254a02c0911..79c175c3ed05270d9898ad3fc1e912cac1c455fe 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithmRunner.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithmRunner.java @@ -22,6 +22,8 @@ import java.util.List; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; /** + * Runs DataSetRegistrationAlgorithm objects. + * * @author Chandrasekhar Ramakrishnan */ public class DataSetRegistrationAlgorithmRunner @@ -40,32 +42,45 @@ public class DataSetRegistrationAlgorithmRunner } - private final TransferredDataSetHandlerDataSetRegistrationAlgorithm registrationHelper; + private final DataSetRegistrationAlgorithm registrationAlgorithm; private final IDataSetRegistrationAlgorithmRunnerDelegate delegate; - public DataSetRegistrationAlgorithmRunner(TransferredDataSetHandlerDataSetRegistrationAlgorithm registrationAlgorithm) + public DataSetRegistrationAlgorithmRunner( + TransferredDataSetHandlerDataSetRegistrationAlgorithm registrationHelper) + { + this(registrationHelper, new NoOpDelegate()); + } + + public DataSetRegistrationAlgorithmRunner( + TransferredDataSetHandlerDataSetRegistrationAlgorithm registrationHelper, + IDataSetRegistrationAlgorithmRunnerDelegate delegate) + { + this(registrationHelper.getRegistrationAlgorithm(), delegate); + } + + public DataSetRegistrationAlgorithmRunner(DataSetRegistrationAlgorithm registrationAlgorithm) { this(registrationAlgorithm, new NoOpDelegate()); } - public DataSetRegistrationAlgorithmRunner(TransferredDataSetHandlerDataSetRegistrationAlgorithm registrationAlgorithm, + public DataSetRegistrationAlgorithmRunner(DataSetRegistrationAlgorithm registrationAlgorithm, IDataSetRegistrationAlgorithmRunnerDelegate delegate) { - this.registrationHelper = registrationAlgorithm; + this.registrationAlgorithm = registrationAlgorithm; this.delegate = delegate; } public List<DataSetInformation> runAlgorithm() { - registrationHelper.prepare(); - if (registrationHelper.hasDataSetBeenIdentified()) + registrationAlgorithm.prepare(); + if (registrationAlgorithm.hasDataSetBeenIdentified()) { - return registrationHelper.registerDataSet(); + return registrationAlgorithm.registerDataSet(); } else { delegate.didNotIdentifyDataSet(); - registrationHelper.dealWithUnidentifiedDataSet(); + registrationAlgorithm.dealWithUnidentifiedDataSet(); return Collections.emptyList(); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/IExtensibleDataSetHandler.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/IExtensibleDataSetHandler.java index 09e3e449b5fa9751be378317c6f6cd5c91e93926..df33f706bd6fb1c2d438e138d847cf0422bd8d63 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/IExtensibleDataSetHandler.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/IExtensibleDataSetHandler.java @@ -20,7 +20,6 @@ import java.io.File; import java.util.List; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; -import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; /** * An interface for data set handlers that give other code a chance to implement the registration of @@ -30,16 +29,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; */ public interface IExtensibleDataSetHandler extends IDataSetHandler { - /** - * Interface for code that is run to register a new data set. - * - * @author Chandrasekhar Ramakrishnan - */ - public static interface IDataSetRegistrator - { - public void registerDataSetInApplicationServer(NewExternalData data) throws Throwable; - } - public List<DataSetInformation> handleDataSet(final File dataSet, - DataSetInformation dataSetInformation, IDataSetRegistrator registrator); + DataSetInformation dataSetInformation, + DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator registrator); } diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java index 7c6e2a6d4fad06eed2394e9d67dd91f1f7ad493c..6ecf4feea80a5d25d0e0e13ed76dbe0f69f8c322 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java @@ -36,6 +36,7 @@ import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.mail.IMailClient; import ch.systemsx.cisd.common.utilities.IDelegatedActionWithResult; +import ch.systemsx.cisd.etlserver.DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator; import ch.systemsx.cisd.etlserver.IStorageProcessor.UnstoreDataAction; import ch.systemsx.cisd.etlserver.utils.PostRegistrationExecutor; import ch.systemsx.cisd.etlserver.utils.PreRegistrationExecutor; @@ -43,7 +44,6 @@ import ch.systemsx.cisd.etlserver.validation.IDataSetValidator; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance; -import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; /** * The class that handles the incoming data set. @@ -227,7 +227,8 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi } public List<DataSetInformation> handleDataSet(final File dataSet, - DataSetInformation dataSetInformation, IDataSetRegistrator registrator) + DataSetInformation dataSetInformation, + DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator registrator) { dataSetInformation.setInstanceCode(getHomeDatabaseInstance().getCode()); dataSetInformation.setInstanceUUID(getHomeDatabaseInstance().getUuid()); @@ -300,7 +301,8 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi } private TransferredDataSetHandlerDataSetRegistrationAlgorithm createRegistrationHelper( - File dataSet, DataSetInformation dataSetInformation, IDataSetRegistrator registrator) + File dataSet, DataSetInformation dataSetInformation, + DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator registrator) { if (useIsFinishedMarkerFile) { @@ -315,7 +317,7 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi private TransferredDataSetHandlerDataSetRegistrationAlgorithm createRegistrationHelperWithIsFinishedFile( final File isFinishedFile, final DataSetInformation dsInfo, - IDataSetRegistrator registrator) + DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator registrator) { assert isFinishedFile != null : "Unspecified is-finished file."; final String name = isFinishedFile.getName(); @@ -353,7 +355,7 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi private TransferredDataSetHandlerDataSetRegistrationAlgorithm createRegistrationHelperWithQuietPeriodFilter( File incomingDataSetFile, final DataSetInformation dsInfo, - IDataSetRegistrator registrator) + DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator registrator) { IDelegatedActionWithResult<Boolean> cleanAftrewardsAction = new IDelegatedActionWithResult<Boolean>() @@ -436,12 +438,6 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi private class RegistrationHelper extends TransferredDataSetHandlerDataSetRegistrationAlgorithm { - /** - * @param transferredDataSetHandler - * @param incomingDataSetFile - * @param cleanAftrewardsAction - * @param postRegistrationAction - */ RegistrationHelper(TransferredDataSetHandler transferredDataSetHandler, File incomingDataSetFile, IDelegatedActionWithResult<Boolean> cleanAftrewardsAction, @@ -452,6 +448,17 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi postRegistrationAction); } + RegistrationHelper(TransferredDataSetHandler transferredDataSetHandler, + File incomingDataSetFile, + IDelegatedActionWithResult<Boolean> cleanAftrewardsAction, + IPreRegistrationAction preRegistrationAction, + IPostRegistrationAction postRegistrationAction, + IDataSetInApplicationServerRegistrator appServerRegistrator) + { + super(incomingDataSetFile, cleanAftrewardsAction, preRegistrationAction, + postRegistrationAction, appServerRegistrator); + } + // state accessors @Override protected IEncapsulatedOpenBISService getOpenBisService() @@ -552,12 +559,12 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi Thread.interrupted(); // Ensure the thread's interrupted state is cleared. getOperationLog().warn( String.format("Requested to stop registration of data set '%s'", - algorithm.getDataSetInformation())); + registrationAlgorithm.getDataSetInformation())); } else { getNotificationLog().error( - String.format(algorithm.getErrorMessageTemplate(), - algorithm.getDataSetInformation()), throwable); + String.format(registrationAlgorithm.getErrorMessageTemplate(), + registrationAlgorithm.getDataSetInformation()), throwable); } // Errors which are not AssertionErrors leave the system in a state that we don't // know and can't trust. Thus we will not perform any operations any more in this @@ -566,25 +573,26 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi { throw (Error) throwable; } - UnstoreDataAction action = algorithm.rollbackStorageProcessor(throwable); + UnstoreDataAction action = registrationAlgorithm.rollbackStorageProcessor(throwable); if (stopped == false) { if (action == UnstoreDataAction.MOVE_TO_ERROR) { final File baseDirectory = - algorithm.createBaseDirectory( + registrationAlgorithm.createBaseDirectory( TransferredDataSetHandler.ERROR_DATA_STRATEGY, - algorithm.getStoreRoot(), algorithm.getDataSetInformation()); - algorithm.setBaseDirectoryHolder(new BaseDirectoryHolder( + registrationAlgorithm.getStoreRoot(), + registrationAlgorithm.getDataSetInformation()); + registrationAlgorithm.setBaseDirectoryHolder(new BaseDirectoryHolder( TransferredDataSetHandler.ERROR_DATA_STRATEGY, baseDirectory, incomingDataSetFile)); boolean moveInCaseOfErrorOk = - FileRenamer.renameAndLog(incomingDataSetFile, algorithm + FileRenamer.renameAndLog(incomingDataSetFile, registrationAlgorithm .getBaseDirectoryHolder().getTargetFile()); writeThrowable(throwable); if (moveInCaseOfErrorOk) { - algorithm.clean(); + registrationAlgorithm.clean(); } } else if (action == UnstoreDataAction.DELETE) { @@ -598,8 +606,6 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi private class OverridingRegistrationHelper extends RegistrationHelper { - private final IDataSetRegistrator registrator; - /** * @param transferredDataSetHandler * @param incomingDataSetFile @@ -610,11 +616,11 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi File incomingDataSetFile, IDelegatedActionWithResult<Boolean> cleanAftrewardsAction, IPreRegistrationAction preRegistrationAction, - IPostRegistrationAction postRegistrationAction, IDataSetRegistrator registrator) + IPostRegistrationAction postRegistrationAction, + DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator registrator) { super(transferredDataSetHandler, incomingDataSetFile, cleanAftrewardsAction, - preRegistrationAction, postRegistrationAction); - this.registrator = registrator; + preRegistrationAction, postRegistrationAction, registrator); } @Override @@ -628,11 +634,5 @@ public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegi { return false; } - - @Override - protected void registerDataSetInApplicationServer(NewExternalData data) throws Throwable - { - registrator.registerDataSetInApplicationServer(data); - } } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerDataSetRegistrationAlgorithm.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerDataSetRegistrationAlgorithm.java index af804280d97ef0f32c22084cf5860065faab6c0c..b939c0a01057266e094b430a9bd46a5ba19bea1b 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerDataSetRegistrationAlgorithm.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerDataSetRegistrationAlgorithm.java @@ -34,11 +34,11 @@ import ch.systemsx.cisd.common.filesystem.IFileOperations; import ch.systemsx.cisd.common.mail.IMailClient; import ch.systemsx.cisd.common.utilities.IDelegatedActionWithResult; import ch.systemsx.cisd.etlserver.DataSetRegistrationAlgorithm.DataSetRegistrationAlgorithmState; +import ch.systemsx.cisd.etlserver.DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator; import ch.systemsx.cisd.etlserver.validation.IDataSetValidator; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance; -import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; public abstract class TransferredDataSetHandlerDataSetRegistrationAlgorithm implements DataSetRegistrationAlgorithm.IRollbackDelegate @@ -61,7 +61,7 @@ public abstract class TransferredDataSetHandlerDataSetRegistrationAlgorithm impl protected final File incomingDataSetFile; - protected final DataSetRegistrationAlgorithm algorithm; + protected final DataSetRegistrationAlgorithm registrationAlgorithm; public TransferredDataSetHandlerDataSetRegistrationAlgorithm(File incomingDataSetFile, IDelegatedActionWithResult<Boolean> cleanAftrewardsAction, @@ -79,16 +79,42 @@ public abstract class TransferredDataSetHandlerDataSetRegistrationAlgorithm impl getStorageProcessor(), getFileOperations(), getDataSetValidator(), getMailClient(), shouldDeleteUnidentified(), getRegistrationLock(), getDataStoreCode(), shouldNotifySuccessfulRegistration()); - algorithm = new DataSetRegistrationAlgorithm(algorithmState, this); + registrationAlgorithm = new DataSetRegistrationAlgorithm(algorithmState, this); this.incomingDataSetFile = algorithmState.getIncomingDataSetFile(); } + public TransferredDataSetHandlerDataSetRegistrationAlgorithm(File incomingDataSetFile, + IDelegatedActionWithResult<Boolean> cleanAftrewardsAction, + IPreRegistrationAction preRegistrationAction, + IPostRegistrationAction postRegistrationAction, IDataSetInApplicationServerRegistrator appServerRegistrator) + { + DataSetInformation dataSetInformation = extractDataSetInformation(incomingDataSetFile); + IDataStoreStrategy dataStoreStrategy = + getDataStrategyStore() + .getDataStoreStrategy(dataSetInformation, incomingDataSetFile); + DataSetRegistrationAlgorithmState algorithmState = + new DataSetRegistrationAlgorithmState(incomingDataSetFile, getOpenBisService(), + cleanAftrewardsAction, preRegistrationAction, postRegistrationAction, + dataSetInformation, dataStoreStrategy, getTypeExtractor(), + getStorageProcessor(), getFileOperations(), getDataSetValidator(), + getMailClient(), shouldDeleteUnidentified(), getRegistrationLock(), + getDataStoreCode(), shouldNotifySuccessfulRegistration()); + registrationAlgorithm = + new DataSetRegistrationAlgorithm(algorithmState, this, appServerRegistrator); + this.incomingDataSetFile = algorithmState.getIncomingDataSetFile(); + } + + public DataSetRegistrationAlgorithm getRegistrationAlgorithm() + { + return registrationAlgorithm; + } + /** * Return the data set information. */ public DataSetInformation getDataSetInformation() { - return algorithm.getDataSetInformation(); + return registrationAlgorithm.getDataSetInformation(); } /** @@ -96,12 +122,12 @@ public abstract class TransferredDataSetHandlerDataSetRegistrationAlgorithm impl */ public final void prepare() { - algorithm.prepare(); + registrationAlgorithm.prepare(); } public final boolean hasDataSetBeenIdentified() { - return algorithm.hasDataSetBeenIdentified(); + return registrationAlgorithm.hasDataSetBeenIdentified(); } /** @@ -109,7 +135,7 @@ public abstract class TransferredDataSetHandlerDataSetRegistrationAlgorithm impl */ public final List<DataSetInformation> registerDataSet() { - return algorithm.registerDataSet(); + return registrationAlgorithm.registerDataSet(); } /** @@ -117,34 +143,7 @@ public abstract class TransferredDataSetHandlerDataSetRegistrationAlgorithm impl */ public final void dealWithUnidentifiedDataSet() { - final boolean ok = - shouldDeleteUnidentified() ? (removeAndLog(incomingDataSetFile.getName() - + " could not be identified.")) : FileRenamer.renameAndLog( - incomingDataSetFile, algorithm.getBaseDirectoryHolder().getTargetFile()); - if (ok) - { - algorithm.clean(); - } - } - - private boolean removeAndLog(String msg) - { - final boolean ok = getFileOperations().removeRecursivelyQueueing(incomingDataSetFile); - if (getOperationLog().isInfoEnabled()) - { - getOperationLog().info("Dataset deleted in registration: " + msg); - } - return ok; - } - - /** - * Contact openBis and register the data set there. Subclasses may override. - * - * @throws Throwable - */ - protected void registerDataSetInApplicationServer(NewExternalData data) throws Throwable - { - getOpenBisService().registerDataSet(algorithm.getDataSetInformation(), data); + registrationAlgorithm.dealWithUnidentifiedDataSet(); } /** @@ -193,8 +192,8 @@ public abstract class TransferredDataSetHandlerDataSetRegistrationAlgorithm impl { final String fileName = incomingDataSetFile.getName() + ".exception"; final File file = - new File(algorithm.getBaseDirectoryHolder().getTargetFile().getParentFile(), - fileName); + new File(registrationAlgorithm.getBaseDirectoryHolder().getTargetFile() + .getParentFile(), fileName); FileWriter writer = null; try { diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetExecutor.java index ef1b0c8e2a939d757c7b73b5f4bd8f5b0c2d7992..541ba1dcb106b5c4759ad228bd9992de537bfadb 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetExecutor.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetExecutor.java @@ -581,7 +581,7 @@ class PutDataSetExecutor implements IDataSetHandlerRpc @Override protected void rollback(Throwable ex) { - algorithm.rollbackStorageProcessor(ex); + registrationAlgorithm.rollbackStorageProcessor(ex); if (ex instanceof UserFailureException) { throw (UserFailureException) ex; diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/entityregistration/SampleAndDataSetRegistrator.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/entityregistration/SampleAndDataSetRegistrator.java index 05efead3dd5ae21fc307336ba77ac73cb35aff30..1bfe32b30fbf40408e036d2ec96e296c01907b3c 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/entityregistration/SampleAndDataSetRegistrator.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/entityregistration/SampleAndDataSetRegistrator.java @@ -19,8 +19,8 @@ package ch.systemsx.cisd.etlserver.entityregistration; import java.io.File; import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.etlserver.DataSetRegistrationAlgorithm; import ch.systemsx.cisd.etlserver.IExtensibleDataSetHandler; -import ch.systemsx.cisd.etlserver.TransferredDataSetHandler; import ch.systemsx.cisd.etlserver.entityregistration.SampleAndDataSetControlFileProcessor.ControlFileRegistrationProperties; import ch.systemsx.cisd.etlserver.entityregistration.SampleDataSetPair.SampleDataSetPairProcessing; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; @@ -41,7 +41,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFa * @author Chandrasekhar Ramakrishnan */ class SampleAndDataSetRegistrator extends AbstractSampleAndDataSetProcessor implements - TransferredDataSetHandler.IDataSetRegistrator + DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator { private final ControlFileRegistrationProperties properties; diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithmTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithmTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5c6c29203f11825865628bc585bcc8851563e07b --- /dev/null +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/DataSetRegistrationAlgorithmTest.java @@ -0,0 +1,339 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.etlserver; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.locks.Lock; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.api.Action; +import org.jmock.api.Invocation; +import org.jmock.lib.action.CustomAction; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import ch.systemsx.cisd.common.filesystem.FileOperations; +import ch.systemsx.cisd.common.filesystem.FileUtilities; +import ch.systemsx.cisd.common.filesystem.IFileOperations; +import ch.systemsx.cisd.common.mail.IMailClient; +import ch.systemsx.cisd.common.test.RecordingMatcher; +import ch.systemsx.cisd.common.utilities.IDelegatedActionWithResult; +import ch.systemsx.cisd.etlserver.DataSetRegistrationAlgorithm.DataSetRegistrationAlgorithmState; +import ch.systemsx.cisd.etlserver.DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator; +import ch.systemsx.cisd.etlserver.DataSetRegistrationAlgorithm.IRollbackDelegate; +import ch.systemsx.cisd.etlserver.validation.IDataSetValidator; +import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; +import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LocatorType; +import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; +import ch.systemsx.cisd.openbis.generic.shared.dto.StorageFormat; + +/** + * @author Chandrasekhar Ramakrishnan + */ +public class DataSetRegistrationAlgorithmTest extends AbstractFileSystemTestCase +{ + + private static final String DATA_STORE_CODE = "data-store"; + + private static final String DATA_SET_CODE = "data-set-code"; + + private static final LocatorType LOCATOR_TYPE = new LocatorType("L1"); + + private static final DataSetType DATA_SET_TYPE = new DataSetType("O1"); + + private static final FileFormatType FILE_FORMAT_TYPE = new FileFormatType("FF1"); + + private static final String EXAMPLE_PROCESSOR_ID = "DATA_ACQUISITION"; + + private DataSetRegistrationAlgorithm registrationAlgorithm; + + private Mockery context; + + private IEncapsulatedOpenBISService openBisService; + + private IRollbackDelegate rollbackDelegate; + + private IDataSetInApplicationServerRegistrator appServerRegistrator; + + private IDelegatedActionWithResult<Boolean> cleanAftrewardsAction; + + private IPreRegistrationAction preRegistrationAction; + + private IPostRegistrationAction postRegistrationAction; + + private IDataStoreStrategy dataStoreStrategy; + + private ITypeExtractor typeExtractor; + + private IStorageProcessor storageProcessor; + + private IFileOperations fileOperations; + + private IDataSetValidator dataSetValidator; + + private IMailClient mailClient; + + private Lock registrationLock; + + private RecordingMatcher<Throwable> exceptionMatcher; + + private DataSetInformation dataSetInformation; + + private File incomingDataSetFile; + + private File storedDataSetFile; + + @SuppressWarnings("unchecked") + @Override + @BeforeMethod + public void setUp() throws IOException + { + super.setUp(); + context = new Mockery(); + openBisService = context.mock(IEncapsulatedOpenBISService.class); + rollbackDelegate = context.mock(IRollbackDelegate.class); + appServerRegistrator = context.mock(IDataSetInApplicationServerRegistrator.class); + cleanAftrewardsAction = context.mock(IDelegatedActionWithResult.class); + preRegistrationAction = context.mock(IPreRegistrationAction.class); + postRegistrationAction = context.mock(IPostRegistrationAction.class); + + dataStoreStrategy = context.mock(IDataStoreStrategy.class); + typeExtractor = context.mock(ITypeExtractor.class); + storageProcessor = context.mock(IStorageProcessor.class); + // fileOperations = context.mock(IFileOperations.class); + fileOperations = FileOperations.getInstance(); + dataSetValidator = context.mock(IDataSetValidator.class); + mailClient = context.mock(IMailClient.class); + registrationLock = context.mock(Lock.class); + exceptionMatcher = new RecordingMatcher<Throwable>(); + + dataSetInformation = new DataSetInformation(); + } + + @Test + public void testSuccessfulRegistrationWithoutNotification() throws Throwable + { + incomingDataSetFile = createDirectory("data_set"); + storedDataSetFile = createDirectory("stored_data_set"); + + FileUtilities.writeToFile(new File(incomingDataSetFile, "read.me"), "hello world"); + setUpExpectations(incomingDataSetFile); + + createAlgorithmAndState(true, false); + + new DataSetRegistrationAlgorithmRunner(registrationAlgorithm).runAlgorithm(); + + for (Throwable ex : exceptionMatcher.getRecordedObjects()) + { + ex.printStackTrace(); + } + + context.assertIsSatisfied(); + } + + private void setUpExpectations(final File incomingDataSetFile) throws Throwable + { + setUpOpenBisExpectations(); + setUpTypeExtractorExpectations(); + setUpStorageProcessorExpectations(); + setUpDataSetValidatorExpectations(); + setUpDataStoreStrategyExpectations(); + setUpPreAndPostRegistrationExpectations(); + setUpLockExpectations(); + setUpDataSetRegistratorExpectations(); + setUpCleanAfterwardsExpectations(); + setUpRollbackExpectations(); + } + + private void setUpOpenBisExpectations() + { + context.checking(new Expectations() + { + { + one(openBisService).createDataSetCode(); + will(returnValue(DATA_SET_CODE)); + } + }); + } + + private void setUpTypeExtractorExpectations() + { + context.checking(new Expectations() + { + { + one(typeExtractor).getLocatorType(incomingDataSetFile); + will(returnValue(LOCATOR_TYPE)); + + one(typeExtractor).getFileFormatType(incomingDataSetFile); + will(returnValue(FILE_FORMAT_TYPE)); + + one(typeExtractor).getProcessorType(incomingDataSetFile); + will(returnValue(EXAMPLE_PROCESSOR_ID)); + + one(typeExtractor).isMeasuredData(incomingDataSetFile); + will(returnValue(true)); + + one(typeExtractor).getDataSetType(incomingDataSetFile); + will(returnValue(DATA_SET_TYPE)); + + one(typeExtractor).getDataSetType(with(any(File.class))); + will(returnValue(DATA_SET_TYPE)); + } + }); + } + + private void setUpStorageProcessorExpectations() + { + final Action storeDataAction = new CustomAction("StoreData") + { + + public Object invoke(Invocation invocation) throws Throwable + { + fileOperations.move(incomingDataSetFile, storedDataSetFile); + return storedDataSetFile; + } + }; + + context.checking(new Expectations() + { + { + one(storageProcessor).getStoreRootDirectory(); + will(returnValue(workingDirectory)); + + one(storageProcessor).storeData(dataSetInformation, typeExtractor, mailClient, + incomingDataSetFile, workingDirectory); + will(storeDataAction); + + one(storageProcessor).getStorageFormat(); + will(returnValue(StorageFormat.PROPRIETARY)); + + one(storageProcessor).commit(incomingDataSetFile, workingDirectory); + } + }); + } + + private void setUpDataStoreStrategyExpectations() + { + context.checking(new Expectations() + { + { + one(dataStoreStrategy).getBaseDirectory(with(workingDirectory), + with(any(DataSetInformation.class)), with(DATA_SET_TYPE)); + will(returnValue(workingDirectory)); + + one(dataStoreStrategy).getKey(); + will(returnValue(DataStoreStrategyKey.IDENTIFIED)); + } + }); + } + + private void setUpDataSetValidatorExpectations() + { + context.checking(new Expectations() + { + { + one(dataSetValidator).assertValidDataSet(DATA_SET_TYPE, incomingDataSetFile); + } + }); + } + + private void setUpPreAndPostRegistrationExpectations() + { + context.checking(new Expectations() + { + { + one(preRegistrationAction).execute(DATA_SET_CODE, + incomingDataSetFile.getAbsolutePath()); + + one(postRegistrationAction).execute(with(DATA_SET_CODE), + with(any(String.class))); + } + }); + } + + private void setUpLockExpectations() + { + context.checking(new Expectations() + { + { + one(registrationLock).lock(); + one(registrationLock).unlock(); + } + }); + } + + private void setUpDataSetRegistratorExpectations() throws Throwable + { + context.checking(new Expectations() + { + { + one(appServerRegistrator).registerDataSetInApplicationServer( + with(any(NewExternalData.class))); + } + }); + } + + private void setUpCleanAfterwardsExpectations() + { + context.checking(new Expectations() + { + { + one(cleanAftrewardsAction).execute(); + will(returnValue(Boolean.TRUE)); + } + }); + } + + private void setUpRollbackExpectations() + { + context.checking(new Expectations() + { + { + allowing(rollbackDelegate).rollback( + with(any(DataSetRegistrationAlgorithm.class)), with(exceptionMatcher)); + } + }); + } + + private void createAlgorithmAndState(boolean shouldDeleteUnidentified, + boolean shouldNotifySuccessfulRegistration) + { + + String dataStoreCode = DATA_STORE_CODE; + DataSetRegistrationAlgorithmState state = + new DataSetRegistrationAlgorithmState(incomingDataSetFile, openBisService, + cleanAftrewardsAction, preRegistrationAction, postRegistrationAction, + dataSetInformation, dataStoreStrategy, typeExtractor, storageProcessor, + fileOperations, dataSetValidator, mailClient, shouldDeleteUnidentified, + registrationLock, dataStoreCode, shouldNotifySuccessfulRegistration); + registrationAlgorithm = + new DataSetRegistrationAlgorithm(state, rollbackDelegate, appServerRegistrator); + } + + private File createDirectory(final String directoryName) + { + final File file = new File(workingDirectory, directoryName); + file.mkdir(); + return file; + } +} diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/entityregistration/SampleAndDatasetRegistrationHandlerTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/entityregistration/SampleAndDatasetRegistrationHandlerTest.java index ad4bb0afa9a5f0836627da08f58507a08da3f5c7..4437d9a146e53acb4ae3f69a40c4a7cef6caa751 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/entityregistration/SampleAndDatasetRegistrationHandlerTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/entityregistration/SampleAndDatasetRegistrationHandlerTest.java @@ -39,8 +39,8 @@ import ch.systemsx.cisd.common.logging.BufferedAppender; import ch.systemsx.cisd.common.mail.EMailAddress; import ch.systemsx.cisd.common.mail.IMailClient; import ch.systemsx.cisd.common.test.RecordingMatcher; +import ch.systemsx.cisd.etlserver.DataSetRegistrationAlgorithm; import ch.systemsx.cisd.etlserver.IExtensibleDataSetHandler; -import ch.systemsx.cisd.etlserver.IExtensibleDataSetHandler.IDataSetRegistrator; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; @@ -500,8 +500,8 @@ public class SampleAndDatasetRegistrationHandlerTest extends AbstractFileSystemT { { final RecordingMatcher<File> fileMatcher = new RecordingMatcher<File>(); - final RecordingMatcher<IExtensibleDataSetHandler.IDataSetRegistrator> registratorMatcher = - new RecordingMatcher<IExtensibleDataSetHandler.IDataSetRegistrator>(); + final RecordingMatcher<DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator> registratorMatcher = + new RecordingMatcher<DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator>(); for (int i = 1; i < 4; ++i) { @@ -520,9 +520,9 @@ public class SampleAndDatasetRegistrationHandlerTest extends AbstractFileSystemT { public Object invoke(Invocation invocation) throws Throwable { - List<IDataSetRegistrator> recordedObjects = + List<DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator> recordedObjects = registratorMatcher.getRecordedObjects(); - IDataSetRegistrator registrator = + DataSetRegistrationAlgorithm.IDataSetInApplicationServerRegistrator registrator = recordedObjects.get(recordedObjects.size() - 1); fillExternalDataFromInformation(externalData, dataSetInfoMatcher .getRecordedObjects().get(recordedObjects.size() - 1));