From 539dbfbe6766951a9e12105fd698e727703feb9c Mon Sep 17 00:00:00 2001
From: jakubs <jakubs>
Date: Tue, 22 May 2012 11:15:10 +0000
Subject: [PATCH] SP-45, BIS-21 Call jython post-registration hook from
 recovery code

SVN: 25330
---
 ...tOmniscientTopLevelDataSetRegistrator.java |   4 +-
 ... => DataSetRegistrationPersistentMap.java} |   9 +-
 .../DataSetRegistrationService.java           |  10 +-
 .../DataSetStorageAlgorithmRunner.java        |  23 ++--
 .../DataSetStoragePrecommitRecoveryState.java |   6 +-
 .../JythonTopLevelDataSetHandler.java         |  51 ++++---
 .../v1/IDataSetRegistrationTransaction.java   |   4 +-
 .../impl/DataSetRegistrationTransaction.java  |  18 ++-
 .../v2/JythonTopLevelDataSetHandlerV2.java    | 124 +++++++++++++++---
 9 files changed, 180 insertions(+), 69 deletions(-)
 rename datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/{DataSetRegistrationContext.java => DataSetRegistrationPersistentMap.java} (87%)

diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/AbstractOmniscientTopLevelDataSetRegistrator.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/AbstractOmniscientTopLevelDataSetRegistrator.java
index 88561c438e3..605cb5e5b81 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/AbstractOmniscientTopLevelDataSetRegistrator.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/AbstractOmniscientTopLevelDataSetRegistrator.java
@@ -613,7 +613,7 @@ public abstract class AbstractOmniscientTopLevelDataSetRegistrator<T extends Dat
      * Subclasses can override and implement their own handling logic.
      */
     public void didPreRegistration(DataSetRegistrationService<T> service,
-            DataSetRegistrationTransaction<T> transaction)
+            DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
     {
     }
 
@@ -623,7 +623,7 @@ public abstract class AbstractOmniscientTopLevelDataSetRegistrator<T extends Dat
      * Subclasses can override and implement their own handling logic.
      */
     public void didPostRegistration(DataSetRegistrationService<T> service,
-            DataSetRegistrationTransaction<T> transaction)
+            DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
     {
     }
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationContext.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationPersistentMap.java
similarity index 87%
rename from datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationContext.java
rename to datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationPersistentMap.java
index c80398f9f35..ec39af853e2 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationContext.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationPersistentMap.java
@@ -12,13 +12,18 @@ import java.util.Set;
  * 
  * @author jakubs
  */
-public class DataSetRegistrationContext implements Serializable
+public class DataSetRegistrationPersistentMap implements Serializable
 {
+    public static interface IHolder
+    {
+        DataSetRegistrationPersistentMap getPersistentMap();
+    }
+    
     private static final long serialVersionUID = 1L;
     
     private HashMap<String, Serializable> persistentMap;
     
-    public DataSetRegistrationContext()
+    public DataSetRegistrationPersistentMap()
     {
         persistentMap  = new HashMap<String, Serializable>();
     }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationService.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationService.java
index 177a2be39a3..2eeb8c838fc 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetRegistrationService.java
@@ -259,19 +259,19 @@ public class DataSetRegistrationService<T extends DataSetInformation> implements
         registrator.didRollbackTransaction(this, transaction, algorithm, ex);
     }
 
-    public void didCommitTransaction(DataSetRegistrationTransaction<T> transaction)
+    public void executePostCommit(DataSetRegistrationTransaction<T> transaction)
     {
         registrator.didCommitTransaction(this, transaction);
     }
 
