X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=cps-ncmp-service%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fcps%2Fncmp%2Fapi%2Finventory%2Fsync%2FSyncUtils.java;h=53d8c797b8d58685bf8a22262f06475904ea1da1;hb=e626c9661fd88a585b50dafab5f5542784690143;hp=8b7dfe6b81fabc6416026eb8faa1ce2e41ccd269;hpb=f7c7848d4cd7654ab94d9c31b62a71ed2bc4b9e8;p=cps.git diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java index 8b7dfe6b8..53d8c797b 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,12 +21,13 @@ package org.onap.cps.ncmp.api.inventory.sync; +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL; + import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.ImmutableMap; -import java.security.SecureRandom; import java.time.Duration; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -38,14 +39,13 @@ import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; -import org.onap.cps.ncmp.api.impl.operations.DmiOperations; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.api.inventory.CmHandleQueries; import org.onap.cps.ncmp.api.inventory.CmHandleState; import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; import org.onap.cps.ncmp.api.inventory.LockReasonCategory; -import org.onap.cps.ncmp.api.inventory.SyncState; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; import org.onap.cps.utils.JsonObjectMapper; @@ -56,10 +56,7 @@ import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class SyncUtils { - - private static final SecureRandom secureRandom = new SecureRandom(); - - private final InventoryPersistence inventoryPersistence; + private final CmHandleQueries cmHandleQueries; private final DmiDataOperations dmiDataOperations; @@ -68,58 +65,52 @@ public class SyncUtils { private static final Pattern retryAttemptPattern = Pattern.compile("^Attempt #(\\d+) failed:"); /** - * Query data nodes for cm handles with an "ADVISED" cm handle state, and select a random entry for processing. + * Query data nodes for cm handles with an "ADVISED" cm handle state. * - * @return a random yang model cm handle with an ADVISED state, return null if not found + * @return cm handles (data nodes) in ADVISED state (empty list if none found) */ - public YangModelCmHandle getAnAdvisedCmHandle() { - final List advisedCmHandles = inventoryPersistence.getCmHandlesByState(CmHandleState.ADVISED); - if (advisedCmHandles.isEmpty()) { - return null; - } - final int randomElementIndex = secureRandom.nextInt(advisedCmHandles.size()); - final String cmHandleId = advisedCmHandles.get(randomElementIndex).getLeaves() - .get("id").toString(); - return inventoryPersistence.getYangModelCmHandle(cmHandleId); + public List getAdvisedCmHandles() { + final List advisedCmHandlesAsDataNodes = cmHandleQueries.queryCmHandlesByState(CmHandleState.ADVISED); + log.debug("Total number of fetched advised cm handle(s) is (are) {}", advisedCmHandlesAsDataNodes.size()); + return advisedCmHandlesAsDataNodes; } /** * First query data nodes for cm handles with CM Handle Operational Sync State in "UNSYNCHRONIZED" and * randomly select a CM Handle and query the data nodes for CM Handle State in "READY". * - * @return a random yang model cm handle with State in READY and Operation Sync State in "UNSYNCHRONIZED", - * return null if not found + * @return a randomized yang model cm handle list with State in READY and Operation Sync State in "UNSYNCHRONIZED", + * return empty list if not found */ - public YangModelCmHandle getAnUnSynchronizedReadyCmHandle() { - final List unSynchronizedCmHandles = inventoryPersistence - .getCmHandlesByOperationalSyncState(SyncState.UNSYNCHRONIZED); - if (unSynchronizedCmHandles.isEmpty()) { - return null; - } - Collections.shuffle(unSynchronizedCmHandles); - for (final DataNode cmHandle : unSynchronizedCmHandles) { - final String cmHandleId = cmHandle.getLeaves().get("id").toString(); - final List readyCmHandles = inventoryPersistence - .getCmHandlesByIdAndState(cmHandleId, CmHandleState.READY); - if (!readyCmHandles.isEmpty()) { - return inventoryPersistence.getYangModelCmHandle(cmHandleId); + public List getUnsynchronizedReadyCmHandles() { + final List unsynchronizedCmHandles = cmHandleQueries + .queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED); + + final List yangModelCmHandles = new ArrayList<>(); + for (final DataNode unsynchronizedCmHandle : unsynchronizedCmHandles) { + final String cmHandleId = unsynchronizedCmHandle.getLeaves().get("id").toString(); + if (cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY)) { + yangModelCmHandles.addAll( + convertCmHandlesDataNodesToYangModelCmHandles( + Collections.singletonList(unsynchronizedCmHandle))); } } - return null; + + Collections.shuffle(yangModelCmHandles); + + return yangModelCmHandles; } /** - * Query data nodes for cm handles with an "LOCKED" cm handle state with reason LOCKED_MISBEHAVING". + * Query data nodes for cm handles with an "LOCKED" cm handle state with reason LOCKED_MODULE_SYNC_FAILED". * - * @return a random yang model cm handle with an ADVISED state, return null if not found + * @return a random LOCKED yang model cm handle, return null if not found */ - public List getLockedMisbehavingYangModelCmHandles() { - final List lockedCmHandleAsDataNodeList = inventoryPersistence.getCmHandleDataNodesByCpsPath( - "//lock-reason[@reason=\"LOCKED_MISBEHAVING\"]/ancestor::cm-handles", - FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); - return lockedCmHandleAsDataNodeList.stream() - .map(cmHandle -> YangDataConverter.convertCmHandleToYangModel(cmHandle, - cmHandle.getLeaves().get("id").toString())).collect(Collectors.toList()); + public List getModuleSyncFailedCmHandles() { + final List lockedCmHandlesAsDataNodeList = cmHandleQueries.queryCmHandleDataNodesByCpsPath( + "//lock-reason[@reason=\"LOCKED_MODULE_SYNC_FAILED\"]", + FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); + return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList); } /** @@ -139,8 +130,8 @@ public class SyncUtils { } } compositeState.setLockReason(CompositeState.LockReason.builder() - .details(String.format("Attempt #%d failed: %s", attempt, errorMessage)) - .lockReasonCategory(lockReasonCategory).build()); + .details(String.format("Attempt #%d failed: %s", attempt, errorMessage)) + .lockReasonCategory(lockReasonCategory).build()); } @@ -151,18 +142,22 @@ public class SyncUtils { * @return if the retry mechanism should be attempted */ public boolean isReadyForRetry(final CompositeState compositeState) { - int timeUntilNextAttempt = 1; + int timeInMinutesUntilNextAttempt = 1; final OffsetDateTime time = - OffsetDateTime.parse(compositeState.getLastUpdateTime(), - DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); + OffsetDateTime.parse(compositeState.getLastUpdateTime(), + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); final Matcher matcher = retryAttemptPattern.matcher(compositeState.getLockReason().getDetails()); if (matcher.find()) { - timeUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(matcher.group(1))); + timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(matcher.group(1))); } else { log.debug("First Attempt: no current attempts found."); } final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes(); - return timeSinceLastAttempt > timeUntilNextAttempt; + if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) { + log.info("Time until next attempt is {} minutes: ", + timeInMinutesUntilNextAttempt - timeSinceLastAttempt); + } + return timeSinceLastAttempt > timeInMinutesUntilNextAttempt; } /** @@ -173,7 +168,8 @@ public class SyncUtils { */ public String getResourceData(final String cmHandleId) { final ResponseEntity resourceDataResponseEntity = dmiDataOperations.getResourceDataFromDmi( - cmHandleId, DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL, + PASSTHROUGH_OPERATIONAL.getDatastoreName(), + cmHandleId, UUID.randomUUID().toString()); if (resourceDataResponseEntity.getStatusCode().is2xxSuccessful()) { return getFirstResource(resourceDataResponseEntity.getBody()); @@ -186,6 +182,13 @@ public class SyncUtils { final JsonNode overallJsonNode = jsonObjectMapper.convertToJsonNode(jsonObjectAsString); final Iterator> overallJsonTreeMap = overallJsonNode.fields(); final Map.Entry firstElement = overallJsonTreeMap.next(); - return jsonObjectMapper.asJsonString(ImmutableMap.of(firstElement.getKey(), firstElement.getValue())); + return jsonObjectMapper.asJsonString(Map.of(firstElement.getKey(), firstElement.getValue())); + } + + private static List convertCmHandlesDataNodesToYangModelCmHandles( + final List cmHandlesAsDataNodeList) { + return cmHandlesAsDataNodeList.stream() + .map(cmHandle -> YangDataConverter.convertCmHandleToYangModel(cmHandle, + cmHandle.getLeaves().get("id").toString())).collect(Collectors.toList()); } }