Improve performance of moduleSetTag lookup
[cps.git] / cps-ncmp-service / src / main / java / org / onap / cps / ncmp / api / impl / inventory / sync / ModuleSyncService.java
index b2949c2..dabfbbc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022-2023 Nordix Foundation
+ *  Copyright (C) 2022-2024 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.api.impl.inventory.sync;
 
+import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME;
+import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
+import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
 
+import java.time.OffsetDateTime;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsAdminService;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.onap.cps.api.CpsAnchorService;
+import org.onap.cps.api.CpsDataService;
 import org.onap.cps.api.CpsModuleService;
+import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
+import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
 import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations;
+import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.spi.CascadeDeleteAllowed;
+import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.exceptions.SchemaSetNotFoundException;
+import org.onap.cps.spi.model.DataNode;
 import org.onap.cps.spi.model.ModuleReference;
+import org.onap.cps.utils.JsonObjectMapper;
 import org.springframework.stereotype.Service;
 
 @Slf4j
@@ -43,40 +58,40 @@ public class ModuleSyncService {
 
     private final DmiModelOperations dmiModelOperations;
     private final CpsModuleService cpsModuleService;
-
-    private final CpsAdminService cpsAdminService;
+    private final CmHandleQueries cmHandleQueries;
+    private final CpsDataService cpsDataService;
+    private final CpsAnchorService cpsAnchorService;
+    private final JsonObjectMapper jsonObjectMapper;
+    private static final Map<String, String> NO_NEW_MODULES = Collections.emptyMap();
 
     /**
      * This method registers a cm handle and initiates modules sync.
      *
      * @param yangModelCmHandle the yang model of cm handle.
      */
-    public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) {
+    public void syncAndCreateOrUpgradeSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) {
+
+        final boolean inUpgrade = ModuleOperationsUtils.inUpgradeOrUpgradeFailed(yangModelCmHandle.getCompositeState());
 
-        final Collection<ModuleReference> allModuleReferencesFromCmHandle =
-                dmiModelOperations.getModuleReferences(yangModelCmHandle);
+        final ImmutableTriple<String, Map<String, String>, Collection<ModuleReference>>
+                allModuleReferencesAndNewModuleNameByModuleSetTag
+                = getAllModuleReferencesAndNewYangResourcesByModuleSetTag(yangModelCmHandle, inUpgrade);
 
-        final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService
-                .identifyNewModuleReferences(allModuleReferencesFromCmHandle);
+        final String moduleSetTag = allModuleReferencesAndNewModuleNameByModuleSetTag.getLeft();
+        final Map<String, String> newYangResources = allModuleReferencesAndNewModuleNameByModuleSetTag.getMiddle();
+        final Collection<ModuleReference> allModuleReferences
+                = allModuleReferencesAndNewModuleNameByModuleSetTag.getRight();
+        final String cmHandleId = yangModelCmHandle.getId();
 
-        final Map<String, String> newModuleNameToContentMap;
-        if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) {
-            newModuleNameToContentMap = Collections.emptyMap();
+        if (inUpgrade) {
+            cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
+                    newYangResources, allModuleReferences);
+            setCmHandleModuleSetTag(yangModelCmHandle, moduleSetTag);
         } else {
-            newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
-                    identifiedNewModuleReferencesFromCmHandle);
+            cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
+                    newYangResources, allModuleReferences);
+            cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId);
         }
-        createSchemaSetAndAnchor(yangModelCmHandle, newModuleNameToContentMap, allModuleReferencesFromCmHandle);
-    }
-
-    private void createSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle,
-                                          final Map<String, String> newModuleNameToContentMap,
-                                          final Collection<ModuleReference> allModuleReferencesFromCmHandle) {
-        final String schemaSetAndAnchorName = yangModelCmHandle.getId();
-        cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName,
-                        newModuleNameToContentMap, allModuleReferencesFromCmHandle);
-        cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName,
-            schemaSetAndAnchorName);
     }
 
     /**
@@ -94,4 +109,62 @@ public class ModuleSyncService {
         }
     }
 
+    private ImmutableTriple<String, Map<String, String>, Collection<ModuleReference>>
+        getAllModuleReferencesAndNewYangResourcesByModuleSetTag(final YangModelCmHandle yangModelCmHandle,
+                                                                final boolean inUpgrade) {
+        final String moduleSetTag = getModuleSetTag(yangModelCmHandle, inUpgrade);
+        final Collection<ModuleReference> allModuleReferences;
+        final Map<String, String> newYangResources;
+
+        final YangModelCmHandle cmHandleWithSameModuleSetTag = getAnyReadyCmHandleByModuleSetTag(moduleSetTag);
+        if (cmHandleWithSameModuleSetTag == null) {
+            allModuleReferences = dmiModelOperations.getModuleReferences(yangModelCmHandle);
+            newYangResources = getNewModuleNameToContentMap(yangModelCmHandle, allModuleReferences);
+        } else {
+            log.info("Found other cm handle having same module set tag: {}", moduleSetTag);
+            allModuleReferences = cpsModuleService.getYangResourcesModuleReferences(
+                    NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleWithSameModuleSetTag.getId());
+            newYangResources = NO_NEW_MODULES;
+        }
+        return ImmutableTriple.of(moduleSetTag, newYangResources, allModuleReferences);
+    }
+
+    private YangModelCmHandle getAnyReadyCmHandleByModuleSetTag(final String moduleSetTag) {
+        if (StringUtils.isBlank(moduleSetTag)) {
+            return null;
+        }
+        final String escapedModuleSetTag = moduleSetTag.replace("'", "''");
+        final List<DataNode> dataNodes = cmHandleQueries.queryNcmpRegistryByCpsPath(
+                NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@module-set-tag='" + escapedModuleSetTag + "']",
+                FetchDescendantsOption.DIRECT_CHILDREN_ONLY);
+        return dataNodes.stream().map(YangDataConverter::convertCmHandleToYangModel)
+                .filter(cmHandle -> cmHandle.getCompositeState().getCmHandleState() == CmHandleState.READY)
+                .findFirst().orElse(null);
+    }
+
+    private void setCmHandleModuleSetTag(final YangModelCmHandle upgradedCmHandle, final String moduleSetTag) {
+        final Map<String, Map<String, String>> dmiRegistryProperties = new HashMap<>(1);
+        final Map<String, String> cmHandleProperties = new HashMap<>(2);
+        cmHandleProperties.put("id", upgradedCmHandle.getId());
+        cmHandleProperties.put("module-set-tag", moduleSetTag);
+        dmiRegistryProperties.put("cm-handles", cmHandleProperties);
+        cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
+                jsonObjectMapper.asJsonString(dmiRegistryProperties), OffsetDateTime.now());
+    }
+
+    private Map<String, String> getNewModuleNameToContentMap(final YangModelCmHandle yangModelCmHandle,
+                                                             final Collection<ModuleReference> moduleReferences) {
+        final Collection<ModuleReference> identifiedNewModuleReferences = cpsModuleService
+                .identifyNewModuleReferences(moduleReferences);
+        return dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, identifiedNewModuleReferences);
+    }
+
+    private String getModuleSetTag(final YangModelCmHandle yangModelCmHandle, final boolean inUpgrade) {
+        if (inUpgrade) {
+            return ModuleOperationsUtils.getUpgradedModuleSetTagFromLockReason(
+                    yangModelCmHandle.getCompositeState().getLockReason());
+        }
+        return yangModelCmHandle.getModuleSetTag();
+    }
+
 }