From a98f91f51df7a527063ca3472b191c363dba5167 Mon Sep 17 00:00:00 2001 From: jakubs <jakubs> Date: Mon, 30 Jul 2012 08:34:09 +0000 Subject: [PATCH] SP-155 BIS-38 make checksum verification optional in rsync archiver SVN: 26273 --- .../plugins/standard/RsyncArchiver.java | 30 +++++--- .../plugins/standard/RsyncArchiverTest.java | 70 ++++++++++++------- 2 files changed, 64 insertions(+), 36 deletions(-) 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 a6fd7b71349..696665022dd 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 @@ -56,6 +56,9 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin @Private static final String STAGING_FOLDER = "archive-staging"; + @Private + static final String VERIFY_CHECKSUMS_KEY = "verify-checksums"; + private static final long serialVersionUID = 1L; private static final Comparator<IHierarchicalContentNode> NODE_COMPARATOR = @@ -106,6 +109,8 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin private final DeleteAction deleteAction; + private final boolean verifyChecksums; + public RsyncArchiver(Properties properties, File storeRoot) { this(properties, storeRoot, new DataSetFileOperationsManager(properties, @@ -125,6 +130,9 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin { deleteAction = DeleteAction.DELETE; } + + verifyChecksums = PropertyUtils.getBoolean(properties, VERIFY_CHECKSUMS_KEY, true); + } @Override @@ -170,7 +178,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin IHierarchicalContentNode root = content.getRootNode(); IHierarchicalContentNode archivedRoot = archivedContent.getRootNode(); - status = checkHierarchySizeAndChecksums(root, archivedRoot); + status = checkHierarchySizeAndChecksums(root, archivedRoot, verifyChecksums); } finally { FileUtils.deleteQuietly(temp); @@ -184,7 +192,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin @Private static Status checkHierarchySizeAndChecksums(IHierarchicalContentNode node, - IHierarchicalContentNode retrievedNode) + IHierarchicalContentNode retrievedNode, boolean verifyChecksums) { String relativePath = node.getRelativePath(); String relativePathOfRetrieved = retrievedNode.getRelativePath(); @@ -218,7 +226,7 @@ public class RsyncArchiver extends AbstractArchiverProcessingPlugin { Status status = checkHierarchySizeAndChecksums(childNodes.get(i), - childNodesOfRetrieved.get(i)); + childNodesOfRetrieved.get(i), verifyChecksums); if (status.isError()) { return status; @@ -233,14 +241,16 @@ 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) + if (verifyChecksums) { - return Status.createError("The file '" + relativePath - + "' has in the store the checksum " + renderChecksum(checksum) + " but " - + renderChecksum(checksumOfRetrieved) + " in the archive."); + long checksum = node.getChecksumCRC32(); + long checksumOfRetrieved = retrievedNode.getChecksumCRC32(); + if (checksum != checksumOfRetrieved) + { + return Status.createError("The file '" + relativePath + + "' has in the store the checksum " + renderChecksum(checksum) + + " but " + renderChecksum(checksumOfRetrieved) + " in the archive."); + } } } return Status.OK; diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiverTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiverTest.java index 7a49b8eaf9c..ffa09311d87 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiverTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/RsyncArchiverTest.java @@ -199,7 +199,7 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase { // ignored } - + allowing(dataSetDirectoryProvider).getStoreRoot(); will(returnValue(store)); } @@ -299,15 +299,17 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase one(fileOperationsManager).copyToDestination(file, ds1); will(returnValue(Status.OK)); + one(fileOperationsManager).isHosted(); + will(returnValue(true)); + one(statusUpdater).update(Arrays.asList("ds1"), DataSetArchivingStatus.AVAILABLE, true); - + one(contentProvider).asContent("ds1"); will(returnValue(new MockContent(":0:0", "f.txt:9:8DA988AF"))); - + FileUtilities.writeToFile(new File(retrievedDataSet, "f.txt"), "abcdefghi"); - one(fileOperationsManager).retrieveFromDestination( - retrievedDataSet, ds1); + one(fileOperationsManager).retrieveFromDestination(retrievedDataSet, ds1); will(returnValue(Status.OK)); } }); @@ -504,14 +506,15 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase public void testCheckHierarchySizeAndChecksumsHappyCase() { IHierarchicalContentNode root1 = - new MockContent(":0:0", "a/:0:0", "a/f1.txt:5:-3", "a/f2.txt:15:13", - "r.txt:7:17").getRootNode(); + new MockContent(":0:0", "a/:0:0", "a/f1.txt:5:-3", "a/f2.txt:15:13", "r.txt:7:17") + .getRootNode(); IHierarchicalContentNode root2 = - new MockContent(":0:0", "a/:0:0", "a/f2.txt:15:13", "a/f1.txt:5:-3", - "r.txt:7:17").getRootNode(); - assertEquals("OK", RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2).toString()); + new MockContent(":0:0", "a/:0:0", "a/f2.txt:15:13", "a/f1.txt:5:-3", "r.txt:7:17") + .getRootNode(); + assertEquals("OK", RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true) + .toString()); } - + @Test public void testCheckHierarchySizeAndChecksumsWrongPaths() { @@ -521,9 +524,9 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase new MockContent(":0:0", "a/:0:0", "a/f3.txt:15:13").getRootNode(); assertEquals("ERROR: \"Different paths: Path in the store is 'a/f1.txt' " + "and in the archive 'a/f3.txt'.\"", - RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2).toString()); + RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true).toString()); } - + @Test public void testCheckHierarchySizeAndChecksumsFileInsteadOfDirectory() { @@ -532,7 +535,7 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase assertEquals("ERROR: \"The path 'a' should be in store and archive either " + "both directories or files but not mixed: In the store it is a directory " + "but in the archive it is a file.\"", RsyncArchiver - .checkHierarchySizeAndChecksums(root1, root2).toString()); + .checkHierarchySizeAndChecksums(root1, root2, true).toString()); } @Test @@ -543,16 +546,16 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase IHierarchicalContentNode root2 = new MockContent(":0:0", "a/:0:0", "a/f2.txt:15:13").getRootNode(); assertEquals("ERROR: \"The directory 'a' has in the store 2 files but 1 in the archive.\"", - RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2).toString()); + RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true).toString()); } - + @Test public void testCheckHierarchySizeAndChecksumsWrongSize() { IHierarchicalContentNode root1 = new MockContent(":0:0", "r.txt:7:17").getRootNode(); IHierarchicalContentNode root2 = new MockContent(":0:0", "r.txt:9:17").getRootNode(); assertEquals("ERROR: \"The file 'r.txt' has in the store 7 bytes but 9 in the archive.\"", - RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2).toString()); + RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true).toString()); } @Test @@ -562,20 +565,34 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase IHierarchicalContentNode root2 = new MockContent(":0:0", "r.txt:7:18").getRootNode(); assertEquals("ERROR: \"The file 'r.txt' has in the store the checksum 00000017 " + "but 00000018 in the archive.\"", - RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2).toString()); + RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, true).toString()); } - + + public void testCheckHierarchySizeAndChecksumsWrongChecksumAreNotChecked() + { + IHierarchicalContentNode root1 = new MockContent(":0:0", "r.txt:7:17").getRootNode(); + IHierarchicalContentNode root2 = new MockContent(":0:0", "r.txt:7:18").getRootNode(); + assertEquals("OK", RsyncArchiver.checkHierarchySizeAndChecksums(root1, root2, false) + .toString()); + } + private static final class MockNode implements IHierarchicalContentNode { - private final List<IHierarchicalContentNode> children = new ArrayList<IHierarchicalContentNode>(); - + private final List<IHierarchicalContentNode> children = + new ArrayList<IHierarchicalContentNode>(); + private String name; + private String relativePath; + private IHierarchicalContentNode parent; + private boolean directory; + private long size; + private int checksum; - + void addNode(MockNode node) { node.parent = this; @@ -653,7 +670,7 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase { return true; } - + @Override public IRandomAccessFile getFileContent() throws UnsupportedOperationException, IOExceptionUnchecked @@ -669,12 +686,13 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase } } - + private static final class MockContent implements IHierarchicalContent { private MockNode root; + private final Map<String, MockNode> nodes = new HashMap<String, MockNode>(); - + MockContent(String... contentDescriptions) { for (String contentDescription : contentDescriptions) @@ -745,6 +763,6 @@ public class RsyncArchiverTest extends AbstractFileSystemTestCase public void close() { } - + } } -- GitLab