Introduce Hazelcast for alternateId-cmHandle relation 74/136974/26
authorleventecsanyi <levente.csanyi@est.tech>
Thu, 11 Jan 2024 11:53:26 +0000 (12:53 +0100)
committerToine Siebelink <toine.siebelink@est.tech>
Thu, 1 Feb 2024 09:37:09 +0000 (09:37 +0000)
    - added new Hazelcast config
    - added cache initialization in CmHandleIdMapper
    - added unit tests
    - updated deployment.rst
    - refactored cache updating

Issue-ID: CPS-1988
Change-Id: Iea6f884e584bf8cea8612ddbced4329e783c60a5
Signed-off-by: leventecsanyi <levente.csanyi@est.tech>
12 files changed:
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyCmHandleQueryService.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfig.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapper.java [new file with mode: 0644]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfigSpec.groovy [new file with mode: 0644]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapperSpec.groovy [new file with mode: 0644]
docs/deployment.rst

index f29fd68..06522f8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============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.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -61,4 +61,11 @@ public interface NetworkCmProxyCmHandleQueryService {
      * @return collection of cm handles
      */
     Collection<NcmpServiceCmHandle> queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
      * @return collection of cm handles
      */
     Collection<NcmpServiceCmHandle> queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
+
+    /**
+     * Query and return all cm handle objects.
+     *
+     * @return collection of cm handles
+     */
+    Collection<NcmpServiceCmHandle> getAllCmHandles();
 }
 }
index 1f6c948..6f92a9e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============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.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -97,6 +97,12 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
         return getNcmpServiceCmHandles(cmHandleIds);
     }
 
         return getNcmpServiceCmHandles(cmHandleIds);
     }
 
+    @Override
+    public Collection<NcmpServiceCmHandle> getAllCmHandles() {
+        final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT).iterator().next();
+        return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
+    }
+
     private Collection<String> queryCmHandlesByDmiPlugin(
             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
         final Map<String, String> dmiPropertyQueryPairs =
     private Collection<String> queryCmHandlesByDmiPlugin(
             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
         final Map<String, String> dmiPropertyQueryPairs =
@@ -216,11 +222,6 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
         return Collections.emptyList();
     }
 
         return Collections.emptyList();
     }
 
-    private Collection<NcmpServiceCmHandle> getAllCmHandles() {
-        final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT).iterator().next();
-        return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
-    }
-
     private Collection<String> getAllCmHandleIds() {
         final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY)
                 .iterator().next();
     private Collection<String> getAllCmHandleIds() {
         final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY)
                 .iterator().next();
index 469d75a..3fa0504 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 highstreet technologies GmbH
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 highstreet technologies GmbH
- *  Modifications Copyright (C) 2021-2023 Nordix Foundation
+ *  Modifications Copyright (C) 2021-2024 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021-2022 Bell Canada
  *  Modifications Copyright (C) 2023 TechMahindra Ltd.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021-2022 Bell Canada
  *  Modifications Copyright (C) 2023 TechMahindra Ltd.
@@ -48,6 +48,7 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.ncmp.api.NcmpResponseStatus;
 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.ncmp.api.NcmpResponseStatus;
 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
@@ -65,6 +66,7 @@ import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
 import org.onap.cps.ncmp.api.impl.operations.OperationType;
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager;
 import org.onap.cps.ncmp.api.impl.operations.OperationType;
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager;
+import org.onap.cps.ncmp.api.impl.utils.CmHandleIdMapper;
 import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions;
 import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions;
 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
 import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions;
 import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions;
 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
@@ -104,10 +106,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     private final IMap<String, Object> moduleSyncStartedOnCmHandles;
     private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
     private final TrustLevelManager trustLevelManager;
     private final IMap<String, Object> moduleSyncStartedOnCmHandles;
     private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
     private final TrustLevelManager trustLevelManager;
+    private final CmHandleIdMapper cmHandleIdMapper;
 
     @Override
     public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
         final DmiPluginRegistration dmiPluginRegistration) {
 
     @Override
     public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
         final DmiPluginRegistration dmiPluginRegistration) {
+        cacheAlternateIds(dmiPluginRegistration.getCreatedCmHandles());
         dmiPluginRegistration.validateDmiPluginRegistration();
         final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse();
 
         dmiPluginRegistration.validateDmiPluginRegistration();
         final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse();
 
@@ -367,10 +371,17 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
 
         yangModelCmHandles.removeIf(yangModelCmHandle -> notDeletedCmHandles.contains(yangModelCmHandle.getId()));
         updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETED);
 
         yangModelCmHandles.removeIf(yangModelCmHandle -> notDeletedCmHandles.contains(yangModelCmHandle.getId()));
         updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETED);
