diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/AbstractPostRegistrationTaskForPhysicalDataSets.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/AbstractPostRegistrationTaskForPhysicalDataSets.java
new file mode 100644
index 0000000000000000000000000000000000000000..af7c460188ffee407db58945751edd08314fd05b
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/AbstractPostRegistrationTaskForPhysicalDataSets.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 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.postregistration;
+
+import java.util.Properties;
+
+import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
+
+/**
+ * Abstract super class for post registration of physical data sets.
+ *
+ * @author Franz-Josef Elmer
+ */
+public abstract class AbstractPostRegistrationTaskForPhysicalDataSets extends AbstractPostRegistrationTask
+{
+
+    public AbstractPostRegistrationTaskForPhysicalDataSets(Properties properties,
+            IEncapsulatedOpenBISService service)
+    {
+        super(properties, service);
+    }
+
+    /**
+     * do not allow concurrent maintenance tasks to run if they alter the data store contents.
+     */
+    @Override
+    public boolean requiresDataStoreLock()
+    {
+        return true;
+    }
+
+    @Override
+    public final IPostRegistrationTaskExecutor createExecutor(String dataSetCode, boolean container)
+    {
+        if (container)
+        {
+            return DummyPostRegistrationTaskExecutor.INSTANCE;
+        }
+        return createExecutor(dataSetCode);
+    }
+
+    protected abstract IPostRegistrationTaskExecutor createExecutor(String dataSetCode);
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/ArchivingExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/ArchivingExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec0ff72cc8dc2ca5703c87aba4e9b9fa2eef92cd
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/ArchivingExecutor.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2013 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.postregistration;
+
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus.AVAILABLE;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus.BACKUP_PENDING;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import ch.systemsx.cisd.common.exceptions.Status;
+import ch.systemsx.cisd.common.logging.ISimpleLogger;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.common.logging.LogLevel;
+import ch.systemsx.cisd.etlserver.plugins.AutoArchiverTask;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ArchiverTaskContext;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IArchiverPlugin;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IDataSetDirectoryProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ProcessingStatus;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatasetLocation;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
+import ch.systemsx.cisd.openbis.generic.shared.translator.DataSetTranslator;
+
+/**
+ * A post-registration task executor that archives data sets.
+ * 
+ * @author Kaloyan Enimanev
+ */
+class ArchivingExecutor implements IPostRegistrationTaskExecutor
+{
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            ArchivingExecutor.class);
+
+    private static final Logger notificationLog = LogFactory.getLogger(LogCategory.NOTIFY,
+            ArchivingExecutor.class);
+
+    private final String dataSetCode;
+
+    private final IEncapsulatedOpenBISService service;
+
+    private final IDataSetDirectoryProvider dataSetDirectoryProvider;
+
+    private final IHierarchicalContentProvider hierarchicalContentProvider;
+
+    private final IArchiverPlugin archiver;
+
+    private final boolean updateStatus;
+
+    ArchivingExecutor(String dataSetCode, boolean updateStatus, IEncapsulatedOpenBISService service,
+            IArchiverPlugin archiver, IDataSetDirectoryProvider dataSetDirectoryProvider,
+            IHierarchicalContentProvider hierarchicalContentProvider)
+    {
+        this.dataSetCode = dataSetCode;
+        this.updateStatus = updateStatus;
+        this.service = service;
+        this.archiver = archiver;
+        this.dataSetDirectoryProvider = dataSetDirectoryProvider;
+        this.hierarchicalContentProvider = hierarchicalContentProvider;
+
+    }
+
+    /**
+     * archives the dataset for the specified dataset code.
+     */
+    @Override
+    public void execute()
+    {
+
+        if (archiver == null)
+        {
+            // no archiver is configured
+            operationLog
+                    .error("Post-registration archiving cannot be completed, because there is "
+                            + "no archiver configured. Please configure an archiver and restart. ");
+            return;
+        }
+
+        AbstractExternalData dataSet = tryGetExternalData(dataSetCode, service);
+        if (dataSet == null)
+        {
+            operationLog.warn("Data set '" + dataSetCode
+                    + "' is no longer available in openBIS."
+                    + "Archiving post-registration task will be skipped...");
+            return;
+        }
+
+        boolean statusUpdated = updateStatus ?
+                service.compareAndSetDataSetStatus(dataSetCode, AVAILABLE, BACKUP_PENDING,
+                        false) : true;
+        if (statusUpdated)
+        {
+            DatasetDescription dataSetDescription =
+                    DataSetTranslator.translateToDescription(dataSet);
+            List<DatasetDescription> dataSetAsList =
+                    Collections.singletonList(dataSetDescription);
+            ArchiverTaskContext context =
+                    new ArchiverTaskContext(dataSetDirectoryProvider,
+                            hierarchicalContentProvider);
+            ProcessingStatus processingStatus = archiver.archive(dataSetAsList, context, false);
+            if (false == processingStatus.getErrorStatuses().isEmpty())
+            {
+                notifyAdministrator(processingStatus);
+            }
+            service.compareAndSetDataSetStatus(dataSetCode, BACKUP_PENDING, AVAILABLE, true);
+        }
+    }
+
+    private void notifyAdministrator(ProcessingStatus processingStatus)
+    {
+        StringBuilder message = new StringBuilder();
+        String failedMessage =
+                String.format("Eager archiving of dataset '%s' has failed. \n", dataSetCode);
+        message.append(failedMessage);
+        for (Status status : processingStatus.getErrorStatuses())
+        {
+            if (status.tryGetErrorMessage() != null)
+            {
+                message.append("Error encountered : " + status.tryGetErrorMessage());
+                message.append("\n");
+            }
+        }
+        String footer =
+                String.format("If you wish to archive the dataset in the future, "
+                        + "you can configure an '%s'.", AutoArchiverTask.class.getSimpleName());
+        message.append(footer);
+
+        notificationLog.error(message);
+    }
+
+    @Override
+    public ICleanupTask createCleanupTask()
+    {
+        return new ArchivingCleanupTask(dataSetCode, updateStatus, service, archiver);
+    }
+
+    private static class ArchivingCleanupTask implements ICleanupTask
+    {
+        private static final long serialVersionUID = 1L;
+
+        private final String dataSetCode;
+
+        private transient IEncapsulatedOpenBISService service;
+
+        private transient IArchiverPlugin archiver;
+
+        private final boolean updateStatus;
+
+        ArchivingCleanupTask(String dataSetCode, boolean updateStatus, IEncapsulatedOpenBISService service,
+                IArchiverPlugin archiver)
+        {
+            this.dataSetCode = dataSetCode;
+            this.updateStatus = updateStatus;
+            this.service = service;
+            this.archiver = archiver;
+        }
+
+        @Override
+        public void cleanup(ISimpleLogger logger)
+        {
+            if (updateStatus)
+            {
+                boolean statusUpdated =
+                        getService().compareAndSetDataSetStatus(dataSetCode, BACKUP_PENDING, AVAILABLE,
+                                false);
+                
+                if (statusUpdated == false)
+                {
+                    // invalid data set status, do not continue
+                    return;
+                }
+            }
+
+            DatasetDescription dataSet = tryGetDatasetWithLocation(dataSetCode, getService());
+            if (getArchiver() != null && dataSet != null && dataSet.getDataSetLocation() != null)
+            {
+                DatasetLocation dataset = new DatasetLocation();
+                dataset.setDatasetCode(dataSetCode);
+                dataset.setDataSetLocation(dataSet.getDataSetLocation());
+
+                List<DatasetLocation> dataSetAsList = Collections.singletonList(dataset);
+                getArchiver().deleteFromArchive(dataSetAsList);
+                logger.log(LogLevel.INFO, "Successfully cleaned up leftovers from incomplete "
+                        + "archiving of dataset '" + dataSetCode + "'.");
+            }
+        }
+        
+        private IEncapsulatedOpenBISService getService()
+        {
+            if (service == null)
+            {
+                service = ServiceProvider.getOpenBISService();
+            }
+            return service;
+        }
+        
+        private IArchiverPlugin getArchiver()
+        {
+            if (archiver == null)
+            {
+                archiver = ServiceProvider.getDataStoreService().getArchiverPlugin();
+            }
+            return archiver;
+        }
+    }
+
+    private static AbstractExternalData tryGetExternalData(String dataSetCode,
+            IEncapsulatedOpenBISService service)
+    {
+        List<String> codeAsList = Collections.singletonList(dataSetCode);
+        List<AbstractExternalData> dataList = service.listDataSetsByCode(codeAsList);
+        if (dataList == null || dataList.isEmpty())
+        {
+            return null;
+        }
+
+        AbstractExternalData data = dataList.get(0);
+        return data;
+    }
+
+    private static DatasetDescription tryGetDatasetWithLocation(String dataSetCode,
+            IEncapsulatedOpenBISService service)
+    {
+        AbstractExternalData data = tryGetExternalData(dataSetCode, service);
+        return (data != null) ? DataSetTranslator.translateToDescription(data) : null;
+    }
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/ArchivingPostRegistrationTask.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/ArchivingPostRegistrationTask.java
index 8c11106bee6501e35b7afe2d4a38dfebe341f9e8..e48f26b4f5f1fd99d2146ccc26686436abde6f52 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/ArchivingPostRegistrationTask.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/ArchivingPostRegistrationTask.java
@@ -16,215 +16,39 @@
 
 package ch.systemsx.cisd.etlserver.postregistration;
 
-import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus.AVAILABLE;
-import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus.BACKUP_PENDING;
 
-import java.util.Collections;
-import java.util.List;
 import java.util.Properties;
 
-import org.apache.log4j.Logger;
-
-import ch.systemsx.cisd.common.exceptions.Status;
-import ch.systemsx.cisd.common.logging.ISimpleLogger;
-import ch.systemsx.cisd.common.logging.LogCategory;
-import ch.systemsx.cisd.common.logging.LogFactory;
-import ch.systemsx.cisd.common.logging.LogLevel;
-import ch.systemsx.cisd.etlserver.plugins.AutoArchiverTask;
-import ch.systemsx.cisd.openbis.dss.generic.shared.ArchiverTaskContext;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IArchiverPlugin;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IDataSetDirectoryProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IDataStoreServiceInternal;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
-import ch.systemsx.cisd.openbis.dss.generic.shared.ProcessingStatus;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
 import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatasetLocation;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
-import ch.systemsx.cisd.openbis.generic.shared.translator.DataSetTranslator;
 
 /**
- * A post-registration task that archives datasets.
+ * A post-registration task that archives data sets.
  * 
  * @author Kaloyan Enimanev
  */
-public class ArchivingPostRegistrationTask extends AbstractPostRegistrationTask
+public class ArchivingPostRegistrationTask extends AbstractPostRegistrationTaskForPhysicalDataSets
 {
-    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
-            ArchivingPostRegistrationTask.class);
-
-    private static final Logger notificationLog = LogFactory.getLogger(LogCategory.NOTIFY,
-            ArchivingPostRegistrationTask.class);
-
     public ArchivingPostRegistrationTask(Properties properties, IEncapsulatedOpenBISService service)
     {
         super(properties, service);
     }
 
-    /**
-     * do not allow concurrent maintenance tasks to run if they alter the data store contents.
-     */
     @Override
-    public boolean requiresDataStoreLock()
-    {
-        return true;
-    }
-
-    @Override
-    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode, boolean container)
-    {
-        if (container)
-        {
-            return DummyPostRegistrationTaskExecutor.INSTANCE;
-        }
-        return new Executor(dataSetCode);
-    }
-    
-    private final class Executor implements IPostRegistrationTaskExecutor
+    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode)
     {
-        private final String dataSetCode;
-
-        Executor(String dataSetCode)
-        {
-            this.dataSetCode = dataSetCode;
-
-        }
-
-        /**
-         * archives the dataset for the specified dataset code.
-         */
-        @Override
-        public void execute()
-        {
-
-            IArchiverPlugin archiver = ServiceProvider.getDataStoreService().getArchiverPlugin();
-            if (archiver == null)
-            {
-                // no archiver is configured
-                operationLog
-                        .error("Post-registration archiving cannot be completed, because there is "
-                                + "no archiver configured. Please configure an archiver and restart. ");
-                return;
-            }
-
-            AbstractExternalData dataSet = tryGetExternalData(dataSetCode, service);
-            if (dataSet == null)
-            {
-                operationLog.warn("Data set '" + dataSetCode
-                        + "' is no longer available in openBIS."
-                        + "Archiving post-registration task will be skipped...");
-                return;
-            }
-
-            boolean statusUpdated =
-                    service.compareAndSetDataSetStatus(dataSetCode, AVAILABLE, BACKUP_PENDING,
-                            false);
-            if (statusUpdated)
-            {
-                DatasetDescription dataSetDescription =
-                        DataSetTranslator.translateToDescription(dataSet);
-                List<DatasetDescription> dataSetAsList =
-                        Collections.singletonList(dataSetDescription);
-                ProcessingStatus processingStatus =
-                        archiver.archive(dataSetAsList, createArchiverContext(), false);
-                if (false == processingStatus.getErrorStatuses().isEmpty())
-                {
-                    notifyAdministrator(processingStatus);
-                }
-                service.compareAndSetDataSetStatus(dataSetCode, BACKUP_PENDING, AVAILABLE, true);
-            }
-        }
-
-        private void notifyAdministrator(ProcessingStatus processingStatus)
-        {
-            StringBuilder message = new StringBuilder();
-            String failedMessage =
-                    String.format("Eager archiving of dataset '%s' has failed. \n", dataSetCode);
-            message.append(failedMessage);
-            for (Status status : processingStatus.getErrorStatuses()) 
-            {
-                if (status.tryGetErrorMessage() != null)
-                {
-                    message.append("Error encountered : " + status.tryGetErrorMessage());
-                    message.append("\n");
-                }
-            }
-            String footer =
-                    String.format("If you wish to archive the dataset in the future, "
-                            + "you can configure an '%s'.", AutoArchiverTask.class.getSimpleName());
-            message.append(footer);
-            
-            notificationLog.error(message);
-        }
-
-        @Override
-        public ICleanupTask createCleanupTask()
-        {
-            return new ArchivingCleanupTask(dataSetCode);
-        }
+        IDataStoreServiceInternal dataStoreService = ServiceProvider.getDataStoreService();
+        IArchiverPlugin archiver = dataStoreService.getArchiverPlugin();
+        IDataSetDirectoryProvider dataSetDirectoryProvider =
+                dataStoreService.getDataSetDirectoryProvider();
+        IHierarchicalContentProvider hierarchicalContentProvider =
+                ServiceProvider.getHierarchicalContentProvider();
+        return new ArchivingExecutor(dataSetCode, true, service, archiver, dataSetDirectoryProvider,
+                hierarchicalContentProvider);
     }
 
