diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
index 6a4b27348a50e01abd4e602ec932004d61324fd6..b986343df1225e22a7acd0d10956651b0124d629 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
@@ -38,8 +38,8 @@ import ch.systemsx.cisd.common.spring.AbstractServiceWithLogger;
 import ch.systemsx.cisd.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.common.utilities.IInitializable;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ArchiverTaskContext;
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ArchiverTaskFactory;
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IArchiverTask;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ArchiverPluginFactory;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IArchiverPlugin;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IProcessingPluginTask;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IReportingPluginTask;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.PluginTaskProvider;
@@ -333,24 +333,33 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
     public void unarchiveDatasets(String sessionToken, List<DatasetDescription> datasets,
             String userEmailOrNull)
     {
-        scheduleArchiverTask(sessionToken, datasets, userEmailOrNull, false);
+        String description = "Unarchiving";
+        IProcessingPluginTask task = new UnarchiveProcessingPluginTask(createArchiver());
+
+        scheduleTask(sessionToken, description, task, datasets, userEmailOrNull);
     }
 
     public void archiveDatasets(String sessionToken, List<DatasetDescription> datasets,
-            String userEmailOrNull)
+            String userEmailOrNull, boolean removeFromDataStore)
     {
-        scheduleArchiverTask(sessionToken, datasets, userEmailOrNull, true);
+        String description = removeFromDataStore ? "Archiving" : "Copying data sets to archive";
+        IProcessingPluginTask task =
+                new ArchiveProcessingPluginTask(createArchiver(), removeFromDataStore);
+        
+        scheduleTask(sessionToken, description, task, datasets, userEmailOrNull);
     }
 
-    private void scheduleArchiverTask(String sessionToken, List<DatasetDescription> datasets,
-            String userEmailOrNull, boolean archive)
+    private IArchiverPlugin createArchiver()
     {
-        sessionTokenManager.assertValidSessionToken(sessionToken);
+        ArchiverPluginFactory factory = pluginTaskParameters.getArchiverTaskFactory();
+        return factory.createInstance(storeRoot, commandExecutor);
+    }
 
-        String description = archive ? "Archiving" : "Unarchiving";
-        ArchiverTaskFactory factory = pluginTaskParameters.getArchiverTaskFactory();
-        final IArchiverTask archiverTask = factory.createInstance(storeRoot);
-        IProcessingPluginTask processingTask = new ArchiverProcessingTask(archiverTask, archive);
+    private void scheduleTask(String sessionToken, String description,
+            IProcessingPluginTask processingTask, List<DatasetDescription> datasets,
+            String userEmailOrNull)
+    {
+        sessionTokenManager.assertValidSessionToken(sessionToken);
         DatastoreServiceDescription pluginDescription =
                 DatastoreServiceDescription.processing(description, description, null, null);
         Map<String, String> parameterBindings = Collections.<String, String> emptyMap();
@@ -358,19 +367,20 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
                 userEmailOrNull, pluginDescription, mailClientParameters);
     }
 
-    private static class ArchiverProcessingTask implements IProcessingPluginTask
+    private static class ArchiveProcessingPluginTask implements IProcessingPluginTask
     {
 
         private static final long serialVersionUID = 1L;
 
-        private boolean archive;
+        private IArchiverPlugin archiverTask;
 
-        private IArchiverTask archiverTask;
+        private boolean removeFromDataStore;
 
-        public ArchiverProcessingTask(final IArchiverTask archiverTask, final boolean archive)
+        public ArchiveProcessingPluginTask(final IArchiverPlugin archiverTask,
+                final boolean removeFromDataStore)
         {
             this.archiverTask = archiverTask;
-            this.archive = archive;
+            this.removeFromDataStore = removeFromDataStore;
         }
 
         public ProcessingStatus process(List<DatasetDescription> datasets,
@@ -378,13 +388,28 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
         {
             ArchiverTaskContext archiverContext =
                     new ArchiverTaskContext(context.getDirectoryProvider());
-            if (archive)
-            {
-                return archiverTask.archive(datasets, archiverContext);
-            } else
-            {
-                return archiverTask.unarchive(datasets, archiverContext);
-            }
+            return archiverTask.archive(datasets, archiverContext, removeFromDataStore);
+        }
+    }
+
+    private static class UnarchiveProcessingPluginTask implements IProcessingPluginTask
+    {
+
+        private static final long serialVersionUID = 1L;
+
+        private IArchiverPlugin archiverTask;
+
+        public UnarchiveProcessingPluginTask(final IArchiverPlugin archiverTask)
+        {
+            this.archiverTask = archiverTask;
+        }
+
+        public ProcessingStatus process(List<DatasetDescription> datasets,
+                DataSetProcessingContext context)
+        {
+            ArchiverTaskContext archiverContext =
+                    new ArchiverTaskContext(context.getDirectoryProvider());
+            return archiverTask.unarchive(datasets, archiverContext);
         }
     }
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
index f49f9fb22982be3a2881e6ed9fffa108792c164a..723c26c2a896c183757d8c4c3b4c43d44d8eb244 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
@@ -133,10 +133,10 @@ class DataStoreServiceLogger implements IDataStoreService, IInitializable
     }
 
     public void archiveDatasets(String sessionToken, List<DatasetDescription> datasets,
-            String userEmailOrNull)
+            String userEmailOrNull, boolean removeFromDataStore)
     {
-        log("archiveDatasets", "NO_OF_DATASETS(%s) USER_EMAIL(%s)", datasets.size(),
-                userEmailOrNull);
+        log("archiveDatasets", "NO_OF_DATASETS(%s) USER_EMAIL(%s) REMOVE_FROM_DATA_STORE(%s)",
+                datasets.size(), userEmailOrNull, removeFromDataStore);
     }
 
     public LinkModel retrieveLinkFromDataSet(String sessionToken, String serviceKey,
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
index 7222d8f2c0b266c526b93afc105b377bfd324d1d..6aed490436529bfa028261df318106a08bd3795a 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
@@ -292,14 +292,14 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer
         }
     }
 
