Skip deleting list xpaths that are list elements 20/133420/4
authordanielhanrahan <daniel.hanrahan@est.tech>
Sun, 26 Feb 2023 14:27:06 +0000 (14:27 +0000)
committerdanielhanrahan <daniel.hanrahan@est.tech>
Tue, 28 Feb 2023 16:29:20 +0000 (16:29 +0000)
List elements cannot be lists. Filtering list elements before trying
to delete lists by xpaths doubles performance when deleting list
elements (which doubles performance of CM handle de-registration).

Issue-ID: CPS-1511
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
Change-Id: Ieb6002212d006396d468f27f853708b5aa1e31f2

cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java
cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathUtil.java
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy

index c9df8df..3985455 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -80,4 +80,13 @@ public class CpsPathQuery {
         return textFunctionConditionLeafName != null;
     }
 
+    /**
+     * Returns boolean indicating xpath is an absolute path to a list element.
+     *
+     * @return true if xpath is an absolute path to a list element
+     */
+    public boolean isPathToListElement() {
+        return cpsPathPrefixType == ABSOLUTE && hasLeafConditions();
+    }
+
 }
index 60f0e2e..bde9b06 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@
 
 package org.onap.cps.cpspath.parser;
 
-import static org.onap.cps.cpspath.parser.CpsPathPrefixType.ABSOLUTE;
-
 import java.util.List;
 import lombok.AccessLevel;
 import lombok.Getter;
@@ -75,7 +73,7 @@ public class CpsPathUtil {
      */
     public static boolean isPathToListElement(final String xpathSource) {
         final CpsPathQuery cpsPathQuery = getCpsPathBuilder(xpathSource).build();
-        return cpsPathQuery.getCpsPathPrefixType() == ABSOLUTE && cpsPathQuery.hasLeafConditions();
+        return cpsPathQuery.isPathToListElement();
     }
 
     /**
index dd2d365..2159cea 100644 (file)
@@ -621,17 +621,23 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
         final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
         final AnchorEntity anchorEntity = anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName);
 
-        final Collection<String> normalizedXpaths = new ArrayList<>(xpathsToDelete.size());
+        final Collection<String> normalizedXPathsToDelete = new ArrayList<>(xpathsToDelete.size());
+        final Collection<String> normalizedXpathsToPotentialLists = new ArrayList<>();
         for (final String xpath : xpathsToDelete) {
             try {
-                normalizedXpaths.add(CpsPathUtil.getNormalizedXpath(xpath));
+                final CpsPathQuery cpsPathQuery = CpsPathUtil.getCpsPathQuery(xpath);
+                final String normalizedXpath = cpsPathQuery.getNormalizedXpath();
+                normalizedXPathsToDelete.add(normalizedXpath);
+                if (!cpsPathQuery.isPathToListElement()) {
+                    normalizedXpathsToPotentialLists.add(normalizedXpath);
+                }
             } catch (final PathParsingException e) {
                 log.debug("Error parsing xpath \"{}\": {}", xpath, e.getMessage());
             }
         }
 
-        fragmentRepository.deleteByAnchorIdAndXpaths(anchorEntity.getId(), normalizedXpaths);
-        fragmentRepository.deleteListsByAnchorIdAndXpaths(anchorEntity.getId(), normalizedXpaths);
+        fragmentRepository.deleteByAnchorIdAndXpaths(anchorEntity.getId(), normalizedXPathsToDelete);
+        fragmentRepository.deleteListsByAnchorIdAndXpaths(anchorEntity.getId(), normalizedXpathsToPotentialLists);
     }
 
     @Override
index 8e74b62..a08d8c6 100644 (file)
@@ -24,15 +24,12 @@ import org.onap.cps.spi.CpsDataPersistenceService
 import org.onap.cps.spi.impl.CpsPersistencePerfSpecBase
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.test.context.jdbc.Sql
-import org.springframework.util.StopWatch
 
 class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase {
 
     @Autowired
     CpsDataPersistenceService objectUnderTest
 
-    def stopWatch = new StopWatch()
-
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
     def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
         when: 'a node with a large number of descendants is created'
@@ -165,8 +162,8 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             objectUnderTest.deleteDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToDelete)
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
-        then: 'delete duration is under 125 milliseconds'
-            recordAndAssertPerformance('Batch delete 500 lists elements', 125, deleteDurationInMillis)
+        then: 'delete duration is under 60 milliseconds'
+            recordAndAssertPerformance('Batch delete 500 lists elements', 60, deleteDurationInMillis)
     }
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])