-    private static AbstractExternalData tryGetExternalData(String dataSetCode,
-            IEncapsulatedOpenBISService service)
-    {
-        List<String> codeAsList = Collections.singletonList(dataSetCode);
-        List<AbstractExternalData> dataList = service.listDataSetsByCode(codeAsList);
-        if (dataList == null || dataList.isEmpty())
-        {
-            return null;
-        }
-
-        AbstractExternalData data = dataList.get(0);
-        return data;
-    }
-
-    private static DatasetDescription tryGetDatasetWithLocation(String dataSetCode,
-            IEncapsulatedOpenBISService service)
-    {
-        AbstractExternalData data = tryGetExternalData(dataSetCode, service);
-        return (data != null) ? DataSetTranslator.translateToDescription(data) : null;
-    }
-
-    private static ArchiverTaskContext createArchiverContext()
-    {
-        return new ArchiverTaskContext(ServiceProvider.getDataStoreService()
-                .getDataSetDirectoryProvider(), ServiceProvider.getHierarchicalContentProvider());
-    }
-
-    private static class ArchivingCleanupTask implements ICleanupTask
-    {
-        private static final long serialVersionUID = 1L;
-
-        private final String dataSetCode;
-
-        ArchivingCleanupTask(String dataSetCode)
-        {
-            this.dataSetCode = dataSetCode;
-        }
-
-        @Override
-        public void cleanup(ISimpleLogger logger)
-        {
-            IEncapsulatedOpenBISService openBISService = ServiceProvider.getOpenBISService();
-            boolean statusUpdated = openBISService
-                    .compareAndSetDataSetStatus(dataSetCode, BACKUP_PENDING, AVAILABLE, false);
-            
-            if (statusUpdated == false) {
-                // invalid data set status, do not continue 
-                return;
-            }
-            
-            IArchiverPlugin archiver = ServiceProvider.getDataStoreService().getArchiverPlugin();
-            DatasetDescription dataSet = tryGetDatasetWithLocation(dataSetCode, openBISService);
-            if (archiver != null && dataSet != null && dataSet.getDataSetLocation() != null)
-            {
-                DatasetLocation dataset = new DatasetLocation();
-                dataset.setDatasetCode(dataSetCode);
-                dataset.setDataSetLocation(dataSet.getDataSetLocation());
-
-                List<DatasetLocation> dataSetAsList = Collections.singletonList(dataset);
-                archiver.deleteFromArchive(dataSetAsList);
-                logger.log(LogLevel.INFO, "Successfully cleaned up leftovers from incomplete "
-                        + "archiving of dataset '" + dataSetCode + "'.");
-            }
-        }
-    }
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/EagerShufflingTask.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/EagerShufflingTask.java
index 374c2eeb8ae990632eb08adc7ceae7317dd1e885..a6ce79cee568f27cb95c033443ab94f5a61784ff 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/EagerShufflingTask.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/EagerShufflingTask.java
@@ -57,7 +57,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
  * 
  * @author Franz-Josef Elmer
  */
