2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2022-2025 OpenInfra Foundation Europe. All rights reserved.
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.cps.ncmp.impl.inventory.sync.lcm;
23 import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.ADVISED;
24 import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.DELETED;
25 import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.LOCKED;
26 import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.READY;
28 import io.micrometer.core.annotation.Timed;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.LinkedHashMap;
33 import java.util.List;
35 import lombok.RequiredArgsConstructor;
36 import lombok.extern.slf4j.Slf4j;
37 import org.onap.cps.ncmp.api.inventory.models.CmHandleState;
38 import org.onap.cps.ncmp.api.inventory.models.CompositeState;
39 import org.onap.cps.ncmp.impl.inventory.CompositeStateUtils;
40 import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
41 import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
42 import org.springframework.stereotype.Service;
47 @RequiredArgsConstructor
48 public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleStateHandler {
50 private final InventoryPersistence inventoryPersistence;
51 private final LcmEventProducer lcmEventProducer;
52 private final CmHandleStateMonitor cmHandleStateMonitor;
55 @Timed(value = "cps.ncmp.cmhandle.state.update.batch",
56 description = "Time taken to update a batch of cm handle states")
57 public void updateCmHandleStateBatch(final Map<YangModelCmHandle, CmHandleState> targetCmHandleStatePerCmHandle) {
58 final Collection<CmHandleTransitionPair> cmHandleTransitionPairs =
59 prepareCmHandleTransitionBatch(targetCmHandleStatePerCmHandle);
60 persistCmHandleBatch(cmHandleTransitionPairs);
61 if (!cmHandleTransitionPairs.isEmpty()) {
62 lcmEventProducer.sendLcmEventBatchAsynchronously(cmHandleTransitionPairs);
63 cmHandleStateMonitor.updateCmHandleStateMetrics(cmHandleTransitionPairs);
68 public void initiateStateAdvised(final Collection<YangModelCmHandle> yangModelCmHandles) {
69 final Map<YangModelCmHandle, CmHandleState> targetCmHandleStatePerCmHandle
70 = new HashMap<>(yangModelCmHandles.size());
71 for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandles) {
72 targetCmHandleStatePerCmHandle.put(yangModelCmHandle, ADVISED);
74 updateCmHandleStateBatch(targetCmHandleStatePerCmHandle);
77 private Collection<CmHandleTransitionPair> prepareCmHandleTransitionBatch(
78 final Map<YangModelCmHandle, CmHandleState> targetCmHandleStatePerCmHandle) {
79 final List<CmHandleTransitionPair> cmHandleTransitionPairs
80 = new ArrayList<>(targetCmHandleStatePerCmHandle.size());
81 targetCmHandleStatePerCmHandle.forEach((yangModelCmHandle, targetCmHandleState) -> {
82 final CompositeState currentCmHandleState = yangModelCmHandle.getCompositeState();
83 if (isCompositeStateSame(currentCmHandleState, targetCmHandleState)) {
84 log.debug("CmHandle: {} already in state: {}", yangModelCmHandle.getId(), targetCmHandleState);
86 final YangModelCmHandle oldYangModelCmHandle = YangModelCmHandle.deepCopyOf(yangModelCmHandle);
87 updateCmHandleState(yangModelCmHandle, targetCmHandleState);
88 final CmHandleTransitionPair cmHandleTransitionPair = new CmHandleTransitionPair(
89 oldYangModelCmHandle, yangModelCmHandle);
90 cmHandleTransitionPairs.add(cmHandleTransitionPair);
93 return cmHandleTransitionPairs;
96 private void persistCmHandleBatch(final Collection<CmHandleTransitionPair> cmHandleTransitionPairs) {
98 final List<YangModelCmHandle> newCmHandles = new ArrayList<>();
99 final Map<String, CompositeState> compositeStatePerCmHandleId = new LinkedHashMap<>();
101 cmHandleTransitionPairs.forEach(cmHandleTransitionPair -> {
102 if (isNew(cmHandleTransitionPair.currentYangModelCmHandle().getCompositeState())) {
103 newCmHandles.add(cmHandleTransitionPair.targetYangModelCmHandle());
104 } else if (!isDeleted(cmHandleTransitionPair.targetYangModelCmHandle().getCompositeState())) {
105 compositeStatePerCmHandleId.put(cmHandleTransitionPair.targetYangModelCmHandle().getId(),
106 cmHandleTransitionPair.targetYangModelCmHandle().getCompositeState());
109 inventoryPersistence.saveCmHandleBatch(newCmHandles);
110 inventoryPersistence.saveCmHandleStateBatch(compositeStatePerCmHandleId);
111 logCmHandleStateChanges(cmHandleTransitionPairs);
114 private void updateCmHandleState(final YangModelCmHandle yangModelCmHandle,
115 final CmHandleState targetCmHandleState) {
116 if (READY == targetCmHandleState) {
117 setInitialState(yangModelCmHandle);
118 } else if (ADVISED == targetCmHandleState) {
119 if (yangModelCmHandle.getCompositeState() == null) {
120 registerNewCmHandle(yangModelCmHandle);
121 } else if (yangModelCmHandle.getCompositeState().getCmHandleState() == LOCKED) {
122 retryCmHandle(yangModelCmHandle);
125 setCmHandleState(yangModelCmHandle, targetCmHandleState);
129 private void setInitialState(final YangModelCmHandle yangModelCmHandle) {
130 CompositeStateUtils.setInitialDataStoreSyncState(yangModelCmHandle.getCompositeState());
131 CompositeStateUtils.setCompositeState(READY, yangModelCmHandle.getCompositeState());
134 private void retryCmHandle(final YangModelCmHandle yangModelCmHandle) {
135 CompositeStateUtils.setCompositeStateForRetry(yangModelCmHandle.getCompositeState());
138 private void registerNewCmHandle(final YangModelCmHandle yangModelCmHandle) {
139 yangModelCmHandle.setCompositeState(new CompositeState());
140 setCmHandleState(yangModelCmHandle, ADVISED);
143 private void setCmHandleState(final YangModelCmHandle yangModelCmHandle, final CmHandleState targetCmHandleState) {
144 CompositeStateUtils.setCompositeState(targetCmHandleState, yangModelCmHandle.getCompositeState());
147 private boolean isNew(final CompositeState existingCompositeState) {
148 return (existingCompositeState == null);
151 private boolean isDeleted(final CompositeState targetCompositeState) {
152 return targetCompositeState.getCmHandleState() == DELETED;
155 private boolean isCompositeStateSame(final CompositeState compositeState, final CmHandleState targetCmHandleState) {
156 return (compositeState != null && compositeState.getCmHandleState() == targetCmHandleState);
159 private static void logCmHandleStateChanges(final Collection<CmHandleTransitionPair> cmHandleTransitionPairs) {
160 cmHandleTransitionPairs.stream()
161 .map(CmHandleTransitionPair::targetYangModelCmHandle)
162 .forEach(yangModelCmHandle -> log.debug("{} is now in {} state", yangModelCmHandle.getId(),
163 yangModelCmHandle.getCompositeState().getCmHandleState().name()));