2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.clamp.controlloop.runtime.supervision;
23 import java.util.List;
24 import org.apache.commons.lang3.tuple.Pair;
25 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
26 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
27 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
28 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
29 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantHealthStatus;
30 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
31 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
32 import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
33 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher;
34 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher;
35 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusReqPublisher;
36 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantUpdatePublisher;
37 import org.onap.policy.models.base.PfModelException;
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.stereotype.Component;
44 * This class is used to scan the control loops in the database and check if they are in the correct state.
47 public class SupervisionScanner {
48 private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionScanner.class);
50 private HandleCounter<ToscaConceptIdentifier> controlLoopCounter = new HandleCounter<>();
51 private HandleCounter<ToscaConceptIdentifier> participantStatusCounter = new HandleCounter<>();
52 private HandleCounter<Pair<ToscaConceptIdentifier, ToscaConceptIdentifier>> participantUpdateCounter =
53 new HandleCounter<>();
55 private final ControlLoopProvider controlLoopProvider;
56 private final ControlLoopStateChangePublisher controlLoopStateChangePublisher;
57 private final ControlLoopUpdatePublisher controlLoopUpdatePublisher;
58 private final ParticipantProvider participantProvider;
59 private final ParticipantStatusReqPublisher participantStatusReqPublisher;
60 private final ParticipantUpdatePublisher participantUpdatePublisher;
62 private final long maxWaitMs;
65 * Constructor for instantiating SupervisionScanner.
67 * @param controlLoopProvider the provider to use to read control loops from the database
68 * @param controlLoopStateChangePublisher the ControlLoop StateChange Publisher
69 * @param controlLoopUpdatePublisher the ControlLoopUpdate Publisher
70 * @param participantProvider the Participant Provider
71 * @param participantStatusReqPublisher the Participant StatusReq Publisher
72 * @param participantUpdatePublisher the Participant Update Publisher
73 * @param clRuntimeParameterGroup the parameters for the control loop runtime
75 public SupervisionScanner(final ControlLoopProvider controlLoopProvider,
76 final ControlLoopStateChangePublisher controlLoopStateChangePublisher,
77 ControlLoopUpdatePublisher controlLoopUpdatePublisher, ParticipantProvider participantProvider,
78 ParticipantStatusReqPublisher participantStatusReqPublisher,
79 ParticipantUpdatePublisher participantUpdatePublisher,
80 final ClRuntimeParameterGroup clRuntimeParameterGroup) {
81 this.controlLoopProvider = controlLoopProvider;
82 this.controlLoopStateChangePublisher = controlLoopStateChangePublisher;
83 this.controlLoopUpdatePublisher = controlLoopUpdatePublisher;
84 this.participantProvider = participantProvider;
85 this.participantStatusReqPublisher = participantStatusReqPublisher;
86 this.participantUpdatePublisher = participantUpdatePublisher;
88 controlLoopCounter.setMaxRetryCount(
89 clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
91 .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
93 participantUpdateCounter.setMaxRetryCount(
94 clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
95 participantUpdateCounter
96 .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
98 participantStatusCounter.setMaxRetryCount(
99 clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
100 participantStatusCounter
101 .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
103 maxWaitMs = clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs();
109 * @param counterCheck if true activate counter and retry
111 public void run(boolean counterCheck) {
112 LOGGER.debug("Scanning control loops in the database . . .");
116 for (Participant participant : participantProvider.getParticipants(null, null)) {
117 scanParticipantStatus(participant);
119 } catch (PfModelException pfme) {
120 LOGGER.warn("error reading participant from database", pfme);
126 for (ControlLoop controlLoop : controlLoopProvider.getControlLoops(null, null)) {
127 scanControlLoop(controlLoop, counterCheck);
129 } catch (PfModelException pfme) {
130 LOGGER.warn("error reading control loops from database", pfme);
133 scanParticipantUpdate();
136 LOGGER.debug("Control loop scan complete . . .");
139 private void scanParticipantUpdate() {
140 LOGGER.debug("Scanning participants to update . . .");
142 for (var id : participantUpdateCounter.keySet()) {
143 if (participantUpdateCounter.isFault(id)) {
144 LOGGER.debug("report Participant Update fault");
146 } else if (participantUpdateCounter.getDuration(id) > maxWaitMs) {
148 if (participantUpdateCounter.count(id)) {
149 LOGGER.debug("retry message ParticipantUpdate");
150 participantUpdatePublisher.send(id.getLeft(), id.getRight(), true);
152 LOGGER.debug("report Participant Update fault");
153 participantUpdateCounter.setFault(id);
158 LOGGER.debug("Participants to update scan complete . . .");
161 private void scanParticipantStatus(Participant participant) throws PfModelException {
162 ToscaConceptIdentifier id = participant.getKey().asIdentifier();
163 if (participantStatusCounter.isFault(id)) {
164 LOGGER.debug("report Participant fault");
167 if (participantStatusCounter.getDuration(id) > maxWaitMs) {
168 if (participantStatusCounter.count(id)) {
169 LOGGER.debug("retry message ParticipantStatusReq");
170 participantStatusReqPublisher.send(id);
171 participant.setHealthStatus(ParticipantHealthStatus.NOT_HEALTHY);
173 LOGGER.debug("report Participant fault");
174 participantStatusCounter.setFault(id);
175 participant.setHealthStatus(ParticipantHealthStatus.OFF_LINE);
177 participantProvider.updateParticipants(List.of(participant));
182 * handle participant Status message.
184 public void handleParticipantStatus(ToscaConceptIdentifier id) {
185 participantStatusCounter.clear(id);
188 public void handleParticipantRegister(Pair<ToscaConceptIdentifier, ToscaConceptIdentifier> id) {
189 participantUpdateCounter.clear(id);
192 public void handleParticipantUpdateAck(Pair<ToscaConceptIdentifier, ToscaConceptIdentifier> id) {
193 participantUpdateCounter.remove(id);
196 private void scanControlLoop(final ControlLoop controlLoop, boolean counterCheck) throws PfModelException {
197 LOGGER.debug("scanning control loop {} . . .", controlLoop.getKey().asIdentifier());
199 if (controlLoop.getState().equals(controlLoop.getOrderedState().asState())) {
200 LOGGER.debug("control loop {} scanned, OK", controlLoop.getKey().asIdentifier());
202 // Clear missed report counter on Control Loop
203 clearFaultAndCounter(controlLoop);
207 boolean completed = true;
208 for (ControlLoopElement element : controlLoop.getElements().values()) {
209 if (!element.getState().equals(element.getOrderedState().asState())) {
216 LOGGER.debug("control loop scan: transition from state {} to {} completed", controlLoop.getState(),
217 controlLoop.getOrderedState());
219 controlLoop.setState(controlLoop.getOrderedState().asState());
220 controlLoopProvider.updateControlLoop(controlLoop);
222 // Clear missed report counter on Control Loop
223 clearFaultAndCounter(controlLoop);
225 LOGGER.debug("control loop scan: transition from state {} to {} not completed", controlLoop.getState(),
226 controlLoop.getOrderedState());
228 handleCounter(controlLoop);
233 private void clearFaultAndCounter(ControlLoop controlLoop) {
234 controlLoopCounter.clear(controlLoop.getKey().asIdentifier());
237 private void handleCounter(ControlLoop controlLoop) {
238 ToscaConceptIdentifier id = controlLoop.getKey().asIdentifier();
239 if (controlLoopCounter.isFault(id)) {
240 LOGGER.debug("report ControlLoop fault");
244 if (controlLoopCounter.count(id)) {
245 if (ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())) {
246 LOGGER.debug("retry message ControlLoopUpdate");
247 controlLoopUpdatePublisher.send(controlLoop);
249 LOGGER.debug("retry message ControlLoopStateChange");
250 controlLoopStateChangePublisher.send(controlLoop);
253 LOGGER.debug("report ControlLoop fault");
254 controlLoopCounter.setFault(id);