Repository: reef Updated Branches: refs/heads/master 18c25fdcf -> 1fc8cd051
[REEF-1642] Make sure there is only one instance of Evaluators per REEFEnvironment/Driver * Improve `SingletonAsserter` to support both global and scoped singletons * Add unit tests for new functionality of `SingletonAsserter` * Use scoped `SingletonAsserter` in the `Evaluators` class This is work towards [REEF-1561](https://issues.apache.org/jira/browse/REEF-1561) *"REEF as a library"* effort. JIRA: [REEF-1642](https://issues.apache.org/jira/browse/REEF-1642) Pull Request: This closes #1157 Project: http://git-wip-us.apache.org/repos/asf/reef/repo Commit: http://git-wip-us.apache.org/repos/asf/reef/commit/1fc8cd05 Tree: http://git-wip-us.apache.org/repos/asf/reef/tree/1fc8cd05 Diff: http://git-wip-us.apache.org/repos/asf/reef/diff/1fc8cd05 Branch: refs/heads/master Commit: 1fc8cd0515dcfa520a8193202b3e9aa099e806c6 Parents: 18c25fd Author: Sergiy Matusevych <mo...@apache.org> Authored: Tue Oct 11 13:52:05 2016 -0700 Committer: Markus Weimer <wei...@apache.org> Committed: Mon Oct 17 15:30:51 2016 -0700 ---------------------------------------------------------------------- .../common/driver/evaluator/Evaluators.java | 10 +++-- .../org/apache/reef/util/SingletonAsserter.java | 29 ++++++++++++-- .../apache/reef/util/SingletonAsserterTest.java | 41 +++++++++++++++++--- 3 files changed, 66 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/reef/blob/1fc8cd05/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/Evaluators.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/Evaluators.java b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/Evaluators.java index 8962895..341d37d 100644 --- a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/Evaluators.java +++ b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/Evaluators.java @@ -20,9 +20,12 @@ package org.apache.reef.runtime.common.driver.evaluator; import org.apache.reef.annotations.audience.DriverSide; import org.apache.reef.annotations.audience.Private; +import org.apache.reef.driver.parameters.DriverIdentifier; import org.apache.reef.runtime.common.driver.resourcemanager.ResourceAllocationEvent; +import org.apache.reef.tang.annotations.Parameter; import org.apache.reef.util.Optional; import org.apache.reef.tang.util.MonotonicSet; +import org.apache.reef.util.SingletonAsserter; import javax.inject.Inject; import java.util.*; @@ -50,12 +53,11 @@ public final class Evaluators implements AutoCloseable { private final MonotonicSet<String> closedEvaluatorIds = new MonotonicSet<>(); @Inject - Evaluators() { - LOG.log(Level.FINE, "Instantiated 'Evaluators'"); - // TODO[REEF-1642] Assert singleton per REEFEnvironment + private Evaluators(@Parameter(DriverIdentifier.class) final String driverId) { + LOG.log(Level.FINE, "Instantiated 'Evaluators' for driver {0}", driverId); // There can be several instances of the class for multiple REEFEnvironments. // It is still a singleton when REEF Driver owns the entire JVM. - // assert SingletonAsserter.assertSingleton(Evaluators.class); + assert SingletonAsserter.assertSingleton(driverId, Evaluators.class); } /** http://git-wip-us.apache.org/repos/asf/reef/blob/1fc8cd05/lang/java/reef-common/src/main/java/org/apache/reef/util/SingletonAsserter.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/util/SingletonAsserter.java b/lang/java/reef-common/src/main/java/org/apache/reef/util/SingletonAsserter.java index 5c6d0a9..da3b994 100644 --- a/lang/java/reef-common/src/main/java/org/apache/reef/util/SingletonAsserter.java +++ b/lang/java/reef-common/src/main/java/org/apache/reef/util/SingletonAsserter.java @@ -18,7 +18,8 @@ */ package org.apache.reef.util; -import java.util.Collections; +import org.apache.reef.io.Tuple; + import java.util.HashSet; import java.util.Set; @@ -27,7 +28,11 @@ import java.util.Set; */ public final class SingletonAsserter { - private static final Set<Class> CLASSES = Collections.synchronizedSet(new HashSet<Class>()); + private static final Set<Class> ALL_CLASSES = new HashSet<>(); + + private static final Set<Class> SINGLETONS_GLOBAL = new HashSet<>(); + + private static final Set<Tuple<String, Class>> SINGLETONS_SCOPED = new HashSet<>(); /** * This class operates purely in static mode. @@ -35,7 +40,23 @@ public final class SingletonAsserter { private SingletonAsserter() { } - public static boolean assertSingleton(final Class clazz) { - return CLASSES.add(clazz); + /** + * Check if a given class is instantiated only once. + * @param clazz Class to check. + * @return True if the class was not instantiated before, false otherwise. + */ + public static synchronized boolean assertSingleton(final Class clazz) { + return SINGLETONS_GLOBAL.add(clazz) && ALL_CLASSES.add(clazz); + } + + /** + * Check if given class is singleton within a particular environment or scope. + * @param scopeId Environment id, e.g. Driver name or REEF job id. + * @param clazz Class that must have no more than 1 instance in that environment. + * @return true if the instance is unique within that particular environment, false otherwise. + */ + public static synchronized boolean assertSingleton(final String scopeId, final Class clazz) { + ALL_CLASSES.add(clazz); + return SINGLETONS_SCOPED.add(new Tuple<>(scopeId, clazz)) && !SINGLETONS_GLOBAL.contains(clazz); } } http://git-wip-us.apache.org/repos/asf/reef/blob/1fc8cd05/lang/java/reef-common/src/test/java/org/apache/reef/util/SingletonAsserterTest.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-common/src/test/java/org/apache/reef/util/SingletonAsserterTest.java b/lang/java/reef-common/src/test/java/org/apache/reef/util/SingletonAsserterTest.java index c25f462..ede9697 100644 --- a/lang/java/reef-common/src/test/java/org/apache/reef/util/SingletonAsserterTest.java +++ b/lang/java/reef-common/src/test/java/org/apache/reef/util/SingletonAsserterTest.java @@ -21,17 +21,46 @@ package org.apache.reef.util; import org.junit.Assert; import org.junit.Test; -import java.util.List; - /** * Test for SingletonAsserter. */ public final class SingletonAsserterTest { + private static final class GlobalA { } + private static final class GlobalB { } + + @Test + public void testSingletonAsserterGlobal() { + Assert.assertTrue(SingletonAsserter.assertSingleton(GlobalA.class)); + Assert.assertTrue(SingletonAsserter.assertSingleton(GlobalB.class)); + Assert.assertFalse(SingletonAsserter.assertSingleton(GlobalA.class)); + } + + private static final class LocalA { } + private static final class LocalB { } + + @Test + public void testSingletonAsserterScoped() { + Assert.assertTrue(SingletonAsserter.assertSingleton("A", LocalA.class)); + Assert.assertTrue(SingletonAsserter.assertSingleton("A", LocalB.class)); + Assert.assertTrue(SingletonAsserter.assertSingleton("B", LocalA.class)); + Assert.assertFalse(SingletonAsserter.assertSingleton("A", LocalA.class)); + } + + private static final class Mixed1 { } + + @Test + public void testSingletonAsserterMixed1() { + Assert.assertTrue(SingletonAsserter.assertSingleton("A", Mixed1.class)); + Assert.assertTrue(SingletonAsserter.assertSingleton("B", Mixed1.class)); + Assert.assertFalse(SingletonAsserter.assertSingleton(Mixed1.class)); + } + + private static final class Mixed2 { } + @Test - public void testSingletonAsserter() { - Assert.assertTrue(SingletonAsserter.assertSingleton(SingletonAsserterTest.class)); - Assert.assertTrue(SingletonAsserter.assertSingleton(List.class)); - Assert.assertFalse(SingletonAsserter.assertSingleton(List.class)); + public void testSingletonAsserterMixed2() { + Assert.assertTrue(SingletonAsserter.assertSingleton(Mixed2.class)); + Assert.assertFalse(SingletonAsserter.assertSingleton("A", Mixed2.class)); } }