Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 18EFB200C53 for ; Tue, 11 Apr 2017 16:13:12 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 177F5160B89; Tue, 11 Apr 2017 14:13:12 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 02035160B9B for ; Tue, 11 Apr 2017 16:13:10 +0200 (CEST) Received: (qmail 92389 invoked by uid 500); 11 Apr 2017 14:13:10 -0000 Mailing-List: contact commits-help@brooklyn.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@brooklyn.apache.org Delivered-To: mailing list commits@brooklyn.apache.org Received: (qmail 92290 invoked by uid 99); 11 Apr 2017 14:13:08 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 11 Apr 2017 14:13:08 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 92088E0117; Tue, 11 Apr 2017 14:13:08 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: drigodwin@apache.org To: commits@brooklyn.apache.org Date: Tue, 11 Apr 2017 14:13:09 -0000 Message-Id: <4df408e8b8804562a442f9a52f086ab1@git.apache.org> In-Reply-To: <413ccc4af65141e898856fd552b65ba6@git.apache.org> References: <413ccc4af65141e898856fd552b65ba6@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/8] brooklyn-server git commit: Add support for configurable sequence sensors and update tests archived-at: Tue, 11 Apr 2017 14:13:12 -0000 Add support for configurable sequence sensors and update tests Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/a5aff680 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/a5aff680 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/a5aff680 Branch: refs/heads/master Commit: a5aff6801dceb2df81b41aa8b178a8f570903cba Parents: 2728745 Author: Andrew Donald Kennedy Authored: Tue Feb 7 09:43:50 2017 +0000 Committer: Andrew Donald Kennedy Committed: Tue Apr 11 14:34:26 2017 +0100 ---------------------------------------------------------------------- .../brooklyn/entity/group/SequenceGroup.java | 70 +++++++++--- .../entity/group/SequenceGroupImpl.java | 32 +++++- .../entity/group/SequenceGroupTest.java | 107 +++++++++++++------ .../entity/stock/SequenceEntityTest.java | 2 - 4 files changed, 161 insertions(+), 50 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a5aff680/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroup.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroup.java b/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroup.java index a6dee56..851d3b7 100644 --- a/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroup.java +++ b/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroup.java @@ -20,6 +20,7 @@ package org.apache.brooklyn.entity.group; import java.util.Map; +import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.ImplementedBy; import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.config.ConfigKey; @@ -27,10 +28,10 @@ import org.apache.brooklyn.core.annotation.Effector; import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.effector.MethodEffector; import org.apache.brooklyn.core.sensor.Sensors; -import org.apache.brooklyn.entity.stock.SequenceEntity; import org.apache.brooklyn.util.core.flags.SetFromFlag; import org.apache.brooklyn.util.text.StringPredicates; +import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.reflect.TypeToken; @@ -44,18 +45,45 @@ import com.google.common.reflect.TypeToken; * brooklyn.config: * entityFilter: * $brooklyn:object: - * type: org.apache.brooklyn.core.entity.EntityPredicates - * factoryMethod.name: "applicationIdEqualTo" + * type: com.google.common.base.Predicates + * factoryMethod.name: "and" * factoryMethod.args: - * - $brooklyn:attributeWhenReady("application.id") + * - $brooklyn:object: + * type: org.apache.brooklyn.core.entity.EntityPredicates + * factoryMethod.name: "applicationIdEqualTo" + * factoryMethod.args: + * - $brooklyn:attributeWhenReady("application.id") + * - $brooklyn:object: + * type: org.apache.brooklyn.core.entity.EntityPredicates + * factoryMethod.name: "configEquelTo" + * factoryMethod.args: + * - "sequence.set" + * - true * sequenceStart: 0 * sequenceIncrement: 1 - * sequenceFormat: "entity%04x" + * sequenceFormat: "Entity %04x" + * sequenceValueSensor: $brooklyn:sensor("entity.sequence") + * sequenceStringSensor: $brooklyn:sensor("entity.name") * } + *