-    public final void updateDataSetStatuses(List<String> codes,
-            DataSetArchivingStatus newStatus) throws UserFailureException
+    public final void updateDataSetStatuses(List<String> codes, DataSetArchivingStatus newStatus,
+            boolean presentInArchive) throws UserFailureException
 
     {
         assert codes != null : "missing data set codes";
         assert newStatus != null : "missing status";
 
-        service.updateDataSetStatuses(session.getToken(), codes, newStatus);
+        service.updateDataSetStatuses(session.getToken(), codes, newStatus, presentInArchive);
         if (operationLog.isInfoEnabled())
         {
             operationLog.info("Updated in openBIS: data sets " + codes + ", status=" + newStatus);
@@ -426,9 +426,10 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer
         return service.listDeletedDataSets(session.getToken(), lastSeenDeletionEventIdOrNull);
     }
 
-    public void archiveDataSets(List<String> dataSetCodes) throws UserFailureException
+    public void archiveDataSets(List<String> dataSetCodes, boolean removeFromDataStore)
+            throws UserFailureException
     {
-        service.archiveDatasets(session.getToken(), dataSetCodes);
+        service.archiveDatasets(session.getToken(), dataSetCodes, removeFromDataStore);
     }
 
     public void unarchiveDataSets(List<String> dataSetCodes) throws UserFailureException
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetCommandExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetCommandExecutor.java
index ee1f5954291c254a6a219a3c13553c5e48256112..e05d54176df78421d6c62cdf923c8006a2b15180 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetCommandExecutor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetCommandExecutor.java
@@ -33,7 +33,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
  * 
  * @author Franz-Josef Elmer
  */
-interface IDataSetCommandExecutor
+public interface IDataSetCommandExecutor
 {
     /**
      * Starts up executor.
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/demo/DemoArchiver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/demo/DemoArchiver.java
index 8cc2074f6d4296ebd223d13aa0ba33c0cc136f4d..b942465059750b19823222fb21501084a6e6f881 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/demo/DemoArchiver.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/demo/DemoArchiver.java
@@ -17,11 +17,15 @@
 package ch.systemsx.cisd.openbis.dss.generic.server.plugins.demo;
 
 import java.io.File;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Properties;
+import java.util.Set;
 
 import ch.systemsx.cisd.common.exceptions.Status;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.common.filesystem.BooleanStatus;
+import ch.systemsx.cisd.openbis.dss.generic.server.IDataSetCommandExecutor;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractArchiverProcessingPlugin;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ArchiverTaskContext;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
@@ -33,9 +37,12 @@ public class DemoArchiver extends AbstractArchiverProcessingPlugin
 {
     private static final long serialVersionUID = 1L;
 
-    public DemoArchiver(Properties properties, File storeRoot)
+    private final static Set<String/* data set code */> archiveContents = new HashSet<String>();
+
+    public DemoArchiver(Properties properties, File storeRoot,
+            IDataSetCommandExecutor commandExecutor)
     {
-        super(properties, storeRoot, null, null);
+        super(properties, storeRoot, commandExecutor, null, null);
     }
 
     @Override
@@ -43,7 +50,8 @@ public class DemoArchiver extends AbstractArchiverProcessingPlugin
             ArchiverTaskContext context) throws UserFailureException
     {
         System.out.println("DemoArchiver - Archived: " + datasets);
-        return createStatusesFrom(Status.OK, datasets, true);
+        archiveContents.addAll(extractCodes(datasets));
+        return createStatuses(Status.OK, datasets, Operation.ARCHIVE);
     }
 
     @Override
@@ -51,7 +59,24 @@ public class DemoArchiver extends AbstractArchiverProcessingPlugin
             ArchiverTaskContext context) throws UserFailureException
     {
         System.out.println("DemoArchiver - Unarchived: " + datasets);
-        return createStatusesFrom(Status.OK, datasets, false);
+        return createStatuses(Status.OK, datasets, Operation.UNARCHIVE);
+    }
+
+    @Override
+    public BooleanStatus isDataSetPresentInArchive(DatasetDescription dataset,
+            ArchiverTaskContext context)
+    {
+        boolean present = archiveContents.contains(dataset.getDatasetCode());
+        return BooleanStatus.createFromBoolean(present);
+    }
+
+    @Override
+    protected DatasetProcessingStatuses doDeleteFromArchive(List<DatasetDescription> datasets,
+            ArchiverTaskContext context) throws UserFailureException
+    {
+        archiveContents.addAll(extractCodes(datasets));
+        System.out.println("DemoArchiver - deleteFromArchive: " + datasets);
+        return createStatuses(Status.OK, datasets, Operation.DELETE_FROM_ARCHIVE);
     }
 
 }
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 d64ac31783bf19916f6edb2e22eb82e46e24e523..7bf9c34921f71b8f505190660bcaf47ce488da26 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
@@ -16,16 +16,23 @@
 
 package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard;
 
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus.ARCHIVED;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus.AVAILABLE;
+
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 
 import ch.systemsx.cisd.common.collections.CollectionUtils;
 import ch.systemsx.cisd.common.exceptions.Status;
-import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.common.filesystem.BooleanStatus;
+import ch.systemsx.cisd.openbis.dss.generic.server.IDataSetCommandExecutor;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ArchiverTaskContext;
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IArchiverTask;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IArchiverPlugin;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ProcessingStatus;
 import ch.systemsx.cisd.openbis.dss.generic.shared.QueueingDataSetStatusUpdaterService;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetCodesWithStatus;
@@ -36,9 +43,10 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
  * The base class for archiving.
  * 
  * @author Piotr Buczek
+ * @author Kaloyan Enimanev
  */
 public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastorePlugin implements
-        IArchiverTask
+        IArchiverPlugin
 {
 
     private static final long serialVersionUID = 1L;
@@ -47,62 +55,134 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
 
     private final IStatusChecker unarchivePrerequisiteOrNull;
 
+    private final IDataSetCommandExecutor commandExecutor;
+
     public AbstractArchiverProcessingPlugin(Properties properties, File storeRoot,
+            IDataSetCommandExecutor commandExecutor,
             IStatusChecker archivePrerequisiteOrNull, IStatusChecker unarchivePrerequisiteOrNull)
     {
         super(properties, storeRoot);
+        this.commandExecutor = commandExecutor;
         this.archivePrerequisiteOrNull = archivePrerequisiteOrNull;
         this.unarchivePrerequisiteOrNull = unarchivePrerequisiteOrNull;
     }
 
+    /**
+     * NOTE: this method is not allowed to throw exception as this will leave data sets in the
+     * openBIS database with an inconsistent status.
+     */
     abstract protected DatasetProcessingStatuses doArchive(List<DatasetDescription> datasets,
-            ArchiverTaskContext context) throws UserFailureException;
+            ArchiverTaskContext context);
 
+    /**
+     * NOTE: this method is not allowed to throw exception as this will leave data sets in the
+     * openBIS database with an inconsistent status.
+     */
     abstract protected DatasetProcessingStatuses doUnarchive(List<DatasetDescription> datasets,
-            ArchiverTaskContext context) throws UserFailureException;
+            ArchiverTaskContext context);
+    
+    /**
+     * NOTE: this method is not allowed to throw exception as this will leave data sets in the
+     * openBIS database with an inconsistent status.
+     */
+    abstract protected DatasetProcessingStatuses doDeleteFromArchive(
+            List<DatasetDescription> datasets, ArchiverTaskContext context);
+    
+    /**
+     * @return <code>true</code> if the dataset is present in the archive, <code>false</code>
+     *         otherwise.
+     */
+    abstract protected BooleanStatus isDataSetPresentInArchive(DatasetDescription dataset,
+            ArchiverTaskContext context);
 
     public ProcessingStatus archive(List<DatasetDescription> datasets,
-            final ArchiverTaskContext context)
+            final ArchiverTaskContext context, boolean removeFromDataStore)
     {
         operationLog.info("Archiving of the following datasets has been requested: "
                 + CollectionUtils.abbreviate(datasets, 10));
-        return handleDatasets(datasets, DataSetArchivingStatus.ARCHIVED,
-                DataSetArchivingStatus.AVAILABLE, new IDatasetDescriptionHandler()
-                    {
-                        public DatasetProcessingStatuses handle(List<DatasetDescription> allDatasets)
-                        {
-                            Status prerequisiteStatus = checkArchivePrerequisite(allDatasets);
-                            if (prerequisiteStatus.isError())
-                            {
-                                return createStatusesFrom(prerequisiteStatus, allDatasets, true);
-                            } else
-                            {
-                                return doArchive(allDatasets, context);
-                            }
-                        }
-                    });
+
+        Status prerequisiteStatus = checkUnarchivePrerequisite(datasets);
+        DatasetProcessingStatuses statuses = null;
+        if (prerequisiteStatus.isError())
+        {
+            statuses = createStatuses(prerequisiteStatus, datasets, Operation.ARCHIVE);
+        } else
+        {
+            statuses = archiveInternal(datasets, context, removeFromDataStore);
+        }
+
+        DataSetArchivingStatus successStatus = (removeFromDataStore) ? ARCHIVED : AVAILABLE;
+
+        asyncUpdateStatuses(statuses.getSuccessfulDatasetCodes(), successStatus, true);
+        asyncUpdateStatuses(statuses.getFailedDatasetCodes(), AVAILABLE, false);
+
+        return statuses.getProcessingStatus();
+    }
+
+    private DatasetProcessingStatuses archiveInternal(List<DatasetDescription> datasets,
+            final ArchiverTaskContext context, boolean removeFromDataStore)
+    {
+
+        GroupedDatasets groupedDatasets = groupByPresenceInArchive(datasets, context);
+        List<DatasetDescription> notPresentInArchive = groupedDatasets.getNotPresentAsList();
+        if (notPresentInArchive.isEmpty() == false)
+        {
+            // copy data sets in the archive
+            // TODO KE: try to keep the error messages from the returned statuses
+            doArchive(notPresentInArchive, context);
+
+            // paranoid check to make sure everything really got archived
+            groupedDatasets = groupByPresenceInArchive(datasets, context);
+        }
+
+        if (removeFromDataStore)
+        {
+            // only remove the when we are sure we have got a backup in the archive
+            removeFromDataStore(groupedDatasets.getPresentInArchive(), context);
+        }
+        
+        DatasetProcessingStatuses statuses = new DatasetProcessingStatuses();
+        statuses.addResult(groupedDatasets.getPresentInArchive(), Status.OK, Operation.ARCHIVE);
+        statuses.addResult(groupedDatasets.getNotPresentInArchive().keySet(), Status.createError(),
+                Operation.ARCHIVE);
+
+        return statuses;
+    }
+
+    protected void removeFromDataStore(List<DatasetDescription> datasets,
+            ArchiverTaskContext context)
+    {
+        // the deletion will happen at a later point in time
+        commandExecutor.scheduleDeletionOfDataSets(datasets);
     }
 
     public ProcessingStatus unarchive(List<DatasetDescription> datasets,
-            final ArchiverTaskContext contex)
+            final ArchiverTaskContext context)
     {
         operationLog.info("Unarchiving of the following datasets has been requested: "
                 + CollectionUtils.abbreviate(datasets, 10));
-        return handleDatasets(datasets, DataSetArchivingStatus.AVAILABLE,
-                DataSetArchivingStatus.ARCHIVED, new IDatasetDescriptionHandler()
-                    {
-                        public DatasetProcessingStatuses handle(List<DatasetDescription> allDatasets)
-                        {
-                            Status prerequisiteStatus = checkUnarchivePrerequisite(allDatasets);
-                            if (prerequisiteStatus.isError())
-                            {
-                                return createStatusesFrom(prerequisiteStatus, allDatasets, false);
-                            } else
-                            {
-                                return doUnarchive(allDatasets, contex);
-                            }
-                        }
-                    });
+
+        Status prerequisiteStatus = checkUnarchivePrerequisite(datasets);
+        DatasetProcessingStatuses statuses = null;
+        if (prerequisiteStatus.isError())
+        {
+            statuses = createStatuses(prerequisiteStatus, datasets, Operation.UNARCHIVE);
+        } else
+        {
+            statuses = doUnarchive(datasets, context);
+        }
+
+        asyncUpdateStatuses(statuses.getSuccessfulDatasetCodes(), AVAILABLE, true);
+        asyncUpdateStatuses(statuses.getFailedDatasetCodes(), ARCHIVED, true);
+
+        return statuses.getProcessingStatus();
+    }
+
+    public ProcessingStatus deleteFromArchive(List<DatasetDescription> datasets,
+            ArchiverTaskContext context)
+    {
+        DatasetProcessingStatuses status = doDeleteFromArchive(datasets, context);
+        return status != null ? status.getProcessingStatus() : null;
     }
 
     protected final Status checkUnarchivePrerequisite(List<DatasetDescription> datasets)
