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;
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());
90 controlLoopCounter.setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs());
92 participantUpdateCounter.setMaxRetryCount(
93 clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
94 participantUpdateCounter
95 .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
97 participantStatusCounter.setMaxRetryCount(
98 clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
99 participantStatusCounter.setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs());
105 * @param counterCheck if true activate counter and retry
107 public void run(boolean counterCheck) {
108 LOGGER.debug("Scanning control loops in the database . . .");
112 for (Participant participant : participantProvider.getParticipants(null, null)) {
113 scanParticipantStatus(participant);
115 } catch (PfModelException pfme) {
116 LOGGER.warn("error reading participant from database", pfme);
122 for (ControlLoop controlLoop : controlLoopProvider.getControlLoops(null, null)) {
123 scanControlLoop(controlLoop, counterCheck);
125 } catch (PfModelException pfme) {
126 LOGGER.warn("error reading control loops from database", pfme);
130 scanParticipantUpdate();
133 LOGGER.debug("Control loop scan complete . . .");
136 private void scanParticipantUpdate() {
137 LOGGER.debug("Scanning participants to update . . .");
139 for (var id : participantUpdateCounter.keySet()) {
140 if (participantUpdateCounter.isFault(id)) {
141 LOGGER.debug("report Participant Update fault");
143 } else if (participantUpdateCounter.getDuration(id) > participantUpdateCounter.getMaxWaitMs()) {
145 if (participantUpdateCounter.count(id)) {
146 LOGGER.debug("retry message ParticipantUpdate");
147 participantUpdatePublisher.send(id.getLeft(), id.getRight(), true);
149 LOGGER.debug("report Participant Update fault");
150 participantUpdateCounter.setFault(id);
155 LOGGER.debug("Participants to update scan complete . . .");
158 private void scanParticipantStatus(Participant participant) throws PfModelException {
159 ToscaConceptIdentifier id = participant.getKey().asIdentifier();
160 if (participantStatusCounter.isFault(id)) {
161 LOGGER.debug("report Participant fault");
164 if (participantStatusCounter.getDuration(id) > participantStatusCounter.getMaxWaitMs()) {
165 if (participantStatusCounter.count(id)) {
166 LOGGER.debug("retry message ParticipantStatusReq");
167 participantStatusReqPublisher.send(id);
168 participant.setHealthStatus(ParticipantHealthStatus.NOT_HEALTHY);
170 LOGGER.debug("report Participant fault");
171 participantStatusCounter.setFault(id);
172 participant.setHealthStatus(ParticipantHealthStatus.OFF_LINE);
174 participantProvider.updateParticipants(List.of(participant));
179 * handle participant Status message.
181 public void handleParticipantStatus(ToscaConceptIdentifier id) {
182 participantStatusCounter.clear(id);
185 public void handleParticipantRegister(Pair<ToscaConceptIdentifier, ToscaConceptIdentifier> id) {
186 participantUpdateCounter.clear(id);
189 public void handleParticipantUpdateAck(Pair<ToscaConceptIdentifier, ToscaConceptIdentifier> id) {
190 participantUpdateCounter.remove(id);
193 private void scanControlLoop(final ControlLoop controlLoop, boolean counterCheck) throws PfModelException {
194 LOGGER.debug("scanning control loop {} . . .", controlLoop.getKey().asIdentifier());
196 if (controlLoop.getState().equals(controlLoop.getOrderedState().asState())) {
197 LOGGER.debug("control loop {} scanned, OK", controlLoop.getKey().asIdentifier());
199 // Clear missed report counter on Control Loop
200 clearFaultAndCounter(controlLoop);
204 var completed = true;
205 for (ControlLoopElement element : controlLoop.getElements().values()) {
206 if (!element.getState().equals(element.getOrderedState().asState())) {
213 LOGGER.debug("control loop scan: transition from state {} to {} completed", controlLoop.getState(),
214 controlLoop.getOrderedState());
216 controlLoop.setState(controlLoop.getOrderedState().asState());
217 controlLoopProvider.updateControlLoop(controlLoop);
219 // Clear missed report counter on Control Loop
220 clearFaultAndCounter(controlLoop);
222 LOGGER.debug("control loop scan: transition from state {} to {} not completed", controlLoop.getState(),
223 controlLoop.getOrderedState());
225 handleCounter(controlLoop);
230 private void clearFaultAndCounter(ControlLoop controlLoop) {
231 controlLoopCounter.clear(controlLoop.getKey().asIdentifier());
234 private void handleCounter(ControlLoop controlLoop) {
235 ToscaConceptIdentifier id = controlLoop.getKey().asIdentifier();
236 if (controlLoopCounter.isFault(id)) {
237 LOGGER.debug("report ControlLoop fault");
241 if (controlLoopCounter.getDuration(id) > controlLoopCounter.getMaxWaitMs()) {
242 if (controlLoopCounter.count(id)) {
243 if (ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())) {
244 LOGGER.debug("retry message ControlLoopUpdate");
245 controlLoopUpdatePublisher.send(controlLoop);
247 LOGGER.debug("retry message ControlLoopStateChange");
248 controlLoopStateChangePublisher.send(controlLoop);
251 LOGGER.debug("report ControlLoop fault");
252 controlLoopCounter.setFault(id);