+        removeEntriesFromAlternateIdCache(yangModelCmHandles);
 
         return cmHandleRegistrationResponses;
     }
 
 
         return cmHandleRegistrationResponses;
     }
 
+    private void removeEntriesFromAlternateIdCache(final Collection<YangModelCmHandle> yangModelCmHandles) {
+        for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandles) {
+            cmHandleIdMapper.removeMapping(yangModelCmHandle.getId());
+        }
+    }
+
     protected List<CmHandleRegistrationResponse> parseAndProcessUpgradedCmHandlesInRegistration(
         final DmiPluginRegistration dmiPluginRegistration) {
 
     protected List<CmHandleRegistrationResponse> parseAndProcessUpgradedCmHandlesInRegistration(
         final DmiPluginRegistration dmiPluginRegistration) {
 
@@ -527,4 +538,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
         }
     }
 
         }
     }
 
+    private void cacheAlternateIds(final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) {
+        for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) {
+            if (!StringUtils.isEmpty(ncmpServiceCmHandle.getAlternateId())) {
+                cmHandleIdMapper.addMapping(ncmpServiceCmHandle.getCmHandleId(), ncmpServiceCmHandle.getAlternateId());
+            }
+        }
+    }
+
 }
 }
index 1520932..13b3fca 100644 (file)
@@ -43,9 +43,9 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import java.util.regex.Pattern;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.api.impl.utils.CmHandleIdMapper;
 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse;
 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse;
