22c7d33653286e4b0b105f3ff90753309256a417
[policy/models.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ActorService
4  * ================================================================================
5  * Copyright (C) 2017-2018, 2020 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 Nordix Foundation.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.controlloop.actorserviceprovider;
23
24 import com.google.common.collect.ImmutableMap;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.ServiceConfigurationError;
30 import java.util.ServiceLoader;
31 import java.util.Set;
32 import org.onap.policy.common.parameters.BeanValidationResult;
33 import org.onap.policy.controlloop.actorserviceprovider.impl.StartConfigPartial;
34 import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
35 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Service that manages a set of actors. To use the service, first invoke
41  * {@link #configure(Map)} to configure all of the actors, and then invoke
42  * {@link #start()} to start all of the actors. When finished using the actor service,
43  * invoke {@link #stop()} or {@link #shutdown()}.
44  */
45 public class ActorService extends StartConfigPartial<Map<String, Map<String, Object>>> {
46     private static final Logger logger = LoggerFactory.getLogger(ActorService.class);
47
48     private final Map<String, Actor> name2actor;
49
50     private static class LazyHolder {
51         static final ActorService INSTANCE = new ActorService();
52     }
53
54     /**
55      * Constructs the object and loads the list of actors.
56      */
57     protected ActorService() {
58         super("actors");
59
60         Map<String, Actor> map = new HashMap<>();
61
62         Iterator<Actor> iter = loadActors().iterator();
63         while (iter.hasNext()) {
64
65             Actor newActor;
66             try {
67                 newActor = iter.next();
68             } catch (ServiceConfigurationError e) {
69                 logger.warn("unable to load actor", e);
70                 continue;
71             }
72
73             map.compute(newActor.getName(), (name, existingActor) -> {
74                 if (existingActor == null) {
75                     return newActor;
76                 }
77
78                 logger.warn("duplicate actor names for {}: {}, ignoring {}", name,
79                                 existingActor.getClass().getSimpleName(), newActor.getClass().getSimpleName());
80                 return existingActor;
81             });
82         }
83
84         name2actor = ImmutableMap.copyOf(map);
85     }
86
87     /**
88      * Get the single instance.
89      *
90      * @return the instance
91      */
92     public static ActorService getInstance() {
93         return LazyHolder.INSTANCE;
94     }
95
96     /**
97      * Gets a particular actor.
98      *
99      * @param name name of the actor of interest
100      * @return the desired actor
101      * @throws IllegalArgumentException if no actor by the given name exists
102      */
103     public Actor getActor(String name) {
104         Actor actor = name2actor.get(name);
105         if (actor == null) {
106             throw new IllegalArgumentException("unknown actor " + name);
107         }
108
109         return actor;
110     }
111
112     /**
113      * Gets the actors.
114      *
115      * @return the actors
116      */
117     public Collection<Actor> getActors() {
118         return name2actor.values();
119     }
120
121     /**
122      * Gets the names of the actors.
123      *
124      * @return the actor names
125      */
126     public Set<String> getActorNames() {
127         return name2actor.keySet();
128     }
129
130     @Override
131     protected void doConfigure(Map<String, Map<String, Object>> parameters) {
132         logger.info("configuring actors");
133
134         BeanValidationResult valres = new BeanValidationResult("ActorService", parameters);
135
136         for (Actor actor : name2actor.values()) {
137             String actorName = actor.getName();
138             Map<String, Object> subparams = parameters.get(actorName);
139
140             if (subparams != null) {
141
142                 try {
143                     actor.configure(subparams);
144
145                 } catch (ParameterValidationRuntimeException e) {
146                     logger.warn("failed to configure actor {}", actorName, e);
147                     valres.addResult(e.getResult());
148
149                 } catch (RuntimeException e) {
150                     logger.warn("failed to configure actor {}", actorName, e);
151                 }
152
153             } else if (actor.isConfigured()) {
154                 logger.warn("missing configuration parameters for actor {}; using previous parameters", actorName);
155
156             } else {
157                 logger.warn("missing configuration parameters for actor {}; actor cannot be started", actorName);
158             }
159         }
160
161         if (!valres.isValid() && logger.isWarnEnabled()) {
162             logger.warn("actor services validation errors:\n{}", valres.getResult());
163         }
164     }
165
166     @Override
167     protected void doStart() {
168         logger.info("starting actors");
169
170         for (Actor actor : name2actor.values()) {
171             if (actor.isConfigured()) {
172                 Util.runFunction(actor::start, "failed to start actor {}", actor.getName());
173
174             } else {
175                 logger.warn("not starting unconfigured actor {}", actor.getName());
176             }
177         }
178     }
179
180     @Override
181     protected void doStop() {
182         logger.info("stopping actors");
183         name2actor.values().forEach(actor -> Util.runFunction(actor::stop, "failed to stop actor {}", actor.getName()));
184     }
185
186     @Override
187     protected void doShutdown() {
188         logger.info("shutting down actors");
189
190         // @formatter:off
191         name2actor.values().forEach(
192             actor -> Util.runFunction(actor::shutdown, "failed to shutdown actor {}", actor.getName()));
193
194         // @formatter:on
195     }
196
197     // the following methods may be overridden by junit tests
198
199     protected Iterable<Actor> loadActors() {
200         return ServiceLoader.load(Actor.class);
201     }
202 }