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 LcmEventsHelper lcmEventsHelper;
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 lcmEventsHelper.sendLcmEventBatchAsynchronously(cmHandleTransitionPairs);
62 cmHandleStateMonitor.updateCmHandleStateMetrics(cmHandleTransitionPairs);
66 public void initiateStateAdvised(final Collection<YangModelCmHandle> yangModelCmHandles) {
67 final Map<YangModelCmHandle, CmHandleState> targetCmHandleStatePerCmHandle
68 = new HashMap<>(yangModelCmHandles.size());
69 for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandles) {
70 targetCmHandleStatePerCmHandle.put(yangModelCmHandle, ADVISED);
72 updateCmHandleStateBatch(targetCmHandleStatePerCmHandle);
75 private Collection<CmHandleTransitionPair> prepareCmHandleTransitionBatch(
76 final Map<YangModelCmHandle, CmHandleState> targetCmHandleStatePerCmHandle) {
77 final List<CmHandleTransitionPair> cmHandleTransitionPairs
78 = new ArrayList<>(targetCmHandleStatePerCmHandle.size());
79 targetCmHandleStatePerCmHandle.forEach((yangModelCmHandle, targetCmHandleState) -> {
80 final CompositeState currentCmHandleState = yangModelCmHandle.getCompositeState();
81 if (isCompositeStateSame(currentCmHandleState, targetCmHandleState)) {
82 log.debug("CmHandle: {} already in state: {}", yangModelCmHandle.getId(), targetCmHandleState);
84 final YangModelCmHandle oldYangModelCmHandle = YangModelCmHandle.deepCopyOf(yangModelCmHandle);
85 updateCmHandleState(yangModelCmHandle, targetCmHandleState);
86 final CmHandleTransitionPair cmHandleTransitionPair = new CmHandleTransitionPair(
87 oldYangModelCmHandle, yangModelCmHandle);
88 cmHandleTransitionPairs.add(cmHandleTransitionPair);
91 return cmHandleTransitionPairs;
94 private void persistCmHandleBatch(final Collection<CmHandleTransitionPair> cmHandleTransitionPairs) {
96 final List<YangModelCmHandle> newCmHandles = new ArrayList<>();
97 final Map<String, CompositeState> compositeStatePerCmHandleId = new LinkedHashMap<>();
99 cmHandleTransitionPairs.forEach(cmHandleTransitionPair -> {
100 if (isNew(cmHandleTransitionPair.currentYangModelCmHandle().getCompositeState())) {
101 newCmHandles.add(cmHandleTransitionPair.targetYangModelCmHandle());
102 } else if (!isDeleted(cmHandleTransitionPair.targetYangModelCmHandle().getCompositeState())) {
103 compositeStatePerCmHandleId.put(cmHandleTransitionPair.targetYangModelCmHandle().getId(),
104 cmHandleTransitionPair.targetYangModelCmHandle().getCompositeState());
107 inventoryPersistence.saveCmHandleBatch(newCmHandles);
108 inventoryPersistence.saveCmHandleStateBatch(compositeStatePerCmHandleId);
109 logCmHandleStateChanges(cmHandleTransitionPairs);
112 private void updateCmHandleState(final YangModelCmHandle yangModelCmHandle,
113 final CmHandleState targetCmHandleState) {
114 if (READY == targetCmHandleState) {
115 setInitialState(yangModelCmHandle);
116 } else if (ADVISED == targetCmHandleState) {
117 if (yangModelCmHandle.getCompositeState() == null) {
118 registerNewCmHandle(yangModelCmHandle);
119 } else if (yangModelCmHandle.getCompositeState().getCmHandleState() == LOCKED) {
120 retryCmHandle(yangModelCmHandle);
123 setCmHandleState(yangModelCmHandle, targetCmHandleState);
127 private void setInitialState(final YangModelCmHandle yangModelCmHandle) {
128 CompositeStateUtils.setInitialDataStoreSyncState(yangModelCmHandle.getCompositeState());
129 CompositeStateUtils.setCompositeState(READY, yangModelCmHandle.getCompositeState());
132 private void retryCmHandle(final YangModelCmHandle yangModelCmHandle) {
133 CompositeStateUtils.setCompositeStateForRetry(yangModelCmHandle.getCompositeState());
136 private void registerNewCmHandle(final YangModelCmHandle yangModelCmHandle) {
137 yangModelCmHandle.setCompositeState(new CompositeState());
138 setCmHandleState(yangModelCmHandle, ADVISED);
141 private void setCmHandleState(final YangModelCmHandle yangModelCmHandle, final CmHandleState targetCmHandleState) {
142 CompositeStateUtils.setCompositeState(targetCmHandleState, yangModelCmHandle.getCompositeState());
145 private boolean isNew(final CompositeState existingCompositeState) {
146 return (existingCompositeState == null);
149 private boolean isDeleted(final CompositeState targetCompositeState) {
150 return targetCompositeState.getCmHandleState() == DELETED;
153 private boolean isCompositeStateSame(final CompositeState compositeState, final CmHandleState targetCmHandleState) {
154 return (compositeState != null && compositeState.getCmHandleState() == targetCmHandleState);
157 private static void logCmHandleStateChanges(final Collection<CmHandleTransitionPair> cmHandleTransitionPairs) {
158 cmHandleTransitionPairs.stream()
159 .map(CmHandleTransitionPair::targetYangModelCmHandle)
160 .forEach(yangModelCmHandle -> log.debug("{} is now in {} state", yangModelCmHandle.getId(),
161 yangModelCmHandle.getCompositeState().getCmHandleState().name()));