@@ -67,6 +67,7 @@ public class NetworkCmProxyDataServicePropertyHandler {
     private final InventoryPersistence inventoryPersistence;
     private final CpsDataService cpsDataService;
     private final JsonObjectMapper jsonObjectMapper;
     private final InventoryPersistence inventoryPersistence;
     private final CpsDataService cpsDataService;
     private final JsonObjectMapper jsonObjectMapper;
+    private final CmHandleIdMapper cmHandleIdMapper;
 
     /**
      * Iterates over incoming ncmpServiceCmHandles and update the dataNodes based on the updated attributes.
 
     /**
      * Iterates over incoming ncmpServiceCmHandles and update the dataNodes based on the updated attributes.
@@ -105,19 +106,15 @@ public class NetworkCmProxyDataServicePropertyHandler {
     private void updateAlternateId(final DataNode existingCmHandleDataNode,
                                    final NcmpServiceCmHandle ncmpServiceCmHandle) {
         final String newAlternateId = ncmpServiceCmHandle.getAlternateId();
     private void updateAlternateId(final DataNode existingCmHandleDataNode,
                                    final NcmpServiceCmHandle ncmpServiceCmHandle) {
         final String newAlternateId = ncmpServiceCmHandle.getAlternateId();
-        if (!StringUtils.isEmpty(newAlternateId)) {
-            final String existingAlternateId = (String) existingCmHandleDataNode.getLeaves().get("alternate-id");
-            if (StringUtils.isEmpty(existingAlternateId)) {
+        if (cmHandleIdMapper.addMapping(ncmpServiceCmHandle.getCmHandleId(), newAlternateId)) {
+            try {
                 final YangModelCmHandle yangModelCmHandle =
                         YangDataConverter.convertCmHandleToYangModel(existingCmHandleDataNode,
                                 ncmpServiceCmHandle.getCmHandleId());
                 setAndUpdateAlternateId(yangModelCmHandle, newAlternateId);
                 final YangModelCmHandle yangModelCmHandle =
                         YangDataConverter.convertCmHandleToYangModel(existingCmHandleDataNode,
                                 ncmpServiceCmHandle.getCmHandleId());
                 setAndUpdateAlternateId(yangModelCmHandle, newAlternateId);
-            } else {
-                if (!newAlternateId.equals(existingAlternateId)) {
-                    log.warn("Unable to update alternateId for cmHandle {}. "
-                                    + "Value for alternateId has been set previously.",
-                            ncmpServiceCmHandle.getCmHandleId());
-                }
+            } catch (final Exception e) {
+                cmHandleIdMapper.removeMapping(ncmpServiceCmHandle.getCmHandleId());
+                throw e;
             }
         }
     }
             }
         }
     }
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfig.java
new file mode 100644 (file)
index 0000000..a69d144
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START========================================================
+ *  Copyright (C) 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.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.config.embeddedcache;
+
+import com.hazelcast.config.MapConfig;
+import java.util.Map;
+import org.onap.cps.cache.HazelcastCacheConfig;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AlternateIdCacheConfig extends HazelcastCacheConfig {
+
+    private static final MapConfig alternateIdPerCmHandleIdMapConfig =
+            createMapConfig("alternateIdPerCmHandleIdMapConfig");
+
+    private static final MapConfig cmHandleIdPerAlternateIdMapConfig =
+            createMapConfig("cmHandleIdPerAlternateIdMapConfig");
+
+    /**
+     * Distributed instance of alternate id cache containing the alternate id per cm handle id.
+     *
+     * @return the cached map.
+     */
+    @Bean
+    public Map<String, String> alternateIdPerCmHandleId() {
+        return createHazelcastInstance("hazelcastInstanceAlternateIdPerCmHandleIdMap",
+                alternateIdPerCmHandleIdMapConfig).getMap("alternateIdPerCmHandleId");
+    }
+
+    /**
+     * Distributed instance of alternate id cache containing the cm handle id per alternate id.
+     *
+     * @return the cached map.
+     */
+    @Bean
+    public Map<String, String> cmHandleIdPerAlternateId() {
+        return createHazelcastInstance("hazelcastInstanceCmHandleIdPerAlternateIdMap",
+                cmHandleIdPerAlternateIdMapConfig).getMap("cmHandleIdPerAlternateId");
+    }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapper.java
new file mode 100644 (file)
index 0000000..8175fb5
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * ============LICENSE_START========================================================
+ * Copyright (c) 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.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an 'AS IS' BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.utils;
+
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CmHandleIdMapper {
+
+    private final Map<String, String> alternateIdPerCmHandleId;
+    private final Map<String, String> cmHandleIdPerAlternateId;
+    private final NetworkCmProxyCmHandleQueryService networkCmProxyCmHandleQueryService;
+
+    private boolean cacheIsInitialized = false;
+
+    public String cmHandleIdToAlternateId(final String cmHandleId) {
+        initializeCache();
+        return alternateIdPerCmHandleId.get(cmHandleId);
+    }
+
+    public String alternateIdToCmHandleId(final String alternateId) {
+        initializeCache();
+        return cmHandleIdPerAlternateId.get(alternateId);
+    }
+
+    public boolean addMapping(final String cmHandleId, final String alternateId) {
+        initializeCache();
+        return addMappingWithValidation(cmHandleId, alternateId);
+    }
+
+
+    private boolean addMappingWithValidation(final String cmHandleId, final String alternateId) {
+        if (alternateIdPerCmHandleId.containsKey(cmHandleId)) {
+            final String originalAlternateId = alternateIdPerCmHandleId.get(cmHandleId);
+            if (!originalAlternateId.equals(alternateId)) {
+                log.warn("Alternate id update ignored, cannot update cm handle {}, already has an alternate id of {}",
+                        cmHandleId, originalAlternateId);
+            }
+            return false;
+        }
+        if (StringUtils.isBlank(alternateId)) {
+            return false;
+        }
+        alternateIdPerCmHandleId.put(cmHandleId, alternateId);
+        cmHandleIdPerAlternateId.put(alternateId, cmHandleId);
+        return true;
+    }
+
+    public void removeMapping(final String cmHandleId) {
+        final String alternateId = alternateIdPerCmHandleId.remove(cmHandleId);
+        cmHandleIdPerAlternateId.remove(alternateId);
+    }
+
+    private void initializeCache() {
+        if (!cacheIsInitialized) {
+            networkCmProxyCmHandleQueryService.getAllCmHandles().forEach(cmHandle ->
+                addMappingWithValidation(cmHandle.getCmHandleId(), cmHandle.getAlternateId())
+            );
+            log.info("Alternate ID cache initialized from DB with {} cm handle/alternate id pairs ",
+                    alternateIdPerCmHandleId.size());
+            cacheIsInitialized = true;
+        }
+    }
+}
index f565ede..59bf942 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation
+ *  Copyright (C) 2021-2024 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,6 +22,7 @@
 package org.onap.cps.ncmp.api.impl
 
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager
 package org.onap.cps.ncmp.api.impl
 
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager
+import org.onap.cps.ncmp.api.impl.utils.CmHandleIdMapper
 import org.onap.cps.ncmp.api.models.UpgradedCmHandles
 
 import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
 import org.onap.cps.ncmp.api.models.UpgradedCmHandles
 
 import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
@@ -71,6 +72,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
     def mockModuleSyncStartedOnCmHandles = Mock(IMap<String, Object>)
     def trustLevelPerDmiPlugin = [:]
     def mockTrustLevelManager = Mock(TrustLevelManager)
     def mockModuleSyncStartedOnCmHandles = Mock(IMap<String, Object>)
     def trustLevelPerDmiPlugin = [:]
     def mockTrustLevelManager = Mock(TrustLevelManager)
+    def mockCmHandleIdMapper = Mock(CmHandleIdMapper)
     def objectUnderTest = getObjectUnderTest()
 
     def 'DMI Registration: Create, Update, Delete & Upgrade operations are processed in the right order'() {
     def objectUnderTest = getObjectUnderTest()
 
     def 'DMI Registration: Create, Update, Delete & Upgrade operations are processed in the right order'() {
@@ -432,11 +434,21 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
         'an unexpected exception'    | 'cmhandle'             | new RuntimeException('Failed')            || UNKNOWN_ERROR        | 'Failed'
     }
 
         'an unexpected exception'    | 'cmhandle'             | new RuntimeException('Failed')            || UNKNOWN_ERROR        | 'Failed'
     }
 
+    def 'Adding data to alternate id caches.'() {
+        given: 'a registration with three CM Handles to be created'
+            def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server',
+                    createdCmHandles: [new NcmpServiceCmHandle(cmHandleId: 'cmhandle1', alternateId: 'my-alternate-id-1')])
+        when: 'the DMI plugin registration happens'
+            objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+        then: 'the new alternate id is added to the cache'
+            1 * mockCmHandleIdMapper.addMapping('cmhandle1', 'my-alternate-id-1')
+    }
+
     def getObjectUnderTest() {
         return Spy(new NetworkCmProxyDataServiceImpl(spiedJsonObjectMapper, mockDmiDataOperations,
                 mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCmHandleQueries,
                 stubbedNetworkCmProxyCmHandlerQueryService, mockLcmEventsCmHandleStateHandler, mockCpsDataService,
     def getObjectUnderTest() {
         return Spy(new NetworkCmProxyDataServiceImpl(spiedJsonObjectMapper, mockDmiDataOperations,
                 mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCmHandleQueries,
                 stubbedNetworkCmProxyCmHandlerQueryService, mockLcmEventsCmHandleStateHandler, mockCpsDataService,
-                mockModuleSyncStartedOnCmHandles, trustLevelPerDmiPlugin, mockTrustLevelManager))
+                mockModuleSyncStartedOnCmHandles, trustLevelPerDmiPlugin as Map<String, TrustLevel>, mockTrustLevelManager, mockCmHandleIdMapper))
     }
 
     def addPersistedYangModelCmHandles(ids) {
     }
 
     def addPersistedYangModelCmHandles(ids) {
index 4f7b726..c1af902 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation
+ *  Copyright (C) 2021-2024 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021-2022 Bell Canada
  *  Modifications Copyright (C) 2023 TechMahindra Ltd.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021-2022 Bell Canada
  *  Modifications Copyright (C) 2023 TechMahindra Ltd.
@@ -22,6 +22,9 @@
  */
 
 package org.onap.cps.ncmp.api.impl
  */
 
 package org.onap.cps.ncmp.api.impl
+
+import org.onap.cps.ncmp.api.impl.utils.CmHandleIdMapper
+
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
 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.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
 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
@@ -78,6 +81,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
     def stubModuleSyncStartedOnCmHandles = Stub(IMap<String, Object>)
     def stubTrustLevelPerDmiPlugin = Stub(Map<String, TrustLevel>)
     def mockTrustLevelManager = Mock(TrustLevelManager)
     def stubModuleSyncStartedOnCmHandles = Stub(IMap<String, Object>)
     def stubTrustLevelPerDmiPlugin = Stub(Map<String, TrustLevel>)
     def mockTrustLevelManager = Mock(TrustLevelManager)
+    def mockCmHandleIdMapper = Mock(CmHandleIdMapper)
 
     def NO_TOPIC = null
     def NO_REQUEST_ID = null
 
     def NO_TOPIC = null
     def NO_REQUEST_ID = null
@@ -97,7 +101,9 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             mockCpsDataService,
             stubModuleSyncStartedOnCmHandles,
             stubTrustLevelPerDmiPlugin,
             mockCpsDataService,
             stubModuleSyncStartedOnCmHandles,
             stubTrustLevelPerDmiPlugin,
-            mockTrustLevelManager)
+            mockTrustLevelManager,
+            mockCmHandleIdMapper
+    )
 
     def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']"
 
 
     def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']"
 
