diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetFileOperationsExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetFileOperationsExecutor.java
index b206ffc123c5691a0c41c3cfcfb416c6b07bf2ab..1a8a89b206048745ad953ed265a042d11ac6d05d 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetFileOperationsExecutor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/IDataSetFileOperationsExecutor.java
@@ -35,6 +35,9 @@ public interface IDataSetFileOperationsExecutor
 
     void copyDataSetToDestination(File dataSet, File destination);
 
+    // uses rsync --delete for performance both locally and remotely
+    void syncDataSetWithDestination(File dataSet, File destination);
+
     void retrieveDataSetFromDestination(File dataSet, File destination);
 
     void renameTo(File newFile, File oldFile);
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/LocalDataSetFileOperationsExcecutor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/LocalDataSetFileOperationsExcecutor.java
index e8b7082926f2de832938fcae44cdc803f165f703..223a13b93cdf4831364ffa774833cb490109f38e 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/LocalDataSetFileOperationsExcecutor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/LocalDataSetFileOperationsExcecutor.java
@@ -32,6 +32,7 @@ import ch.systemsx.cisd.common.exceptions.Status;
 import ch.systemsx.cisd.common.filesystem.BooleanStatus;
 import ch.systemsx.cisd.common.filesystem.FileUtilities;
 import ch.systemsx.cisd.common.filesystem.IFileOperations;
+import ch.systemsx.cisd.common.filesystem.IPathCopier;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 
@@ -40,11 +41,21 @@ public final class LocalDataSetFileOperationsExcecutor implements IDataSetFileOp
     final static Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
             LocalDataSetFileOperationsExcecutor.class);
 
+    private final IPathCopier copier;
+
+    private final String rsyncModuleNameOrNull;
+
+    private final String rsyncPasswordFileOrNull;
+
     private final IFileOperations fileOperations;
 
-    public LocalDataSetFileOperationsExcecutor(IFileOperations fileOperations)
+    public LocalDataSetFileOperationsExcecutor(IFileOperations fileOperations, IPathCopier copier,
+            String rsyncModuleNameOrNull, String rsyncPasswordFileOrNull)
     {
         this.fileOperations = fileOperations;
+        this.copier = copier;
+        this.rsyncModuleNameOrNull = rsyncModuleNameOrNull;
+        this.rsyncPasswordFileOrNull = rsyncPasswordFileOrNull;
     }
 
     public BooleanStatus checkSame(File dataSet, File destination)
@@ -63,7 +74,6 @@ public final class LocalDataSetFileOperationsExcecutor implements IDataSetFileOp
             if (destination.isDirectory())
             {
                 FileFilter nullFilter = null;
-                // TODO ignore symlinks?
                 List<File> storeFiles = FileUtilities.listFiles(dataSet, nullFilter, true);
                 List<File> destFiles = FileUtilities.listFiles(destination, nullFilter, true);
 
@@ -154,6 +164,19 @@ public final class LocalDataSetFileOperationsExcecutor implements IDataSetFileOp
         }
     }
 
+    public void syncDataSetWithDestination(File dataSet, File destination)
+    {
+        // rsync --delete is more effective then deletion of destination directory & copy all
+        String host = null; // local
+        Status result =
+                copier.copyToRemote(dataSet, destination, host, rsyncModuleNameOrNull,
+                        rsyncPasswordFileOrNull);
+        if (result.isError())
+        {
+            throw new ExceptionWithStatus(result);
+        }
+    }
+
     public void retrieveDataSetFromDestination(File dataSet, File destination)
     {
         try
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/RemoteDataSetFileOperationsExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/RemoteDataSetFileOperationsExecutor.java
index c3932d0b4f9b5fc390f2a456218958aee63e13eb..72180f09bce5b04644a7968f0e019a383222e826 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/RemoteDataSetFileOperationsExecutor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/RemoteDataSetFileOperationsExecutor.java
@@ -128,6 +128,11 @@ public final class RemoteDataSetFileOperationsExecutor implements IDataSetFileOp
         }
     }
 