@@ -127,6 +207,24 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
         }
     }
 
+    protected static enum Operation
+    {
+        ARCHIVE("Archiving"), UNARCHIVE("Unarchiving"),
+        DELETE_FROM_ARCHIVE("Deleting from archive");
+
+        private final String description;
+
+        Operation(String description)
+        {
+            this.description = description;
+        }
+
+        public String getDescription()
+        {
+            return description;
+        }
+    }
+
     protected static class DatasetProcessingStatuses
     {
         private final List<String> successfulDatasetCodes;
@@ -142,9 +240,23 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
             this.processingStatus = new ProcessingStatus();
         }
 
-        public void addResult(String datasetCode, Status status, boolean isArchiving)
+        public void addResult(Collection<DatasetDescription> datasets, Status status,
+                Operation operation)
         {
-            String logMessage = createLogMessage(datasetCode, status, isArchiving);
+            for (DatasetDescription dataset : datasets)
+            {
+                addResult(dataset.getDatasetCode(), status, operation.getDescription());
+            }
+        }
+
+        public void addResult(String datasetCode, Status status, Operation operation)
+        {
+            addResult(datasetCode, status, operation.getDescription());
+        }
+
+        public void addResult(String datasetCode, Status status, String operationDescription)
+        {
+            String logMessage = createLogMessage(datasetCode, status, operationDescription);
             if (status.isError())
             {
                 operationLog.error(logMessage);
@@ -157,11 +269,10 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
             processingStatus.addDatasetStatus(datasetCode, status);
         }
 
-        private String createLogMessage(String datasetCode, Status status, boolean isArchiving)
+        private String createLogMessage(String datasetCode, Status status, String operation)
         {
-            String operationDescription = isArchiving ? "Archiving" : "Unarchiving";
-            return String.format("%s for dataset %s finished with the status: %s.",
-                    operationDescription, datasetCode, status);
+            return String.format("%s for dataset %s finished with the status: %s.", operation,
+                    datasetCode, status);
         }
 
         public List<String> getSuccessfulDatasetCodes()
@@ -180,44 +291,89 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
         }
     }
 
-    private ProcessingStatus handleDatasets(List<DatasetDescription> datasets,
-            DataSetArchivingStatus success, DataSetArchivingStatus failure,
-            IDatasetDescriptionHandler handler)
+    protected final static DatasetProcessingStatuses createStatuses(Status status,
+            List<DatasetDescription> datasets, Operation operation)
     {
-        DatasetProcessingStatuses statuses = handler.handle(datasets);
-        asyncUpdateStatuses(statuses, success, failure);
-        return statuses.getProcessingStatus();
+        return createStatuses(status, datasets, operation.getDescription());
     }
 
     // creates the same status for all datasets
-    protected final static DatasetProcessingStatuses createStatusesFrom(Status status,
-            List<DatasetDescription> datasets, boolean isArchiving)
+    protected final static DatasetProcessingStatuses createStatuses(Status status,
+            List<DatasetDescription> datasets, String operationDescription)
     {
         DatasetProcessingStatuses statuses = new DatasetProcessingStatuses();
         for (DatasetDescription dataset : datasets)
         {
-            statuses.addResult(dataset.getDatasetCode(), status, isArchiving);
+            statuses.addResult(dataset.getDatasetCode(), status, operationDescription);
         }
         return statuses;
     }
 
-    private void asyncUpdateStatuses(DatasetProcessingStatuses statuses,
-            DataSetArchivingStatus success, DataSetArchivingStatus failure)
+    protected List<String> extractCodes(List<DatasetDescription> dataSets)
     {
-        asyncUpdateStatuses(statuses.getSuccessfulDatasetCodes(), success);
-        asyncUpdateStatuses(statuses.getFailedDatasetCodes(), failure);
+        List<String> result = new ArrayList<String>();
+        for (DatasetDescription description : dataSets)
+        {
+            result.add(description.getDatasetCode());
+        }
+        return result;
     }
 
     private static void asyncUpdateStatuses(List<String> dataSetCodes,
-            DataSetArchivingStatus newStatus)
+            DataSetArchivingStatus newStatus, boolean presentInArchive)
     {
         QueueingDataSetStatusUpdaterService.update(new DataSetCodesWithStatus(dataSetCodes,
-                newStatus));
+                newStatus, presentInArchive));
     }
 
-    private interface IDatasetDescriptionHandler
+    protected static class GroupedDatasets
     {
-        public DatasetProcessingStatuses handle(List<DatasetDescription> datasets);
+        private List<DatasetDescription> presentInArchive;
+
+        private Map<DatasetDescription, BooleanStatus> notPresentInArchive;
+
+        GroupedDatasets(List<DatasetDescription> presentInArchive,
+                Map<DatasetDescription, BooleanStatus> notPresentInArchive)
+        {
+            this.presentInArchive = presentInArchive;
+            this.notPresentInArchive = notPresentInArchive;
+        }
+
+        public List<DatasetDescription> getPresentInArchive()
+        {
+            return presentInArchive;
+        }
+
+        public Map<DatasetDescription, BooleanStatus> getNotPresentInArchive()
+        {
+            return notPresentInArchive;
+        }
+
+        public List<DatasetDescription> getNotPresentAsList()
+        {
+
+            return new ArrayList<DatasetDescription>(notPresentInArchive.keySet());
+        }
+    }
+
+    protected GroupedDatasets groupByPresenceInArchive(List<DatasetDescription> datasets,
+            ArchiverTaskContext context)
+    {
+        List<DatasetDescription> present = new ArrayList<DatasetDescription>();
+        Map<DatasetDescription, BooleanStatus> notPresent = new HashMap<DatasetDescription, BooleanStatus>();
+        
+        for (DatasetDescription dataset : datasets) {
+            BooleanStatus presentStatus = isDataSetPresentInArchive(dataset, context);
+            if (presentStatus.isSuccess())
+            {
+                present.add(dataset);
+            } else {
+                notPresent.put(dataset, presentStatus);
+            }
+        }
+        
+        return new GroupedDatasets(present, notPresent);
     }
 
+
 }
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 5c2b5420579b7fc3229ece6a5bd6eb6e10348599..968fe01e44f5bc88af713ec81766546de576b7fd 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
@@ -24,6 +24,7 @@ import ch.rinn.restrictions.Private;
 import ch.systemsx.cisd.common.exceptions.Status;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.filesystem.BooleanStatus;