index 2a15e6c..f94c34c 100644 (file)
 
 package org.onap.cps.ncmp.api.impl
 
 
 package org.onap.cps.ncmp.api.impl
 
-import ch.qos.logback.classic.Level
-import ch.qos.logback.classic.Logger
-import ch.qos.logback.classic.spi.ILoggingEvent
+
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.databind.ObjectMapper
-import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.BeforeEach
-import org.slf4j.LoggerFactory
+import org.onap.cps.ncmp.api.impl.utils.CmHandleIdMapper
 
 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_DATASPACE_NAME
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
@@ -37,7 +33,6 @@ import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID
 import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
 import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
 
 import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
 import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
 
-import ch.qos.logback.core.read.ListAppender
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.utils.JsonObjectMapper
 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.utils.JsonObjectMapper
 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
@@ -53,20 +48,9 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
     def mockInventoryPersistence = Mock(InventoryPersistence)
     def mockCpsDataService = Mock(CpsDataService)
     def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
     def mockInventoryPersistence = Mock(InventoryPersistence)
     def mockCpsDataService = Mock(CpsDataService)
     def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
-    def logger = Spy(ListAppender<ILoggingEvent>)
-
-    @BeforeEach
-    void setup() {
-        ((Logger) LoggerFactory.getLogger(NetworkCmProxyDataServicePropertyHandler.class)).addAppender(logger);
-        logger.start();
-    }
+    def mockCmHandleIdMapper = Mock(CmHandleIdMapper)
 
 
-    @AfterEach
-    void teardown() {
-        ((Logger) LoggerFactory.getLogger(NetworkCmProxyDataServicePropertyHandler.class)).detachAndStopAllAppenders();
-    }
-
-    def objectUnderTest = new NetworkCmProxyDataServicePropertyHandler(mockInventoryPersistence, mockCpsDataService, jsonObjectMapper)
+    def objectUnderTest = new NetworkCmProxyDataServicePropertyHandler(mockInventoryPersistence, mockCpsDataService, jsonObjectMapper, mockCmHandleIdMapper)
     def static cmHandleId = 'myHandle1'
     def static cmHandleXpath = "/dmi-registry/cm-handles[@id='${cmHandleId}']"
 
     def static cmHandleId = 'myHandle1'
     def static cmHandleXpath = "/dmi-registry/cm-handles[@id='${cmHandleId}']"
 
