You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by dr...@apache.org on 2017/04/11 14:13:08 UTC
[1/8] brooklyn-server git commit: An entity that emits a sequence of
integers
Repository: brooklyn-server
Updated Branches:
refs/heads/master a23d42ffb -> d9a8c1df5
An entity that emits a sequence of integers
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/f2bd6538
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/f2bd6538
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/f2bd6538
Branch: refs/heads/master
Commit: f2bd6538d32dddcab6820059f5910f09bda79770
Parents: a23d42f
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Tue Jan 31 09:32:29 2017 +0000
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Tue Apr 11 14:34:25 2017 +0100
----------------------------------------------------------------------
.../brooklyn/entity/stock/SequenceEntity.java | 112 ++++++++++++
.../entity/stock/SequenceEntityImpl.java | 99 ++++++++++
.../entity/stock/SequenceEntityTest.java | 181 +++++++++++++++++++
3 files changed, 392 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f2bd6538/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
new file mode 100644
index 0000000..5135f3c
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.brooklyn.entity.stock;
+
+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;
+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.entity.trait.Startable;
+import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.util.text.StringPredicates;
+
+import com.google.common.base.Predicates;
+
+/**
+ * An entity that supplies a sequence of values through an effector.
+ * <p>
+ * Usage:
+ * <pre>{@code
+ * - type: org.apache.brooklyn.entity.stock.SequenceEntity
+ * id: global-sequence
+ * brooklyn.config:
+ * sequence.start: 0
+ * sequence.increment: 1
+ * sequence.format: "global-%03d"
+ * sequence.name: "global"
+ * }</pre>
+ */
+@ImplementedBy(SequenceEntityImpl.class)
+public interface SequenceEntity extends Entity, Startable {
+
+ @SetFromFlag("sequenceStart")
+ ConfigKey<Integer> SEQUENCE_START = ConfigKeys.builder(Integer.class)
+ .name("sequence.start")
+ .description("The starting point of the sequence")
+ .defaultValue(1)
+ .constraint(Predicates.<Integer>notNull())
+ .build();
+
+ @SetFromFlag("sequenceIncrement")
+ ConfigKey<Integer> SEQUENCE_INCREMENT = ConfigKeys.builder(Integer.class)
+ .name("sequence.increment")
+ .description("The sequence increment for the next value")
+ .defaultValue(1)
+ .constraint(Predicates.<Integer>notNull())
+ .build();
+
+ @SetFromFlag("sequenceFormat")
+ ConfigKey<String> SEQUENCE_FORMAT = ConfigKeys.builder(String.class)
+ .name("sequence.format")
+ .description("A format used to generate a string representation of the sequence")
+ .defaultValue("%d")
+ .constraint(StringPredicates.containsRegex("%[-#+ 0,(]*[0-9]*[doxX]"))
+ .build();
+
+ @SetFromFlag("sequenceName")
+ AttributeSensorAndConfigKey<String, String> SEQUENCE_NAME = ConfigKeys.newStringSensorAndConfigKey("sequence.name", "The name of the sequence", "sequence");
+
+ AttributeSensor<Integer> SEQUENCE_VALUE = Sensors.builder(Integer.class, "sequence.value")
+ .description("The current value of the sequence")
+ .build();
+
+ AttributeSensor<String> SEQUENCE_STRING = Sensors.builder(String.class, "sequence.string")
+ .description("The current value of the sequence formatted as a string")
+ .build();
+
+ MethodEffector<Void> RESET = new MethodEffector<Void>(SequenceEntity.class, "reset");
+ MethodEffector<Void> INCREMENT = new MethodEffector<Void>(SequenceEntity.class, "increment");
+ MethodEffector<Integer> CURRENT_VALUE = new MethodEffector<Integer>(SequenceEntity.class, "currentValue");
+ MethodEffector<String> CURRENT_STRING = new MethodEffector<String>(SequenceEntity.class, "currentString");
+ MethodEffector<Integer> NEXT_VALUE = new MethodEffector<Integer>(SequenceEntity.class, "nextValue");
+ MethodEffector<String> NEXT_STRING = new MethodEffector<String>(SequenceEntity.class, "nextString");
+
+ @Effector(description = "Reset the sequence to initial value")
+ Void reset();
+
+ @Effector(description = "Update the value of the sequence by the configured increment")
+ Void increment();
+
+ @Effector(description = "Return the current numeric value of the sequence")
+ Integer currentValue();
+
+ @Effector(description = "Return the current string representation of the sequence")
+ String currentString();
+
+ @Effector(description = "Update and return the next numeric value of the sequence")
+ Integer nextValue();
+
+ @Effector(description = "Update and return the next string representation of the sequence")
+ String nextString();
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f2bd6538/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
new file mode 100644
index 0000000..338b323
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.brooklyn.entity.stock;
+
+import java.util.Collection;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.core.feed.ConfigToAttributes;
+
+public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity {
+
+ public SequenceEntityImpl() { }
+
+ public void init() {
+ super.init();
+
+ ConfigToAttributes.apply(this, SEQUENCE_NAME);
+ }
+
+ @Override
+ public void start(Collection<? extends Location> locations) {
+ addLocations(locations);
+ reset();
+ sensors().set(SERVICE_UP, Boolean.TRUE);
+ }
+
+ @Override
+ public void stop() {
+ sensors().set(SERVICE_UP, Boolean.FALSE);
+ }
+
+ @Override
+ public void restart() {
+ stop();
+ start(getLocations());
+ }
+
+ protected void sequence(Integer value) {
+ String format = config().get(SEQUENCE_FORMAT);
+
+ sensors().set(SEQUENCE_VALUE, value);
+ sensors().set(SEQUENCE_STRING, String.format(format, value));
+ }
+
+ @Override
+ public Integer currentValue() {
+ return sensors().get(SEQUENCE_VALUE);
+ }
+
+ @Override
+ public String currentString() {
+ return sensors().get(SEQUENCE_STRING);
+ }
+
+ @Override
+ public synchronized Integer nextValue() {
+ increment();
+ return currentValue();
+ }
+
+ @Override
+ public synchronized String nextString() {
+ increment();
+ return currentString();
+ }
+
+ @Override
+ public synchronized Void increment() {
+ Integer increment = config().get(SEQUENCE_INCREMENT);
+ Integer current = currentValue();
+ sequence(current + increment);
+ return null;
+ }
+
+ @Override
+ public synchronized Void reset() {
+ Integer start = config().get(SEQUENCE_START);
+ sequence(start);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f2bd6538/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
new file mode 100644
index 0000000..2b20f8d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/entity/stock/SequenceEntityTest.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.brooklyn.entity.stock;
+
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEquals;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEqualsEventually;
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.SimulatedLocation;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class SequenceEntityTest extends BrooklynAppUnitTestSupport {
+
+ private SimulatedLocation loc1;
+ private SequenceEntity sequence;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ loc1 = mgmt.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+ }
+
+ @Test
+ public void testSequenceInitial() throws Exception {
+ sequence = app.addChild(EntitySpec.create(SequenceEntity.class)
+ .configure(SequenceEntity.SEQUENCE_START, 0));
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
+
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 0);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "0");
+ }
+
+ @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));
+
+ assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
+
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 42);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "id-2a");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_NAME, "forty-two");
+ }
+
+ @Test
+ public void testSequenceIncrementEffector() throws Exception {
+ sequence = app.addChild(EntitySpec.create(SequenceEntity.class));
+ app.start(ImmutableList.of(loc1));
+
+ EntityAsserts.assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(1));
+ assertEquals(sequence.currentString(), "1");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 1);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "1");
+
+ sequence.increment();
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(2));
+ assertEquals(sequence.currentString(), "2");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 2);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "2");
+
+ sequence.invoke(SequenceEntity.INCREMENT, ImmutableMap.<String, Object>of()).getUnchecked();
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(3));
+ assertEquals(sequence.currentString(), "3");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 3);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "3");
+ }
+
+ @Test
+ public void testSequenceIncrementEffectorConfig() throws Exception {
+ sequence = app.addChild(EntitySpec.create(SequenceEntity.class)
+ .configure(SequenceEntity.SEQUENCE_START, 0)
+ .configure(SequenceEntity.SEQUENCE_INCREMENT, 2)
+ .configure(SequenceEntity.SEQUENCE_FORMAT, "%03d"));
+ app.start(ImmutableList.of(loc1));
+
+ EntityAsserts.assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(0));
+ assertEquals(sequence.currentString(), "000");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 0);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "000");
+
+ sequence.increment();
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(2));
+ assertEquals(sequence.currentString(), "002");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 2);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "002");
+
+ sequence.invoke(SequenceEntity.INCREMENT, ImmutableMap.<String, Object>of()).getUnchecked();
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(4));
+ assertEquals(sequence.currentString(), "004");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 4);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "004");
+ }
+
+ @Test
+ public void testSequenceNextEffectors() throws Exception {
+ sequence = app.addChild(EntitySpec.create(SequenceEntity.class));
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(1));
+ assertEquals(sequence.currentString(), "1");
+
+ Integer nextValue = sequence.invoke(SequenceEntity.NEXT_VALUE, ImmutableMap.<String, Object>of()).getUnchecked();
+ assertEquals(nextValue, Integer.valueOf(2));
+
+ String nextString = sequence.invoke(SequenceEntity.NEXT_STRING, ImmutableMap.<String, Object>of()).getUnchecked();
+ assertEquals(nextString, "3");
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(3));
+ assertEquals(sequence.currentString(), "3");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 3);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "3");
+ }
+
+ @Test
+ public void testSequenceReset() throws Exception {
+ sequence = app.addChild(EntitySpec.create(SequenceEntity.class));
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(1));
+
+ sequence.increment();
+ sequence.increment();
+ sequence.increment();
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(4));
+ assertEquals(sequence.currentString(), "4");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 4);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "4");
+
+ sequence.invoke(SequenceEntity.RESET, ImmutableMap.<String, Object>of()).getUnchecked();
+
+ assertEquals(sequence.currentValue(), Integer.valueOf(1));
+ assertEquals(sequence.currentString(), "1");
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 1);
+ assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "1");
+ }
+
+}
[8/8] brooklyn-server git commit: This closes #546
Posted by dr...@apache.org.
This closes #546
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/d9a8c1df
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/d9a8c1df
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/d9a8c1df
Branch: refs/heads/master
Commit: d9a8c1df522e4e3bdc92db28466a415481207be4
Parents: a23d42f 62989ac
Author: Duncan Godwin <dr...@googlemail.com>
Authored: Tue Apr 11 15:12:52 2017 +0100
Committer: Duncan Godwin <dr...@googlemail.com>
Committed: Tue Apr 11 15:12:52 2017 +0100
----------------------------------------------------------------------
.../entity/lifecycle/ServiceStateLogic.java | 150 +++++++++-----
.../brooklyn/entity/group/SequenceGroup.java | 140 +++++++++++++
.../entity/group/SequenceGroupImpl.java | 109 ++++++++++
.../brooklyn/entity/stock/SequenceEntity.java | 77 +++++++
.../entity/stock/SequenceEntityImpl.java | 97 +++++++++
.../entity/group/SequenceGroupTest.java | 202 +++++++++++++++++++
.../entity/stock/SequenceEntityTest.java | 156 ++++++++++++++
7 files changed, 876 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
[3/8] brooklyn-server git commit: A group that sets a sequence of
values as sensors on members
Posted by dr...@apache.org.
A group that sets a sequence of values as sensors on members
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/2728745b
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/2728745b
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/2728745b
Branch: refs/heads/master
Commit: 2728745be0f1222d84b0230bb5c5576b54765bdb
Parents: f2bd653
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Tue Jan 31 10:27:27 2017 +0000
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Tue Apr 11 14:34:26 2017 +0100
----------------------------------------------------------------------
.../brooklyn/entity/group/SequenceGroup.java | 104 ++++++++++++++++
.../entity/group/SequenceGroupImpl.java | 85 +++++++++++++
.../entity/group/SequenceGroupTest.java | 118 +++++++++++++++++++
3 files changed, 307 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2728745b/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
new file mode 100644
index 0000000..a6dee56
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroup.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.brooklyn.entity.group;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.config.ConfigKey;
+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.Predicates;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * A group that sets a sequence of values as sensors on its member entities
+ * <p>
+ * Usage:
+ * <pre>{@code
+ * - type: org.apache.brooklyn.entity.stock.SequenceGroup
+ * id: entity-sequence
+ * brooklyn.config:
+ * entityFilter:
+ * $brooklyn:object:
+ * type: org.apache.brooklyn.core.entity.EntityPredicates
+ * factoryMethod.name: "applicationIdEqualTo"
+ * factoryMethod.args:
+ * - $brooklyn:attributeWhenReady("application.id")
+ * sequenceStart: 0
+ * sequenceIncrement: 1
+ * sequenceFormat: "entity%04x"
+ * }</pre>
+ */
+@ImplementedBy(SequenceGroupImpl.class)
+public interface SequenceGroup extends DynamicGroup {
+
+ @SetFromFlag("sequenceStart")
+ ConfigKey<Integer> SEQUENCE_START = ConfigKeys.builder(Integer.class)
+ .name("sequence.start")
+ .description("The starting point of the sequence")
+ .defaultValue(1)
+ .constraint(Predicates.<Integer>notNull())
+ .build();
+
+ @SetFromFlag("sequenceIncrement")
+ ConfigKey<Integer> SEQUENCE_INCREMENT = ConfigKeys.builder(Integer.class)
+ .name("sequence.increment")
+ .description("The sequence increment for the next value")
+ .defaultValue(1)
+ .constraint(Predicates.<Integer>notNull())
+ .build();
+
+ @SetFromFlag("sequenceFormat")
+ ConfigKey<String> SEQUENCE_FORMAT = ConfigKeys.builder(String.class)
+ .name("sequence.format")
+ .description("A format used to generate a string representation of the sequence")
+ .defaultValue("%d")
+ .constraint(StringPredicates.containsRegex("%[-#+ 0,(]*[0-9]*[doxX]"))
+ .build();
+
+ AttributeSensor<Integer> SEQUENCE_NEXT = Sensors.builder(Integer.class, "sequence.next")
+ .description("The next value of the sequence")
+ .build();
+
+ AttributeSensor<Map<String, Integer>> SEQUENCE_CACHE = Sensors.builder(new TypeToken<Map<String, Integer>>() { }, "sequence.cache")
+ .description("The current cache of entity ids to sequence numbers")
+ .build();
+
+ MethodEffector<Void> RESET = new MethodEffector<Void>(SequenceEntity.class, "reset");
+
+ @Effector(description = "Reset the sequence to initial value")
+ Void reset();
+
+ AttributeSensor<Integer> SEQUENCE_VALUE = Sensors.builder(Integer.class, "sequence.value")
+ .description("The current value of the sequence")
+ .build();
+
+ AttributeSensor<String> 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/2728745b/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
new file mode 100644
index 0000000..f9fc04e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/SequenceGroupImpl.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.brooklyn.entity.group;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SequenceGroupImpl.class);
+
+ public SequenceGroupImpl() { }
+
+ @Override
+ public Void reset() {
+ synchronized (memberChangeMutex) {
+ sensors().set(SEQUENCE_CACHE, Maps.<String, Integer>newConcurrentMap());
+ Integer initial = config().get(SEQUENCE_START);
+ sensors().set(SEQUENCE_NEXT, initial);
+ return null;
+ }
+ }
+
+ @Override
+ public void rescanEntities() {
+ synchronized (memberChangeMutex) {
+ reset();
+ super.rescanEntities();
+ }
+ }
+
+ @Override
+ public boolean addMember(Entity member) {
+ synchronized (memberChangeMutex) {
+ boolean changed = super.addMember(member);
+ if (changed) {
+ Map<String, Integer> cache = sensors().get(SEQUENCE_CACHE);
+ if (!cache.containsKey(member.getId())) {
+ Integer value = sequence(member);
+ cache.put(member.getId(), value);
+ }
+ }
+ 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);
+
+ entity.sensors().set(SEQUENCE_VALUE, current);
+ entity.sensors().set(SEQUENCE_STRING,string);
+
+ Integer increment = config().get(SEQUENCE_INCREMENT);
+ Integer next = current + increment;
+ LOG.debug("Sequence for {} incremented to {}", this, next);
+
+ sensors().set(SEQUENCE_NEXT, next);
+
+ return current;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2728745b/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
new file mode 100644
index 0000000..afb5425
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/entity/group/SequenceGroupTest.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.brooklyn.entity.group;
+
+import static org.apache.brooklyn.test.Asserts.assertEqualsIgnoringOrder;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+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.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;
+
+import com.google.common.base.Predicates;
+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;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ group = app.createAndManageChild(EntitySpec.create(SequenceGroup.class));
+ e1 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ e2 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ }
+
+ @AfterMethod(alwaysRun=true)
+ @Override
+ public void tearDown() throws Exception {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+
+ super.tearDown();
+ }
+
+ @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);
+ }
+
+ @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);
+ }
+
+ @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() {
+ public void run() {
+ assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e3));
+ EntityAsserts.assertAttributeEquals(e3, SequenceGroup.SEQUENCE_VALUE, 1);
+ EntityAsserts.assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 2);
+ }});
+ }
+
+ @Test
+ 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);
+
+ final Entity e3 = app.addChild(EntitySpec.create(TestEntity.class));
+
+ Asserts.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);
+ }});
+ }
+}
[4/8] brooklyn-server git commit: Simplify and tidy up tests for both
entities
Posted by dr...@apache.org.
Simplify and tidy up tests for both entities
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/68a6f146
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/68a6f146
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/68a6f146
Branch: refs/heads/master
Commit: 68a6f1465b01e6cb49163149af173d4680ac7a7f
Parents: 77d0ddb
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Tue Feb 7 14:26:22 2017 +0000
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Tue Apr 11 14:34:26 2017 +0100
----------------------------------------------------------------------
.../brooklyn/entity/group/SequenceGroup.java | 7 +-
.../entity/group/SequenceGroupImpl.java | 14 ++-
.../brooklyn/entity/stock/SequenceEntity.java | 27 ++----
.../entity/stock/SequenceEntityImpl.java | 28 +-----
.../entity/group/SequenceGroupTest.java | 96 +++++++++++++-------
.../entity/stock/SequenceEntityTest.java | 55 ++++-------
6 files changed, 98 insertions(+), 129 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/68a6f146/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 851d3b7..4d7d082 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
@@ -55,7 +55,7 @@ import com.google.common.reflect.TypeToken;
* - $brooklyn:attributeWhenReady("application.id")
* - $brooklyn:object:
* type: org.apache.brooklyn.core.entity.EntityPredicates
- * factoryMethod.name: "configEquelTo"
+ * factoryMethod.name: "configEqualTo"
* factoryMethod.args:
* - "sequence.set"
* - true
@@ -65,11 +65,6 @@ import com.google.common.reflect.TypeToken;
* sequenceValueSensor: $brooklyn:sensor("entity.sequence")
* sequenceStringSensor: $brooklyn:sensor("entity.name")
* }</pre>
- * <p>
- * <b>IMPORTANT</b> 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 {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/68a6f146/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 fc9c526..0e8c39c 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
@@ -33,6 +33,11 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup
public SequenceGroupImpl() { }
+ public void init() {
+ super.init();
+ reset();
+ }
+
@Override
public Void reset() {
synchronized (memberChangeMutex) {
@@ -45,14 +50,6 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup
}
@Override
- public void rescanEntities() {
- synchronized (memberChangeMutex) {
- reset();
- super.rescanEntities();
- }
- }
-
- @Override
public boolean addMember(Entity member) {
synchronized (memberChangeMutex) {
boolean changed = super.addMember(member);
@@ -96,6 +93,7 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup
entity.sensors().set(valueSensor, current);
entity.sensors().set(stringSensor, string);
+ LOG.debug("Sequence on {} set to to {}", entity, current);
sensors().set(SEQUENCE_CURRENT, entity);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/68a6f146/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
index f53ba65..6b73d8f 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
@@ -28,6 +28,8 @@ import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.entity.group.SequenceGroup;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import com.google.common.base.Supplier;
+
/**
* An entity that supplies a sequence of values through an effector.
* <p>
@@ -38,31 +40,23 @@ import org.apache.brooklyn.util.core.flags.SetFromFlag;
* brooklyn.config:
* sequence.start: 0
* sequence.increment: 1
- * sequence.format: "global-%03d"
* }</pre>
*/
@ImplementedBy(SequenceEntityImpl.class)
-public interface SequenceEntity extends Entity, Startable {
+public interface SequenceEntity extends Entity, Startable, Supplier<Integer> {
AttributeSensor<Integer> SEQUENCE_VALUE = SequenceGroup.SEQUENCE_VALUE;
- AttributeSensor<String> SEQUENCE_STRING = SequenceGroup.SEQUENCE_STRING;
-
@SetFromFlag("sequenceStart")
ConfigKey<Integer> SEQUENCE_START = SequenceGroup.SEQUENCE_START;
@SetFromFlag("sequenceIncrement")
ConfigKey<Integer> SEQUENCE_INCREMENT = SequenceGroup.SEQUENCE_INCREMENT;
- @SetFromFlag("sequenceFormat")
- ConfigKey<String> SEQUENCE_FORMAT = SequenceGroup.SEQUENCE_FORMAT;
-
MethodEffector<Void> RESET = new MethodEffector<Void>(SequenceEntity.class, "reset");
MethodEffector<Void> INCREMENT = new MethodEffector<Void>(SequenceEntity.class, "increment");
- MethodEffector<Integer> CURRENT_VALUE = new MethodEffector<Integer>(SequenceEntity.class, "currentValue");
- MethodEffector<String> CURRENT_STRING = new MethodEffector<String>(SequenceEntity.class, "currentString");
- MethodEffector<Integer> NEXT_VALUE = new MethodEffector<Integer>(SequenceEntity.class, "nextValue");
- MethodEffector<String> NEXT_STRING = new MethodEffector<String>(SequenceEntity.class, "nextString");
+ MethodEffector<Integer> GET = new MethodEffector<Integer>(SequenceEntity.class, "get");
+ MethodEffector<Integer> INCREMENT_AND_GET = new MethodEffector<Integer>(SequenceEntity.class, "incrementAndGet");
@Effector(description = "Reset the sequence to initial value")
Void reset();
@@ -71,14 +65,9 @@ public interface SequenceEntity extends Entity, Startable {
Void increment();
@Effector(description = "Return the current numeric value of the sequence")
- Integer currentValue();
-
- @Effector(description = "Return the current string representation of the sequence")
- String currentString();
+ Integer get();
- @Effector(description = "Update and return the next numeric value of the sequence")
- Integer nextValue();
+ @Effector(description = "Update and return the next value of the sequence")
+ Integer incrementAndGet();
- @Effector(description = "Update and return the next string representation of the sequence")
- String nextString();
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/68a6f146/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
index 0ddb134..b731dfe 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
@@ -52,32 +52,17 @@ public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity
}
@Override
- public Integer currentValue() {
+ public Integer get() {
synchronized (mutex) {
return sensors().get(SEQUENCE_VALUE);
}
}
@Override
- public String currentString() {
- synchronized (mutex) {
- return sensors().get(SEQUENCE_STRING);
- }
- }
-
- @Override
- public Integer nextValue() {
+ public Integer incrementAndGet() {
synchronized (mutex) {
increment();
- return currentValue();
- }
- }
-
- @Override
- public String nextString() {
- synchronized (mutex) {
- increment();
- return currentString();
+ return get();
}
}
@@ -85,7 +70,7 @@ public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity
public Void increment() {
synchronized (mutex) {
Integer increment = config().get(SEQUENCE_INCREMENT);
- Integer current = currentValue();
+ Integer current = get();
sequence(current + increment);
return null;
}
@@ -101,12 +86,7 @@ public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity
}
private void sequence(Integer value) {
- String format = config().get(SEQUENCE_FORMAT);
- String string = String.format(format, value);
-
sensors().set(SEQUENCE_VALUE, value);
- sensors().set(SEQUENCE_STRING, string);
-
LOG.debug("Sequence for {} set to {}", this, value);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/68a6f146/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 148eb5b..d835c7d 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
@@ -18,22 +18,22 @@
*/
package org.apache.brooklyn.entity.group;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttribute;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEquals;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEqualsEventually;
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 static org.apache.brooklyn.test.Asserts.assertTrue;
+import static org.apache.brooklyn.test.Asserts.succeedsEventually;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityPredicates;
+import org.apache.brooklyn.core.location.SimulatedLocation;
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.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -43,7 +43,7 @@ import com.google.common.collect.ImmutableSet;
public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
- private TestApplication app;
+ private SimulatedLocation loc1;
private SequenceGroup group;
private TestEntity e1, e2, e3;
@@ -51,33 +51,35 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
@Override
public void setUp() throws Exception {
super.setUp();
-
- app = TestApplication.Factory.newManagedInstanceForTests();
- 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));
+ loc1 = mgmt.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
}
- @AfterMethod(alwaysRun=true)
- @Override
- public void tearDown() throws Exception {
- if (app != null) Entities.destroyAll(app.getManagementContext());
-
- super.tearDown();
+ protected void createTestEntities() throws Exception {
+ e1 = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("test-one"));
+ e2 = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("test-two"));
+ e3 = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("test-three"));
}
-
@Test
public void testGroupDefaults() throws Exception {
+ group = app.addChild(EntitySpec.create(SequenceGroup.class));
+ createTestEntities();
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(group, SequenceGroup.RUNNING, true);
+
+ assertAttribute(group, SequenceGroup.SEQUENCE_VALUE, Predicates.isNull());
assertTrue(group.getMembers().isEmpty());
}
@Test
public void testGroupWithMatchingFilterReturnsOnlyMatchingMembers() throws Exception {
- group.setEntityFilter(EntityPredicates.idEqualTo(e1.getId()));
+ group = app.addChild(EntitySpec.create(SequenceGroup.class)
+ .configure(SequenceGroup.ENTITY_FILTER, EntityPredicates.displayNameEqualTo("test-one")));
+ createTestEntities();
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(group, SequenceGroup.RUNNING, true);
assertEqualsIgnoringOrder(group.getMembers(), ImmutableList.of(e1));
assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 1);
@@ -86,9 +88,17 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
@Test
public void testGroupConfiguration() throws Exception {
- group.setEntityFilter(EntityPredicates.idEqualTo(e1.getId()));
+ group = app.addChild(EntitySpec.create(SequenceGroup.class)
+ .configure(SequenceGroup.SEQUENCE_STRING_SENSOR, Sensors.newStringSensor("test.sequence"))
+ .configure(SequenceGroup.SEQUENCE_FORMAT, "test-%02d")
+ .configure(SequenceGroup.ENTITY_FILTER, EntityPredicates.displayNameEqualTo("test-one")));
+ createTestEntities();
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(group, SequenceGroup.RUNNING, true);
assertEqualsIgnoringOrder(group.getMembers(), ImmutableList.of(e1));
+ assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 1);
assertAttributeEquals(e1, SequenceGroup.SEQUENCE_STRING, null);
assertAttributeEquals(e1, Sensors.newStringSensor("test.sequence"), "test-01");
}
@@ -97,13 +107,17 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
public void testAlternateGroupConfiguration() throws Exception {
AttributeSensor<Integer> value = Sensors.newIntegerSensor("test.value");
AttributeSensor<String> string = Sensors.newStringSensor("test.string");
- group = app.createAndManageChild(EntitySpec.create(SequenceGroup.class)
+ group = app.addChild(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"));
+ .configure(SequenceGroup.SEQUENCE_FORMAT, "0x%04X")
+ .configure(SequenceGroup.ENTITY_FILTER, EntityPredicates.hasInterfaceMatching(".*TestEntity")));
+ createTestEntities();
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(group, SequenceGroup.RUNNING, true);
assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, e3));
assertAttributeEquals(e1, value, 12345);
@@ -116,7 +130,12 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
@Test
public void testGroupWithMatchingFilterReturnsEverythingThatMatches() throws Exception {
- group.setEntityFilter(Predicates.alwaysTrue());
+ group = app.addChild(EntitySpec.create(SequenceGroup.class)
+ .configure(SequenceGroup.ENTITY_FILTER, Predicates.alwaysTrue()));
+ createTestEntities();
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(group, SequenceGroup.RUNNING, true);
assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, e3, app, group));
assertAttributeEquals(app, SequenceGroup.SEQUENCE_VALUE, 1);
@@ -130,8 +149,14 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
@Test
public void testGroupDetectsNewlyManagedMatchingMember() throws Exception {
- group.setEntityFilter(EntityPredicates.displayNameEqualTo("myname"));
- final Entity e = app.addChild(EntitySpec.create(TestEntity.class).displayName("myname"));
+ group = app.addChild(EntitySpec.create(SequenceGroup.class)
+ .configure(SequenceGroup.ENTITY_FILTER, EntityPredicates.displayNameEqualTo("test-four")));
+ createTestEntities();
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(group, SequenceGroup.RUNNING, true);
+
+ final Entity e = app.addChild(EntitySpec.create(TestEntity.class).displayName("test-four"));
succeedsEventually(new Runnable() {
public void run() {
@@ -142,8 +167,13 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
}
@Test
- public void testGroupUsesNewFilter() throws Exception {
- group.setEntityFilter(EntityPredicates.hasInterfaceMatching(".*TestEntity"));
+ public void testGroupAddsNewMatchingMember() throws Exception {
+ group = app.addChild(EntitySpec.create(SequenceGroup.class)
+ .configure(SequenceGroup.ENTITY_FILTER, EntityPredicates.hasInterfaceMatching(".*TestEntity")));
+ createTestEntities();
+ app.start(ImmutableList.of(loc1));
+
+ assertAttributeEqualsEventually(group, SequenceGroup.RUNNING, true);
assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e1, e2, e3));
assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 1);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/68a6f146/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 2ec8a79..c4b3b86 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
@@ -55,20 +55,17 @@ public class SequenceEntityTest extends BrooklynAppUnitTestSupport {
assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 0);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "0");
}
@Test
public void testSequenceInitialConfig() throws Exception {
sequence = app.addChild(EntitySpec.create(SequenceEntity.class)
- .configure(SequenceEntity.SEQUENCE_START, 42)
- .configure(SequenceEntity.SEQUENCE_FORMAT, "id-%02x"));
+ .configure(SequenceEntity.SEQUENCE_START, 42));
app.start(ImmutableList.of(loc1));
assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 42);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "id-2a");
}
@Test
@@ -78,54 +75,41 @@ public class SequenceEntityTest extends BrooklynAppUnitTestSupport {
EntityAsserts.assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
- assertEquals(sequence.currentValue(), Integer.valueOf(1));
- assertEquals(sequence.currentString(), "1");
+ assertEquals(sequence.get(), Integer.valueOf(1));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 1);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "1");
sequence.increment();
- assertEquals(sequence.currentValue(), Integer.valueOf(2));
- assertEquals(sequence.currentString(), "2");
+ assertEquals(sequence.get(), Integer.valueOf(2));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 2);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "2");
sequence.invoke(SequenceEntity.INCREMENT, ImmutableMap.<String, Object>of()).getUnchecked();
- assertEquals(sequence.currentValue(), Integer.valueOf(3));
- assertEquals(sequence.currentString(), "3");
+ assertEquals(sequence.get(), Integer.valueOf(3));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 3);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "3");
}
@Test
public void testSequenceIncrementEffectorConfig() throws Exception {
sequence = app.addChild(EntitySpec.create(SequenceEntity.class)
.configure(SequenceEntity.SEQUENCE_START, 0)
- .configure(SequenceEntity.SEQUENCE_INCREMENT, 2)
- .configure(SequenceEntity.SEQUENCE_FORMAT, "%03d"));
+ .configure(SequenceEntity.SEQUENCE_INCREMENT, 2));
app.start(ImmutableList.of(loc1));
EntityAsserts.assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
- assertEquals(sequence.currentValue(), Integer.valueOf(0));
- assertEquals(sequence.currentString(), "000");
+ assertEquals(sequence.get(), Integer.valueOf(0));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 0);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "000");
sequence.increment();
- assertEquals(sequence.currentValue(), Integer.valueOf(2));
- assertEquals(sequence.currentString(), "002");
+ assertEquals(sequence.get(), Integer.valueOf(2));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 2);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "002");
sequence.invoke(SequenceEntity.INCREMENT, ImmutableMap.<String, Object>of()).getUnchecked();
- assertEquals(sequence.currentValue(), Integer.valueOf(4));
- assertEquals(sequence.currentString(), "004");
+ assertEquals(sequence.get(), Integer.valueOf(4));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 4);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "004");
}
@Test
@@ -135,19 +119,16 @@ public class SequenceEntityTest extends BrooklynAppUnitTestSupport {
assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
- assertEquals(sequence.currentValue(), Integer.valueOf(1));
- assertEquals(sequence.currentString(), "1");
+ assertEquals(sequence.get(), Integer.valueOf(1));
- Integer nextValue = sequence.invoke(SequenceEntity.NEXT_VALUE, ImmutableMap.<String, Object>of()).getUnchecked();
+ Integer nextValue = sequence.invoke(SequenceEntity.INCREMENT_AND_GET, ImmutableMap.<String, Object>of()).getUnchecked();
assertEquals(nextValue, Integer.valueOf(2));
- String nextString = sequence.invoke(SequenceEntity.NEXT_STRING, ImmutableMap.<String, Object>of()).getUnchecked();
- assertEquals(nextString, "3");
+ nextValue = sequence.invoke(SequenceEntity.INCREMENT_AND_GET, ImmutableMap.<String, Object>of()).getUnchecked();
+ assertEquals(nextValue, Integer.valueOf(3));
- assertEquals(sequence.currentValue(), Integer.valueOf(3));
- assertEquals(sequence.currentString(), "3");
+ assertEquals(sequence.get(), Integer.valueOf(3));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 3);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "3");
}
@Test
@@ -157,23 +138,19 @@ public class SequenceEntityTest extends BrooklynAppUnitTestSupport {
assertAttributeEqualsEventually(sequence, Startable.SERVICE_UP, true);
- assertEquals(sequence.currentValue(), Integer.valueOf(1));
+ assertEquals(sequence.get(), Integer.valueOf(1));
sequence.increment();
sequence.increment();
sequence.increment();
- assertEquals(sequence.currentValue(), Integer.valueOf(4));
- assertEquals(sequence.currentString(), "4");
+ assertEquals(sequence.get(), Integer.valueOf(4));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 4);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "4");
sequence.invoke(SequenceEntity.RESET, ImmutableMap.<String, Object>of()).getUnchecked();
- assertEquals(sequence.currentValue(), Integer.valueOf(1));
- assertEquals(sequence.currentString(), "1");
+ assertEquals(sequence.get(), Integer.valueOf(1));
assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_VALUE, 1);
- assertAttributeEquals(sequence, SequenceEntity.SEQUENCE_STRING, "1");
}
}
[7/8] brooklyn-server git commit: Formatting
Posted by dr...@apache.org.
Formatting
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/62989ac9
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/62989ac9
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/62989ac9
Branch: refs/heads/master
Commit: 62989ac9d615d89d0e95e44fe6f772b116a9aaf8
Parents: ff6e7a3
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Tue Feb 28 14:20:44 2017 +0000
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Tue Apr 11 14:34:27 2017 +0100
----------------------------------------------------------------------
.../entity/lifecycle/ServiceStateLogic.java | 150 ++++++++++++-------
1 file changed, 95 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62989ac9/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java b/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java
index 21d8b58..386eb56 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/lifecycle/ServiceStateLogic.java
@@ -50,6 +50,7 @@ import org.apache.brooklyn.core.entity.EntityAdjuncts;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.entity.EntityPredicates;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle.Transition;
+import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.enricher.stock.AbstractMultipleSensorAggregator;
import org.apache.brooklyn.enricher.stock.Enrichers;
import org.apache.brooklyn.enricher.stock.UpdatingMap;
@@ -58,6 +59,7 @@ import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.collections.QuorumCheck;
+import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
import org.apache.brooklyn.util.core.task.ValueResolver;
import org.apache.brooklyn.util.guava.Functionals;
import org.apache.brooklyn.util.guava.Maybe;
@@ -77,15 +79,15 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
-/** Logic, sensors and enrichers, and conveniences, for computing service status */
+/** Logic, sensors and enrichers, and conveniences, for computing service status */
public class ServiceStateLogic {
private static final Logger log = LoggerFactory.getLogger(ServiceStateLogic.class);
-
+
public static final AttributeSensor<Boolean> SERVICE_UP = Attributes.SERVICE_UP;
public static final AttributeSensor<Map<String,Object>> SERVICE_NOT_UP_INDICATORS = Attributes.SERVICE_NOT_UP_INDICATORS;
public static final AttributeSensor<Map<String,Object>> SERVICE_NOT_UP_DIAGNOSTICS = Attributes.SERVICE_NOT_UP_DIAGNOSTICS;
-
+
public static final AttributeSensor<Lifecycle> SERVICE_STATE_ACTUAL = Attributes.SERVICE_STATE_ACTUAL;
public static final AttributeSensor<Lifecycle.Transition> SERVICE_STATE_EXPECTED = Attributes.SERVICE_STATE_EXPECTED;
public static final AttributeSensor<Map<String,Object>> SERVICE_PROBLEMS = Attributes.SERVICE_PROBLEMS;
@@ -98,7 +100,7 @@ public class ServiceStateLogic {
if (map==null) return null;
return map.get(key);
}
-
+
@SuppressWarnings("unchecked")
public static <TKey,TVal> void clearMapSensorEntry(Entity entity, AttributeSensor<Map<TKey,TVal>> sensor, TKey key) {
updateMapSensorEntry(entity, sensor, key, (TVal)Entities.REMOVE);
@@ -109,9 +111,9 @@ public class ServiceStateLogic {
/*
* Important to *not* modify the existing attribute value; must make a copy, modify that, and publish.
* This is because a Propagator enricher will set this same value on another entity. There was very
- * strange behaviour when this was done for a SERVICE_UP_INDICATORS sensor - the updates done here
+ * strange behaviour when this was done for a SERVICE_UP_INDICATORS sensor - the updates done here
* applied to the attribute of both entities!
- *
+ *
* Need to do this update atomically (i.e. sequentially) because there is no threading control for
* what is calling updateMapSensorEntity. It is called directly on start, on initialising enrichers,
* and in event listeners. These calls could be concurrent.
@@ -120,7 +122,7 @@ public class ServiceStateLogic {
@Override public Maybe<Map<TKey, TVal>> apply(Map<TKey, TVal> map) {
boolean created = (map==null);
if (created) map = MutableMap.of();
-
+
boolean changed;
if (v == Entities.REMOVE) {
changed = map.containsKey(key);
@@ -147,22 +149,22 @@ public class ServiceStateLogic {
}
}
};
-
- if (!Entities.isNoLongerManaged(entity)) {
+
+ if (!Entities.isNoLongerManaged(entity)) {
entity.sensors().modify(sensor, modifier);
}
}
-
+
public static void setExpectedState(Entity entity, Lifecycle state) {
waitBrieflyForServiceUpIfStateIsRunning(entity, state);
((EntityInternal)entity).sensors().set(Attributes.SERVICE_STATE_EXPECTED, new Lifecycle.Transition(state, new Date()));
-
+
Maybe<Enricher> enricher = EntityAdjuncts.tryFindWithUniqueTag(entity.enrichers(), ComputeServiceState.DEFAULT_ENRICHER_UNIQUE_TAG);
if (enricher.isPresent() && enricher.get() instanceof ComputeServiceState) {
((ComputeServiceState)enricher.get()).onEvent(null);
}
}
-
+
public static Lifecycle getExpectedState(Entity entity) {
Transition expected = entity.getAttribute(Attributes.SERVICE_STATE_EXPECTED);
if (expected==null) return null;
@@ -197,13 +199,13 @@ public class ServiceStateLogic {
public static boolean isExpectedState(Entity entity, Lifecycle state) {
return getExpectedState(entity)==state;
}
-
+
public static class ServiceNotUpLogic {
public static final String DEFAULT_ENRICHER_UNIQUE_TAG = "service.isUp if no service.notUp.indicators";
-
+
/** static only; not for instantiation */
private ServiceNotUpLogic() {}
-
+
public static final EnricherSpec<?> newEnricherForServiceUpIfNotUpIndicatorsEmpty() {
// The function means: if the serviceNotUpIndicators is not null, then serviceNotUpIndicators.size()==0;
// otherwise return the default value.
@@ -217,8 +219,8 @@ public class ServiceStateLogic {
.uniqueTag(DEFAULT_ENRICHER_UNIQUE_TAG)
.build();
}
-
- /** puts the given value into the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map as if the
+
+ /** puts the given value into the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map as if the
* {@link UpdatingMap} enricher for the given key */
public static void updateNotUpIndicator(Entity entity, String key, Object value) {
updateMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, key, value);
@@ -246,17 +248,17 @@ public class ServiceStateLogic {
if (nodes==null || nodes.isEmpty()) ServiceNotUpLogic.updateNotUpIndicator(entity, mapSensor, "Should have at least one entry");
else ServiceNotUpLogic.clearNotUpIndicator(entity, mapSensor);
}
-
+
}
-
- /** Enricher which sets {@link Attributes#SERVICE_STATE_ACTUAL} on changes to
+
+ /** Enricher which sets {@link Attributes#SERVICE_STATE_ACTUAL} on changes to
* {@link Attributes#SERVICE_STATE_EXPECTED}, {@link Attributes#SERVICE_PROBLEMS}, and {@link Attributes#SERVICE_UP}
* <p>
* The default implementation uses {@link #computeActualStateWhenExpectedRunning(Map, Boolean)} if the last expected transition
- * was to {@link Lifecycle#RUNNING} and
+ * was to {@link Lifecycle#RUNNING} and
* {@link #computeActualStateWhenNotExpectedRunning(Map, Boolean, org.apache.brooklyn.core.entity.lifecycle.Lifecycle.Transition)} otherwise.
* If these methods return null, the {@link Attributes#SERVICE_STATE_ACTUAL} sensor will be cleared (removed).
- * Either of these methods can be overridden for custom logic, and that custom enricher can be created using
+ * Either of these methods can be overridden for custom logic, and that custom enricher can be created using
* {@link ServiceStateLogic#newEnricherForServiceState(Class)} and added to an entity.
*/
public static class ComputeServiceState extends AbstractEnricher implements SensorEventListener<Object> {
@@ -267,13 +269,13 @@ public class ServiceStateLogic {
public ComputeServiceState() {}
public ComputeServiceState(Map<?,?> flags) { super(flags); }
-
+
@Override
public void init() {
super.init();
if (uniqueTag==null) uniqueTag = DEFAULT_ENRICHER_UNIQUE_TAG;
}
-
+
@Override
public void setEntity(EntityLocal entity) {
super.setEntity(entity);
@@ -281,7 +283,7 @@ public class ServiceStateLogic {
// only publish on changes, unless it is configured otherwise
suppressDuplicates = true;
}
-
+
Map<String, ?> notifyOfInitialValue = ImmutableMap.of("notifyOfInitialValue", Boolean.TRUE);
subscriptions().subscribe(notifyOfInitialValue, entity, SERVICE_PROBLEMS, this);
subscriptions().subscribe(notifyOfInitialValue, entity, SERVICE_UP, this);
@@ -291,11 +293,11 @@ public class ServiceStateLogic {
@Override
public void onEvent(@Nullable SensorEvent<Object> event) {
Preconditions.checkNotNull(entity, "Cannot handle subscriptions or compute state until associated with an entity");
-
+
Map<String, Object> serviceProblems = entity.getAttribute(SERVICE_PROBLEMS);
Boolean serviceUp = entity.getAttribute(SERVICE_UP);
Lifecycle.Transition serviceExpected = entity.getAttribute(SERVICE_STATE_EXPECTED);
-
+
if (serviceExpected!=null && serviceExpected.getState()==Lifecycle.RUNNING) {
setActualState( computeActualStateWhenExpectedRunning(serviceProblems, serviceUp) );
} else {
@@ -315,12 +317,12 @@ public class ServiceStateLogic {
return Maybe.of(Lifecycle.ON_FIRE);
}
}
-
+
protected Maybe<Lifecycle> computeActualStateWhenNotExpectedRunning(Map<String, Object> problems, Boolean up, Lifecycle.Transition stateTransition) {
if (stateTransition!=null) {
// if expected state is present but not running, just echo the expected state (ignore problems and up-ness)
return Maybe.of(stateTransition.getState());
-
+
} else if (problems!=null && !problems.isEmpty()) {
// if there is no expected state, then if service is not up, say stopped, else say on fire (whether service up is true or not present)
if (Boolean.FALSE.equals(up)) {
@@ -335,7 +337,7 @@ public class ServiceStateLogic {
// if the problems map is non-null, then infer from service up;
// if there is no problems map, then leave unchanged (user may have set it explicitly)
if (problems!=null)
- return Maybe.of(up==null ? null /* remove if up is not set */ :
+ return Maybe.of(up==null ? null /* remove if up is not set */ :
(up ? Lifecycle.RUNNING : Lifecycle.STOPPED));
else
return Maybe.absent();
@@ -355,19 +357,57 @@ public class ServiceStateLogic {
}
}
-
+
public static final EnricherSpec<?> newEnricherForServiceStateFromProblemsAndUp() {
return newEnricherForServiceState(ComputeServiceState.class);
}
public static final EnricherSpec<?> newEnricherForServiceState(Class<? extends Enricher> type) {
+ newEnricherForServiceUpFromChildren();
return EnricherSpec.create(type);
}
-
+
+ /**
+ * An enricher that sets {@link Startable#SERVICE_UP servive.isUp} on an entity only when all children are
+ * also reporting as healthy.
+ * <p>
+ * Equivalent to the following YAML configuration.
+ * <pre>
+ * brooklyn.enrichers:
+ * - type: org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic$ComputeServiceIndicatorsFromChildrenAndMembers
+ * brooklyn.config:
+ * enricher.aggregating.fromChildren: true
+ * enricher.aggregating.fromMembers: false
+ * enricher.suppressDuplicates: true
+ * enricher.service_state.children_and_members.quorum.up: all
+ * enricher.service_state.children_and_members.ignore_entities.service_state_values: [ "STOPPING", "STOPPED", "DESTROYED" ]
+ * </pre>
+ */
+ public static final EnricherSpec<?> newEnricherForServiceUpFromChildren() {
+ return newEnricherForServiceUp(Boolean.TRUE, Boolean.FALSE);
+ }
+ public static final EnricherSpec<?> newEnricherForServiceUpFromMembers() {
+ return newEnricherForServiceUp(Boolean.FALSE, Boolean.TRUE);
+ }
+ public static final EnricherSpec<?> newEnricherForServiceUpFromChildrenWithQuorumCheck(QuorumCheck quorumCheck) {
+ EnricherSpec<?> serviceUp = newEnricherForServiceUpFromChildren()
+ .configure(ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK, quorumCheck);
+ return serviceUp;
+ }
+ public static final EnricherSpec<?> newEnricherForServiceUp(Boolean fromChildren, Boolean fromMembers) {
+ EnricherSpec<?> serviceUp = EnricherSpec.create(ComputeServiceIndicatorsFromChildrenAndMembers.class)
+ .configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_CHILDREN, fromChildren)
+ .configure(ComputeServiceIndicatorsFromChildrenAndMembers.FROM_MEMBERS, fromMembers)
+ .configure(ComputeServiceIndicatorsFromChildrenAndMembers.SUPPRESS_DUPLICATES, Boolean.TRUE)
+ .configure(ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK, QuorumChecks.all())
+ .configure(ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES, ImmutableSet.of(Lifecycle.STOPPING, Lifecycle.STOPPED, Lifecycle.DESTROYED));
+ return serviceUp;
+ }
+
public static class ServiceProblemsLogic {
/** static only; not for instantiation */
private ServiceProblemsLogic() {}
-
- /** puts the given value into the {@link Attributes#SERVICE_PROBLEMS} map as if the
+
+ /** puts the given value into the {@link Attributes#SERVICE_PROBLEMS} map as if the
* {@link UpdatingMap} enricher for the given sensor reported this value */
public static void updateProblemsIndicator(Entity entity, Sensor<?> sensor, Object value) {
updateMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, sensor.getName(), value);
@@ -393,11 +433,11 @@ public class ServiceStateLogic {
clearMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, key);
}
}
-
+
public static class ComputeServiceIndicatorsFromChildrenAndMembers extends AbstractMultipleSensorAggregator<Void> implements SensorEventListener<Object> {
/** standard unique tag identifying instances of this enricher at runtime, also used for the map sensor if no unique tag specified */
public final static String DEFAULT_UNIQUE_TAG = "service-lifecycle-indicators-from-children-and-members";
-
+
/** as {@link #DEFAULT_UNIQUE_TAG}, but when a second distinct instance is responsible for computing service up */
public final static String DEFAULT_UNIQUE_TAG_UP = "service-not-up-indicators-from-children-and-members";
@@ -406,7 +446,7 @@ public class ServiceStateLogic {
.defaultValue(QuorumCheck.QuorumChecks.atLeastOneUnlessEmpty())
.runtimeInheritance(BasicConfigInheritance.NOT_REINHERITED)
.build();
- public static final ConfigKey<QuorumCheck> RUNNING_QUORUM_CHECK = ConfigKeys.builder(QuorumCheck.class, "enricher.service_state.children_and_members.quorum.running")
+ public static final ConfigKey<QuorumCheck> RUNNING_QUORUM_CHECK = ConfigKeys.builder(QuorumCheck.class, "enricher.service_state.children_and_members.quorum.running")
.description("Logic for checking whether this service is healthy, based on children and/or members running, defaulting to requiring none to be ON-FIRE")
.defaultValue(QuorumCheck.QuorumChecks.all())
.runtimeInheritance(BasicConfigInheritance.NOT_REINHERITED)
@@ -417,8 +457,8 @@ public class ServiceStateLogic {
public static final ConfigKey<Boolean> IGNORE_ENTITIES_WITH_SERVICE_UP_NULL = ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.ignore_entities.service_up_null", "Whether to ignore children reporting null values for service up", true);
@SuppressWarnings("serial")
public static final ConfigKey<Set<Lifecycle>> IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES = ConfigKeys.newConfigKey(new TypeToken<Set<Lifecycle>>() {},
- "enricher.service_state.children_and_members.ignore_entities.service_state_values",
- "Service states (including null) which indicate an entity should be ignored when looking at children service states; anything apart from RUNNING not in this list will be treated as not healthy (by default just ON_FIRE will mean not healthy)",
+ "enricher.service_state.children_and_members.ignore_entities.service_state_values",
+ "Service states (including null) which indicate an entity should be ignored when looking at children service states; anything apart from RUNNING not in this list will be treated as not healthy (by default just ON_FIRE will mean not healthy)",
MutableSet.<Lifecycle>builder().addAll(Lifecycle.values()).add(null).remove(Lifecycle.RUNNING).remove(Lifecycle.ON_FIRE).build().asUnmodifiable());
protected String getKeyForMapSensor() {
@@ -455,9 +495,9 @@ public class ServiceStateLogic {
final static Set<ConfigKey<?>> RECONFIGURABLE_KEYS = ImmutableSet.<ConfigKey<?>>of(
UP_QUORUM_CHECK, RUNNING_QUORUM_CHECK,
- DERIVE_SERVICE_NOT_UP, DERIVE_SERVICE_NOT_UP,
+ DERIVE_SERVICE_NOT_UP, DERIVE_SERVICE_NOT_UP,
IGNORE_ENTITIES_WITH_SERVICE_UP_NULL, IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES);
-
+
@Override
protected <T> void doReconfigureConfig(ConfigKey<T> key, T val) {
if (RECONFIGURABLE_KEYS.contains(key)) {
@@ -466,14 +506,14 @@ public class ServiceStateLogic {
super.doReconfigureConfig(key, val);
}
}
-
+
@Override
protected void onChanged() {
super.onChanged();
if (entity != null && isRunning())
onUpdated();
}
-
+
private final List<Sensor<?>> SOURCE_SENSORS = ImmutableList.<Sensor<?>>of(SERVICE_UP, SERVICE_STATE_ACTUAL);
@Override
protected Collection<Sensor<?>> getSourceSensors() {
@@ -511,7 +551,7 @@ public class ServiceStateLogic {
continue;
entries++;
Lifecycle entityState = state.getKey().getAttribute(SERVICE_STATE_ACTUAL);
-
+
if (Boolean.TRUE.equals(state.getValue())) numUp++;
else if (!ignoreStates.contains(entityState)) {
violators.add(state.getKey());
@@ -544,7 +584,7 @@ public class ServiceStateLogic {
Set<Lifecycle> ignoreStates = getConfig(IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES);
for (Map.Entry<Entity,Lifecycle> state: values.entrySet()) {
if (state.getValue()==Lifecycle.RUNNING) numRunning++;
- else if (!ignoreStates.contains(state.getValue()))
+ else if (!ignoreStates.contains(state.getValue()))
onesNotHealthy.add(state.getKey());
}
@@ -582,14 +622,14 @@ public class ServiceStateLogic {
return null;
}
}
-
+
public static class ComputeServiceIndicatorsFromChildrenAndMembersSpec extends ExtensibleEnricherSpec<ComputeServiceIndicatorsFromChildrenAndMembers,ComputeServiceIndicatorsFromChildrenAndMembersSpec> {
private static final long serialVersionUID = -607444925297963712L;
-
+
protected ComputeServiceIndicatorsFromChildrenAndMembersSpec() {
this(ComputeServiceIndicatorsFromChildrenAndMembers.class);
}
-
+
protected ComputeServiceIndicatorsFromChildrenAndMembersSpec(Class<? extends ComputeServiceIndicatorsFromChildrenAndMembers> clazz) {
super(clazz);
}
@@ -626,14 +666,14 @@ public class ServiceStateLogic {
configure(ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK, check);
return self();
}
-
+
public ComputeServiceIndicatorsFromChildrenAndMembersSpec entityFilter(Predicate<? super Entity> val) {
configure(ComputeServiceIndicatorsFromChildrenAndMembers.ENTITY_FILTER, val);
return self();
}
}
- /** provides the default {@link ComputeServiceIndicatorsFromChildrenAndMembers} enricher,
+ /** provides the default {@link ComputeServiceIndicatorsFromChildrenAndMembers} enricher,
* using the default unique tag ({@link ComputeServiceIndicatorsFromChildrenAndMembers#DEFAULT_UNIQUE_TAG}),
* configured here to require none on fire, and either no children or at least one up child,
* the spec can be further configured as appropriate */
@@ -642,10 +682,10 @@ public class ServiceStateLogic {
.uniqueTag(ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG);
}
- /** as {@link #newEnricherFromChildren()} but only publishing service not-up indicators,
+ /** as {@link #newEnricherFromChildren()} but only publishing service not-up indicators,
* using a different unique tag ({@link ComputeServiceIndicatorsFromChildrenAndMembers#DEFAULT_UNIQUE_TAG_UP}),
* listening to children only, ignoring lifecycle/service-state,
- * and using the same logic
+ * and using the same logic
* (viz looking only at children (not members) and requiring either no children or at least one child up) by default */
public static ComputeServiceIndicatorsFromChildrenAndMembersSpec newEnricherFromChildrenUp() {
return newEnricherFromChildren()
@@ -653,14 +693,14 @@ public class ServiceStateLogic {
.checkChildrenOnly()
.configure(ComputeServiceIndicatorsFromChildrenAndMembers.DERIVE_SERVICE_PROBLEMS, false);
}
-
+
/** as {@link #newEnricherFromChildren()} but only publishing service problems,
* listening to children and members, ignoring service up,
- * and using the same logic
+ * and using the same logic
* (viz looking at children and members and requiring none are on fire) by default */
public static ComputeServiceIndicatorsFromChildrenAndMembersSpec newEnricherFromChildrenState() {
return newEnricherFromChildren()
.configure(ComputeServiceIndicatorsFromChildrenAndMembers.DERIVE_SERVICE_NOT_UP, false);
}
-
+
}
[5/8] brooklyn-server git commit: Use configuration definitions from
SequenceGroup and add local mutex
Posted by dr...@apache.org.
Use configuration definitions from SequenceGroup and add local mutex
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/77d0ddb7
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/77d0ddb7
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/77d0ddb7
Branch: refs/heads/master
Commit: 77d0ddb7336e60dcf9ed9b1f3085c422c6811a3f
Parents: a5aff68
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Tue Feb 7 09:44:37 2017 +0000
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Tue Apr 11 14:34:26 2017 +0100
----------------------------------------------------------------------
.../brooklyn/entity/stock/SequenceEntity.java | 44 +++---------
.../entity/stock/SequenceEntityImpl.java | 74 ++++++++++++--------
2 files changed, 52 insertions(+), 66 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/77d0ddb7/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
index 5135f3c..f53ba65 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
@@ -23,15 +23,10 @@ import org.apache.brooklyn.api.entity.ImplementedBy;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.config.ConfigKey;
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.entity.trait.Startable;
-import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
-import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.group.SequenceGroup;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
-import org.apache.brooklyn.util.text.StringPredicates;
-
-import com.google.common.base.Predicates;
/**
* An entity that supplies a sequence of values through an effector.
@@ -44,46 +39,23 @@ import com.google.common.base.Predicates;
* sequence.start: 0
* sequence.increment: 1
* sequence.format: "global-%03d"
- * sequence.name: "global"
* }</pre>
*/
@ImplementedBy(SequenceEntityImpl.class)
public interface SequenceEntity extends Entity, Startable {
+ AttributeSensor<Integer> SEQUENCE_VALUE = SequenceGroup.SEQUENCE_VALUE;
+
+ AttributeSensor<String> SEQUENCE_STRING = SequenceGroup.SEQUENCE_STRING;
+
@SetFromFlag("sequenceStart")
- ConfigKey<Integer> SEQUENCE_START = ConfigKeys.builder(Integer.class)
- .name("sequence.start")
- .description("The starting point of the sequence")
- .defaultValue(1)
- .constraint(Predicates.<Integer>notNull())
- .build();
+ ConfigKey<Integer> SEQUENCE_START = SequenceGroup.SEQUENCE_START;
@SetFromFlag("sequenceIncrement")
- ConfigKey<Integer> SEQUENCE_INCREMENT = ConfigKeys.builder(Integer.class)
- .name("sequence.increment")
- .description("The sequence increment for the next value")
- .defaultValue(1)
- .constraint(Predicates.<Integer>notNull())
- .build();
+ ConfigKey<Integer> SEQUENCE_INCREMENT = SequenceGroup.SEQUENCE_INCREMENT;
@SetFromFlag("sequenceFormat")
- ConfigKey<String> SEQUENCE_FORMAT = ConfigKeys.builder(String.class)
- .name("sequence.format")
- .description("A format used to generate a string representation of the sequence")
- .defaultValue("%d")
- .constraint(StringPredicates.containsRegex("%[-#+ 0,(]*[0-9]*[doxX]"))
- .build();
-
- @SetFromFlag("sequenceName")
- AttributeSensorAndConfigKey<String, String> SEQUENCE_NAME = ConfigKeys.newStringSensorAndConfigKey("sequence.name", "The name of the sequence", "sequence");
-
- AttributeSensor<Integer> SEQUENCE_VALUE = Sensors.builder(Integer.class, "sequence.value")
- .description("The current value of the sequence")
- .build();
-
- AttributeSensor<String> SEQUENCE_STRING = Sensors.builder(String.class, "sequence.string")
- .description("The current value of the sequence formatted as a string")
- .build();
+ ConfigKey<String> SEQUENCE_FORMAT = SequenceGroup.SEQUENCE_FORMAT;
MethodEffector<Void> RESET = new MethodEffector<Void>(SequenceEntity.class, "reset");
MethodEffector<Void> INCREMENT = new MethodEffector<Void>(SequenceEntity.class, "increment");
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/77d0ddb7/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
index 338b323..0ddb134 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
@@ -22,17 +22,16 @@ import java.util.Collection;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.core.entity.AbstractEntity;
-import org.apache.brooklyn.core.feed.ConfigToAttributes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity {
- public SequenceEntityImpl() { }
+ private static final Logger LOG = LoggerFactory.getLogger(SequenceEntity.class);
- public void init() {
- super.init();
+ private Object mutex = new Object();
- ConfigToAttributes.apply(this, SEQUENCE_NAME);
- }
+ public SequenceEntityImpl() { }
@Override
public void start(Collection<? extends Location> locations) {
@@ -52,48 +51,63 @@ public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity
start(getLocations());
}
- protected void sequence(Integer value) {
- String format = config().get(SEQUENCE_FORMAT);
-
- sensors().set(SEQUENCE_VALUE, value);
- sensors().set(SEQUENCE_STRING, String.format(format, value));
- }
-
@Override
public Integer currentValue() {
- return sensors().get(SEQUENCE_VALUE);
+ synchronized (mutex) {
+ return sensors().get(SEQUENCE_VALUE);
+ }
}
@Override
public String currentString() {
- return sensors().get(SEQUENCE_STRING);
+ synchronized (mutex) {
+ return sensors().get(SEQUENCE_STRING);
+ }
}
@Override
- public synchronized Integer nextValue() {
- increment();
- return currentValue();
+ public Integer nextValue() {
+ synchronized (mutex) {
+ increment();
+ return currentValue();
+ }
}
@Override
- public synchronized String nextString() {
- increment();
- return currentString();
+ public String nextString() {
+ synchronized (mutex) {
+ increment();
+ return currentString();
+ }
}
@Override
- public synchronized Void increment() {
- Integer increment = config().get(SEQUENCE_INCREMENT);
- Integer current = currentValue();
- sequence(current + increment);
- return null;
+ public Void increment() {
+ synchronized (mutex) {
+ Integer increment = config().get(SEQUENCE_INCREMENT);
+ Integer current = currentValue();
+ sequence(current + increment);
+ return null;
+ }
}
@Override
- public synchronized Void reset() {
- Integer start = config().get(SEQUENCE_START);
- sequence(start);
- return null;
+ public Void reset() {
+ synchronized (mutex) {
+ Integer start = config().get(SEQUENCE_START);
+ sequence(start);
+ return null;
+ }
+ }
+
+ private void sequence(Integer value) {
+ String format = config().get(SEQUENCE_FORMAT);
+ String string = String.format(format, value);
+
+ sensors().set(SEQUENCE_VALUE, value);
+ sensors().set(SEQUENCE_STRING, string);
+
+ LOG.debug("Sequence for {} set to {}", this, value);
}
}
[6/8] brooklyn-server git commit: Use AtomicIntegers for internal
sequencer state
Posted by dr...@apache.org.
Use AtomicIntegers for internal sequencer state
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/ff6e7a37
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/ff6e7a37
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/ff6e7a37
Branch: refs/heads/master
Commit: ff6e7a376a135ffd2e8e672d25bacefdb662b594
Parents: 68a6f14
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Wed Feb 8 19:47:11 2017 +0000
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Tue Apr 11 14:34:27 2017 +0100
----------------------------------------------------------------------
.../brooklyn/entity/group/SequenceGroup.java | 5 +++--
.../entity/group/SequenceGroupImpl.java | 16 ++++++++--------
.../brooklyn/entity/stock/SequenceEntity.java | 4 ++++
.../entity/stock/SequenceEntityImpl.java | 20 ++++++++++++--------
.../entity/group/SequenceGroupTest.java | 19 +++++++++++++------
.../entity/stock/SequenceEntityTest.java | 2 +-
6 files changed, 41 insertions(+), 25 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ff6e7a37/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 4d7d082..170e90d 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
@@ -19,6 +19,7 @@
package org.apache.brooklyn.entity.group;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ImplementedBy;
@@ -123,8 +124,8 @@ public interface SequenceGroup extends DynamicGroup {
.description("The current entity in the sequence")
.build();
- AttributeSensor<Integer> SEQUENCE_NEXT = Sensors.builder(Integer.class, "sequence.next")
- .description("The next value of the sequence")
+ AttributeSensor<AtomicInteger> SEQUENCE_STATE = Sensors.builder(AtomicInteger.class, "sequence.state")
+ .description("The current state of the sequence")
.build();
AttributeSensor<Map<String, Integer>> SEQUENCE_CACHE = Sensors.builder(new TypeToken<Map<String, Integer>>() { }, "sequence.cache")
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ff6e7a37/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 0e8c39c..6aca7af 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
@@ -19,6 +19,7 @@
package org.apache.brooklyn.entity.group;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.sensor.AttributeSensor;
@@ -44,7 +45,8 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup
sensors().set(SEQUENCE_CACHE, Maps.<String, Integer>newConcurrentMap());
sensors().set(SEQUENCE_CURRENT, null);
Integer initial = config().get(SEQUENCE_START);
- sensors().set(SEQUENCE_NEXT, initial);
+ AtomicInteger state = new AtomicInteger(initial);
+ sensors().set(SEQUENCE_STATE, state);
return null;
}
}
@@ -86,7 +88,10 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup
private Integer sequence(Entity entity) {
String format = config().get(SEQUENCE_FORMAT);
- Integer current = sensors().get(SEQUENCE_NEXT);
+ Integer increment = config().get(SEQUENCE_INCREMENT);
+ AtomicInteger state = sensors().get(SEQUENCE_STATE);
+ Integer current = state.getAndAdd(increment);
+
String string = String.format(format, current);
AttributeSensor<Integer> valueSensor = config().get(SEQUENCE_VALUE_SENSOR);
AttributeSensor<String> stringSensor = config().get(SEQUENCE_STRING_SENSOR);
@@ -96,12 +101,7 @@ public class SequenceGroupImpl extends DynamicGroupImpl implements SequenceGroup
LOG.debug("Sequence on {} set to to {}", entity, current);
sensors().set(SEQUENCE_CURRENT, entity);
-
- Integer increment = config().get(SEQUENCE_INCREMENT);
- Integer next = current + increment;
- LOG.debug("Sequence for {} incremented to {}", this, next);
-
- sensors().set(SEQUENCE_NEXT, next);
+ LOG.debug("Sequence for {} incremented to {}", this, state.get());
return current;
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ff6e7a37/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
index 6b73d8f..bc58f47 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntity.java
@@ -18,6 +18,8 @@
*/
package org.apache.brooklyn.entity.stock;
+import java.util.concurrent.atomic.AtomicInteger;
+
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ImplementedBy;
import org.apache.brooklyn.api.sensor.AttributeSensor;
@@ -47,6 +49,8 @@ public interface SequenceEntity extends Entity, Startable, Supplier<Integer> {
AttributeSensor<Integer> SEQUENCE_VALUE = SequenceGroup.SEQUENCE_VALUE;
+ AttributeSensor<AtomicInteger> SEQUENCE_STATE = SequenceGroup.SEQUENCE_STATE;
+
@SetFromFlag("sequenceStart")
ConfigKey<Integer> SEQUENCE_START = SequenceGroup.SEQUENCE_START;
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ff6e7a37/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
index b731dfe..06fee53 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/stock/SequenceEntityImpl.java
@@ -19,6 +19,7 @@
package org.apache.brooklyn.entity.stock;
import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.core.entity.AbstractEntity;
@@ -61,7 +62,7 @@ public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity
@Override
public Integer incrementAndGet() {
synchronized (mutex) {
- increment();
+ sequence();
return get();
}
}
@@ -69,9 +70,7 @@ public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity
@Override
public Void increment() {
synchronized (mutex) {
- Integer increment = config().get(SEQUENCE_INCREMENT);
- Integer current = get();
- sequence(current + increment);
+ sequence();
return null;
}
}
@@ -80,14 +79,19 @@ public class SequenceEntityImpl extends AbstractEntity implements SequenceEntity
public Void reset() {
synchronized (mutex) {
Integer start = config().get(SEQUENCE_START);
- sequence(start);
+ AtomicInteger state = new AtomicInteger(start);
+ sensors().set(SEQUENCE_STATE, state);
+ sensors().set(SEQUENCE_VALUE, state.get());
return null;
}
}
- private void sequence(Integer value) {
- sensors().set(SEQUENCE_VALUE, value);
- LOG.debug("Sequence for {} set to {}", this, value);
+ private void sequence() {
+ Integer increment = config().get(SEQUENCE_INCREMENT);
+ AtomicInteger state = sensors().get(SEQUENCE_STATE);
+ Integer current = state.addAndGet(increment);
+ sensors().set(SEQUENCE_VALUE, current);
+ LOG.debug("Sequence for {} set to {}", this, current);
}
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ff6e7a37/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 d835c7d..f1d85c5 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
@@ -22,9 +22,11 @@ import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttribute;
import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEquals;
import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEqualsEventually;
import static org.apache.brooklyn.test.Asserts.assertEqualsIgnoringOrder;
-import static org.apache.brooklyn.test.Asserts.assertTrue;
+import static org.apache.brooklyn.test.Asserts.*;
import static org.apache.brooklyn.test.Asserts.succeedsEventually;
+import java.util.concurrent.atomic.AtomicInteger;
+
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
@@ -83,7 +85,8 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
assertEqualsIgnoringOrder(group.getMembers(), ImmutableList.of(e1));
assertAttributeEquals(e1, SequenceGroup.SEQUENCE_VALUE, 1);
- assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 2);
+ AtomicInteger state = group.sensors().get(SequenceGroup.SEQUENCE_STATE);
+ assertEquals(state.get(), 2);
}
@Test
@@ -143,8 +146,9 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
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);
+ AtomicInteger state = group.sensors().get(SequenceGroup.SEQUENCE_STATE);
+ assertEquals(state.get(), 6);
}
@Test
@@ -162,7 +166,8 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
public void run() {
assertEqualsIgnoringOrder(group.getMembers(), ImmutableSet.of(e));
assertAttributeEquals(e, SequenceGroup.SEQUENCE_VALUE, 1);
- assertAttributeEquals(group, SequenceGroup.SEQUENCE_NEXT, 2);
+ AtomicInteger state = group.sensors().get(SequenceGroup.SEQUENCE_STATE);
+ assertEquals(state.get(), 2);
}});
}
@@ -179,8 +184,9 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
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);
+ AtomicInteger state = group.sensors().get(SequenceGroup.SEQUENCE_STATE);
+ assertEquals(state.get(), 4);
final Entity e = app.addChild(EntitySpec.create(TestEntity.class));
@@ -188,8 +194,9 @@ public class SequenceGroupTest extends BrooklynAppUnitTestSupport {
public void run() {
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);
+ AtomicInteger state = group.sensors().get(SequenceGroup.SEQUENCE_STATE);
+ assertEquals(state.get(), 5);
}});
}
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ff6e7a37/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 c4b3b86..0acafaf 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
@@ -113,7 +113,7 @@ public class SequenceEntityTest extends BrooklynAppUnitTestSupport {
}
@Test
- public void testSequenceNextEffectors() throws Exception {
+ public void testSequenceIncrementAndGetEffector() throws Exception {
sequence = app.addChild(EntitySpec.create(SequenceEntity.class));
app.start(ImmutableList.of(loc1));
[2/8] brooklyn-server git commit: Add support for configurable
sequence sensors and update tests
Posted by dr...@apache.org.
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 <an...@cloudsoftcorp.com>
Authored: Tue Feb 7 09:43:50 2017 +0000
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
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")
* }</pre>
+ * <p>
+ * <b>IMPORTANT</b> 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<Integer> SEQUENCE_VALUE = Sensors.builder(Integer.class, "sequence.value")
+ .description("The current value of the sequence")
+ .build();
+
+ AttributeSensor<String> SEQUENCE_STRING = Sensors.builder(String.class, "sequence.string")
+ .description("The current value of the sequence formatted as a string")
+ .build();
+
+ ConfigKey<Predicate<? super Entity>> ENTITY_FILTER = ConfigKeys.newConfigKeyWithDefault(DynamicGroup.ENTITY_FILTER, Predicates.alwaysFalse());
+
@SetFromFlag("sequenceStart")
ConfigKey<Integer> SEQUENCE_START = ConfigKeys.builder(Integer.class)
.name("sequence.start")
@@ -65,7 +93,7 @@ public interface SequenceGroup extends DynamicGroup {
.build();
@SetFromFlag("sequenceIncrement")
- ConfigKey<Integer> SEQUENCE_INCREMENT = ConfigKeys.builder(Integer.class)
+ ConfigKey<Integer> 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<AttributeSensor<Integer>> SEQUENCE_VALUE_SENSOR = ConfigKeys.builder(new TypeToken<AttributeSensor<Integer>>() { })
+ .name("sequence.sensor.value")
+ .description("The sensor for the sequence value")
+ .defaultValue(SEQUENCE_VALUE)
+ .constraint(Predicates.<AttributeSensor<Integer>>notNull())
+ .build();
+
+ @SetFromFlag("sequenceStringSensor")
+ ConfigKey<AttributeSensor<String>> SEQUENCE_STRING_SENSOR = ConfigKeys.builder(new TypeToken<AttributeSensor<String>>() { })
+ .name("sequence.sensor.string")
+ .description("The sensor for the sequence string")
+ .defaultValue(SEQUENCE_STRING)
+ .constraint(Predicates.<AttributeSensor<String>>notNull())
+ .build();
+
+ AttributeSensor<Entity> SEQUENCE_CURRENT = Sensors.builder(Entity.class, "sequence.current")
+ .description("The current entity in the sequence")
+ .build();
+
AttributeSensor<Integer> 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<Void> RESET = new MethodEffector<Void>(SequenceEntity.class, "reset");
+ MethodEffector<Void> RESET = new MethodEffector<Void>(SequenceGroup.class, "reset");
@Effector(description = "Reset the sequence to initial value")
Void reset();
- AttributeSensor<Integer> SEQUENCE_VALUE = Sensors.builder(Integer.class, "sequence.value")
- .description("The current value of the sequence")
- .build();
-
- AttributeSensor<String> 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.<String, Integer>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<String, Integer> 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<String, Integer> cache = sensors().get(SEQUENCE_CACHE);
+ if (cache.containsKey(member.getId())) {
+ cache.remove(member.getId());
+
+ AttributeSensor<Integer> valueSensor = config().get(SEQUENCE_VALUE_SENSOR);
+ AttributeSensor<String> 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<Integer> valueSensor = config().get(SEQUENCE_VALUE_SENSOR);
+ AttributeSensor<String> 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<Integer> value = Sensors.newIntegerSensor("test.value");
+ AttributeSensor<String> 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