-public class EagerShufflingTask extends AbstractPostRegistrationTask
+public class EagerShufflingTask extends AbstractPostRegistrationTaskForPhysicalDataSets
 {
     @Private
     public static final String SHARE_FINDER_KEY = "share-finder";
@@ -165,12 +165,6 @@ public class EagerShufflingTask extends AbstractPostRegistrationTask
         verifyChecksum = PropertyUtils.getBoolean(properties, VERIFY_CHECKSUM_KEY, true);
     }
 
-    @Override
-    public boolean requiresDataStoreLock()
-    {
-        return true;
-    }
-
     private IChecksumProvider getChecksumProvider()
     {
         if (verifyChecksum)
@@ -183,12 +177,8 @@ public class EagerShufflingTask extends AbstractPostRegistrationTask
     }
 
     @Override
-    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode, boolean container)
+    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode)
     {
-        if (container)
-        {
-            return DummyPostRegistrationTaskExecutor.INSTANCE;
-        }
         return new Executor(dataSetCode);
     }
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/Hdf5CompressingPostRegistrationTask.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/Hdf5CompressingPostRegistrationTask.java
index f979778db417c2b5f431acb4325b8da1fd13cb4d..4308ea02a0b3e7cdd56d99a3961d1032443f838d 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/Hdf5CompressingPostRegistrationTask.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/Hdf5CompressingPostRegistrationTask.java
@@ -76,7 +76,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFa
  * 
  * @author Kaloyan Enimanev
  */