+import ch.systemsx.cisd.openbis.dss.generic.server.IDataSetCommandExecutor;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ArchiverTaskContext;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
 
@@ -49,16 +50,19 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
 
     private final ISshCommandExecutorFactory sshCommandExecutorFactory;
 
-    public RsyncArchiver(Properties properties, File storeRoot)
+    public RsyncArchiver(Properties properties, File storeRoot,
+            IDataSetCommandExecutor commandExecutor)
     {
-        this(properties, storeRoot, new RsyncCopierFactory(), new SshCommandExecutorFactory());
+        this(properties, storeRoot, commandExecutor, new RsyncCopierFactory(),
+                new SshCommandExecutorFactory());
     }
 
     @Private
-    RsyncArchiver(Properties properties, File storeRoot, IPathCopierFactory pathCopierFactory,
+    RsyncArchiver(Properties properties, File storeRoot, IDataSetCommandExecutor commandExecutor,
+            IPathCopierFactory pathCopierFactory,
             ISshCommandExecutorFactory sshCommandExecutorFactory)
     {
-        super(properties, storeRoot, null, null);
+        super(properties, storeRoot, commandExecutor, null, null);
         this.pathCopierFactory = pathCopierFactory;
         this.sshCommandExecutorFactory = sshCommandExecutorFactory;
     }
@@ -74,7 +78,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
         {
             File originalData = getDatasetDirectory(context, dataset);
             Status status = doArchive(dataset, originalData);
-            statuses.addResult(dataset.getDatasetCode(), status, true);
+            statuses.addResult(dataset.getDatasetCode(), status, Operation.ARCHIVE);
         }
 
         return statuses;
@@ -92,12 +96,13 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
         {
             File originalData = getDatasetDirectory(context, dataset);
             Status status = doUnarchive(dataset, originalData);
-            statuses.addResult(dataset.getDatasetCode(), status, false);
+            statuses.addResult(dataset.getDatasetCode(), status, Operation.UNARCHIVE);
         }
 
         return statuses;
     }
 
+    @Override
     protected DatasetProcessingStatuses doDeleteFromArchive(List<DatasetDescription> datasets,
             ArchiverTaskContext context)
     {
@@ -108,12 +113,13 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
         for (DatasetDescription dataset : datasets)
         {
             Status status = doDeleteFromArchive(dataset);
-            statuses.addResult(dataset.getDatasetCode(), status, false); // false -> deletion
+            statuses.addResult(dataset.getDatasetCode(), status, Operation.DELETE_FROM_ARCHIVE);
         }
 
         return statuses;
     }
 
