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 c4c1068ab57461cc713dcc8ed8578e839519adf6..0a1dd4d5699efe1a25700c09c851f33462817b52 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 @@ -94,6 +94,8 @@ public class DataSetFileOperationsManager implements IDataSetFileOperationsManag private final long timeoutInMillis; + private final boolean isHosted; + public DataSetFileOperationsManager(Properties properties, IPathCopierFactory pathCopierFactory, ISshCommandExecutorFactory sshCommandExecutorFactory) @@ -102,6 +104,8 @@ public class DataSetFileOperationsManager implements IDataSetFileOperationsManag HostAwareFile hostAwareFile = HostAwareFileWithHighwaterMark.create(hostFile, -1); String hostOrNull = hostAwareFile.tryGetHost(); + this.isHosted = hostOrNull == null; + this.destination = hostAwareFile.getFile(); long timeoutInSeconds = PropertyUtils.getLong(properties, TIMEOUT_KEY, DEFAULT_TIMEOUT_SECONDS); @@ -341,4 +345,16 @@ public class DataSetFileOperationsManager implements IDataSetFileOperationsManag } return destinationExists; } + + @Override + public boolean isHosted() + { + return isHosted; + } + + @Override + public File getDestinationFile(DatasetDescription dataset) + { + return new File(destination, dataset.getDataSetLocation()); + } } \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IDataSetFileOperationsManager.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IDataSetFileOperationsManager.java index 60d9cc8c0d3baf110efae29d5542f1adf5849e94..adb03a60ec7d3f6f838625d07d984fc6937eef73 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IDataSetFileOperationsManager.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IDataSetFileOperationsManager.java @@ -33,35 +33,46 @@ public interface IDataSetFileOperationsManager * Copies specified dataset's data to destination specified in constructor. The path at the * destination is defined by the original location of the data set. */ - public abstract Status copyToDestination(File originalData, DatasetDescription dataset); + public Status copyToDestination(File originalData, DatasetDescription dataset); /** * Retrieves specified dataset's data from the destination specified in constructor. The path at * the destination is defined by original location of the data set. */ - public abstract Status retrieveFromDestination(File originalData, DatasetDescription dataset); + public Status retrieveFromDestination(File originalData, DatasetDescription dataset); /** * Deletes specified dataset's data from the destination specified in constructor. The path at * the destination is defined by original location of the data set. */ - public abstract Status deleteFromDestination(IDatasetLocation dataset); + public Status deleteFromDestination(IDatasetLocation dataset); /** * Marks the specified data set as deleted. Does not delete the dataset's data. */ - public abstract Status markAsDeleted(IDatasetLocation dataset); + public Status markAsDeleted(IDatasetLocation dataset); /** * Checks if specified dataset's data are present and synchronized in the destination specified * in constructor. The path at the destination is defined by original location of the data set. */ - public abstract BooleanStatus isSynchronizedWithDestination(File originalData, + public BooleanStatus isSynchronizedWithDestination(File originalData, DatasetDescription dataset); /** * Checks if specified dataset's data are present in the destination specified in constructor. * The path at the destination is defined by original location of the data set. */ - public abstract BooleanStatus isPresentInDestination(DatasetDescription dataset); + public BooleanStatus isPresentInDestination(DatasetDescription dataset); + + /** + * @return true if the destination includes a host information (it means it is not + * local/mounted) + */ + public boolean isHosted(); + + /** + * @return the dataset file in the destination location + */ + public File getDestinationFile(DatasetDescription dataset); } \ 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 552067307965dcb6d9a0222006fe0ed515d57fcd..a6fd7b7134915a663570be28f552438ac1656ee3 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 @@ -50,9 +50,11 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription; */ public class RsyncArchiver extends AbstractArchiverProcessingPlugin { - @Private static final String ONLY_MARK_AS_DELETED_KEY = "only-mark-as-deleted"; - - @Private static final String STAGING_FOLDER = "archive-staging"; + @Private + static final String ONLY_MARK_AS_DELETED_KEY = "only-mark-as-deleted"; + + @Private + static final String STAGING_FOLDER = "archive-staging"; private static final long serialVersionUID = 1L; @@ -145,13 +147,30 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin temp.mkdirs(); try { - fileOperationsManager.retrieveFromDestination(temp, dataset); - IHierarchicalContent retrievedContent = - new DefaultFileBasedHierarchicalContentFactory().asHierarchicalContent( - temp, null); + IHierarchicalContent archivedContent; + // We want to perform the check if the archived content is correct + // (filesizes/checksums) + // For this we want to have the archived content locally. If it is not available + // locally - we have to retrieve it from the archive first. + if (fileOperationsManager.isHosted()) + { + fileOperationsManager.retrieveFromDestination(temp, dataset); + archivedContent = + new DefaultFileBasedHierarchicalContentFactory() + .asHierarchicalContent(temp, null); + } else + { + archivedContent = + new DefaultFileBasedHierarchicalContentFactory() + .asHierarchicalContent( + fileOperationsManager.getDestinationFile(dataset), + null); + } + IHierarchicalContentNode root = content.getRootNode(); - IHierarchicalContentNode retrievedRoot = retrievedContent.getRootNode(); - status = checkHierarchySizeAndChecksums(root, retrievedRoot); + IHierarchicalContentNode archivedRoot = archivedContent.getRootNode(); + + status = checkHierarchySizeAndChecksums(root, archivedRoot); } finally { FileUtils.deleteQuietly(temp); @@ -163,7 +182,8 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin return statuses; } - @Private static Status checkHierarchySizeAndChecksums(IHierarchicalContentNode node, + @Private + static Status checkHierarchySizeAndChecksums(IHierarchicalContentNode node, IHierarchicalContentNode retrievedNode) { String relativePath = node.getRelativePath(); @@ -213,6 +233,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin return Status.createError("The file '" + relativePath + "' has in the store " + fileLength + " bytes but " + fileLengthOfRetrieved + " in the archive."); } + // TODO: check the configuration if should allow checksum checking for archiver long checksum = node.getChecksumCRC32(); long checksumOfRetrieved = retrievedNode.getChecksumCRC32(); if (checksum != checksumOfRetrieved) @@ -259,7 +280,8 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin } @Override - protected DatasetProcessingStatuses doDeleteFromArchive(List<? extends IDatasetLocation> datasets) + protected DatasetProcessingStatuses doDeleteFromArchive( + List<? extends IDatasetLocation> datasets) { return delete(datasets, deleteAction); } @@ -282,7 +304,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin } return statuses; } - + @Override protected BooleanStatus isDataSetSynchronizedWithArchive(DatasetDescription dataset, ArchiverTaskContext context)