-public class Hdf5CompressingPostRegistrationTask extends AbstractPostRegistrationTask
+public class Hdf5CompressingPostRegistrationTask extends AbstractPostRegistrationTaskForPhysicalDataSets
 {
     public static final String DATA_SET_TYPES = "data-set-types";
 
@@ -97,22 +97,9 @@ public class Hdf5CompressingPostRegistrationTask extends AbstractPostRegistratio
                 new HashSet<String>(PropertyUtils.tryGetList(properties, DATA_SET_TYPES));
     }
 
-    /**
-     * do not allow concurrent maintenance tasks to run if they alter the data store contents.
-     */
-    @Override
-    public boolean requiresDataStoreLock()
-    {
-        return true;
-    }
-
     @Override
-    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode, boolean container)
+    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode)
     {
-        if (container)
-        {
-            return DummyPostRegistrationTaskExecutor.INSTANCE;
-        }
         return new Executor(dataSetCode);
     }
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/SecondCopyPostRegistrationTask.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/SecondCopyPostRegistrationTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..2db42b3db1b4737f87a9df102014d92f9aa1925a
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/postregistration/SecondCopyPostRegistrationTask.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013 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.postregistration;
+
+import java.io.File;
+import java.util.List;
+import java.util.Properties;
+
+import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractArchiverProcessingPlugin;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.DataSetFileOperationsManager;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.IDataSetFileOperationsManager;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.RsyncArchiveCopierFactory;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.RsyncArchiver;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.SshCommandExecutorFactory;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IArchiverPlugin;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IDataSetDirectoryProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IDataSetStatusUpdater;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IDataStoreServiceInternal;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus;
+
+/**
+ * Creates a second copy of the data set.
+ *
+ * @author Franz-Josef Elmer
+ */
+public class SecondCopyPostRegistrationTask extends AbstractPostRegistrationTaskForPhysicalDataSets
+{
+
+    private final DataSetFileOperationsManager fileOperationManager;
+    private final IHierarchicalContentProvider hierarchicalContentProvider;
+    private final IDataSetDirectoryProvider dataSetDirectoryProvider;
+    private final IArchiverPlugin archiver;
+
+    public SecondCopyPostRegistrationTask(Properties properties, IEncapsulatedOpenBISService service)
+    {
+        this(properties, service, ServiceProvider.getDataStoreService(), ServiceProvider
+                .getHierarchicalContentProvider());
+    }
+
+    SecondCopyPostRegistrationTask(Properties properties, IEncapsulatedOpenBISService service,
+            IDataStoreServiceInternal dataStoreService,
+            IHierarchicalContentProvider hierarchicalContentProvider)
+    {
+        super(properties, service);
+        this.hierarchicalContentProvider = hierarchicalContentProvider;
+        fileOperationManager = new DataSetFileOperationsManager(properties,
+                new RsyncArchiveCopierFactory(), new SshCommandExecutorFactory());
+        if (fileOperationManager.isHosted())
+        {
+            throw new ConfigurationFailureException(
+                    "Destination should be on a local or mounted drive.");
+        }
+        dataSetDirectoryProvider = dataStoreService.getDataSetDirectoryProvider();
+        File storeRoot = dataSetDirectoryProvider.getStoreRoot();
+        properties.setProperty(AbstractArchiverProcessingPlugin.SYNCHRONIZE_ARCHIVE, "false");
+        archiver = new Archiver(properties, storeRoot, fileOperationManager);
+    }
+
+    @Override
+    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode)
+    {
+        return new ArchivingExecutor(dataSetCode, false, service, archiver, dataSetDirectoryProvider,
+                hierarchicalContentProvider);
+    }
+    
+    private static final class Archiver extends RsyncArchiver
+    {
+
+        private static final long serialVersionUID = 1L;
+
+        Archiver(Properties properties, File storeRoot,
+                IDataSetFileOperationsManager fileOperationsManager)
+        {
+            super(properties, storeRoot, fileOperationsManager, RsyncArchiver.DeleteAction.DELETE,
+                    ChecksumVerificationCondition.IF_AVAILABLE);
+            setStatusUpdater(new IDataSetStatusUpdater()
+                {
+                    @Override
+                    public void update(List<String> dataSetCodes, DataSetArchivingStatus status,
+                            boolean presentInArchive)
+                    {
+                    }
+                });
+        }
+
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractArchiverProcessingPlugin.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractArchiverProcessingPlugin.java
index bac63dbcba8bada5d75f64db0f12ac84d8237340..504926852e11d679f708045bc3632fc841bd7f1e 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractArchiverProcessingPlugin.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractArchiverProcessingPlugin.java
@@ -79,7 +79,7 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
     @Private
     public static final String SHARE_FINDER_KEY = "share-finder";
 
-    @Private static final String SYNCHRONIZE_ARCHIVE = "synchronize-archive";
+    public static final String SYNCHRONIZE_ARCHIVE = "synchronize-archive";
 
     private final IStatusChecker archivePrerequisiteOrNull;
 
@@ -547,8 +547,7 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
         return service;
     }
 