+    public void syncDataSetWithDestination(File dataSet, File destination)
+    {
+        copyDataSetToDestination(dataSet, destination);
+    }
+
     public void retrieveDataSetFromDestination(File dataSet, File destination)
     {
         Status result =
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetFileOperationsManager.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetFileOperationsManager.java
index 8745915c786a572a7ad72b9cde493d6b1fd1b53d..770dc5cedc4f7c57bb6d3997ad61c68a3d9c9034 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetFileOperationsManager.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetFileOperationsManager.java
@@ -92,9 +92,16 @@ public class DataSetFileOperationsManager
 
         if (hostOrNull == null)
         {
+            File sshExecutable = null; // don't use ssh locally
+            File rsyncExecutable = Copier.getExecutable(properties, RSYNC_EXEC);
+            IPathCopier copier = pathCopierFactory.create(rsyncExecutable, sshExecutable);
+            copier.check();
+            String rsyncModule = hostAwareFile.tryGetRsyncModule();
+            String rsyncPasswordFile = properties.getProperty(RSYNC_PASSWORD_FILE_KEY);
             this.executor =
                     new LocalDataSetFileOperationsExcecutor(
-                            FileOperations.getMonitoredInstanceForCurrentThread());
+                            FileOperations.getMonitoredInstanceForCurrentThread(), copier,
+                            rsyncModule, rsyncPasswordFile);
         } else
         {
             File sshExecutable = Copier.getExecutable(properties, SSH_EXEC);
@@ -124,10 +131,18 @@ public class DataSetFileOperationsManager
         try
         {
             File destinationFolder = new File(destination, dataset.getDataSetLocation());
-            createFolderIfNotExists(destinationFolder.getParentFile());
-            operationLog.info("Copy dataset '" + dataset.getDatasetCode() + "' from '"
-                    + originalData.getPath() + "' to '" + destinationFolder.getParentFile());
-            executor.copyDataSetToDestination(originalData, destinationFolder.getParentFile());
+            if (createFolderIfNotExists(destinationFolder.getParentFile())
+                    || destinationExists(destinationFolder).isSuccess() == false)
+            {
+                operationLog.info("Copy dataset '" + dataset.getDatasetCode() + "' from '"
+                        + originalData.getPath() + "' to '" + destinationFolder.getParentFile());
+                executor.copyDataSetToDestination(originalData, destinationFolder.getParentFile());
+            } else
+            {
+                operationLog.info("Update dataset '" + dataset.getDatasetCode() + "' from '"
+                        + originalData.getPath() + "' to '" + destinationFolder.getParentFile());
+                executor.syncDataSetWithDestination(originalData, destinationFolder.getParentFile());
+            }
             return Status.OK;
         } catch (ExceptionWithStatus ex)
         {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiveCopierFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiveCopierFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0898ecf996fa14fe4280187ea193de96c90debe
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiveCopierFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010 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.openbis.dss.generic.server.plugins.standard;
+
+import java.io.File;
+import java.io.Serializable;
+
+import ch.systemsx.cisd.common.filesystem.IPathCopier;
+import ch.systemsx.cisd.common.filesystem.rsync.RsyncCopier;
+
+/**
+ * {@link IPathCopierFactory} that is more reliable than {@link RsyncCopierFactory} when it comes to
+ * deciding which files to transfer. {@link IPathCopier} created by {@link RsyncCopierFactory} uses
+ * "--append" flag causing files that are bigger in destination than in source to be ignored.
+ * {@link IPathCopier} created by this factory is supposed to ignore only those files that have same
+ * sizes and modification times.
+ */
+public final class RsyncArchiveCopierFactory implements Serializable, IPathCopierFactory
+{
+    private static final long serialVersionUID = 1L;
+
+    public IPathCopier create(File rsyncExecutable, File sshExecutableOrNull)
+    {
+        // TODO 2011-04-05, Piotr Buczek: should we use --no-whole-file?
+        return new RsyncCopier(rsyncExecutable, sshExecutableOrNull, "--archive", "--delete",
+                "--inplace");
+    }
+}
\ No newline at end of file
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 770df7c92be59595d11f87f6b64f3e4a9415068c..934f347010664fdfe182c7ccb775ccd724533cb6 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
@@ -52,12 +52,12 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
 
     public RsyncArchiver(Properties properties, File storeRoot)
     {
-        this(properties, storeRoot, new RsyncCopierFactory(), new SshCommandExecutorFactory());
+        this(properties, storeRoot, new RsyncArchiveCopierFactory(),
+                new SshCommandExecutorFactory());
     }
 
     @Private
-    RsyncArchiver(Properties properties, File storeRoot,
-            IPathCopierFactory pathCopierFactory,
+    RsyncArchiver(Properties properties, File storeRoot, IPathCopierFactory pathCopierFactory,
             ISshCommandExecutorFactory sshCommandExecutorFactory)
     {
         super(properties, storeRoot, null, null);
@@ -131,7 +131,8 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin
         if (fileOperationsManager == null)
         {
             this.fileOperationsManager =
-                    new DataSetFileOperationsManager(properties, pathCopierFactory, sshCommandExecutorFactory);
+                    new DataSetFileOperationsManager(properties, pathCopierFactory,
+                            sshCommandExecutorFactory);
         }
     }
 
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetFileOperationsManagerTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetFileOperationsManagerTest.java
index b4cdae4e5d088594128eb73b5b4c96c5689a6bc5..112a24a96654f33e9ef797d20938a0b9ff291388 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetFileOperationsManagerTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetFileOperationsManagerTest.java
@@ -249,6 +249,18 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase
         /*
          * archive 2nd time (could happen on crash of DSS, but shouldn't hurt)
          */
+        context.checking(new Expectations()
+            {
+                {
+                    /*
+                     * use rsync
+                     */
+                    one(copier).copyToRemote(ds1Location,
+                            ds1ArchivedLocationFile.getParentFile().getAbsoluteFile(), null, null,
+                            null);
+                    will(returnValue(Status.OK));
+                }
+            });
         status = dataSetCopier.copyToDestination(ds1Location, ds1);
         assertSuccessful(status);
         // check that data set is now in archive
@@ -482,6 +494,9 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase
     {
         final Properties properties = new Properties();
         properties.setProperty(DataSetFileOperationsManager.DESTINATION_KEY, destination.getPath());
+        properties.setProperty(DataSetFileOperationsManager.RSYNC_EXEC + "-executable",
+                rsyncExec.getPath());
+        prepareLocalCreateAndCheckCopier();
         return properties;
     }
 
@@ -521,6 +536,8 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase
                     one(sshExecutor).exists(ds2ArchivedLocationFile.getParentFile().getPath(),
                             SSH_TIMEOUT_MILLIS);
                     will(returnValue(BooleanStatus.createTrue()));
+                    one(sshExecutor).exists(ds2ArchivedLocationFile.getPath(), SSH_TIMEOUT_MILLIS);
+                    will(returnValue(BooleanStatus.createTrue()));
 
                     one(copier).copyToRemote(ds2Location, ds2ArchivedLocationFile.getParentFile(),
                             HOST, null, null);
@@ -851,6 +868,19 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase
     // context.assertIsSatisfied();
     // }
 
+    private void prepareLocalCreateAndCheckCopier()
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(copierFactory).create(rsyncExec, null);
+                    will(returnValue(copier));
+
+                    one(copier).check();
+                }
+            });
+    }
+
     private void prepareRemoteCreateAndCheckCopier(final String hostOrNull,
             final String rsyncModuleOrNull, final boolean checkingResult)
     {
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/dss/phosphonetx/server/plugins/LocalAndRemoteCopier.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/dss/phosphonetx/server/plugins/LocalAndRemoteCopier.java
index bb1c99fecbcf20067606fd0bd589bb06b1eed7e2..4630408b2cf6fda8b5a13fdb7805eb1ac3b8eaae 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/dss/phosphonetx/server/plugins/LocalAndRemoteCopier.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/dss/phosphonetx/server/plugins/LocalAndRemoteCopier.java
@@ -99,9 +99,17 @@ class LocalAndRemoteCopier implements Serializable, IPostRegistrationDatasetHand
         destination = hostAwareFile.getFile();
         if (hostOrNull == null)
         {
+            File sshExecutable = null; // don't use ssh locally
+            File rsyncExecutable = Copier.getExecutable(properties, DataSetCopier.RSYNC_EXEC);
+            IPathCopier copier = pathCopierFactory.create(rsyncExecutable, sshExecutable);
+            copier.check();
+            String rsyncModule = hostAwareFile.tryGetRsyncModule();
+            String rsyncPasswordFile =
+                    properties.getProperty(DataSetCopier.RSYNC_PASSWORD_FILE_KEY);
             executor =
                     new LocalDataSetFileOperationsExcecutor(
-                            FileOperations.getMonitoredInstanceForCurrentThread());
+                            FileOperations.getMonitoredInstanceForCurrentThread(), copier,
+                            rsyncModule, rsyncPasswordFile);
         } else
         {
             File sshExecutable = Copier.getExecutable(properties, DataSetCopier.SSH_EXEC);