+    @Override
     protected BooleanStatus isDataSetPresentInArchive(DatasetDescription dataset,
             ArchiverTaskContext context)
     {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ArchiverTaskFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ArchiverPluginFactory.java
similarity index 86%
rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ArchiverTaskFactory.java
rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ArchiverPluginFactory.java
index 50a53559952cfb8f3c7f5422cb38eedf38cf096c..0a399668baaf4c97851943314ace0a310e1f6757 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ArchiverTaskFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ArchiverPluginFactory.java
@@ -28,16 +28,17 @@ import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.utilities.ClassUtils;
 import ch.systemsx.cisd.common.utilities.PropertyParametersUtil.SectionProperties;
+import ch.systemsx.cisd.openbis.dss.generic.server.IDataSetCommandExecutor;
 
 /**
  * Factory of Archiver Tasks.
  * 
  * @author Piotr Buczek
  */
-public class ArchiverTaskFactory
+public class ArchiverPluginFactory
 {
     private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, ArchiverTaskFactory.class);
+            LogFactory.getLogger(LogCategory.OPERATION, ArchiverPluginFactory.class);
 
     private final String className;
 
@@ -47,7 +48,7 @@ public class ArchiverTaskFactory
     @Private
     public final static String CLASS_PROPERTY_NAME = "class";
 
-    public ArchiverTaskFactory(SectionProperties sectionProperties)
+    public ArchiverPluginFactory(SectionProperties sectionProperties)
     {
         this.className = sectionProperties.getProperties().getProperty(CLASS_PROPERTY_NAME);
         this.archiverProperties = sectionProperties.getProperties();
@@ -58,7 +59,7 @@ public class ArchiverTaskFactory
         return className != null;
     }
 
-    public IArchiverTask createInstance(File storeRoot)
+    public IArchiverPlugin createInstance(File storeRoot, IDataSetCommandExecutor commandExecutor)
     {
         if (isArchiverConfigured() == false)
         {
@@ -66,7 +67,8 @@ public class ArchiverTaskFactory
         }
         try
         {
-            return ClassUtils.create(IArchiverTask.class, className, archiverProperties, storeRoot);
+            return ClassUtils.create(IArchiverPlugin.class, className, archiverProperties,
+                    storeRoot, commandExecutor);
         } catch (ConfigurationFailureException ex)
         {
             throw ex; // rethrow the exception without changing the message
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IArchiverTask.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IArchiverPlugin.java
similarity index 76%
rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IArchiverTask.java
rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IArchiverPlugin.java
index 4fb82103bb2f38aa2bed66a5218834e496ea865b..7101dce639798f060798c02afdfb435c77d83454 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IArchiverTask.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IArchiverPlugin.java
@@ -25,8 +25,9 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
  * Interface of the archiver task.
  * 
  * @author Piotr Buczek
+ * @author Kaloyan Enimanev
  */
-public interface IArchiverTask extends Serializable
+public interface IArchiverPlugin extends Serializable
 {
     /**
      * Asynchronously processes archiving of the specified datasets.
@@ -35,7 +36,8 @@ public interface IArchiverTask extends Serializable
      *          all scheduled data sets or null if processing succeeded for all datasets and no
      *          additional information is provided.
      */
-    ProcessingStatus archive(List<DatasetDescription> datasets, ArchiverTaskContext context);
+    ProcessingStatus archive(List<DatasetDescription> datasets, ArchiverTaskContext context,
+            boolean removeFromDataStore);
 
     /**
      * Asynchronously processes unarchiving of the specified datasets.
@@ -45,4 +47,13 @@ public interface IArchiverTask extends Serializable
      *          additional information is provided.
      */
     ProcessingStatus unarchive(List<DatasetDescription> datasets, ArchiverTaskContext context);
+
+    /**
+     * Delete data sets from the archive.
+     * 
+     * @returns {@link ProcessingStatus} containing the deletion statuses for all data sets or null
+     *          if processing succeeded for all datasets and no additional information is provided.
+     */
+    ProcessingStatus deleteFromArchive(List<DatasetDescription> datasets,
+            ArchiverTaskContext context);
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskProviders.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskProviders.java
index 69358745be985d4849056fb4b6cdc95e1a198c1a..edc1b860e298249deee33bc416f5962a11991295 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskProviders.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskProviders.java
@@ -48,7 +48,7 @@ public class PluginTaskProviders
 
     private final PluginTaskProvider<IProcessingPluginTask> processingPlugins;
 
-    private final ArchiverTaskFactory archiverTaskFactory;
+    private final ArchiverPluginFactory archiverTaskFactory;
 
     private final File storeRoot;
 
@@ -92,7 +92,7 @@ public class PluginTaskProviders
         return processingPlugins;
     }
 
-    public ArchiverTaskFactory getArchiverTaskFactory()
+    public ArchiverPluginFactory getArchiverTaskFactory()
     {
         return archiverTaskFactory;
     }
@@ -142,12 +142,12 @@ public class PluginTaskProviders
         return new PluginTaskProvider<IProcessingPluginTask>(factories);
     }
 
-    private ArchiverTaskFactory createArchiverTaskFactory(Properties serviceProperties,
+    private ArchiverPluginFactory createArchiverTaskFactory(Properties serviceProperties,
             String datastoreCode)
     {
         SectionProperties sectionsProperties =
                 extractSingleSectionProperties(serviceProperties, ARCHIVER_SECTION_NAME);
-        return new ArchiverTaskFactory(sectionsProperties);
+        return new ArchiverPluginFactory(sectionsProperties);
     }
 
     private static SectionProperties[] extractSectionProperties(Properties serviceProperties,
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
index a4d614fb8a83ae8f2b25e700b5d6eed1ea914a36..dc0ce6cbe570a8c9e8ffd1a9a0019607a4983590 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
@@ -318,18 +318,22 @@ public interface IEncapsulatedOpenBISService
     public List<ExternalData> listAvailableDataSets(ArchiverDataSetCriteria criteria)
             throws UserFailureException;
 
-    /** See {@link IETLLIMSService#archiveDatasets(String, List)} */
+    /** See {@link IETLLIMSService#archiveDatasets(String, List, boolean)} */
     @ManagedAuthentication
-    public void archiveDataSets(List<String> dataSetCodes) throws UserFailureException;
+    public void archiveDataSets(List<String> dataSetCodes, boolean removeFromDataStore)
+            throws UserFailureException;
 
     /** See {@link IETLLIMSService#unarchiveDatasets(String, List)} */
     @ManagedAuthentication
     public void unarchiveDataSets(List<String> dataSetCodes) throws UserFailureException;
 
-    /** See {@link IETLLIMSService#updateDataSetStatuses(String, List, DataSetArchivingStatus)} */
+    /**
+     * See
+     * {@link IETLLIMSService#updateDataSetStatuses(String, List, DataSetArchivingStatus, boolean)}
+     */
     @ManagedAuthentication
-    public void updateDataSetStatuses(List<String> codes, DataSetArchivingStatus newStatus)
-            throws UserFailureException;
+    public void updateDataSetStatuses(List<String> codes, DataSetArchivingStatus newStatus,
+            boolean presentInArchive) throws UserFailureException;
 
     /** See {@link IETLLIMSService#checkSpaceAccess(String, SpaceIdentifier)} */
     @ManagedAuthentication
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/QueueingDataSetStatusUpdaterService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/QueueingDataSetStatusUpdaterService.java
index 3c8658f94643abfa7fc32259dad5b5f51b0baac7..5e58c902d90eacdc1302d9039cb57cd8d46380d3 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/QueueingDataSetStatusUpdaterService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/QueueingDataSetStatusUpdaterService.java
@@ -105,8 +105,8 @@ public class QueueingDataSetStatusUpdaterService
                             final DataSetCodesWithStatus dataSets = queue.peekWait();
                             try
                             {
-                                updater.updateDataSetStatuses(dataSets.getDataSetCodes(), dataSets
-                                        .getStatus());
+                                updater.updateDataSetStatuses(dataSets.getDataSetCodes(),
+                                        dataSets.getStatus(), dataSets.isPresentInArchive());
                                 // Note: this is the only consumer of this queue.
                                 queue.take();
                                 // If update succeeded than it is possible that other updates
@@ -158,10 +158,10 @@ public class QueueingDataSetStatusUpdaterService
         return new IDataSetStatusUpdater()
             {
                 public void updateDataSetStatuses(List<String> dataSetCodes,
-                        DataSetArchivingStatus newStatus)
+                        DataSetArchivingStatus newStatus, boolean presentInArchive)
                 {
                     ServiceProvider.getOpenBISService().updateDataSetStatuses(dataSetCodes,
-                            newStatus);
+                            newStatus, presentInArchive);
                     operationLog.info("Data Sets " + CollectionUtils.abbreviate(dataSetCodes, 10)
                             + " changed status to " + newStatus);
                 }
@@ -310,9 +310,10 @@ public class QueueingDataSetStatusUpdaterService
          * 
          * @param dataSetCodes codes of data sets to be updated
          * @param newStatus status to be set
+         * @param presentInArchive the present in archive flag to set
          */
         public void updateDataSetStatuses(List<String> dataSetCodes,
-                DataSetArchivingStatus newStatus);
+                DataSetArchivingStatus newStatus, boolean presentInArchive);
     }
 
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetCodesWithStatus.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetCodesWithStatus.java
index 5a72c8ea7617d747370335ff304ee761f28ddc3f..c4a388c2272488028b363a0868ff17682656026d 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetCodesWithStatus.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetCodesWithStatus.java
@@ -28,14 +28,18 @@ public class DataSetCodesWithStatus implements Serializable
 {
     private static final long serialVersionUID = 1L;
 
-    private List<String> dataSetCodes;
+    private final List<String> dataSetCodes;
 
-    private DataSetArchivingStatus status;
+    private final DataSetArchivingStatus status;
 
-    public DataSetCodesWithStatus(List<String> dataSetCodes, DataSetArchivingStatus status)
+    private final boolean presentInArchive;
+
+    public DataSetCodesWithStatus(List<String> dataSetCodes, DataSetArchivingStatus status,
+            boolean presentInArchive)
     {
         this.dataSetCodes = dataSetCodes;
         this.status = status;
+        this.presentInArchive = presentInArchive;
     }
 
     public List<String> getDataSetCodes()
@@ -48,6 +52,11 @@ public class DataSetCodesWithStatus implements Serializable
         return status;
     }
 
+    public boolean isPresentInArchive()
+    {
+        return presentInArchive;
+    }
+
     @Override
     public String toString()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java
index 62c0fd1f111a8a875701aa1ffa0ada4ec1c8032e..e882b4d3f7853e81f0ec81670180f95dfb0d99f5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java
@@ -91,13 +91,14 @@ abstract class AbstractCommonServer<T extends IServer> extends AbstractServer<T>
 
     }
 
-    public int archiveDatasets(String sessionToken, List<String> datasetCodes)
+    public int archiveDatasets(String sessionToken, List<String> datasetCodes,
+            boolean deleteFromDataStore)
     {
         Session session = getSession(sessionToken);
         IExternalDataTable externalDataTable =
                 businessObjectFactory.createExternalDataTable(session);
         externalDataTable.loadByDataSetCodes(datasetCodes, false, true);
-        return externalDataTable.archiveDatasets();
+        return externalDataTable.archiveDatasets(deleteFromDataStore);
     }
 
     public int unarchiveDatasets(String sessionToken, List<String> datasetCodes)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
index 9594114ea895eb2284aeb68ef24748fb80df7923..8d0243a6d26ac98920225897daf540eabaa4760d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
@@ -666,12 +666,12 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET
     }
 
     public void updateDataSetStatuses(String sessionToken, List<String> dataSetCodes,
-            DataSetArchivingStatus newStatus) throws UserFailureException
+            DataSetArchivingStatus newStatus, boolean presentInArchive) throws UserFailureException
     {
         assert sessionToken != null : "Unspecified session token.";
         final Session session = getSession(sessionToken);
         final IExternalDataBO externalDataBO = businessObjectFactory.createExternalDataBO(session);
-        externalDataBO.updateStatuses(dataSetCodes, newStatus);
+        externalDataBO.updateStatuses(dataSetCodes, newStatus, presentInArchive);
     }
 
     public ExternalData tryGetDataSet(String sessionToken, String dataSetCode)
@@ -1075,4 +1075,5 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET
 
         return externalDataBO;
     }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
index 066d329df93d34a716b76a70a2dfcff8a62dba7f..1d1cb22c2478372e7e4fedc5cf6be18ed672ee86 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
@@ -328,10 +328,11 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLServic
     }
 
     public void updateDataSetStatuses(String sessionToken, List<String> dataSetCodes,
-            DataSetArchivingStatus newStatus) throws UserFailureException
+            DataSetArchivingStatus newStatus, boolean presentInArchive) throws UserFailureException
     {
-        logTracking(sessionToken, "updateDataSetStatus", "NO_OF_DATASETS(%s) STATUS(%s)",
-                dataSetCodes.size(), newStatus);
+        logTracking(sessionToken, "updateDataSetStatus",
+                "NO_OF_DATASETS(%s) STATUS(%s) PRESENT_IN_ARCHIVE(%s)", dataSetCodes.size(),
+                newStatus, presentInArchive);
     }
 
     public String getDefaultPutDataStoreBaseURL(String sessionToken)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java
index 877d5258e018ba0906c7f8132927d27fa5f3818a..2e5a18519f462830c54c497f845c1095c3c5d4d8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java
@@ -683,9 +683,10 @@ public class ExternalDataBO extends AbstractExternalDataBusinessObject implement
         return result;
     }
 
-    public void updateStatuses(List<String> dataSetCodes, DataSetArchivingStatus newStatus)
+    public void updateStatuses(List<String> dataSetCodes, DataSetArchivingStatus newStatus,
+            boolean newPresentInArchive)
     {
-        getExternalDataDAO().updateDataSetStatuses(dataSetCodes, newStatus);
+        getExternalDataDAO().updateDataSetStatuses(dataSetCodes, newStatus, newPresentInArchive);
     }
 
     public void updateManagedProperty(IManagedProperty managedProperty)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java