@@ -198,36 +182,41 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
             2 * mockInventoryPersistence.replaceListContent(cmHandleXpath,_)
     }
 
             2 * mockInventoryPersistence.replaceListContent(cmHandleXpath,_)
     }
 
-    def 'Update CM Handle Alternate ID when #scenario'() {
-        given: 'an existing cm handle with alternate id #existingAlternateId'
-            DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath, leaves: ['alternate-id': oldAlternateId])
-        and: 'an update request with an alternate id #newAlternateId'
-            def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: newAlternateId)
-        when: 'update data node leaves is called with the update request'
+    def 'Update CM Handle Alternate ID with #scenario'() {
+        given: 'an existing cm handle'
+            DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath)
+        and: 'an update request with an alternate id'
+            def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: 'alt-1' )
+        when: 'update alternate id method is called with the update request'
             objectUnderTest.updateAlternateId(existingCmHandleDataNode, ncmpServiceCmHandle)
         then: 'the update node leaves method is invoked as many times as expected'
             objectUnderTest.updateAlternateId(existingCmHandleDataNode, ncmpServiceCmHandle)
         then: 'the update node leaves method is invoked as many times as expected'
-            numberOfInvocations * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', _, _) >> { args ->
-                assert args[3].contains(newAlternateId)
-            }
-        and: 'correct information is logged'
-            def lastLoggingEvent = logger.list[0]
-            if (expectLogWarning) {
-                assert lastLoggingEvent.level == Level.WARN
-                assert lastLoggingEvent.formattedMessage.contains('Unable')
-            } else if (numberOfInvocations == 1) {
-                assert lastLoggingEvent.level == Level.INFO
-                assert lastLoggingEvent.formattedMessage.contains('Updating alternateId')
-            } else {
-                assert lastLoggingEvent == null
-            }
+            callsToDataService * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', _, _) >>
+                    { args ->
+                        assert args[3].contains('alt-1')
+                    }
+            mockCmHandleIdMapper.addMapping(cmHandleId, 'alt-1') >> isNewMapping
         where: 'following updates are attempted'
         where: 'following updates are attempted'
