diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/DataStoreServer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/DataStoreServer.java index a41d38051d4f71eee2a60c8501e0db88c3960d3d..6d6b597251f1d31cf83a6c29864f88b3ba10fecd 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/DataStoreServer.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/DataStoreServer.java @@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.dss.generic; import java.io.File; import java.lang.Thread.UncaughtExceptionHandler; +import java.util.List; import org.apache.log4j.Logger; @@ -32,6 +33,7 @@ import ch.systemsx.cisd.openbis.dss.BuildAndEnvironmentInfo; import ch.systemsx.cisd.openbis.dss.generic.server.CommandQueueLister; import ch.systemsx.cisd.openbis.dss.generic.shared.QueueingDataSetStatusUpdaterService; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DssPropertyParametersUtil; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.RSyncConfig; /** * Main class starting {@link ch.systemsx.cisd.openbis.dss.generic.server.DataStoreServer}, {@link ETLDaemon}. @@ -102,6 +104,9 @@ public class DataStoreServer ExtendedProperties props = DssPropertyParametersUtil.loadProperties(DssPropertyParametersUtil.SERVICE_PROPERTIES_FILE); File storeRootDir = DssPropertyParametersUtil.getStoreRootDir(props); + List<String> rsyncOps = DssPropertyParametersUtil.getRsyncOptions(props); + notificationLog.info("Rsync configured with additional options: " + rsyncOps); + RSyncConfig.getInstance(rsyncOps); // Initialize the shredder and updater _before_ the DataSetCommandExecutor which uses them. QueueingPathRemoverService.start(storeRootDir, ETLDaemon.shredderQueueFile); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Copier.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Copier.java index f6bc517408eae692983c97797c1fed5788c09470..1744977bc9ed27b91395d168a3a64e8fd7eaf6a8 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Copier.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Copier.java @@ -39,6 +39,7 @@ import ch.systemsx.cisd.common.process.ProcessResult; import ch.systemsx.cisd.common.properties.PropertyUtils; import ch.systemsx.cisd.openbis.dss.generic.shared.IPostRegistrationDatasetHandler; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.RSyncConfig; public class Copier implements Serializable, IPostRegistrationDatasetHandler { @@ -112,7 +113,7 @@ public class Copier implements Serializable, IPostRegistrationDatasetHandler String rsyncModule = hostAwareFile.tryGetRsyncModule(); IPathCopier copier = pathCopierFactory.create(rsyncExecutable, sshExecutable, - DataSetCopier.SSH_TIMEOUT_MILLIS); + DataSetCopier.SSH_TIMEOUT_MILLIS, RSyncConfig.getInstance().getAdditionalCommandLineOptions()); copier.check(); if (host != null) { diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IPathCopierFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IPathCopierFactory.java index c85f54517c23c1d2f8bdca870492ee2143a22a80..dc020f35b697cbf6d4b4e29307d7f38ed1ea7d86 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IPathCopierFactory.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IPathCopierFactory.java @@ -17,10 +17,11 @@ package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard; import java.io.File; +import java.util.List; import ch.systemsx.cisd.common.filesystem.IPathCopier; public interface IPathCopierFactory { - IPathCopier create(File rsyncExecutable, File sshExecutableOrNull, long timeoutInMillis); + IPathCopier create(File rsyncExecutable, File sshExecutableOrNull, long timeoutInMillis, List<String> additionalCmdLineFlagsOrNull); } \ No newline at end of file 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 index 8132fe6f114f303dbce608a1e4dc8b4e29ad5e8e..8a76f64c9d4ca527d7f45b832d345f554f48e7bd 100644 --- 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 @@ -18,6 +18,8 @@ package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard; import java.io.File; import java.io.Serializable; +import java.util.Arrays; +import java.util.List; import org.apache.commons.lang.time.DateUtils; @@ -39,10 +41,14 @@ public final class RsyncArchiveCopierFactory implements Serializable, IPathCopie private static final long serialVersionUID = 1L; @Override - public IPathCopier create(File rsyncExecutable, File sshExecutableOrNull, long timeoutInMillis) + public IPathCopier create(File rsyncExecutable, File sshExecutableOrNull, long timeoutInMillis, List<String> additionalCmdLineFlagsOrNull) { - return new RsyncCopier(rsyncExecutable, sshExecutableOrNull, "--archive", "--delete", - "--inplace", "--checksum", getTimeoutParameter(timeoutInMillis)); + List<String> additionalCmdLineFlags = Arrays.asList("--archive", "--delete", "--inplace", "--checksum", getTimeoutParameter(timeoutInMillis)); + if (additionalCmdLineFlagsOrNull != null) + { + additionalCmdLineFlags.addAll(additionalCmdLineFlagsOrNull); + } + return new RsyncCopier(rsyncExecutable, sshExecutableOrNull, additionalCmdLineFlags.toArray(new String[0])); } private String getTimeoutParameter(long timeoutInMillis) diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncCopierFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncCopierFactory.java index 3e92d913e73b4a5df760b27862355655b8a23a72..ce99c65af6e99b91e520dcadea464387fce97ad8 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncCopierFactory.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncCopierFactory.java @@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard; import java.io.File; import java.io.Serializable; +import java.util.List; import ch.systemsx.cisd.common.filesystem.IPathCopier; import ch.systemsx.cisd.common.filesystem.rsync.RsyncCopier; @@ -27,8 +28,8 @@ public final class RsyncCopierFactory implements Serializable, IPathCopierFactor private static final long serialVersionUID = 1L; @Override - public IPathCopier create(File rsyncExecutable, File sshExecutableOrNull, long timeoutInMillis) + public IPathCopier create(File rsyncExecutable, File sshExecutableOrNull, long timeoutInMillis, List<String> additionalCmdLineFlagsOrNull) { - return new RsyncCopier(rsyncExecutable, sshExecutableOrNull, false, false); + return new RsyncCopier(rsyncExecutable, sshExecutableOrNull, false, false, additionalCmdLineFlagsOrNull.toArray(new String[0])); } } \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/archiver/ArchiveDestinationFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/archiver/ArchiveDestinationFactory.java index 660227480236941a9e3669657464313e27ed7ca6..9a84404a7a1ff49b327ac7b16b3eb86347d9e2e1 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/archiver/ArchiveDestinationFactory.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/archiver/ArchiveDestinationFactory.java @@ -32,6 +32,7 @@ import ch.systemsx.cisd.openbis.dss.generic.server.RemoteDataSetFileOperationsEx import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.Copier; import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.IPathCopierFactory; import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.ISshCommandExecutorFactory; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.RSyncConfig; /** * @author Jakub Straszewski @@ -90,7 +91,8 @@ public class ArchiveDestinationFactory implements Serializable File gfindExecutable = Copier.getExecutable(properties, AbstractDataSetFileOperationsManager.GFIND_EXEC); IPathCopier copier = - pathCopierFactory.create(rsyncExecutable, sshExecutable, timeoutInMillis); + pathCopierFactory.create(rsyncExecutable, sshExecutable, timeoutInMillis, + RSyncConfig.getInstance().getAdditionalCommandLineOptions()); copier.check(); String rsyncModule = hostAwareFile.tryGetRsyncModule(); String rsyncPasswordFile = properties.getProperty(AbstractDataSetFileOperationsManager.RSYNC_PASSWORD_FILE_KEY); @@ -110,7 +112,8 @@ public class ArchiveDestinationFactory implements Serializable File sshExecutable = null; // don't use ssh locally File rsyncExecutable = Copier.getExecutable(properties, AbstractDataSetFileOperationsManager.RSYNC_EXEC); IPathCopier copier = - pathCopierFactory.create(rsyncExecutable, sshExecutable, timeoutInMillis); + pathCopierFactory.create(rsyncExecutable, sshExecutable, timeoutInMillis, + RSyncConfig.getInstance().getAdditionalCommandLineOptions()); copier.check(); String rsyncModule = hostAwareFile.tryGetRsyncModule(); String rsyncPasswordFile = properties.getProperty(AbstractDataSetFileOperationsManager.RSYNC_PASSWORD_FILE_KEY); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/DssPropertyParametersUtil.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/DssPropertyParametersUtil.java index 4fb76749ef8fa193728a59485cdd2b71b2261adf..f552867e2b4b7bfb496068da399f83057bca2efa 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/DssPropertyParametersUtil.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/DssPropertyParametersUtil.java @@ -17,6 +17,8 @@ package ch.systemsx.cisd.openbis.dss.generic.shared.utils; import java.io.File; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; @@ -56,6 +58,8 @@ public class DssPropertyParametersUtil public static final String SERVER_URL_KEY = "server-url"; + public static final String RSYNC_OPTIONS = "rsync-options"; + public static final String DATA_STREAM_TIMEOUT = "data-stream-timeout"; public static final String DATA_STREAM_MAX_TIMEOUT = "data-stream-max-timeout"; @@ -157,6 +161,18 @@ public class DssPropertyParametersUtil STOREROOT_DIR_KEY))); } + public static List<String> getRsyncOptions(Properties serviceProperties) + { + String rsyncOptions = serviceProperties.getProperty(RSYNC_OPTIONS, null); + if (rsyncOptions == null) + { + return null; + } else + { + return Arrays.asList(rsyncOptions.split(" ")); + } + } + public static String getOpenBisServerUrl(Properties serviceProperties) { return PropertyUtils.getMandatoryProperty(serviceProperties, SERVER_URL_KEY); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/RSyncConfig.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/RSyncConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..6957877d9801bf144528b745e8647c3b16b893ce --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/RSyncConfig.java @@ -0,0 +1,35 @@ +package ch.systemsx.cisd.openbis.dss.generic.shared.utils; + +import java.util.List; + +public class RSyncConfig +{ + private final List<String> additionalCommandLineOptions; + + private static RSyncConfig instance = new RSyncConfig(); + + private RSyncConfig() + { + this.additionalCommandLineOptions = null; + } + + private RSyncConfig(List<String> additionalCommandLineOptions) + { + this.additionalCommandLineOptions = additionalCommandLineOptions; + } + + public List<String> getAdditionalCommandLineOptions() + { + return additionalCommandLineOptions; + } + + public synchronized static RSyncConfig getInstance(List<String> additionalCommandLineOptions) + { + return instance = new RSyncConfig(additionalCommandLineOptions); + } + + public synchronized static RSyncConfig getInstance() + { + return instance; + } +} diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetCopierForUsersTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetCopierForUsersTest.java index 3d173079d277e26fa33a3fa1c007aa5ffc321dee..24c94ab1602a1f9bc5ec8c6faaa5c7ea0b0628b7 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetCopierForUsersTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetCopierForUsersTest.java @@ -47,6 +47,7 @@ import ch.systemsx.cisd.common.test.RecordingMatcher; import ch.systemsx.cisd.common.utilities.ITimeProvider; import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetProcessingContext; import ch.systemsx.cisd.openbis.dss.generic.shared.ProcessingStatus; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.RSyncConfig; import ch.systemsx.cisd.openbis.generic.shared.Constants; import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription; import ch.systemsx.cisd.openbis.generic.shared.dto.builders.DatasetDescriptionBuilder; @@ -219,7 +220,7 @@ public class DataSetCopierForUsersTest extends AbstractFileSystemTestCase { { one(pathFactory).create(rsyncExecutableDummy, sshExecutableDummy, - DataSetCopier.SSH_TIMEOUT_MILLIS); + DataSetCopier.SSH_TIMEOUT_MILLIS, RSyncConfig.getInstance().getAdditionalCommandLineOptions()); will(returnValue(copier)); one(sshFactory).create(sshExecutableDummy, null); diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetCopierTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetCopierTest.java index 8d9d93865bb2a4deb4b82889bbe3c7adb1b94e10..f7d43cf56111d481e722e84f30b471b877944507 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetCopierTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DataSetCopierTest.java @@ -50,13 +50,13 @@ import ch.systemsx.cisd.common.test.RecordingMatcher; import ch.systemsx.cisd.common.utilities.ITimeProvider; import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetProcessingContext; import ch.systemsx.cisd.openbis.dss.generic.shared.ProcessingStatus; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.RSyncConfig; import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription; /** * @author Franz-Josef Elmer */ -@Friend(toClasses = -{ DataSetCopier.class, AbstractDropboxProcessingPlugin.class }) +@Friend(toClasses = { DataSetCopier.class, AbstractDropboxProcessingPlugin.class }) public class DataSetCopierTest extends AbstractFileSystemTestCase { private static final String RSYNC_EXECUTABLE = "rsync-executable"; @@ -236,7 +236,8 @@ public class DataSetCopierTest extends AbstractFileSystemTestCase { assertEquals( "Path to executable 'rsync' is not a file: " - + rsyncExecutableDummy.getAbsolutePath(), ex.getMessage()); + + rsyncExecutableDummy.getAbsolutePath(), + ex.getMessage()); } context.assertIsSatisfied(); @@ -254,7 +255,8 @@ public class DataSetCopierTest extends AbstractFileSystemTestCase { assertEquals( "Path to executable 'ssh' is not a file: " - + sshExecutableDummy.getAbsolutePath(), ex.getMessage()); + + sshExecutableDummy.getAbsolutePath(), + ex.getMessage()); } context.assertIsSatisfied(); @@ -775,7 +777,7 @@ public class DataSetCopierTest extends AbstractFileSystemTestCase { { exactly(numberOfExpectedCreations).of(pathFactory).create(rsyncExecutableDummy, - sshExecutableDummy, DataSetCopier.SSH_TIMEOUT_MILLIS); + sshExecutableDummy, DataSetCopier.SSH_TIMEOUT_MILLIS, RSyncConfig.getInstance().getAdditionalCommandLineOptions()); will(returnValue(copier)); exactly(numberOfExpectedCreations).of(sshFactory).create(sshExecutableDummy, 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 1919cb09da8aa9da3707b9fc1d616dd6026d585e..1dc67bbf20531b8eed5ea36c213ef1695a80e3af 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 @@ -41,6 +41,7 @@ import ch.systemsx.cisd.common.filesystem.IPathCopier; import ch.systemsx.cisd.common.filesystem.ssh.ISshCommandExecutor; import ch.systemsx.cisd.common.logging.LogInitializer; import ch.systemsx.cisd.common.process.ProcessResult; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.RSyncConfig; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatasetLocation; import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription; @@ -780,7 +781,8 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase one(sshExecutor).executeCommandRemotely( gfindExec.getPath() + " " + ds1ArchivedLocationFile.getPath() - + " -type f -printf \"%p\\t%s\\n\"", timeoutMillis()); + + " -type f -printf \"%p\\t%s\\n\"", + timeoutMillis()); String filePath1 = ds1ArchivedLocationFile.getPath() + File.separator + "original/data1_2.txt"; @@ -797,7 +799,8 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase will(returnValue(BooleanStatus.createTrue())); one(sshExecutor).executeCommandRemotely( gfindExec.getPath() + " " + ds2ArchivedLocationFile.getPath() - + " -type f -printf \"%p\\t%s\\n\"", timeoutMillis()); + + " -type f -printf \"%p\\t%s\\n\"", + timeoutMillis()); String filePath2 = ds2ArchivedLocationFile.getPath() + File.separator + "original/data2.txt"; @@ -840,7 +843,8 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase one(sshExecutor).executeCommandRemotely( gfindExec.getPath() + " " + ds2ArchivedLocationFile.getPath() - + " -type f -printf \"%p\\t%s\\n\"", timeoutMillis()); + + " -type f -printf \"%p\\t%s\\n\"", + timeoutMillis()); will(returnValue(ERROR_RESULT)); } }); @@ -1056,7 +1060,7 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase context.checking(new Expectations() { { - one(copierFactory).create(rsyncExec, null, DEFAULT_TIMEOUT_MILLIS); + one(copierFactory).create(rsyncExec, null, DEFAULT_TIMEOUT_MILLIS, RSyncConfig.getInstance().getAdditionalCommandLineOptions()); will(returnValue(copier)); one(copier).check(); @@ -1070,7 +1074,7 @@ public class DataSetFileOperationsManagerTest extends AbstractFileSystemTestCase context.checking(new Expectations() { { - one(copierFactory).create(rsyncExec, sshExec, timeoutMillis()); + one(copierFactory).create(rsyncExec, sshExec, timeoutMillis(), RSyncConfig.getInstance().getAdditionalCommandLineOptions()); will(returnValue(copier)); one(sshFactory).create(sshExec, hostOrNull);