index 5496abcea42c4d853fb9bbfed686e9da10841c83..e35b9f9ed2c9a767899a26d5a96d84ea093f0dfb 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java
@@ -150,6 +150,25 @@ public final class ExternalDataTable extends AbstractExternalDataBusinessObject
         }
     }
 
+    private static void assertDatasetsAreDeletable(List<ExternalDataPE> datasets)
+    {
+        List<String> notDeletableDatasets = new ArrayList<String>();
+        for (ExternalDataPE dataSet : datasets)
+        {
+            if (dataSet.getStatus().isDeletable() == false)
+            {
+                notDeletableDatasets.add(dataSet.getCode());
+            }
+        }
+        if (notDeletableDatasets.isEmpty() == false)
+        {
+            throw UserFailureException.fromTemplate(
+                    "Deletion failed because the following data sets are required "
+                            + "by a background process (their status is pending): %s. ",
+                    CollectionUtils.abbreviate(notDeletableDatasets, 10));
+        }
+    }
+
     private final IDataStoreServiceFactory dssFactory;
 
     private List<ExternalDataPE> externalData;
@@ -205,7 +224,7 @@ public final class ExternalDataTable extends AbstractExternalDataBusinessObject
 
     public void deleteLoadedDataSets(String reason)
     {
-        assertDatasetsAreAvailable(externalData);
+        assertDatasetsAreDeletable(externalData);
         Map<DataStorePE, List<ExternalDataPE>> map = groupDataSetsByDataStores();
         assertDataSetsAreKnown(map);
         for (Map.Entry<DataStorePE, List<ExternalDataPE>> entry : map.entrySet())
@@ -533,13 +552,13 @@ public final class ExternalDataTable extends AbstractExternalDataBusinessObject
     // Archiving
     //
 
-    public int archiveDatasets()
+    public int archiveDatasets(boolean removeFromDataStore)
     {
         Map<DataStorePE, List<ExternalDataPE>> datasetsByStore = groupDataSetsByDataStores();
         int result =
                 filterByStatusAndUpdate(datasetsByStore, DataSetArchivingStatus.AVAILABLE,
                         DataSetArchivingStatus.ARCHIVE_PENDING);
-        performArchiving(datasetsByStore);
+        performArchiving(datasetsByStore, removeFromDataStore);
         return result;
     }
 
@@ -615,14 +634,16 @@ public final class ExternalDataTable extends AbstractExternalDataBusinessObject
 
     }
 
-    private void performArchiving(Map<DataStorePE, List<ExternalDataPE>> datasetsByStore)
+    private void performArchiving(Map<DataStorePE, List<ExternalDataPE>> datasetsByStore,
+            final boolean removeFromDataStore)
     {
         performArchivingAction(datasetsByStore, new IArchivingAction()
             {
                 public void execute(String sessionToken, IDataStoreService service,
                         List<DatasetDescription> descriptions, String userEmailOrNull)
                 {
-                    service.archiveDatasets(sessionToken, descriptions, userEmailOrNull);
+                    service.archiveDatasets(sessionToken, descriptions, userEmailOrNull,
+                            removeFromDataStore);
                 }
             });
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataBO.java
index 1f5cad12a4ff8637d2c2b5417232d29d926ef474..7b14087f03c85b69c3c3e3bcf3a1886c0d95bbf2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataBO.java
@@ -73,8 +73,8 @@ public interface IExternalDataBO extends IEntityBusinessObject
      * 
      * @throws UserFailureException if a data set does not exist or status couldn't be set.
      */
-    public void updateStatuses(List<String> dataSetCodes, DataSetArchivingStatus newStatus)
-            throws UserFailureException;
+    public void updateStatuses(List<String> dataSetCodes, DataSetArchivingStatus newStatus,
+            boolean newPresentInArchive) throws UserFailureException;
 
     /**
      * Adds chosen properties to given data set. If given property has been already defined, the
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataTable.java
index ca35aa59b2dd7288edc72d3777357f3ec25ff99a..f85d26b1434408c604700c15d6064f1b7574f814 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataTable.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataTable.java
@@ -79,9 +79,11 @@ public interface IExternalDataTable
      * Schedules archiving of loaded data sets. Only available data sets that are not locked will be
      * archived.
      * 
+     * @param removeFromDataStore when set to <code>true</code> the data sets will be removed from
+     *            the data store after a successful archiving operation.
      * @return number of data sets scheduled for archiving.
      */
-    int archiveDatasets();
+    int archiveDatasets(boolean removeFromDataStore);
 
     /**
      * Schedules unarchiving of loaded data sets. Only archived datasets will be unarchived.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
index 3a78ca7195cb514e218acb9b62069e468a803008..fdc337579e67622479ca2c55a4065c7b1656f1c3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
@@ -348,15 +348,16 @@ public class DatasetLister extends AbstractLister implements IDatasetLister
         final Long dataStoreId = extractDataStoreId(dataStoreCode);
         final Date lastRegistrationDate = extractLastRegistrationDate(criteria);
         final String dataSetTypeCodeOrNull = criteria.tryGetDataSetTypeCode();
+        final boolean presentInArchive = criteria.isPresentInArchive();
         if (dataSetTypeCodeOrNull == null)
         {
             return enrichDatasets(query.getAvailableDataSetsRegisteredBefore(dataStoreId,
-                    lastRegistrationDate));
+                    lastRegistrationDate, presentInArchive));
         } else
         {
             Long dataSetTypeId = extractDataSetTypeId(dataSetTypeCodeOrNull);
             return enrichDatasets(query.getAvailableDataSetsRegisteredBeforeWithDataSetType(
-                    dataStoreId, lastRegistrationDate, dataSetTypeId));
+                    dataStoreId, lastRegistrationDate, presentInArchive, dataSetTypeId));
         }
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
index 243944dc633cbc276a05cb2e54271fc88be58f78..ba8dd76616294ff3fe8a270e0148cae18cb76609 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
@@ -86,19 +86,21 @@ public interface IDatasetListingQuery extends TransactionQuery, IPropertyListing
      */
     @Select(sql = "SELECT * FROM data JOIN external_data ON data.id = external_data.data_id"
             + "    WHERE data.dast_id = ?{1} AND external_data.status = 'AVAILABLE' "
-            + "    AND data.registration_timestamp < ?{2}", fetchSize = FETCH_SIZE)
+            + "    AND data.registration_timestamp < ?{2} AND external_data.present_in_archive=?{3}", fetchSize = FETCH_SIZE)
     public DataIterator<DatasetRecord> getAvailableDataSetsRegisteredBefore(long dataStoreId,
-            Date lastModificationDate);
+            Date lastModificationDate, boolean presentInArchive);
 
     /**
-     * Like {@link #getAvailableDataSetsRegisteredBefore(long, Date)} with additional condition for
-     * data set type id.
+     * Like {@link #getAvailableDataSetsRegisteredBefore(long, Date, boolean)} with additional
+     * condition for data set type id.
      */
     @Select(sql = "SELECT * FROM data JOIN external_data ON data.id = external_data.data_id"
             + "    WHERE data.dast_id = ?{1} AND external_data.status = 'AVAILABLE' "
-            + "    AND data.registration_timestamp < ?{2} AND data.dsty_id = ?{3}", fetchSize = FETCH_SIZE)
+            + "    AND data.registration_timestamp < ?{2} AND external_data.present_in_archive=?{3} "
+            + "    AND data.dsty_id = ?{4}", fetchSize = FETCH_SIZE)
     public DataIterator<DatasetRecord> getAvailableDataSetsRegisteredBeforeWithDataSetType(
-            long dataStoreId, Date lastModificationDate, long dataSetTypeId);
+            long dataStoreId, Date lastModificationDate, boolean presentInArchive,
+            long dataSetTypeId);
 
     /**
      * Returns the directly connected dataset ids for the given sample id.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExternalDataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExternalDataDAO.java
index c3b76177cdd49b78ad0658f06ea67b6b7b9575c4..921112fe7687977ee569c0fb6e71ee25fc387b56 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExternalDataDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExternalDataDAO.java
@@ -61,6 +61,16 @@ public interface IExternalDataDAO extends IGenericDAO<ExternalDataPE>
      */
     public List<ExternalDataPE> listExternalData(final SamplePE sample) throws DataAccessException;
 