-            scenario                     | oldAlternateId | newAlternateId || numberOfInvocations | expectLogWarning
-            'old alternate id null'      | null           | 'new'          || 1                   | false
-            'old alternate id empty'     | ''             | 'new'          || 1                   | false
-            'old alternate id not empty' | 'old'          | 'new'          || 0                   | true
-            'same alternate id'          | 'old'          | 'old'          || 0                   | false
-            'empty new alternate id'     | 'old'          | ''             || 0                   | false
-            'null new alternate id'      | 'old'          | null           || 0                   | false
+            scenario                | isNewMapping || callsToDataService
+            'new alternate id   '   | true         || 1
+            'existing alternate id' | false        || 0
+    }
+
+    def 'Alternate ID removed from cache when persisting fails.'() {
+        given: 'an existing data node and an update request with an alternate id'
+            def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: 'alt-1')
+            DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath, leaves: ['alternate-id': null])
+        and: 'a new mapping is added'
+            mockCmHandleIdMapper.addMapping(cmHandleId, 'alt-1') >> true
+        and: 'but an exception occurs while saving'
+            def originalException = new NullPointerException('some exception')
+            mockCpsDataService.updateNodeLeaves(*_) >> { throw originalException }
+        when: 'updating of alternate id called'
+            objectUnderTest.updateAlternateId(existingCmHandleDataNode, ncmpServiceCmHandle)
+        then: 'the original exception is thrown up'
+            def thrownException = thrown(NullPointerException)
+            assert thrownException == originalException
+        and: 'the mapping is removed from the cache'
+            1 * mockCmHandleIdMapper.removeMapping(cmHandleId)
     }
 
     def convertToProperties(expectedPropertiesAfterUpdateAsMap) {
     }
 
     def convertToProperties(expectedPropertiesAfterUpdateAsMap) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfigSpec.groovy