-    public void executePreRegistration(DataSetRegistrationTransaction<T> transaction)
+    public void executePreRegistration(DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
     {
-        registrator.didPreRegistration(this, transaction);
+        registrator.didPreRegistration(this, persistentMapHolder);
     }
 
-    public void executePostRegistration(DataSetRegistrationTransaction<T> transaction)
+    public void executePostRegistration(DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
     {
-        registrator.didPostRegistration(this, transaction);
+        registrator.didPostRegistration(this, persistentMapHolder);
     }
 
     public void didEncounterSecondaryTransactionErrors(
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetStorageAlgorithmRunner.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetStorageAlgorithmRunner.java
index e48c1bb7a04..a9105811583 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetStorageAlgorithmRunner.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetStorageAlgorithmRunner.java
@@ -66,9 +66,9 @@ public class DataSetStorageAlgorithmRunner<T extends DataSetInformation>
 
     public static interface IPrePostRegistrationHook<T extends DataSetInformation>
     {
-        public void executePreRegistration(DataSetRegistrationTransaction<T> transaction);
+        public void executePreRegistration(DataSetRegistrationPersistentMap.IHolder persistentMapHolder);
 
-        public void executePostRegistration(DataSetRegistrationTransaction<T> transaction);
+        public void executePostRegistration(DataSetRegistrationPersistentMap.IHolder persistentMapHolder);
     }
 
     static private final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
@@ -89,8 +89,8 @@ public class DataSetStorageAlgorithmRunner<T extends DataSetInformation>
 
     private final IRollbackStack rollbackStack;
 
-    private final DataSetRegistrationTransaction<T> transaction;
-
+    private final DataSetRegistrationPersistentMap.IHolder persistentMapHolder;
+    
     private final IPrePostRegistrationHook<T> postPreRegistrationHooks;
 
     private final DssRegistrationLogger dssRegistrationLog;
@@ -113,7 +113,7 @@ public class DataSetStorageAlgorithmRunner<T extends DataSetInformation>
                 new ArrayList<DataSetStorageAlgorithm<T>>(dataSetStorageAlgorithms);
         this.rollbackDelegate = transaction;
         this.applicationServerRegistrator = transaction;
-        this.transaction = transaction;
+        this.persistentMapHolder = transaction;
         this.rollbackStack = rollbackStack;
         this.dssRegistrationLog = dssRegistrationLog;
         this.openBISService = openBISService;
@@ -130,13 +130,14 @@ public class DataSetStorageAlgorithmRunner<T extends DataSetInformation>
             IRollbackDelegate<T> rollbackDelegate, IRollbackStack rollbackStack,
             DssRegistrationLogger dssRegistrationLog, IEncapsulatedOpenBISService openBISService,
             IPrePostRegistrationHook<T> postPreRegistrationHooks,
-            IDataSetStorageRecoveryManager storageRecoveryManager)
+            IDataSetStorageRecoveryManager storageRecoveryManager,
+            DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
     {
         this.dataSetStorageAlgorithms =
                 new ArrayList<DataSetStorageAlgorithm<T>>(dataSetStorageAlgorithms);
         this.rollbackDelegate = rollbackDelegate;
         this.applicationServerRegistrator = null;
-        this.transaction = null;
+        this.persistentMapHolder = persistentMapHolder;
         this.rollbackStack = rollbackStack;
         this.dssRegistrationLog = dssRegistrationLog;
         this.openBISService = openBISService;
@@ -249,7 +250,7 @@ public class DataSetStorageAlgorithmRunner<T extends DataSetInformation>
     {
         try
         {
-            postPreRegistrationHooks.executePreRegistration(transaction);
+            postPreRegistrationHooks.executePreRegistration(persistentMapHolder);
         } catch (Throwable throwable)
         {
             rollbackDuringPreRegistration(throwable);
@@ -483,7 +484,7 @@ public class DataSetStorageAlgorithmRunner<T extends DataSetInformation>
     {
         try
         {
-            postPreRegistrationHooks.executePostRegistration(transaction);
+            postPreRegistrationHooks.executePostRegistration(persistentMapHolder);
         } catch (final Throwable throwable)
         {
             dssRegistrationLog.log("Post-registration action failed:");
@@ -562,8 +563,8 @@ public class DataSetStorageAlgorithmRunner<T extends DataSetInformation>
         return incomingDataSetFile;
     }
     
-    public DataSetRegistrationContext getPersistentMap()
+    public DataSetRegistrationPersistentMap getPersistentMap()
     {
-        return transaction.getTransactionPersistentMap();
+        return persistentMapHolder.getPersistentMap();
     }
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetStoragePrecommitRecoveryState.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetStoragePrecommitRecoveryState.java
index b4f5c95f6ca..91d1f0d122e 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetStoragePrecommitRecoveryState.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DataSetStoragePrecommitRecoveryState.java
@@ -43,9 +43,9 @@ public class DataSetStoragePrecommitRecoveryState<T extends DataSetInformation>
 
     private final DataSetFile incomingDataSetFile;
     
-    private final DataSetRegistrationContext persistentMap;
+    private final DataSetRegistrationPersistentMap persistentMap;
     
-    public DataSetRegistrationContext getPersistentMap()
+    public DataSetRegistrationPersistentMap getPersistentMap()
     {
         return persistentMap;
     }
@@ -53,7 +53,7 @@ public class DataSetStoragePrecommitRecoveryState<T extends DataSetInformation>
     public DataSetStoragePrecommitRecoveryState(
             List<DataSetStorageAlgorithm<T>> dataSetStorageAlgorithms,
             DssRegistrationLogger logger, IRollbackStack rollbackStack, DataSetFile incomingDataSetFile,
-            DataSetRegistrationContext persistentMap)
+            DataSetRegistrationPersistentMap persistentMap)
     {
         this.dataSetRecoveryStorageAlgorithms =
                 new ArrayList<DataSetStoragePrecommitRecoveryAlgorithm<T>>();
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 f1530488d62..ef133ae9a04 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
@@ -45,7 +45,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
         AbstractOmniscientTopLevelDataSetRegistrator<T>
 {
-    private enum JythonHookFunction
+    protected enum JythonHookFunction
     {
         /**
          * The name of the function to define to hook into the service rollback mechanism.
@@ -129,7 +129,7 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
     // The key for the script in the properties file
     public static final String SCRIPT_PATH_KEY = "script-path";
 
-    private final File scriptFile;
+    protected final File scriptFile;
 
     /**
      * Constructor.
@@ -176,7 +176,7 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
         interpreter.exec(scriptString);
 
         executeJythonProcessFunction(service.interpreter);
-        
+
         verifyEvaluatorHookFunctions(interpreter);
     }
 
@@ -188,7 +188,7 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
 
     }
 
-    private void verifyEvaluatorHookFunctions(PythonInterpreter interpreter)
+    protected void verifyEvaluatorHookFunctions(PythonInterpreter interpreter)
     {
         for (JythonHookFunction function : JythonHookFunction.values())
         {
@@ -290,18 +290,18 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
 
     @Override
     public void didPreRegistration(DataSetRegistrationService<T> service,
-            DataSetRegistrationTransaction<T> transaction)
+            DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
     {
-        super.didPreRegistration(service, transaction);
-        invokePreRegistrationFunction(service, transaction);
+        super.didPreRegistration(service, persistentMapHolder);
+        invokePreRegistrationFunction(service, persistentMapHolder);
     }
 
     @Override
     public void didPostRegistration(DataSetRegistrationService<T> service,
-            DataSetRegistrationTransaction<T> transaction)
+            DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
     {
-        super.didPostRegistration(service, transaction);
-        invokePostRegistrationFunction(service, transaction);
+        super.didPostRegistration(service, persistentMapHolder);
+        invokePostRegistrationFunction(service, persistentMapHolder);
     }
 
     @Override
@@ -408,7 +408,7 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
     }
 
     private void invokePreRegistrationFunction(DataSetRegistrationService<T> service,
-            DataSetRegistrationTransaction<T> transaction)
+            DataSetRegistrationPersistentMap.IHolder persistentMapholder)
     {
         PythonInterpreter interpreter = getInterpreterFromService(service);
         PyFunction function =
@@ -416,17 +416,17 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
 
         if (null != function)
         {
-            invokeTransactionFunctionWithContext(function, service, transaction);
+            invokeTransactionFunctionWithContext(function, service, persistentMapholder);
         }
     }
 
     private void invokePostRegistrationFunction(DataSetRegistrationService<T> service,
-            DataSetRegistrationTransaction<T> transaction)
+            DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
     {
         PyFunction function = tryGetPostRegistrationFunction(service);
         if (null != function)
         {
-            invokeTransactionFunctionWithContext(function, service, transaction);
+            invokeTransactionFunctionWithContext(function, service, persistentMapHolder);
         }
     }
 
@@ -449,7 +449,7 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
         }
     }
 
-    private PyFunction tryJythonFunction(PythonInterpreter interpreter,
+    protected PyFunction tryJythonFunction(PythonInterpreter interpreter,
             JythonHookFunction functionDefinition)
     {
         try
@@ -482,16 +482,16 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
     }
 
     private void invokeTransactionFunctionWithContext(PyFunction function,
-            DataSetRegistrationService<T> service, DataSetRegistrationTransaction<T> transaction,
+            DataSetRegistrationService<T> service, DataSetRegistrationPersistentMap.IHolder persistentMapHolder,
             Object... additionalArgs)
     {
         if (additionalArgs.length > 0)
         {
-            invokeFunction(service, function, transaction.getTransactionPersistentMap(),
+            invokeFunction(service, function,  persistentMapHolder.getPersistentMap(),
                     additionalArgs);
         } else
         {
-            invokeFunction(service, function, transaction.getTransactionPersistentMap());
+            invokeFunction(service, function, persistentMapHolder.getPersistentMap());
         }
     }
 
@@ -502,6 +502,7 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
         invokeFunction(service, function, service, transaction, secondaryErrors);
     }
 
+    //TODO: refactor tests to not use the service to test the hooks!
     /**
      * Turns all arguments into a python objects, and calls the specified function. Service is here
      * only for the tests, so that the tests can hook it
@@ -517,6 +518,20 @@ public class JythonTopLevelDataSetHandler<T extends DataSetInformation> extends
         function.__call__(pyArgs);
     }
 
+    /**
+     * Turn all arguments into a python objects, and calls the specified
+     * function. Preferable way of calling functions.
+     */
+    protected void invokeFunction(PyFunction function, Object... args)
+    {
+        PyObject[] pyArgs = new PyObject[args.length];
+        for (int i = 0; i < args.length; i++)
+        {
+            pyArgs[i] = Py.java2py(args[i]);
+        }
+        function.__call__(pyArgs);
+    }
+
     /**
      * Set the factory available to the python script. Subclasses may want to override.
      */
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java
index 9f8ee8a087c..a59777ff138 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java
@@ -18,7 +18,7 @@ package ch.systemsx.cisd.etlserver.registrator.api.v1;
 
 import net.lemnik.eodsql.DynamicTransactionQuery;
 
-import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationContext;
+import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationPersistentMap;
 import ch.systemsx.cisd.etlserver.registrator.AbstractOmniscientTopLevelDataSetRegistrator.OmniscientTopLevelDataSetRegistratorState;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IDataSetImmutable;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IExperimentImmutable;
@@ -245,7 +245,7 @@ public interface IDataSetRegistrationTransaction
      * 
      * @return The context, a hash-map-like object.
      */
-    DataSetRegistrationContext getTransactionPersistentMap();
+    DataSetRegistrationPersistentMap getPersistentMap();
 
     /**
      * Returns the service registrator context.
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java
index 845fab10e0d..f5eb113b241 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java
@@ -34,7 +34,7 @@ import ch.systemsx.cisd.etlserver.DssRegistrationLogger;
 import ch.systemsx.cisd.etlserver.registrator.AbstractOmniscientTopLevelDataSetRegistrator.OmniscientTopLevelDataSetRegistratorState;
 import ch.systemsx.cisd.etlserver.registrator.AutoRecoverySettings;
 import ch.systemsx.cisd.etlserver.registrator.DataSetFile;
-import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationContext;
+import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationPersistentMap;
 import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationDetails;
 import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationService;
 import ch.systemsx.cisd.etlserver.registrator.DataSetStorageAlgorithmRunner;
@@ -85,7 +85,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
  */
 public class DataSetRegistrationTransaction<T extends DataSetInformation> implements
         IDataSetRegistrationTransaction, DataSetStorageAlgorithmRunner.IRollbackDelegate<T>,
-        DataSetStorageAlgorithmRunner.IDataSetInApplicationServerRegistrator<T>
+        DataSetStorageAlgorithmRunner.IDataSetInApplicationServerRegistrator<T>,
+        DataSetRegistrationPersistentMap.IHolder
 {
     private static final String ROLLBACK_QUEUE1_FILE_NAME_SUFFIX = "rollBackQueue1";
 
@@ -186,7 +187,7 @@ public class DataSetRegistrationTransaction<T extends DataSetInformation> implem
 
     private AbstractTransactionState<T> state;
 
-    private DataSetRegistrationContext registrationContext;
+    private DataSetRegistrationPersistentMap registrationContext;
 
     // The registration service that owns this transaction
     private final DataSetRegistrationService<T> registrationService;
@@ -215,7 +216,7 @@ public class DataSetRegistrationTransaction<T extends DataSetInformation> implem
         this.openBisService =
                 this.registrationService.getRegistratorContext().getGlobalState()
                         .getOpenBisService();
-        this.registrationContext = new DataSetRegistrationContext();
+        this.registrationContext = new DataSetRegistrationPersistentMap();
         this.autoRecoverySettings = autoRecoverySettings;
     }
 
@@ -375,7 +376,12 @@ public class DataSetRegistrationTransaction<T extends DataSetInformation> implem
         getStateAsLiveState().deleteFile(src);
     }
 
-    public DataSetRegistrationContext getTransactionPersistentMap()
+    /**
+     * Marked as deprecated, to prevent using this method directly. Instead it should only be used
+     * implicitly as an implementation of the persistent map holder interface.
+     */
+    @Deprecated
+    public DataSetRegistrationPersistentMap getPersistentMap()
     {
         return registrationContext;
     }
@@ -412,7 +418,7 @@ public class DataSetRegistrationTransaction<T extends DataSetInformation> implem
     {
         try
         {
-            registrationService.didCommitTransaction(this);
+            registrationService.executePostCommit(this);
         } catch (Throwable t)
         {
             DssRegistrationLogger dssRegistrationLog = registrationService.getDssRegistrationLog();
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 0d481e1450f..679b48da498 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
@@ -26,6 +26,8 @@ import org.python.core.PyFunction;
 import org.python.util.PythonInterpreter;
 
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
+import ch.systemsx.cisd.common.exceptions.NotImplementedException;
+import ch.systemsx.cisd.common.filesystem.FileUtilities;
 import ch.systemsx.cisd.common.utilities.IDelegatedActionWithResult;
 import ch.systemsx.cisd.common.utilities.PythonUtils;
 import ch.systemsx.cisd.etlserver.DssRegistrationLogger;
@@ -33,6 +35,7 @@ import ch.systemsx.cisd.etlserver.IStorageProcessorTransactional.UnstoreDataActi
 import ch.systemsx.cisd.etlserver.ITopLevelDataSetRegistratorDelegate;
 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.DataSetStorageAlgorithmRunner;
 import ch.systemsx.cisd.etlserver.registrator.DataSetStorageAlgorithmRunner.IPrePostRegistrationHook;
@@ -43,7 +46,6 @@ 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.DataSetRegistrationTransaction;
 import ch.systemsx.cisd.etlserver.registrator.api.v1.impl.RollbackStack.IRollbackStackDelegate;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
@@ -106,9 +108,13 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend
             PythonInterpreter interpreter)
     {
         interpreter.set(INCOMING_DATA_SET_VARIABLE_NAME, dataSetFile);
-        interpreter.set(TRANSACTION_VARIABLE_NAME, service.transaction());
         interpreter.set(STATE_VARIABLE_NAME, getGlobalState());
-        interpreter.set(FACTORY_VARIABLE_NAME, service.getDataSetRegistrationDetailsFactory());
+
+        if (service != null)
+        {
+            interpreter.set(TRANSACTION_VARIABLE_NAME, service.transaction());
+            interpreter.set(FACTORY_VARIABLE_NAME, service.getDataSetRegistrationDetailsFactory());
+        }
     }
 
     @Override
@@ -266,7 +272,7 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend
         return c.getTime().before(new Date());
     }
 
-    private void handleRecoveryState(DataSetStoragePrecommitRecoveryState<T> recoveryState,
+    private void handleRecoveryState(final DataSetStoragePrecommitRecoveryState<T> recoveryState,
             final IDelegatedActionWithResult<Boolean> cleanAfterwardsAction,
             final IDelegatedActionWithResult<Boolean> recoveryMarkerCleanup)
     {
@@ -295,7 +301,19 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend
             };
 
         // hookAdaptor
-        IPrePostRegistrationHook<T> hookAdaptor = createRecoveryHookAdaptor();
+            RecoveryHookAdaptor hookAdaptor =
+                new RecoveryHookAdaptor(recoveryState.getIncomingDataSetFile()
+                        .getLogicalIncomingFile());
+
+        DataSetRegistrationPersistentMap.IHolder persistentMapHolder =
+                new DataSetRegistrationPersistentMap.IHolder()
+                    {
+
+                        public DataSetRegistrationPersistentMap getPersistentMap()
+                        {
+                            return recoveryState.getPersistentMap();
+                        }
+                    };
 
         DataSetStorageAlgorithmRunner<T> runner =
                 new DataSetStorageAlgorithmRunner<T>(recoveryState.getIncomingDataSetFile(), // incoming
@@ -305,7 +323,7 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend
                         logger, // registrationLogger
                         state.getGlobalState().getOpenBisService(), // openBisService
                         hookAdaptor, // the hooks
-                        state.getGlobalState().getStorageRecoveryManager());
+                        state.getGlobalState().getStorageRecoveryManager(), persistentMapHolder);
 
         boolean registrationSuccessful = false;
 
@@ -345,10 +363,9 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend
                 rollbacker.doRollback(logger);
 
                 shouldDeleteRecoveryFiles = true;
-                //
-                // invokeRollbackTransactionFunction
-                //
-                // // rollback during metadata registration
+                
+                hookAdaptor.executePreRegistrationRollback(persistentMapHolder, null);
+                
             } else
             {
                 operationLog
@@ -357,6 +374,8 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend
                 logger.registerSuccess();
                 registrationSuccessful = true;
 
+                hookAdaptor.executePostStorage(persistentMapHolder);
+
                 shouldDeleteRecoveryFiles = true;
             }
         } catch (Throwable error)
@@ -385,18 +404,83 @@ public class JythonTopLevelDataSetHandlerV2<T extends DataSetInformation> extend
     /**
      * Create an adaptor that offers access to the recovery hook functions.
      */
-    protected IPrePostRegistrationHook<T> createRecoveryHookAdaptor()
+    protected class RecoveryHookAdaptor implements IPrePostRegistrationHook<T>
     {
-        IPrePostRegistrationHook<T> hookAdaptor = new IPrePostRegistrationHook<T>()
+        /**
+         * internally use only with getInterpreter
+         */
+        private PythonInterpreter internalInterpreter;
+
+        private final File incoming;
+
+        public RecoveryHookAdaptor(File incoming)
+        {
+            this.incoming = incoming;
+        }
+
+        private PythonInterpreter getInterpreter()
+        {
+            if (internalInterpreter == null)
             {
-                public void executePreRegistration(DataSetRegistrationTransaction<T> transaction)
-                {
-                }
+                internalInterpreter = PythonUtils.createIsolatedPythonInterpreter();
+                // interpreter.execute script
 
-                public void executePostRegistration(DataSetRegistrationTransaction<T> transaction)
-                {
-                }
-            };
-        return hookAdaptor;
+                configureEvaluator(incoming, null, internalInterpreter);
+
+                // Load the script
+                String scriptString = FileUtilities.loadToString(scriptFile);
+
+                // Invoke the evaluator
+                internalInterpreter.exec(scriptString);
+
+                verifyEvaluatorHookFunctions(internalInterpreter);
+            }
+            return internalInterpreter;
+        }
+
+        public void executePreRegistration(
+                DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
+        {
+            throw new NotImplementedException("Recovery cannot execute pre-registration hook.");
+        }
+
+        public void executePostRegistration(
+                DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
+        {
+            PyFunction function =
+                    tryJythonFunction(getInterpreter(),
+                            JythonHookFunction.POST_REGISTRATION_FUNCTION_NAME);
+            if (function != null)
+            {
+                invokeFunction(function, persistentMapHolder.getPersistentMap());
+            }
+        }
+
+        /**
+         * This method does not belong to the IPrePostRegistrationHook interface. Is called directly
+         * by recovery.
+         */
+        public void executePostStorage(DataSetRegistrationPersistentMap.IHolder persistentMapHolder)
+        {
+            PyFunction function =
+                    tryJythonFunction(getInterpreter(),
+                            JythonHookFunction.POST_STORAGE_FUNCTION_NAME);
+            if (function != null)
+            {
+                invokeFunction(function, persistentMapHolder.getPersistentMap());
+            }
+        }
+        
+        public void executePreRegistrationRollback(DataSetRegistrationPersistentMap.IHolder persistentMapHolder, Throwable t)
+        {
+            PyFunction function =
+                    tryJythonFunction(getInterpreter(),
+                            JythonHookFunction.ROLLBACK_PRE_REGISTRATION_FUNCTION_NAME);
+            if (function != null)
+            {
+                invokeFunction(function, persistentMapHolder.getPersistentMap(), t);
+            }
+        }
+        
     }
 }
-- 
GitLab