2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Nordix Foundation.
4 * ================================================================================
5 * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.clamp.controlloop.runtime.supervision;
25 import java.util.List;
26 import org.apache.commons.lang3.tuple.Pair;
27 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
28 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
29 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
30 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
31 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantHealthStatus;
32 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
33 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
34 import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
35 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher;
36 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher;
37 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusReqPublisher;
38 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantUpdatePublisher;
39 import org.onap.policy.models.base.PfModelException;
40 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43 import org.springframework.stereotype.Component;
46 * This class is used to scan the control loops in the database and check if they are in the correct state.
49 public class SupervisionScanner {
50 private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionScanner.class);
52 private HandleCounter<ToscaConceptIdentifier> controlLoopCounter = new HandleCounter<>();
53 private HandleCounter<ToscaConceptIdentifier> participantStatusCounter = new HandleCounter<>();
54 private HandleCounter<Pair<ToscaConceptIdentifier, ToscaConceptIdentifier>> participantUpdateCounter =
55 new HandleCounter<>();
57 private final ControlLoopProvider controlLoopProvider;
58 private final ControlLoopStateChangePublisher controlLoopStateChangePublisher;
59 private final ControlLoopUpdatePublisher controlLoopUpdatePublisher;
60 private final ParticipantProvider participantProvider;
61 private final ParticipantStatusReqPublisher participantStatusReqPublisher;
62 private final ParticipantUpdatePublisher participantUpdatePublisher;
64 private final long maxWaitMs;
67 * Constructor for instantiating SupervisionScanner.
69 * @param controlLoopProvider the provider to use to read control loops from the database
70 * @param controlLoopStateChangePublisher the ControlLoop StateChange Publisher
71 * @param controlLoopUpdatePublisher the ControlLoopUpdate Publisher
72 * @param participantProvider the Participant Provider
73 * @param participantStatusReqPublisher the Participant StatusReq Publisher
74 * @param participantUpdatePublisher the Participant Update Publisher
75 * @param clRuntimeParameterGroup the parameters for the control loop runtime
77 public SupervisionScanner(final ControlLoopProvider controlLoopProvider,
78 final ControlLoopStateChangePublisher controlLoopStateChangePublisher,
79 ControlLoopUpdatePublisher controlLoopUpdatePublisher, ParticipantProvider participantProvider,
80 ParticipantStatusReqPublisher participantStatusReqPublisher,
81 ParticipantUpdatePublisher participantUpdatePublisher,
82 final ClRuntimeParameterGroup clRuntimeParameterGroup) {
83 this.controlLoopProvider = controlLoopProvider;
84 this.controlLoopStateChangePublisher = controlLoopStateChangePublisher;
85 this.controlLoopUpdatePublisher = controlLoopUpdatePublisher;
86 this.participantProvider = participantProvider;
87 this.participantStatusReqPublisher = participantStatusReqPublisher;
88 this.participantUpdatePublisher = participantUpdatePublisher;
90 controlLoopCounter.setMaxRetryCount(
91 clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
93 .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
95 participantUpdateCounter.setMaxRetryCount(
96 clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
97 participantUpdateCounter
98 .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
100 participantStatusCounter.setMaxRetryCount(
101 clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
102 participantStatusCounter
103 .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
105 maxWaitMs = clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs();
111 * @param counterCheck if true activate counter and retry
113 public void run(boolean counterCheck) {
114 LOGGER.debug("Scanning control loops in the database . . .");
118 for (Participant participant : participantProvider.getParticipants(null, null)) {
119 scanParticipantStatus(participant);
121 } catch (PfModelException pfme) {
122 LOGGER.warn("error reading participant from database", pfme);
128 for (ControlLoop controlLoop : controlLoopProvider.getControlLoops(null, null)) {
129 scanControlLoop(controlLoop, counterCheck);
131 } catch (PfModelException pfme) {
132 LOGGER.warn("error reading control loops from database", pfme);
135 scanParticipantUpdate();
138 LOGGER.debug("Control loop scan complete . . .");
141 private void scanParticipantUpdate() {
142 LOGGER.debug("Scanning participants to update . . .");
144 for (var id : participantUpdateCounter.keySet()) {
145 if (participantUpdateCounter.isFault(id)) {
146 LOGGER.debug("report Participant Update fault");
148 } else if (participantUpdateCounter.getDuration(id) > maxWaitMs) {
150 if (participantUpdateCounter.count(id)) {
151 LOGGER.debug("retry message ParticipantUpdate");
152 participantUpdatePublisher.send(id.getLeft(), id.getRight(), true);
154 LOGGER.debug("report Participant Update fault");
155 participantUpdateCounter.setFault(id);
160 LOGGER.debug("Participants to update scan complete . . .");
163 private void scanParticipantStatus(Participant participant) throws PfModelException {
164 ToscaConceptIdentifier id = participant.getKey().asIdentifier();
165 if (participantStatusCounter.isFault(id)) {
166 LOGGER.debug("report Participant fault");
169 if (participantStatusCounter.getDuration(id) > maxWaitMs) {
170 if (participantStatusCounter.count(id)) {
171 LOGGER.debug("retry message ParticipantStatusReq");
172 participantStatusReqPublisher.send(id);
173 participant.setHealthStatus(ParticipantHealthStatus.NOT_HEALTHY);
175 LOGGER.debug("report Participant fault");
176 participantStatusCounter.setFault(id);
177 participant.setHealthStatus(ParticipantHealthStatus.OFF_LINE);
179 participantProvider.updateParticipants(List.of(participant));
184 * handle participant Status message.
186 public void handleParticipantStatus(ToscaConceptIdentifier id) {
187 participantStatusCounter.clear(id);
190 public void handleParticipantRegister(Pair<ToscaConceptIdentifier, ToscaConceptIdentifier> id) {
191 participantUpdateCounter.clear(id);
194 public void handleParticipantUpdateAck(Pair<ToscaConceptIdentifier, ToscaConceptIdentifier> id) {
195 participantUpdateCounter.remove(id);
198 private void scanControlLoop(final ControlLoop controlLoop, boolean counterCheck) throws PfModelException {
199 LOGGER.debug("scanning control loop {} . . .", controlLoop.getKey().asIdentifier());
201 if (controlLoop.getState().equals(controlLoop.getOrderedState().asState())) {
202 LOGGER.debug("control loop {} scanned, OK", controlLoop.getKey().asIdentifier());
204 // Clear missed report counter on Control Loop
205 clearFaultAndCounter(controlLoop);
209 var completed = true;
210 for (ControlLoopElement element : controlLoop.getElements().values()) {
211 if (!element.getState().equals(element.getOrderedState().asState())) {
218 LOGGER.debug("control loop scan: transition from state {} to {} completed", controlLoop.getState(),
219 controlLoop.getOrderedState());
221 controlLoop.setState(controlLoop.getOrderedState().asState());
222 controlLoopProvider.updateControlLoop(controlLoop);
224 // Clear missed report counter on Control Loop
225 clearFaultAndCounter(controlLoop);
227 LOGGER.debug("control loop scan: transition from state {} to {} not completed", controlLoop.getState(),
228 controlLoop.getOrderedState());
230 handleCounter(controlLoop);
235 private void clearFaultAndCounter(ControlLoop controlLoop) {
236 controlLoopCounter.clear(controlLoop.getKey().asIdentifier());
239 private void handleCounter(ControlLoop controlLoop) {
240 ToscaConceptIdentifier id = controlLoop.getKey().asIdentifier();
241 if (controlLoopCounter.isFault(id)) {
242 LOGGER.debug("report ControlLoop fault");
246 if (controlLoopCounter.count(id)) {
247 if (ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())) {
248 LOGGER.debug("retry message ControlLoopUpdate");
249 controlLoopUpdatePublisher.send(controlLoop);
251 LOGGER.debug("retry message ControlLoopStateChange");
252 controlLoopStateChangePublisher.send(controlLoop);
255 LOGGER.debug("report ControlLoop fault");
256 controlLoopCounter.setFault(id);