+    // /**
+    // * List the all {@link ExternalDataPE} for given {@link DataSetArchivingStatus}.
+    // *
+    // * @param maxResultSize the maximum size of the returned list. Specifying a negative number
+    // * (e.g. -1) is equal to no limitation.
+    // * @returns list of {@link ExternalDataPE}s with the specified status.
+    // */
+    // public List<ExternalDataPE> listByArchivingStatus(DataSetArchivingStatus status,
+    // int maxResultSize);
+
     /**
      * List the {@link ExternalDataPE} for given <var>experiment</var>.
      * 
@@ -91,6 +101,12 @@ public interface IExternalDataDAO extends IGenericDAO<ExternalDataPE>
      */
     public void updateDataSetStatuses(List<String> dataSetCodes, DataSetArchivingStatus status);
 
+    /**
+     * Updates the status and the present in archive flag for given datasets.
+     */
+    public void updateDataSetStatuses(List<String> dataSetCodes, DataSetArchivingStatus status,
+            boolean newPresentInArchive);
+
     /**
      * Persists the specified data set.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
index a694d582c9fb3506db977f0b89f54262786cb281..0e462471d2cd1cd1996b19f60aaad15a75c12716 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
@@ -24,7 +24,7 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
 public final class DatabaseVersionHolder
 {
     /** Current version of the database. */
-    private static final String DATABASE_VERSION = "066";// S100
+    private static final String DATABASE_VERSION = "067";// S120
 
     private DatabaseVersionHolder()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java
index 5f1e39cffd72a5186490a8e71271c36c97be935b..151a91058cdeb85fd3b7fea8eb8227fedc5846b3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java
@@ -323,6 +323,54 @@ final class ExternalDataDAO extends AbstractGenericEntityWithPropertiesDAO<Exter
         }
     }
 
+    public void updateDataSetStatuses(final List<String> dataSetCodes,
+            final DataSetArchivingStatus status, final boolean presentInArchive)
+    {
+        assert dataSetCodes != null : "Unspecified data set codes";
+        assert status != null : "Unspecified code";
+
+        if (dataSetCodes.size() == 0)
+        {
+            return;
+        }
+
+        final HibernateTemplate hibernateTemplate = getHibernateTemplate();
+        int updatedRows = (Integer) hibernateTemplate.execute(new HibernateCallback()
+            {
+
+                //
+                // HibernateCallback
+                //
+
+                public final Object doInHibernate(final Session session) throws HibernateException,
+                        SQLException
+                {
+                    // NOTE: 'VERSIONED' makes modification time modified too
+                    return session
+                            .createQuery(
+                                    "UPDATE VERSIONED " + TABLE_NAME
+                                            + " SET status = :status, isPresentInArchive = :presentInArchive"
+                                            + " WHERE code IN (:codes) ")
+                            .setParameter("status", status)
+                            .setParameter("presentInArchive", presentInArchive)
+                            .setParameterList("codes", dataSetCodes)
+                            .executeUpdate();
+                }
+            });
+        hibernateTemplate.flush();
+        if (updatedRows != dataSetCodes.size())
+        {
+            throw UserFailureException.fromTemplate(
+                    "Update of %s data set statuses to '%s' and presentInArchive to '%s' failed.",
+                    dataSetCodes.size(), status, presentInArchive);
+        } else if (operationLog.isInfoEnabled())
+        {
+            operationLog.info(String.format(
+                    "UPDATED: %s data set statuses to '%s' and presentInArchive flag to '%s'.",
+                    dataSetCodes.size(), status, presentInArchive));
+        }
+    }
+
     public void createDataSet(DataPE dataset)
     {
         assert dataset != null : "Unspecified data set.";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/AbstractServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/AbstractServerLogger.java
index 1ee8d178c7eebf67db4444c07531609264b9e2ca..84ba5738502cafa33af339d891b7743357a3dd55 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/AbstractServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/AbstractServerLogger.java
@@ -279,9 +279,11 @@ public abstract class AbstractServerLogger implements IServer
         return 0;
     }
 
-    public int archiveDatasets(String sessionToken, List<String> datasetCodes)
+    public int archiveDatasets(String sessionToken, List<String> datasetCodes,
+            boolean removeFromDataStore)
     {
-        logTracking(sessionToken, "archiveDatasets", "DATASETS(%s)", abbreviate(datasetCodes));
+        logTracking(sessionToken, "archiveDatasets", "DATASETS(%s), REMOVE_FROM_DATA_STORE(%s)",
+                abbreviate(datasetCodes), removeFromDataStore);
         return 0;
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 8726967c5cd586601c65f86f6d71fa7cfea551c9..610cec0ebf6e87149b9927ce7434d33935e8129e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -1016,6 +1016,8 @@ public interface ICommonServer extends IServer
     /**
      * Schedules archiving of specified data sets.
      * 
+     * @param removeFromDataStore when set to <code>true</code> the data sets will be removed from
+     *            the data store after a successful archiving operation.
      * @return number of data sets scheduled for archiving.
      */
     @Transactional
@@ -1023,7 +1025,8 @@ public interface ICommonServer extends IServer
     @DatabaseUpdateModification(value = ObjectKind.DATA_SET)
     public int archiveDatasets(
             String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes);
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes,
+            boolean removeFromDataStore);
 
     /**
      * Schedules unarchiving of specified data sets.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
index 7cefba2da43268de1d4295f085dc98587796b2da..8fcce253dfca48b9914b9db178406157cfc6500a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
@@ -37,7 +37,7 @@ public interface IDataStoreService
     /**
      * Every time this interface and related DTO's are changed, we should increment this number.
      */
-    public static final int VERSION = 5; // for release S77
+    public static final int VERSION = 6; // for release 102
 
     /**
      * Returns the version of this service.
@@ -101,9 +101,11 @@ public interface IDataStoreService
      * @param userEmailOrNull Email of user who initiated archiving and will get a message after the
      *            task is finished. It may be null if the user doesn't have email and no message
      *            will be send in such case.
+     * @param removeFromDataStore when set to <code>true</code> the data sets will be removed from
+     *            the data store after a successful archiving operation.
      */
     public void archiveDatasets(String sessionToken, List<DatasetDescription> datasets,
-            String userEmailOrNull);
+            String userEmailOrNull, boolean removeFromDataStore);
 
     /**
      * Schedules unarchiving of provided datasets.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
index 8f546360b35748d9bdb6a64c59477bb264388411..5049423d96909295759e3aa956f963463d9bc269 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
@@ -471,11 +471,14 @@ public interface IETLLIMSService extends IServer, ISessionProvider
     public void updateDataSetStatuses(
             String sessionToken,
             @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> dataSetCodes,
-            final DataSetArchivingStatus newStatus) throws UserFailureException;
+            final DataSetArchivingStatus newStatus, boolean presentInArchive)
+            throws UserFailureException;
 
     /**
      * Schedules archiving of specified data sets.
      * 
+     * @param removeFromDataStore when set to <code>true</code> the data sets will be removed from
+     *            the data store after a successful archiving operation.
      * @return number of data sets scheduled for archiving.
      */
     @Transactional
@@ -483,7 +486,8 @@ public interface IETLLIMSService extends IServer, ISessionProvider
     @DatabaseUpdateModification(value = ObjectKind.DATA_SET)
     public int archiveDatasets(
             String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes);
