diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinder.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinder.java index 041895c028ccdec1b3b4790c6e98b60a55c9665a..194237ee416965fa3fb736e3a6a589bc2b6b2aee 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinder.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinder.java @@ -24,6 +24,7 @@ import org.apache.commons.io.FileUtils; import ch.rinn.restrictions.Private; import ch.systemsx.cisd.common.utilities.PropertyUtils; import ch.systemsx.cisd.openbis.dss.generic.shared.AbstractShareFinder; +import ch.systemsx.cisd.openbis.dss.generic.shared.ISpeedChecker; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share; import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/AbstractShareFinder.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/AbstractShareFinder.java index 2605ab176106b7c4aa31facaa95c3ac872702144..d3aa2f187b0e1ad194ff1632a4e6bd24ebd3cf4d 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/AbstractShareFinder.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/AbstractShareFinder.java @@ -29,44 +29,6 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; */ public abstract class AbstractShareFinder implements IShareFinder { - /** - * Returns <code>true</code> if speed of specified share and speed hint of specified data set - * are allowed. - * - * @author Franz-Josef Elmer - */ - public static interface ISpeedChecker - { - boolean check(SimpleDataSetInformationDTO dataSet, Share share); - } - - private enum SpeedChecker implements ISpeedChecker - { - MATCHING_CHECKER() - { - public boolean check(SimpleDataSetInformationDTO dataSet, Share share) - { - return Math.abs(dataSet.getSpeedHint()) == share.getSpeed(); - } - }, - RESPECTUNG_SPEED_HINT_CHECKER() - { - public boolean check(SimpleDataSetInformationDTO dataSet, Share share) - { - int speedHint = dataSet.getSpeedHint(); - int speed = share.getSpeed(); - return speedHint < 0 ? speed < Math.abs(speedHint) : speed > speedHint; - } - }, - IGNORING_SPEED_HINT_CHECKER() - { - public boolean check(SimpleDataSetInformationDTO dataSet, Share share) - { - return true; - } - } - } - /** * Tries to find a share fulfilling speed hint contract. */ diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISpeedChecker.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISpeedChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..0a4f50fa20b56754b1cda93d520067a592e54ee3 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISpeedChecker.java @@ -0,0 +1,15 @@ +package ch.systemsx.cisd.openbis.dss.generic.shared; + +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share; +import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; + +/** + * Returns <code>true</code> if speed of specified share and speed hint of specified data set + * are allowed. + * + * @author Franz-Josef Elmer + */ +public interface ISpeedChecker +{ + public boolean check(SimpleDataSetInformationDTO dataSet, Share share); +} \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedChecker.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..de231c579180c0ae87ba48a93cca1edd7a95b841 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedChecker.java @@ -0,0 +1,53 @@ +/* + * Copyright 2011 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.shared; + +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share; +import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; + +/** + * Enumeration of {@link ISpeedChecker} ordered in accordance to strictness. + * + * + * @author Franz-Josef Elmer + */ +public enum SpeedChecker implements ISpeedChecker +{ + MATCHING_CHECKER() + { + public boolean check(SimpleDataSetInformationDTO dataSet, Share share) + { + return Math.abs(dataSet.getSpeedHint()) == share.getSpeed(); + } + }, + RESPECTUNG_SPEED_HINT_CHECKER() + { + public boolean check(SimpleDataSetInformationDTO dataSet, Share share) + { + int speedHint = dataSet.getSpeedHint(); + int speed = share.getSpeed(); + return speedHint < 0 ? speed < Math.abs(speedHint) : speed > speedHint; + } + }, + IGNORING_SPEED_HINT_CHECKER() + { + public boolean check(SimpleDataSetInformationDTO dataSet, Share share) + { + return true; + } + } +} \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinder.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinder.java new file mode 100644 index 0000000000000000000000000000000000000000..ae6db7f3e865296e3b019ca3ab5e9cc6e3f228e1 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinder.java @@ -0,0 +1,81 @@ +/* + * Copyright 2011 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.shared; + +import java.util.List; +import java.util.Properties; + +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share; +import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; + +/** + * A share finder which first searches for the extension share with most free space which matches + * speed. If nothing found it does the same also for all extension shares but speed needs not to + * match but speed hint needs to be respected. If this isn't working {@link SimpleShareFinder} is + * used ignoring speed hint. + * + * @author Franz-Josef Elmer + */ +public class SpeedOptimizedShareFinder implements IShareFinder +{ + private final SimpleShareFinder simpleFinder; + + public SpeedOptimizedShareFinder(Properties properties) + { + simpleFinder = new SimpleShareFinder(properties); + } + + public Share tryToFindShare(SimpleDataSetInformationDTO dataSet, List<Share> shares) + { + Share share = tryToFindeExtensionShare(dataSet, shares, SpeedChecker.MATCHING_CHECKER); + if (share != null) + { + return share; + } + share = + tryToFindeExtensionShare(dataSet, shares, + SpeedChecker.RESPECTUNG_SPEED_HINT_CHECKER); + if (share != null) + { + return share; + } + return simpleFinder.tryToFindShare(dataSet, shares, + SpeedChecker.IGNORING_SPEED_HINT_CHECKER); + } + + private Share tryToFindeExtensionShare(SimpleDataSetInformationDTO dataSet, List<Share> shares, + ISpeedChecker speedChecker) + { + Share result = null; + long maxFreeSpace = dataSet.getDataSetSize(); + for (Share share : shares) + { + if (share.isIncoming() || speedChecker.check(dataSet, share) == false) + { + continue; + } + long freeSpace = share.calculateFreeSpace(); + if (freeSpace > maxFreeSpace) + { + maxFreeSpace = freeSpace; + result = share; + } + } + return result; + } + +} diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinderTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinderTest.java index 19212c2a0e6c752fb32b857255328524b0655998..f681f1e8f9644413a760973aa76fcf508a6d4d40 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinderTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinderTest.java @@ -36,7 +36,7 @@ import ch.rinn.restrictions.Friend; import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; import ch.systemsx.cisd.common.filesystem.HostAwareFile; import ch.systemsx.cisd.common.filesystem.IFreeSpaceProvider; -import ch.systemsx.cisd.openbis.dss.generic.shared.AbstractShareFinder; +import ch.systemsx.cisd.openbis.dss.generic.shared.ISpeedChecker; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share; import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; @@ -50,7 +50,7 @@ public class SimpleShufflingShareFinderTest extends AssertJUnit { private static final String DATA_SET_CODE = "ds-1"; - private static final class MockSpeedChecker implements AbstractShareFinder.ISpeedChecker + private static final class MockSpeedChecker implements ISpeedChecker { private final boolean[] checkingResults; diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SimpleShareFinderTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SimpleShareFinderTest.java index a6db43a8641bc898524b064fa042de606b169b90..10cdebf9b1cb1fc60240f95efcefac19759a45d2 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SimpleShareFinderTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SimpleShareFinderTest.java @@ -40,7 +40,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; */ public class SimpleShareFinderTest extends AssertJUnit { - private static final class MockSpeedChecker implements AbstractShareFinder.ISpeedChecker + private static final class MockSpeedChecker implements ISpeedChecker { private final boolean[] checkingResults; diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinderTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..babf246483a30d857068ae0139762692b14e67fe --- /dev/null +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinderTest.java @@ -0,0 +1,142 @@ +/* + * Copyright 2011 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.shared; + +import static org.apache.commons.io.FileUtils.ONE_MB; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.testng.AssertJUnit; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; +import ch.systemsx.cisd.common.filesystem.HostAwareFile; +import ch.systemsx.cisd.common.filesystem.IFreeSpaceProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share; +import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class SpeedOptimizedShareFinderTest extends AssertJUnit +{ + private static final String DATA_SET_CODE = "ds-1"; + + private SpeedOptimizedShareFinder finder; + + private Mockery context; + private IFreeSpaceProvider freeSpaceProvider; + private SimpleDataSetInformationDTO dataSet; + + @BeforeMethod + public void setUp() + { + context = new Mockery(); + freeSpaceProvider = context.mock(IFreeSpaceProvider.class); + dataSet = new SimpleDataSetInformationDTO(); + dataSet.setDataSetCode(DATA_SET_CODE); + dataSet.setDataSetSize(FileUtils.ONE_MB); + finder = new SpeedOptimizedShareFinder(new Properties()); + } + + @AfterMethod + public void tearDown(Method method) + { + try + { + context.assertIsSatisfied(); + } catch (Throwable t) + { + // assert expectations were met, including the name of the failed method + throw new Error(method.getName() + "() : ", t); + } + } + + @Test + public void testFindMatchingExtensionShare() + { + dataSet.setSpeedHint(-50); + Share s1 = share(false, 50, 10 * ONE_MB); + Share s2 = share(true, 50, 0); + Share s3 = share(false, 40, 0); + Share s4 = share(false, 50, 11 * ONE_MB); + + Share foundShare = finder.tryToFindShare(dataSet, Arrays.asList(s1, s2, s3, s4)); + assertSame(s4.getShare(), foundShare.getShare()); + } + + @Test + public void testFindExtensionShareRespectingSpeedHint() + { + dataSet.setSpeedHint(-50); + Share s1 = share(false, 49, 10 * ONE_MB); + Share s2 = share(true, 50, 0); + Share s3 = share(false, 40, 11 * ONE_MB); + + Share foundShare = finder.tryToFindShare(dataSet, Arrays.asList(s1, s2, s3)); + assertSame(s3.getShare(), foundShare.getShare()); + } + + @Test + public void testFindShareIgnoringSpeedHint() + { + dataSet.setSpeedHint(-50); + dataSet.setDataSetShareId("20"); + Share s1 = share(false, 51, 10 * ONE_MB); + Share s2 = share(true, 50, 20 * ONE_MB); + Share s3 = share(false, 60, 11 * ONE_MB); + Share s4 = share(true, 50, 15 * ONE_MB); + + Share foundShare = finder.tryToFindShare(dataSet, Arrays.asList(s1, s2, s3, s4)); + assertSame(s3.getShare(), foundShare.getShare()); + } + + private Share share(boolean incoming, int speed, final long freeSpace) + { + final File file = new File(Integer.toString(speed) + "/" + incoming + "/" + freeSpace); + if (freeSpace > 0) + { + context.checking(new Expectations() + { + { + try + { + one(freeSpaceProvider).freeSpaceKb(new HostAwareFile(file)); + will(returnValue(freeSpace / FileUtils.ONE_KB)); + } catch (IOException ex) + { + throw CheckedExceptionTunnel.wrapIfNecessary(ex); + } + } + }); + } + Share share = new Share(file, speed, freeSpaceProvider); + share.setIncoming(incoming); + return share; + } +}