diff --git a/deep_sequencing_unit/.classpath b/deep_sequencing_unit/.classpath index 417fb1931958ed5f1692dab880073df47f1735a2..238c07c192773c1b5d8f0336c43075d687d8de07 100644 --- a/deep_sequencing_unit/.classpath +++ b/deep_sequencing_unit/.classpath @@ -6,5 +6,7 @@ <classpathentry combineaccessrules="false" kind="src" path="/datastore_server"/> <classpathentry combineaccessrules="false" kind="src" path="/common"/> <classpathentry kind="lib" path="/libraries/testng/testng-jdk15.jar" sourcepath="/libraries/testng/src.zip"/> + <classpathentry kind="lib" path="/libraries/cisd-base/cisd-base-test.jar" sourcepath="/libraries/cisd-base/cisd-base-src.zip"/> + <classpathentry kind="lib" path="/libraries/cisd-base/cisd-base.jar" sourcepath="/libraries/cisd-base/cisd-base-src.zip"/> <classpathentry kind="output" path="targets/classes"/> </classpath> diff --git a/deep_sequencing_unit/dist/etc/service.properties b/deep_sequencing_unit/dist/etc/service.properties index 6210f2c083487950f3a8eea753cdb4ade39c798b..fdf1278cd0cf065be4aecd58da59bdac351bd548 100644 --- a/deep_sequencing_unit/dist/etc/service.properties +++ b/deep_sequencing_unit/dist/etc/service.properties @@ -124,3 +124,5 @@ flow-cell.type-extractor.is-measured = true # The storage processor (IStorageProcessor implementation) flow-cell.storage-processor = ch.ethz.bsse.cisd.dsu.dss.StorageProcessor flow-cell.storage-processor.processor = ch.systemsx.cisd.etlserver.DefaultStorageProcessor +# Template of flow-line drop boxes. {0} is the place holder for flow line number +flow-cell.storage-processor.flow-line-drop-box-template = data/drop-box-{0} diff --git a/deep_sequencing_unit/etc/service.properties b/deep_sequencing_unit/etc/service.properties index b973b46b7e70c1379ca5350fbaa75b417d58c567..9a0d8770e48bcfed6b99fad5ac835c838f79e067 100644 --- a/deep_sequencing_unit/etc/service.properties +++ b/deep_sequencing_unit/etc/service.properties @@ -124,3 +124,4 @@ flow-cell.type-extractor.is-measured = true # The storage processor (IStorageProcessor implementation) flow-cell.storage-processor = ch.ethz.bsse.cisd.dsu.dss.StorageProcessor flow-cell.storage-processor.processor = ch.systemsx.cisd.etlserver.DefaultStorageProcessor +flow-cell.storage-processor.flow-line-drop-box-template = targets/playground/drop-box-{0} diff --git a/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java b/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java index a06534e63e903ee5ffa0847372ed0d3310cca891..18bd8ea30ac0d25046c2ad4a1e3233cb9543cdcc 100644 --- a/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java +++ b/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java @@ -22,8 +22,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; +import ch.systemsx.cisd.common.TimingParameters; import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; +import ch.systemsx.cisd.common.filesystem.FastRecursiveHardLinkMaker; +import ch.systemsx.cisd.common.filesystem.FileOperations; +import ch.systemsx.cisd.common.filesystem.IFileOperations; +import ch.systemsx.cisd.common.filesystem.IImmutableCopier; import ch.systemsx.cisd.common.utilities.PropertyUtils; import ch.systemsx.cisd.openbis.dss.generic.shared.IPostRegistrationDatasetHandler; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; @@ -39,17 +44,21 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler static final String FILE_TYPE = ".srf"; private final MessageFormat flowLineDropBoxTemplate; + private final IImmutableCopier copier; + private final IFileOperations fileOperations; + private final List<File> flowLineDataSets = new ArrayList<File>(); FlowLineFeeder(Properties properties) { flowLineDropBoxTemplate = new MessageFormat(PropertyUtils.getMandatoryProperty(properties, FLOW_LINE_DROP_BOX_TEMPLATE)); + copier = FastRecursiveHardLinkMaker.tryCreate(TimingParameters.getDefaultParameters()); + fileOperations = FileOperations.getInstance(); } public void handle(File originalData, DataSetInformation dataSetInformation) { - System.out.println("FlowLineFeeder.handle(): "+originalData+" "+dataSetInformation); String flowcellID = originalData.getName(); List<File> files = new ArrayList<File>(); findFiles(originalData, files); @@ -58,20 +67,27 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler String flowLine = extractFlowLine(file); File dropBox = createDropBoxFile(flowLine); File flowLineDataSet = new File(dropBox, flowcellID + "_" + flowLine); + flowLineDataSets.add(flowLineDataSet); boolean success = flowLineDataSet.mkdir(); if (success == false) { throw new EnvironmentFailureException("Couldn't create folder '" + flowLineDataSet.getAbsolutePath() + "'."); } - + success = copier.copyImmutably(file, flowLineDataSet, null); + if (success == false) + { + throw new EnvironmentFailureException("Couldn't create a hard-link copy of '" + + file.getAbsolutePath() + "' in folder '" + + flowLineDataSet.getAbsolutePath() + "'."); + } } } private File createDropBoxFile(String flowLine) { - File dropBox = new File(flowLineDropBoxTemplate.format(flowLine)); + File dropBox = new File(flowLineDropBoxTemplate.format(new Object[] {flowLine})); if (dropBox.exists() == false) { throw new ConfigurationFailureException("Drop box '" + dropBox + "' does not exist."); @@ -86,12 +102,7 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler private String extractFlowLine(File file) { String name = file.getName(); - int lastIndexOfDot = name.lastIndexOf('.'); - String nameWithoutType = name; - if (lastIndexOfDot >= 0) - { - nameWithoutType = name.substring(0, lastIndexOfDot); - } + String nameWithoutType = name.substring(0, name.lastIndexOf('.')); int lastIndexOfUnderScore = nameWithoutType.lastIndexOf('_'); String flowLine = nameWithoutType; if (lastIndexOfUnderScore >= 0) @@ -118,7 +129,10 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler public void undoLastOperation() { - System.out.println("FlowLineFeeder.undoLastOperation()"); + for (File file : flowLineDataSets) + { + fileOperations.deleteRecursively(file); + } } } diff --git a/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java b/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1c728db677aeea052ce4d920b7cf2b4020e6ed59 --- /dev/null +++ b/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java @@ -0,0 +1,135 @@ +/* + * Copyright 2009 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.ethz.bsse.cisd.dsu.dss; + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; +import ch.systemsx.cisd.common.filesystem.FileUtilities; +import ch.systemsx.cisd.common.test.AssertionUtil; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class FlowLineFeederTest extends AbstractFileSystemTestCase +{ + private static final String DROP_BOX_PREFIX = "drop-box-"; + private FlowLineFeeder flowLineFeeder; + + @Override + @BeforeMethod + public void setUp() throws IOException + { + super.setUp(); + assertEquals(true, new File(workingDirectory, DROP_BOX_PREFIX + "1").mkdirs()); + assertEquals(true, new File(workingDirectory, DROP_BOX_PREFIX + "2").mkdirs()); + Properties properties = new Properties(); + properties.setProperty(FlowLineFeeder.FLOW_LINE_DROP_BOX_TEMPLATE, new File( + workingDirectory, DROP_BOX_PREFIX).getAbsolutePath() + + "{0}"); + flowLineFeeder = new FlowLineFeeder(properties); + } + + @Test + public void testMissingProperty() + { + try + { + new FlowLineFeeder(new Properties()); + fail("ConfigurationFailureException expected"); + } catch (ConfigurationFailureException ex) + { + assertEquals("Given key '" + FlowLineFeeder.FLOW_LINE_DROP_BOX_TEMPLATE + + "' not found in properties '[]'", ex.getMessage()); + } + } + + @Test + void testMissingDropBox() + { + File flowCell = new File(workingDirectory, "abc"); + assertEquals(true, flowCell.mkdir()); + FileUtilities.writeToFile(new File(flowCell, "s_3.srf"), "hello flow line 3"); + + try + { + flowLineFeeder.handle(flowCell, null); + fail("ConfigurationFailureException expected"); + } catch (ConfigurationFailureException ex) + { + AssertionUtil.assertContains(DROP_BOX_PREFIX + "3", ex.getMessage()); + } + } + + @Test + public void testHappyCase() + { + File flowCell = new File(workingDirectory, "abc"); + assertEquals(true, flowCell.mkdir()); + File logs = new File(flowCell, "logs"); + assertEquals(true, logs.mkdir()); + FileUtilities.writeToFile(new File(logs, "basic.log"), "hello log"); + File srfFolder = new File(flowCell, "SRF"); + assertEquals(true, srfFolder.mkdir()); + File originalFlowLine1 = new File(srfFolder, "s_1.srf"); + FileUtilities.writeToFile(originalFlowLine1, "hello flow line 1"); + File originalFlowLine2 = new File(srfFolder, "2.srf"); + FileUtilities.writeToFile(originalFlowLine2, "hello flow line 2"); + + flowLineFeeder.handle(flowCell, null); + + checkFlowLineDataSet(originalFlowLine1, "1"); + checkFlowLineDataSet(originalFlowLine2, "2"); + } + + @Test + public void testUndoLastOperation() + { + testHappyCase(); + assertEquals(1, new File(workingDirectory, DROP_BOX_PREFIX + "1").list().length); + assertEquals(1, new File(workingDirectory, DROP_BOX_PREFIX + "2").list().length); + + flowLineFeeder.undoLastOperation(); + + assertEquals(0, new File(workingDirectory, DROP_BOX_PREFIX + "1").list().length); + assertEquals(0, new File(workingDirectory, DROP_BOX_PREFIX + "2").list().length); + } + + private void checkFlowLineDataSet(File originalFlowLine, String flowLineNumber) + { + File dropBox = new File(workingDirectory, DROP_BOX_PREFIX + flowLineNumber); + File ds = new File(dropBox, "abc_" + flowLineNumber); + assertEquals(true, ds.isDirectory()); + + File flowLine = new File(ds, originalFlowLine.getName()); + assertEquals(true, flowLine.isFile()); + assertEquals(FileUtilities.loadToString(originalFlowLine), FileUtilities + .loadToString(flowLine)); + // check hard-link copy by changing last-modified date of one file should change + // last-modified date of the other file. + originalFlowLine.setLastModified(4711000); + assertEquals(4711000, flowLine.lastModified()); + } +}