-    @Private
-    void setStatusUpdater(IDataSetStatusUpdater statusUpdater)
+    public void setStatusUpdater(IDataSetStatusUpdater statusUpdater)
     {
         this.statusUpdater = statusUpdater;
     }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiver.java
index d33cf766d11cf8a9bb374cb3f99d507f78488b76..c5214a04721ab31dba94f02f9defca42353e66bc 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiver.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiver.java
@@ -61,6 +61,36 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
 
     private static final long serialVersionUID = 1L;
 
+    public enum ChecksumVerificationCondition
+    {
+        NO()
+        {
+            @Override
+            boolean verifyChecksum(IHierarchicalContentNode node)
+            {
+                return false;
+            }
+        },
+        YES()
+        {
+            @Override
+            boolean verifyChecksum(IHierarchicalContentNode node)
+            {
+                return true;
+            }
+        },
+        IF_AVAILABLE()
+        {
+            @Override
+            boolean verifyChecksum(IHierarchicalContentNode node)
+            {
+                return node.isChecksumCRC32Precalculated();
+            }
+        };
+
+        abstract boolean verifyChecksum(IHierarchicalContentNode node);
+    }
+
     private static final Comparator<IHierarchicalContentNode> NODE_COMPARATOR =
             new Comparator<IHierarchicalContentNode>()
                 {
@@ -71,7 +101,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
                     }
                 };
 