new file mode 100644 (file)
index 0000000..71c5293
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START========================================================
+ *  Copyright (C) 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.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.config.embeddedcache
+
+import com.hazelcast.core.Hazelcast
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import spock.lang.Specification
+
+@SpringBootTest(classes = [AlternateIdCacheConfig])
+class AlternateIdCacheConfigSpec extends Specification {
+
+    @Autowired
+    private Map<String, String> cmHandleIdPerAlternateId
+    @Autowired
+    private Map<String, String> alternateIdPerCmHandleId
+
+    def 'Embedded (hazelcast) cache for alternate id - cm handle id caches.'() {
+        expect: 'system is able to create an instance of the Alternate ID Cache'
+            assert null != cmHandleIdPerAlternateId
+            assert null != alternateIdPerCmHandleId
+        and: 'there are at least 2 instances'
+            assert Hazelcast.allHazelcastInstances.size() > 1
+        and: 'Alternate ID Caches are present'
+            assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceAlternateIdPerCmHandleIdMap')
+                    && Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceCmHandleIdPerAlternateIdMap')
+    }
+
+    def 'Verify configs of the alternate id distributed objects.'(){
+        when: 'retrieving the map config of module set tag'
+            def alternateIdConfig =  Hazelcast.getHazelcastInstanceByName('hazelcastInstanceAlternateIdPerCmHandleIdMap').config
+            def alternateIdMapConfig = alternateIdConfig.mapConfigs.get('alternateIdPerCmHandleIdMapConfig')
+            def cmHandleIdConfig =  Hazelcast.getHazelcastInstanceByName('hazelcastInstanceCmHandleIdPerAlternateIdMap').config
+            def cmHandleIdIdMapConfig = cmHandleIdConfig.mapConfigs.get('cmHandleIdPerAlternateIdMapConfig')
+        then: 'the map configs have the correct number of backups'
+            assert alternateIdMapConfig.backupCount == 3
+            assert alternateIdMapConfig.asyncBackupCount == 3
+            assert cmHandleIdIdMapConfig.backupCount == 3
+            assert cmHandleIdIdMapConfig.asyncBackupCount == 3
+    }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapperSpec.groovy
new file mode 100644 (file)
index 0000000..0a2962e
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * ============LICENSE_START========================================================
+ * Copyright (c) 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.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an 'AS IS' BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.utils
+
+import ch.qos.logback.classic.Level
+import ch.qos.logback.classic.Logger
+import ch.qos.logback.classic.spi.ILoggingEvent
+import ch.qos.logback.core.read.ListAppender
+import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import org.slf4j.LoggerFactory
+import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService
+import spock.lang.Specification
+
+class CmHandleIdMapperSpec extends Specification {
+
+    def alternateIdPerCmHandle = new HashMap<String, String>()
+    def cmHandlePerAlternateId = new HashMap<String, String>()
+    def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandleQueryService)
+
+    def objectUnderTest = new CmHandleIdMapper(alternateIdPerCmHandle, cmHandlePerAlternateId, mockCpsCmHandlerQueryService)
+
+    def logger = Spy(ListAppender<ILoggingEvent>)
+
+    def setup() {
+        ((Logger) LoggerFactory.getLogger(CmHandleIdMapper.class)).addAppender(logger)
+        logger.start()
+        mockCpsCmHandlerQueryService.getAllCmHandles() >> []
+        assert objectUnderTest.addMapping('my cmhandle id', 'my alternate id')
+    }
+
+    void cleanup() {
+        ((Logger) LoggerFactory.getLogger(CmHandleIdMapper.class)).detachAndStopAllAppenders()
+    }
+
+    def 'Checking entries in the cache.'() {
+        expect: 'the alternate id can be converted to cmhandle id'
+            assert objectUnderTest.alternateIdToCmHandleId('my alternate id') == 'my cmhandle id'
+        and: 'the cmhandle id can be converted to alternate id'
+            assert objectUnderTest.cmHandleIdToAlternateId('my cmhandle id') == 'my alternate id'
+    }
+
+    def 'Attempt adding #scenario alternate id.'() {
+        expect: 'cmhandle id - alternate id mapping fails'
+            assert objectUnderTest.addMapping('ch-1', alternateId) == false
+        and: 'alternate id looked up by cmhandle id unsuccessfully'
+            assert objectUnderTest.cmHandleIdToAlternateId('ch-1') == null
+        where: 'alternate id has an invalid value'
+            scenario | alternateId
+            'empty'  | ''
+            'blank'  | '  '
+            'null'   | null
+    }
+
+    def 'Remove an entry from the cache.'() {
+        when: 'removing an entry'
+            objectUnderTest.removeMapping('my cmhandle id')
+        then: 'converting alternate id returns null'
+            assert objectUnderTest.alternateIdToCmHandleId('my alternate id') == null
+        and: 'converting cmhandle id returns null'
+            assert objectUnderTest.cmHandleIdToAlternateId('my cmhandle id') == null
+    }
+
+    def 'Cannot update existing alternate id.'() {
+        given: 'attempt to update an existing alternate id'
+            objectUnderTest.addMapping('my cmhandle id', 'other id')
+        expect: 'still returns the original alternate id'
+            assert objectUnderTest.cmHandleIdToAlternateId('my cmhandle id') == 'my alternate id'
+        and: 'converting other alternate id returns null'
+            assert objectUnderTest.alternateIdToCmHandleId('other id') == null
+        and: 'a warning is logged with the original alternate id'
+            def lastLoggingEvent = logger.list[1]
+            assert lastLoggingEvent.level == Level.WARN
+            assert lastLoggingEvent.formattedMessage.contains('my alternate id')
+    }
+
+    def 'Update existing alternate id with the same value.'() {
+        expect: 'update an existing alternate id with the same value returns false (no update)'
+            assert objectUnderTest.addMapping('my cmhandle id', 'my alternate id') == false
+        and: 'conversion still returns the original alternate id'
+            assert objectUnderTest.cmHandleIdToAlternateId('my cmhandle id') == 'my alternate id'
+    }
+
+    def 'Initializing cache #scenario.'() {
+        when: 'the cache is (re-)initialized'
+            objectUnderTest.cacheIsInitialized = false
+            objectUnderTest.initializeCache()
+        then: 'the alternate id can be converted to cmhandle id'
+            assert objectUnderTest.alternateIdToCmHandleId('alt-1') == convertedCmHandleId
+        and: 'the cm handle id can be converted to alternate id'
+            assert objectUnderTest.cmHandleIdToAlternateId('ch-1') == convertedAlternatId
+        and: 'the query service is called to get the initial data'
+            1 * mockCpsCmHandlerQueryService.getAllCmHandles() >> persistedCmHandles
+        where: 'the initial data has a cm handle #scenario'
+            scenario                  | persistedCmHandles                                                  || convertedAlternatId | convertedCmHandleId
+            'with alternate id'       | [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: 'alt-1')] || 'alt-1'             | 'ch-1'
+            'without alternate id'    | [new NcmpServiceCmHandle(cmHandleId: 'ch-1')]                       || null                | null
+            'with blank alternate id' | [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: ' ')]     || null                | null
+    }
+}
\ No newline at end of file
index 7ba163d..ca7824d 100644 (file)
@@ -1,6 +1,6 @@
 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
 .. http://creativecommons.org/licenses/by/4.0
 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
 .. http://creativecommons.org/licenses/by/4.0