+ * IMPORTANT Relationship management will fail in unpredictable ways + * if an entity is a member of multiple sequences that use the same + * {@link #SEQUENCE_VALUE_SENSOR sensor}, however this usage will probably + * not have the desired effect in any case. */ @ImplementedBy(SequenceGroupImpl.class) public interface SequenceGroup extends DynamicGroup { + AttributeSensor SEQUENCE_VALUE = Sensors.builder(Integer.class, "sequence.value") + .description("The current value of the sequence") + .build(); + + AttributeSensor SEQUENCE_STRING = Sensors.builder(String.class, "sequence.string") + .description("The current value of the sequence formatted as a string") + .build(); + + ConfigKey> ENTITY_FILTER = ConfigKeys.newConfigKeyWithDefault(DynamicGroup.ENTITY_FILTER, Predicates.alwaysFalse()); + @SetFromFlag("sequenceStart") ConfigKey SEQUENCE_START = ConfigKeys.builder(Integer.class) .name("sequence.start") @@ -65,7 +93,7 @@ public interface SequenceGroup extends DynamicGroup { .build(); @SetFromFlag("sequenceIncrement") - ConfigKey SEQUENCE_INCREMENT = ConfigKeys.builder(Integer.class) + ConfigKey SEQUENCE_INCREMENT = ConfigKeys.builder(Integer.class) .name("sequence.increment") .description("The sequence increment for the next value") .defaultValue(1) @@ -80,6 +108,26 @@ public interface SequenceGroup extends DynamicGroup { .constraint(StringPredicates.containsRegex("%[-#+ 0,(]*[0-9]*[doxX]")) .build(); + @SetFromFlag("sequenceValueSensor") + ConfigKey> SEQUENCE_VALUE_SENSOR = ConfigKeys.builder(new TypeToken>() { }) + .name("sequence.sensor.value") + .description("The sensor for the sequence value") + .defaultValue(SEQUENCE_VALUE) + .constraint(Predicates.>notNull()) + .build(); + + @SetFromFlag("sequenceStringSensor") + ConfigKey> SEQUENCE_STRING_SENSOR = ConfigKeys.builder(new TypeToken>() { }) + .name("sequence.sensor.string") + .description("The sensor for the sequence string") + .defaultValue(SEQUENCE_STRING) + .constraint(Predicates.>notNull()) + .build(); + + AttributeSensor SEQUENCE_CURRENT = Sensors.builder(Entity.class, "sequence.current") + .description("The current entity in the sequence") + .build(); + AttributeSensor SEQUENCE_NEXT = Sensors.builder(Integer.class, "sequence.next") .description("The next value of the sequence") .build(); @@ -88,17 +136,9 @@ public interface SequenceGroup extends DynamicGroup { .description("The current cache of entity ids to sequence numbers") .build(); - MethodEffector RESET = new MethodEffector(SequenceEntity.class, "reset"); + MethodEffector RESET = new MethodEffector(SequenceGroup.class, "reset"); @Effector(description = "Reset the sequence to initial value") Void reset(); - AttributeSensor SEQUENCE_VALUE = Sensors.builder(Integer.class, "sequence.value") - .description("The current value of the sequence") - .build(); - - AttributeSensor SEQUENCE_STRING = Sensors.builder(String.class, "sequence.string") - .description("The current value of the sequence formatted as a string") - .build(); - } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a5aff680/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroupImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroupImpl.java b/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroupImpl.java index f9fc04e..fc9c526 100644 --- a/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroupImpl.java +++ b/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroupImpl.java @@ -21,6 +21,7 @@ package org.apache.brooklyn.entity.group; import java.util.Map; import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.sensor.AttributeSensor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +29,7 @@ import com.google.common.collect.Maps; public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup { - private static final Logger LOG = LoggerFactory.getLogger(SequenceGroupImpl.class); + private static final Logger LOG = LoggerFactory.getLogger(SequenceGroup.class); public SequenceGroupImpl() { } @@ -36,6 +37,7 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup public Void reset() { synchronized (memberChangeMutex) { sensors().set(SEQUENCE_CACHE, Maps.newConcurrentMap()); + sensors().set(SEQUENCE_CURRENT, null); Integer initial = config().get(SEQUENCE_START); sensors().set(SEQUENCE_NEXT, initial); return null; @@ -58,6 +60,7 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup Map cache = sensors().get(SEQUENCE_CACHE); if (!cache.containsKey(member.getId())) { Integer value = sequence(member); + cache.put(member.getId(), value); } } @@ -65,13 +68,36 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup } } + @Override + public boolean removeMember(Entity member) { + synchronized (memberChangeMutex) { + boolean changed = super.removeMember(member); + if (changed) { + Map cache = sensors().get(SEQUENCE_CACHE); + if (cache.containsKey(member.getId())) { + cache.remove(member.getId()); + + AttributeSensor valueSensor = config().get(SEQUENCE_VALUE_SENSOR); + AttributeSensor stringSensor = config().get(SEQUENCE_STRING_SENSOR); + member.sensors().set(valueSensor, null); + member.sensors().set(stringSensor, null); + } + } + return changed; + } + } + private Integer sequence(Entity entity) { String format = config().get(SEQUENCE_FORMAT); Integer current = sensors().get(SEQUENCE_NEXT); String string = String.format(format, current); + AttributeSensor valueSensor = config().get(SEQUENCE_VALUE_SENSOR); + AttributeSensor stringSensor = config().get(SEQUENCE_STRING_SENSOR); + + entity.sensors().set(valueSensor, current); + entity.sensors().set(stringSensor, string); - entity.sensors().set(SEQUENCE_VALUE, current); - entity.sensors().set(SEQUENCE_STRING,string); + sensors().set(SEQUENCE_CURRENT, entity); Integer increment = config().get(SEQUENCE_INCREMENT); Integer next = current + increment; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a5aff680/core/src/test/java/org/apache/brooklyn/entity/group/SequenceGroupTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/entity/group/SequenceGroupTest.java b/core/src/test/java/org/apache/brooklyn/entity/group/SequenceGroupTest.java index afb5425..148eb5b 100644 --- a/core/src/test/java/org/apache/brooklyn/entity/group/SequenceGroupTest.java +++ b/core/src/test/java/org/apache/brooklyn/entity/group/SequenceGroupTest.java @@ -19,16 +19,20 @@ package org.apache.brooklyn.entity.group; import static org.apache.brooklyn.test.Asserts.assertEqualsIgnoringOrder; +import static org.apache.brooklyn.test.Asserts.*; +import static org.apache.brooklyn.core.entity.EntityAsserts.*; + +import java.util.Set; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.core.entity.Entities; -import org.apache.brooklyn.core.entity.EntityAsserts; import org.apache.brooklyn.core.entity.EntityPredicates; +import org.apache.brooklyn.core.sensor.Sensors; import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; import org.apache.brooklyn.core.test.entity.TestApplication; import org.apache.brooklyn.core.test.entity.TestEntity; -import org.apache.brooklyn.test.Asserts; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -38,11 +42,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; public class SequenceGroupTest extends BrooklynAppUnitTestSupport { - + private TestApplication app; private SequenceGroup group; - private TestEntity e1; - private TestEntity e2; + private TestEntity e1, e2, e3; @BeforeMethod(alwaysRun=true) @Override @@ -50,9 +53,12 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport { super.setUp(); app = TestApplication.Factory.newManagedInstanceForTests(); - group = app.createAndManageChild(EntitySpec.create(SequenceGroup.class)); + group = app.createAndManageChild(EntitySpec.create(SequenceGroup.class) + .configure(SequenceGroup.SEQUENCE_STRING_SENSOR, Sensors.newStringSensor("test.sequence")) + .configure(SequenceGroup.SEQUENCE_FORMAT, "test-%02d")); e1 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); e2 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); + e3 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); } @AfterMethod(alwaysRun=true) @@ -63,37 +69,75 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport { super.tearDown(); } + + @Test + public void testGroupDefaults() throws Exception { + assertTrue(group.getMembers().isEmpty()); + } + @Test public void testGroupWithMatchingFilterReturnsOnlyMatchingMembers() throws Exception { group.setEntityFilter(EntityPredicates.idEqualTo(e1.getId())); assertEqualsIgnoringOrder(group.getMembers(), ImmutableList.of(e1)); - EntityAsserts.assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 1); - EntityAsserts.assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 2); + assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 1); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 2); + } + + @Test + public void testGroupConfiguration() throws Exception { + group.setEntityFilter(EntityPredicates.idEqualTo(e1.getId())); + + assertEqualsIgnoringOrder(group.getMembers(), ImmutableList.of(e1)); + assertAttributeEquals(e1, SequenceGroup.SEQUENCE_STRING, null); + assertAttributeEquals(e1, Sensors.newStringSensor("test.sequence"), "test-01"); + } + + @Test + public void testAlternateGroupConfiguration() throws Exception { + AttributeSensor value = Sensors.newIntegerSensor("test.value"); + AttributeSensor string = Sensors.newStringSensor("test.string"); + group = app.createAndManageChild(EntitySpec.create(SequenceGroup.class) + .configure(SequenceGroup.SEQUENCE_START, 12345) + .configure(SequenceGroup.SEQUENCE_INCREMENT, 678) + .configure(SequenceGroup.SEQUENCE_VALUE_SENSOR, value) + .configure(SequenceGroup.SEQUENCE_STRING_SENSOR, string) + .configure(SequenceGroup.SEQUENCE_FORMAT, "0x%04X")); + group.setEntityFilter(EntityPredicates.hasInterfaceMatching(".*TestEntity")); + + assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, e3)); + assertAttributeEquals(e1, value, 12345); + assertAttributeEquals(e1, string, "0x3039"); + assertAttributeEquals(e2, value, 13023); + assertAttributeEquals(e2, string, "0x32DF"); + assertAttributeEquals(e3, value, 13701); + assertAttributeEquals(e3, string, "0x3585"); } @Test public void testGroupWithMatchingFilterReturnsEverythingThatMatches() throws Exception { group.setEntityFilter(Predicates.alwaysTrue()); - assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, app, group)); - EntityAsserts.assertAttributeEquals(app, SequenceGroup.SEQUENCE_VALUE, 1); - EntityAsserts.assertAttributeEquals(group, SequenceGroup.SEQUENCE_VALUE, 2); - EntityAsserts.assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 3); - EntityAsserts.assertAttributeEquals(e2, SequenceGroup.SEQUENCE_VALUE, 4); - EntityAsserts.assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 5); + assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, e3, app, group)); + assertAttributeEquals(app, SequenceGroup.SEQUENCE_VALUE, 1); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_VALUE, 2); + assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 3); + assertAttributeEquals(e2, SequenceGroup.SEQUENCE_VALUE, 4); + assertAttributeEquals(e3, SequenceGroup.SEQUENCE_VALUE, 5); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 6); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_CURRENT, e3); } - + @Test public void testGroupDetectsNewlyManagedMatchingMember() throws Exception { group.setEntityFilter(EntityPredicates.displayNameEqualTo("myname")); - final Entity e3 = app.addChild(EntitySpec.create(TestEntity.class).displayName("myname")); - - Asserts.succeedsEventually(new Runnable() { + final Entity e = app.addChild(EntitySpec.create(TestEntity.class).displayName("myname")); + + succeedsEventually(new Runnable() { public void run() { - assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e3)); - EntityAsserts.assertAttributeEquals(e3, SequenceGroup.SEQUENCE_VALUE, 1); - EntityAsserts.assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 2); + assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e)); + assertAttributeEquals(e, SequenceGroup.SEQUENCE_VALUE, 1); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 2); }}); } @@ -101,18 +145,21 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport { public void testGroupUsesNewFilter() throws Exception { group.setEntityFilter(EntityPredicates.hasInterfaceMatching(".*TestEntity")); - assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2)); - EntityAsserts.assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 1); - EntityAsserts.assertAttributeEquals(e2, SequenceGroup.SEQUENCE_VALUE, 2); - EntityAsserts.assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 3); + assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, e3)); + assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 1); + assertAttributeEquals(e2, SequenceGroup.SEQUENCE_VALUE, 2); + assertAttributeEquals(e3, SequenceGroup.SEQUENCE_VALUE, 3); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 4); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_CURRENT, e3); - final Entity e3 = app.addChild(EntitySpec.create(TestEntity.class)); + final Entity e = app.addChild(EntitySpec.create(TestEntity.class)); - Asserts.succeedsEventually(new Runnable() { + succeedsEventually(new Runnable() { public void run() { - assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, e3)); - EntityAsserts.assertAttributeEquals(e3, SequenceGroup.SEQUENCE_VALUE, 3); - EntityAsserts.assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 4); + assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, e3, e)); + assertAttributeEquals(e, SequenceGroup.SEQUENCE_VALUE, 4); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 5); + assertAttributeEquals(group, SequenceGroup.SEQUENCE_CURRENT, e); }}); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a5aff680/core/src/test/java/org/apache/brooklyn/entity/stock/SequenceEntityTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/entity/stock/SequenceEntityTest.java b/core/src/test/java/org/apache/brooklyn/entity/stock/SequenceEntityTest.java index 2b20f8d..2ec8a79 100644 --- a/core/src/test/java/org/apache/brooklyn/entity/stock/SequenceEntityTest.java +++ b/core/src/test/java/org/apache/brooklyn/entity/stock/SequenceEntityTest.java @@ -61,7 +61,6 @@ public class SequenceEntityTest extends BrooklynAppUnitTestSupport { @Test public void testSequenceInitialConfig() throws Exception { sequence = app.addChild(EntitySpec.create(SequenceEntity.class) - .configure(SequenceEntity.SEQUENCE_NAME, "forty-two") .configure(SequenceEntity.SEQUENCE_START, 42) .configure(SequenceEntity.SEQUENCE_FORMAT, "id-%02x")); app.start(ImmutableList.of(loc1)); @@ -70,7 +69,6 @@ public class SequenceEntityTest extends BrooklynAppUnitTestSupport { assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 42); assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "id-2a"); - assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_NAME, "forty-two"); } @Test