package org.onap.policy.controlloop.actorserviceprovider.impl;
-import com.google.common.collect.ImmutableMap;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import org.onap.policy.common.parameters.BeanValidationResult;
import org.onap.policy.controlloop.actorserviceprovider.Operator;
/**
* Maps a name to an operator.
*/
- private Map<String, Operator> name2operator;
+ private final Map<String, Operator> name2operator = new ConcurrentHashMap<>();
/**
* Constructs the object.
*
* @param name actor name
- * @param operators the operations supported by this actor
*/
- public ActorImpl(String name, Operator... operators) {
+ public ActorImpl(String name) {
super(name);
- setOperators(Arrays.asList(operators));
}
/**
- * Sets the operators supported by this actor, overriding any previous list.
+ * Adds an operator supported by this actor.
*
- * @param operators the operations supported by this actor
+ * @param operator operation to be added
*/
- protected void setOperators(List<Operator> operators) {
+ protected synchronized void addOperator(Operator operator) {
+ /*
+ * This method is "synchronized" to prevent the state from changing while the
+ * operator is added. The map, itself, does not need synchronization as it's a
+ * concurrent map.
+ */
+
if (isConfigured()) {
throw new IllegalStateException("attempt to set operators on a configured actor: " + getName());
}
- Map<String, Operator> map = new HashMap<>();
- for (Operator newOp : operators) {
- map.compute(newOp.getName(), (opName, existingOp) -> {
- if (existingOp == null) {
- return newOp;
- }
-
- // TODO: should this throw an exception?
- logger.warn("duplicate names for actor operation {}.{}: {}, ignoring {}", getName(), opName,
- existingOp.getClass().getSimpleName(), newOp.getClass().getSimpleName());
- return existingOp;
- });
- }
+ name2operator.compute(operator.getName(), (opName, existingOp) -> {
+ if (existingOp == null) {
+ return operator;
+ }
- this.name2operator = ImmutableMap.copyOf(map);
+ logger.warn("duplicate names for actor operation {}.{}: {}, ignoring {}", getName(), opName,
+ existingOp.getClass().getSimpleName(), operator.getClass().getSimpleName());
+ return existingOp;
+ });
}
@Override
for (Operator oper : name2operator.values()) {
if (oper.isConfigured()) {
- Util.logException(oper::start, "failed to start operation {}.{}", actorName, oper.getName());
+ Util.runFunction(oper::start, "failed to start operation {}.{}", actorName, oper.getName());
} else {
logger.warn("not starting unconfigured operation {}.{}", actorName, oper.getName());
// @formatter:off
name2operator.values().forEach(
- oper -> Util.logException(oper::stop, "failed to stop operation {}.{}", actorName, oper.getName()));
+ oper -> Util.runFunction(oper::stop, "failed to stop operation {}.{}", actorName, oper.getName()));
// @formatter:on
}
logger.info("shutting down operations for actor {}", actorName);
// @formatter:off
- name2operator.values().forEach(oper -> Util.logException(oper::shutdown,
+ name2operator.values().forEach(oper -> Util.runFunction(oper::shutdown,
"failed to shutdown operation {}.{}", actorName, oper.getName()));
// @formatter:on
}