-.. Copyright (C) 2021-2022 Nordix Foundation
+.. Copyright (C) 2021-2024 Nordix Foundation
 .. Modifications Copyright (C) 2021 Bell Canada.
 
 .. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
 .. Modifications Copyright (C) 2021 Bell Canada.
 
 .. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
@@ -316,24 +316,28 @@ These instances require some additional ports to be available. The default range
 
 Below are the list of distributed datastructures that we have.
 
 
 Below are the list of distributed datastructures that we have.
 
-+--------------+---------------------------------+----------------------------------------------------------+
-| Component    | Datastructure name              |                 Use                                      |
-+==============+=================================+==========================================================+
-| cps-core     | anchorDataCache                 | Used to resolve prefix for the container name.           |
-+--------------+---------------------------------+----------------------------------------------------------+
-| cps-ncmp     | moduleSyncStartedOnCmHandles    | Watchdog process to register cmHandles.                  |
-+--------------+---------------------------------+----------------------------------------------------------+
-| cps-ncmp     | dataSyncSemaphores              | Watchdog process to sync data from the nodes.            |
-+--------------+---------------------------------+----------------------------------------------------------+
-| cps-ncmp     | moduleSyncWorkQueue             | Queue used internally for workers to pick the task.      |
-+--------------+---------------------------------+----------------------------------------------------------+
-| cps-ncmp     | untrustworthyCmHandlesSet       | Stores untrustworthy cmHandles whose TrustLevel is NONE. |
-+--------------+---------------------------------+----------------------------------------------------------+
-| cps-ncmp     | trustLevelPerDmiPlugin          | Stores the TrustLevel for the dmi-plugins.               |
-+--------------+---------------------------------+----------------------------------------------------------+
-| cps-ncmp     | moduleSetTagCacheMapConfig      | Stores the Module Set Tags for cmHandles.                |
-+--------------+---------------------------------+----------------------------------------------------------+
-| cps-ncmp     | cmSubscriptionEventCache        | Stores and tracks CmSubscription requests.               |
-+--------------+---------------------------------+----------------------------------------------------------+
-
-Total number of caches : 8
++--------------+------------------------------------+-----------------------------------------------------------+
+| Component    | Datastructure name                 |                 Use                                       |
++==============+====================================+===========================================================+
+| cps-core     | anchorDataCache                    | Used to resolve prefix for the container name.            |
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | moduleSyncStartedOnCmHandles       | Watchdog process to register cm handles.                  |
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | dataSyncSemaphores                 | Watchdog process to sync data from the nodes.             |
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | moduleSyncWorkQueue                | Queue used internally for workers to pick the task.       |
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | untrustworthyCmHandlesSet          | Stores untrustworthy cm handles whose trust level is NONE.|
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | trustLevelPerDmiPlugin             | Stores the trust level for the dmi-plugins.               |
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | moduleSetTagCacheMapConfig         | Stores the module set tags for cm handles.                |
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | cmSubscriptionEventCache           | Stores and tracks cm notification subscription requests.  |
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | alternateIdPerCmHandleId           | Stores the alternate id for each cm handle id.            |
++--------------+------------------------------------+-----------------------------------------------------------+
+| cps-ncmp     | cmHandleIdPerAlternateId           | Stores the cm handle id for each alternate id.            |
++--------------+------------------------------------+-----------------------------------------------------------+
+
+Total number of caches : 10