-    private enum DeleteAction
+    public enum DeleteAction
     {
         DELETE(Operation.DELETE_FROM_ARCHIVE)
         {
@@ -109,7 +139,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
 
     private final DeleteAction deleteAction;
 
-    private final boolean verifyChecksums;
+    private final ChecksumVerificationCondition checksumVerificationCondition;
 
     public RsyncArchiver(Properties properties, File storeRoot)
     {
@@ -117,22 +147,25 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
                 new RsyncArchiveCopierFactory(), new SshCommandExecutorFactory()));
     }
 
-    @Private
-    RsyncArchiver(Properties properties, File storeRoot,
+    @Private RsyncArchiver(Properties properties, File storeRoot,
             IDataSetFileOperationsManager fileOperationsManager)
     {
-        super(properties, storeRoot, null, null);
-        this.fileOperationsManager = fileOperationsManager;
-        if (PropertyUtils.getBoolean(properties, ONLY_MARK_AS_DELETED_KEY, true))
-        {
-            deleteAction = DeleteAction.MARK_AS_DELETED;
-        } else
-        {
-            deleteAction = DeleteAction.DELETE;
-        }
+        this(properties, storeRoot, fileOperationsManager, PropertyUtils.getBoolean(properties,
+                ONLY_MARK_AS_DELETED_KEY, true) ? DeleteAction.MARK_AS_DELETED
+                : DeleteAction.DELETE, PropertyUtils.getBoolean(properties, VERIFY_CHECKSUMS_KEY,
+                true) ? ChecksumVerificationCondition.YES : ChecksumVerificationCondition.NO);
 
-        verifyChecksums = PropertyUtils.getBoolean(properties, VERIFY_CHECKSUMS_KEY, true);
+    }
 
+    public RsyncArchiver(Properties properties, File storeRoot,
+            IDataSetFileOperationsManager fileOperationsManager, DeleteAction deleteAction,
+            ChecksumVerificationCondition checksumVerificationCondition)
+    {
+        super(properties, storeRoot, null, null);
+        this.fileOperationsManager = fileOperationsManager;
+        this.deleteAction = deleteAction;
+        this.checksumVerificationCondition = checksumVerificationCondition;
+        
     }
 
     @Override
@@ -178,7 +211,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
                     IHierarchicalContentNode root = content.getRootNode();
                     IHierarchicalContentNode archivedRoot = archivedContent.getRootNode();
 
-                    status = checkHierarchySizeAndChecksums(root, archivedRoot, verifyChecksums);
+                    status = checkHierarchySizeAndChecksums(root, archivedRoot, checksumVerificationCondition);
                 } finally
                 {
                     FileUtils.deleteQuietly(temp);
@@ -192,7 +225,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
 
     @Private
     static Status checkHierarchySizeAndChecksums(IHierarchicalContentNode node,
-            IHierarchicalContentNode retrievedNode, boolean verifyChecksums)
+            IHierarchicalContentNode retrievedNode, ChecksumVerificationCondition checksumVerificationCondition)
     {
         String relativePath = node.getRelativePath();
         String relativePathOfRetrieved = retrievedNode.getRelativePath();
@@ -226,7 +259,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
             {
                 Status status =
                         checkHierarchySizeAndChecksums(childNodes.get(i),
-                                childNodesOfRetrieved.get(i), verifyChecksums);
+                                childNodesOfRetrieved.get(i), checksumVerificationCondition);
                 if (status.isError())
                 {
                     return status;
@@ -241,7 +274,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
                 return Status.createError("The file '" + relativePath + "' has in the store "
                         + fileLength + " bytes but " + fileLengthOfRetrieved + " in the archive.");
             }
-            if (verifyChecksums)
+            if (checksumVerificationCondition.verifyChecksum(node))
             {
                 long checksum = node.getChecksumCRC32();
                 long checksumOfRetrieved = retrievedNode.getChecksumCRC32();
@@ -255,7 +288,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
         }
         return Status.OK;
     }