+            @AuthorizationGuard(guardClass = DataSetCodeCollectionPredicate.class) List<String> datasetCodes,
+            boolean removeFromDataStore);
 
     /**
      * Schedules unarchiving of specified data sets.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ArchiverDataSetCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ArchiverDataSetCriteria.java
index 5f8cbda74de9838e913efc57afb982198d6c82a4..e979267004215a20dca2d077b097548ba0d91106 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ArchiverDataSetCriteria.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ArchiverDataSetCriteria.java
@@ -32,10 +32,14 @@ public class ArchiverDataSetCriteria implements Serializable
 
     private final String dataSetTypeCodeOrNull;
 
-    public ArchiverDataSetCriteria(int olderThan, String dataSetTypeCodeOrNull)
+    private final boolean presentInArchive;
+
+    public ArchiverDataSetCriteria(int olderThan, String dataSetTypeCodeOrNull,
+            boolean presentInArchive)
     {
         this.olderThan = olderThan;
         this.dataSetTypeCodeOrNull = dataSetTypeCodeOrNull;
+        this.presentInArchive = presentInArchive;
     }
 
     public int getOlderThan()
@@ -48,6 +52,11 @@ public class ArchiverDataSetCriteria implements Serializable
         return dataSetTypeCodeOrNull;
     }
 
+    public boolean isPresentInArchive()
+    {
+        return presentInArchive;
+    }
+
     @Override
     public String toString()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetArchivingStatus.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetArchivingStatus.java
index 87deb6853daf884f264898e6a9cfe3596c11ac80..bba72f525be549650345ac5f087d621f23b48482 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetArchivingStatus.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DataSetArchivingStatus.java
@@ -21,12 +21,34 @@ import com.google.gwt.user.client.rpc.IsSerializable;
 /**
  * Status of data set archiving process.
  * 
+ * <pre>
+ *                                                                                                                  |                                                         
+ *       archive                                           
+ *    ---------------> ARCHIVE_PENDING -------> ARCHIVED 
+ *    |                                          |             
+ *    |                                          |  unarchive
+ *    |                                          |           
+ * AVAILABLE  <--------------------|             |  
+ *    ^                            |             |  
+ *    |                            |             V             
+ *    |------>LOCKED               |----- UNARCHIVE_PENDING
+ * 
+ * </pre>
+ * 
  * @author Piotr Buczek
  */
 public enum DataSetArchivingStatus implements IsSerializable
 {
-    AVAILABLE("AVAILABLE", true), LOCKED("AVAILABLE (LOCKED)", true), ARCHIVED("ARCHIVED", false),
-    UNARCHIVE_PENDING("UNARCHIVE PENDING", false), ARCHIVE_PENDING("ARCHIVE PENDING", false);
+    AVAILABLE("AVAILABLE", true), // the data set is present in the data store only
+
+    // TODO KE: we might want to archive data sets in this state too
+    LOCKED("AVAILABLE (LOCKED)", true),
+
+    ARCHIVED("ARCHIVED", false), // the data set is present in the archive only
+
+    UNARCHIVE_PENDING("UNARCHIVE PENDING", false),
+
+    ARCHIVE_PENDING("ARCHIVE PENDING", false);
 
     private final String description;
 
@@ -48,4 +70,12 @@ public enum DataSetArchivingStatus implements IsSerializable
         return available;
     }
 
+    /**
+     * when deleting datasets from the archive
+     */
+    public boolean isDeletable()
+    {
+        return isAvailable() || this == ARCHIVED;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ColumnNames.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ColumnNames.java
index 4201cc455ca1bf673b8484ce04c3f163fe9f623c..6c8a2d7eb3ca1619b9ec9a1cf11a7a12ef291260 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ColumnNames.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ColumnNames.java
@@ -268,6 +268,8 @@ public final class ColumnNames
 
     public static final String SCRIPT_TYPE = "script_type";
 
+    public static final String PRESENT_IN_ARCHIVE = "present_in_archive";
+
     private ColumnNames()
     {
         // Can not be instantiated.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalDataPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalDataPE.java
index 903451e034611a0ceaf44f5dc3898397f5a930a6..d04de6563265b2bed0c37b8d128fbd7210131b11 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalDataPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalDataPE.java
@@ -77,6 +77,8 @@ public final class ExternalDataPE extends DataPE
 
     private DataSetArchivingStatus status = DataSetArchivingStatus.AVAILABLE;
 
+    private boolean isPresentInArchive;
+
     /**
      * Returns the id of the locator type of the location of this external data, or
      * <code>null</code> if not yet set.
@@ -207,4 +209,15 @@ public final class ExternalDataPE extends DataPE
         this.status = status;
     }
 
+    @Column(name = ColumnNames.PRESENT_IN_ARCHIVE)
+    public boolean isPresentInArchive()
+    {
+        return isPresentInArchive;
+    }
+
+    public void setPresentInArchive(boolean isPresentInArchive)
+    {
+        this.isPresentInArchive = isPresentInArchive;
+    }
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
index 8fbe2b05cad60158b1afc1e0a28a37c97b0d02d9..af278137a744baf0ca30ae5d4d1f91e359e5eede 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
@@ -1408,6 +1408,7 @@ public final class CommonServerTest extends AbstractServerTestCase
     public void testArchiveDataSets()
     {
         prepareGetSession();
+        final boolean removeFromDataStore = true;
         final List<String> dataSetCodes = Arrays.asList("a", "b");
         context.checking(new Expectations()
             {
@@ -1416,11 +1417,11 @@ public final class CommonServerTest extends AbstractServerTestCase
                     will(returnValue(externalDataTable));
 
                     one(externalDataTable).loadByDataSetCodes(dataSetCodes, false, true);
-                    one(externalDataTable).archiveDatasets();
+                    one(externalDataTable).archiveDatasets(removeFromDataStore);
                 }
             });
 
-        createServer().archiveDatasets(SESSION_TOKEN, dataSetCodes);
+        createServer().archiveDatasets(SESSION_TOKEN, dataSetCodes, removeFromDataStore);
 
         context.assertIsSatisfied();
     }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBOTest.java
index 1abf7ae9f888f7ed8fc7ae5ef79f3a9fb9c14c3e..c48e5ed0d3120574d4510f191979eb541e2b1c14 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBOTest.java
@@ -396,12 +396,12 @@ public class ExternalDataBOTest extends AbstractBOTest
             {
                 {
                     one(externalDataDAO).updateDataSetStatuses(codes,
-                            DataSetArchivingStatus.ARCHIVED);
+                            DataSetArchivingStatus.ARCHIVED, true);
                 }
             });
 
         IExternalDataBO dataBO = createExternalDataBO();
-        dataBO.updateStatuses(codes, DataSetArchivingStatus.ARCHIVED);
+        dataBO.updateStatuses(codes, DataSetArchivingStatus.ARCHIVED, true);
         // TODO 2010-04-26, Piotr Buczek: write a DAO test
         context.assertIsSatisfied();
     }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTableTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTableTest.java
index 67d525597763599975022b15befb266d56066fe1..056887d961265f019d094ef5720333afd17e513c 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTableTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTableTest.java
@@ -295,10 +295,10 @@ public final class ExternalDataTableTest extends AbstractBOTest
             fail("UserFailureException expected");
         } catch (UserFailureException e)
         {
-            assertEquals("Operation failed because following data sets are not available "
-                    + "(they are archived or their status is pending): [d3n, d4n, d5n]. "
-                    + "Unarchive these data sets or filter them out using data set status "
-                    + "before performing the operation once again.", e.getMessage());
+
+            assertEquals("Deletion failed because the following data sets are "
+                    + "required by a background process (their status is pending): "
+                    + "[d4n, d5n]. ", e.getMessage());
         }
 
         context.assertIsSatisfied();
@@ -568,7 +568,7 @@ public final class ExternalDataTableTest extends AbstractBOTest
         ExternalDataTable externalDataTable = createExternalDataTable();
         externalDataTable.loadByDataSetCodes(Code.extractCodes(Arrays.asList(allDataSets)), false,
                 true);
-        int archived = externalDataTable.archiveDatasets();
+        int archived = externalDataTable.archiveDatasets(true);
         assertEquals(3, archived);
 
         context.assertIsSatisfied();
@@ -629,7 +629,8 @@ public final class ExternalDataTableTest extends AbstractBOTest
                 {
                     one(service).archiveDatasets(with(equal(store.getSessionToken())),
                             with(createDatasetDescriptionsMatcher(dataSets)),
-                            with(equal(ManagerTestTool.EXAMPLE_PERSON.getEmail())));
+                            with(equal(ManagerTestTool.EXAMPLE_PERSON.getEmail())),
+                            with(equal(true)));
                 }
             });
     }
diff --git a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/etl/MLArchiverTask.java b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/etl/MLArchiverTask.java
index 22377aaa6bff3c5f74c560abb470c67f23747bcc..23dba3c5aa5ce74aa9eac7fa44ad0d8a4b624ed3 100644
--- a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/etl/MLArchiverTask.java
+++ b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/etl/MLArchiverTask.java
@@ -214,7 +214,8 @@ public class MLArchiverTask extends AbstractArchiverProcessingPlugin
     }
 
     @Override
-    public BooleanStatus isDataSetPresentInArchive(DatasetDescription dataset)
+    public BooleanStatus isDataSetPresentInArchive(DatasetDescription dataset,
+            ArchiverTaskContext context)
     {
         // data is always present, since there is no archive
         return BooleanStatus.createTrue();