-
+    
     private static List<IHierarchicalContentNode> getChildNodes(IHierarchicalContentNode node)
     {
         List<IHierarchicalContentNode> childNodes = node.getChildNodes();
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiverTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiverTest.java
index 6466243798f6dd4238a0e22a6247179a1d7cf8bc..6c49eb627260fb03c925c90048a12695de509acb 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiverTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiverTest.java
@@ -478,8 +478,10 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase
         IHierarchicalContentNode root2 =
                 new MockContent(":0:0", "a/:0:0", "a/f2.txt:15:13", "a/f1.txt:5:-3", "r.txt:7:17")
                         .getRootNode();
-        assertEquals("OK", RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true)
-                .toString());
+        assertEquals(
+                "OK",
+                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2,
+                        RsyncArchiver.ChecksumVerificationCondition.YES).toString());
     }
 
     @Test
@@ -489,9 +491,11 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase
                 new MockContent(":0:0", "a/:0:0", "a/f1.txt:5:-3").getRootNode();
         IHierarchicalContentNode root2 =
                 new MockContent(":0:0", "a/:0:0", "a/f3.txt:15:13").getRootNode();
-        assertEquals("ERROR: \"Different paths: Path in the store is 'a/f1.txt' "
-                + "and in the archive 'a/f3.txt'.\"",
-                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true).toString());
+        assertEquals(
+                "ERROR: \"Different paths: Path in the store is 'a/f1.txt' "
+                        + "and in the archive 'a/f3.txt'.\"",
+                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2,
+                        RsyncArchiver.ChecksumVerificationCondition.YES).toString());
     }
 
     @Test
@@ -499,10 +503,12 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase
     {
         IHierarchicalContentNode root1 = new MockContent(":0:0", "a/:0:0").getRootNode();
         IHierarchicalContentNode root2 = new MockContent(":0:0", "a:1:2").getRootNode();
-        assertEquals("ERROR: \"The path 'a' should be in store and archive either "
-                + "both directories or files but not mixed: In the store it is a directory "
-                + "but in the archive it is a file.\"", RsyncArchiver
-                .checkHierarchySizeAndChecksums(root1, root2, true).toString());
+        assertEquals(
+                "ERROR: \"The path 'a' should be in store and archive either "
+                        + "both directories or files but not mixed: In the store it is a directory "
+                        + "but in the archive it is a file.\"",
+                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2,
+                        RsyncArchiver.ChecksumVerificationCondition.YES).toString());
     }
 
     @Test
@@ -512,8 +518,10 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase
                 new MockContent(":0:0", "a/:0:0", "a/f1.txt:5:-3", "a/f2.txt:15:13").getRootNode();
         IHierarchicalContentNode root2 =
                 new MockContent(":0:0", "a/:0:0", "a/f2.txt:15:13").getRootNode();
-        assertEquals("ERROR: \"The directory 'a' has in the store 2 files but 1 in the archive.\"",
-                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true).toString());
+        assertEquals(
+                "ERROR: \"The directory 'a' has in the store 2 files but 1 in the archive.\"",
+                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2,
+                        RsyncArchiver.ChecksumVerificationCondition.YES).toString());
     }
 
     @Test
@@ -521,8 +529,10 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase
     {
         IHierarchicalContentNode root1 = new MockContent(":0:0", "r.txt:7:17").getRootNode();
         IHierarchicalContentNode root2 = new MockContent(":0:0", "r.txt:9:17").getRootNode();
-        assertEquals("ERROR: \"The file 'r.txt' has in the store 7 bytes but 9 in the archive.\"",
-                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true).toString());
+        assertEquals(
+                "ERROR: \"The file 'r.txt' has in the store 7 bytes but 9 in the archive.\"",
+                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2,
+                        RsyncArchiver.ChecksumVerificationCondition.YES).toString());
     }
 
     @Test
@@ -530,17 +540,21 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase
     {
         IHierarchicalContentNode root1 = new MockContent(":0:0", "r.txt:7:17").getRootNode();
         IHierarchicalContentNode root2 = new MockContent(":0:0", "r.txt:7:18").getRootNode();
-        assertEquals("ERROR: \"The file 'r.txt' has in the store the checksum 00000017 "
-                + "but 00000018 in the archive.\"",
-                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true).toString());
+        assertEquals(
+                "ERROR: \"The file 'r.txt' has in the store the checksum 00000017 "
+                        + "but 00000018 in the archive.\"",
+                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2,
+                        RsyncArchiver.ChecksumVerificationCondition.YES).toString());
     }
 
     public void testCheckHierarchySizeAndChecksumsWrongChecksumAreNotChecked()
     {
         IHierarchicalContentNode root1 = new MockContent(":0:0", "r.txt:7:17").getRootNode();
         IHierarchicalContentNode root2 = new MockContent(":0:0", "r.txt:7:18").getRootNode();
-        assertEquals("OK", RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, false)
-                .toString());
+        assertEquals(
+                "OK",
+                RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2,
+                        RsyncArchiver.ChecksumVerificationCondition.NO).toString());
     }
 
     private static final class MockNode implements IHierarchicalContentNode
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/postregistration/ScreeningHdf5PostRegistrationTask.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/postregistration/ScreeningHdf5PostRegistrationTask.java
index 731ff12372f63e5a7b929d0f26f3ae97324c751f..6630ba70a5a212832a27a2574b589b3632dbbd5f 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/postregistration/ScreeningHdf5PostRegistrationTask.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/postregistration/ScreeningHdf5PostRegistrationTask.java
@@ -27,7 +27,6 @@ import org.apache.log4j.Logger;
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
-import ch.systemsx.cisd.etlserver.postregistration.DummyPostRegistrationTaskExecutor;
 import ch.systemsx.cisd.etlserver.postregistration.Hdf5CompressingPostRegistrationTask;
 import ch.systemsx.cisd.etlserver.postregistration.IPostRegistrationTaskExecutor;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
@@ -52,12 +51,8 @@ public class ScreeningHdf5PostRegistrationTask extends Hdf5CompressingPostRegist
     }
 
     @Override
-    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode, boolean container)
+    public IPostRegistrationTaskExecutor createExecutor(String dataSetCode)
     {
-        if (container)
-        {
-            return DummyPostRegistrationTaskExecutor.INSTANCE;
-        }
         return new ScreeningExecutor(dataSetCode, properties);
     }