diff options
Diffstat (limited to 'cps-ri/src/main')
10 files changed, 121 insertions, 21 deletions
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/entities/DataspaceEntity.java b/cps-ri/src/main/java/org/onap/cps/spi/entities/DataspaceEntity.java index 45b41dbe81..593746d94f 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/entities/DataspaceEntity.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/DataspaceEntity.java @@ -1,12 +1,14 @@ /* - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. All rights reserved. + * ============LICENSE_START======================================================= + * Copyright (C) 2020-2021 Nordix Foundation. + * Modifications Copyright (C) 2020-2021 Pantheon.tech * ================================================================================ * 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. @@ -62,4 +64,4 @@ public class DataspaceEntity implements Serializable { public DataspaceEntity(final String name) { this.name = name; } -}
\ No newline at end of file +} diff --git a/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntity.java b/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntity.java index 74f75d1de2..00d1d98df3 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntity.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntity.java @@ -1,7 +1,7 @@ -/*- +/* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. All rights reserved. - * Modifications Copyright (C) 2021 Pantheon.tech + * Copyright (C) 2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java index 64c6ff507e..2776c4d67d 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. All rights reserved. - * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. - * Modifications Copyright (C) 2021 Pantheon.tech + * Copyright (C) 2020 Nordix Foundation. + * Modifications Copyright (C) 2020 Bell Canada. + * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -112,4 +112,4 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic .schemaSetName(anchorEntity.getSchemaSet().getName()) .build(); } -}
\ No newline at end of file +} diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java index 42364ead69..844ad84744 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java @@ -1,5 +1,5 @@ /* - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * Copyright (C) 2021 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2020-2021 Bell Canada. @@ -9,6 +9,7 @@ * 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. diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java index ae6543dabe..1b3dc2486f 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java @@ -1,13 +1,15 @@ /* - * ============LICENSE_START======================================================= + * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation - * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. + * Modifications Copyright (C) 2020-2021 Bell Canada. + * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ * 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. @@ -25,10 +27,15 @@ import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.transaction.Transactional; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.exception.ConstraintViolationException; import org.onap.cps.spi.CascadeDeleteAllowed; import org.onap.cps.spi.CpsAdminPersistenceService; import org.onap.cps.spi.CpsModulePersistenceService; @@ -36,6 +43,7 @@ import org.onap.cps.spi.entities.AnchorEntity; import org.onap.cps.spi.entities.SchemaSetEntity; import org.onap.cps.spi.entities.YangResourceEntity; import org.onap.cps.spi.exceptions.AlreadyDefinedException; +import org.onap.cps.spi.exceptions.DuplicatedYangResourceException; import org.onap.cps.spi.exceptions.SchemaSetInUseException; import org.onap.cps.spi.repository.AnchorRepository; import org.onap.cps.spi.repository.DataspaceRepository; @@ -44,12 +52,18 @@ import org.onap.cps.spi.repository.SchemaSetRepository; import org.onap.cps.spi.repository.YangResourceRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Component; @Component +@Slf4j public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceService { + private static final String YANG_RESOURCE_CHECKSUM_CONSTRAINT_NAME = "yang_resource_checksum_key"; + private static final Pattern CHECKSUM_EXCEPTION_PATTERN = Pattern.compile(".*\\(checksum\\)=\\((\\w+)\\).*"); + @Autowired private YangResourceRepository yangResourceRepository; @@ -70,6 +84,9 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ @Override @Transactional + // A retry is made to store the schema set if it fails because of duplicated yang resource exception that + // can occur in case of specific concurrent requests. + @Retryable(value = DuplicatedYangResourceException.class, maxAttempts = 2, backoff = @Backoff(delay = 500)) public void storeSchemaSet(final String dataspaceName, final String schemaSetName, final Map<String, String> yangResourcesNameToContentMap) { @@ -107,7 +124,21 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ final Collection<YangResourceEntity> newYangResourceEntities = checksumToEntityMap.values(); if (!newYangResourceEntities.isEmpty()) { - yangResourceRepository.saveAll(newYangResourceEntities); + try { + yangResourceRepository.saveAll(newYangResourceEntities); + } catch (final DataIntegrityViolationException dataIntegrityViolationException) { + // Throw a CPS duplicated Yang resource exception if the cause of the error is a yang checksum + // database constraint violation. + // If it is not, then throw the original exception + final Optional<DuplicatedYangResourceException> convertedException = + convertToDuplicatedYangResourceException( + dataIntegrityViolationException, newYangResourceEntities); + convertedException.ifPresent( + e -> log.warn( + "Cannot persist duplicated yang resource. " + + "A total of 2 attempts to store the schema set are planned.", e)); + throw convertedException.isPresent() ? convertedException.get() : dataIntegrityViolationException; + } } return ImmutableSet.<YangResourceEntity>builder() @@ -116,6 +147,67 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ .build(); } + /** + * Convert the specified data integrity violation exception into a CPS duplicated Yang resource exception + * if the cause of the error is a yang checksum database constraint violation. + * @param originalException the original db exception. + * @param yangResourceEntities the collection of Yang resources involved in the db failure. + * @return an optional converted CPS duplicated Yang resource exception. The optional is empty if the original + * cause of the error is not a yang checksum database constraint violation. + */ + private Optional<DuplicatedYangResourceException> convertToDuplicatedYangResourceException( + final DataIntegrityViolationException originalException, + final Collection<YangResourceEntity> yangResourceEntities) { + + // The exception result + DuplicatedYangResourceException duplicatedYangResourceException = null; + + final Throwable cause = originalException.getCause(); + if (cause instanceof ConstraintViolationException) { + final ConstraintViolationException constraintException = (ConstraintViolationException) cause; + if (YANG_RESOURCE_CHECKSUM_CONSTRAINT_NAME.equals(constraintException.getConstraintName())) { + // Db constraint related to yang resource checksum uniqueness is not respected + final String checksumInError = getDuplicatedChecksumFromException(constraintException); + final String nameInError = getNameForChecksum(checksumInError, yangResourceEntities); + duplicatedYangResourceException = + new DuplicatedYangResourceException(nameInError, checksumInError, constraintException); + } + } + + return Optional.ofNullable(duplicatedYangResourceException); + + } + + /** + * Get the checksum that caused the constraint violation exception. + * @param exception the exception having the checksum in error. + * @return the checksum in error or null if not found. + */ + private String getDuplicatedChecksumFromException(final ConstraintViolationException exception) { + String checksum = null; + final var matcher = CHECKSUM_EXCEPTION_PATTERN.matcher(exception.getSQLException().getMessage()); + if (matcher.find() && matcher.groupCount() == 1) { + checksum = matcher.group(1); + } + return checksum; + } + + /** + * Get the name of the yang resource having the specified checksum. + * @param checksum the checksum. Null is supported. + * @param yangResourceEntities the list of yang resources to search among. + * @return the name found or null if none. + */ + private String getNameForChecksum( + final String checksum, final Collection<YangResourceEntity> yangResourceEntities) { + return + yangResourceEntities.stream() + .filter(entity -> StringUtils.equals(checksum, (entity.getChecksum()))) + .findFirst() + .map(YangResourceEntity::getName) + .orElse(null); + } + @Override public Map<String, String> getYangSchemaResources(final String dataspaceName, final String schemaSetName) { final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName); diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java index ee77b73c9f..4d7e7ff547 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java @@ -1,7 +1,8 @@ -/*-
+/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-201 Nordix Foundation. All rights reserved.
- * Modifications Copyright (C) 2020-2021 Bell Canada. All rights reserved.
+ * Copyright (C) 2020-201 Nordix Foundation.
+ * Modifications Copyright (C) 2020-2021 Bell Canada.
+ * Modifications Copyright (C) 2020-2021 Pantheon.tech.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/cps-ri/src/main/resources/changelog/db/changes/05-loadData-fragment.yaml b/cps-ri/src/main/resources/changelog/db/changes/05-loadData-fragment.yaml index 1c4598fe67..d1125f8c8a 100644 --- a/cps-ri/src/main/resources/changelog/db/changes/05-loadData-fragment.yaml +++ b/cps-ri/src/main/resources/changelog/db/changes/05-loadData-fragment.yaml @@ -1,11 +1,13 @@ # ============LICENSE_START======================================================= # Copyright (C) 2021 Nordix Foundation +# Modifications Copyright (C) 2021 Pantheon.tech # ================================================================================ # 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. @@ -66,4 +68,4 @@ databaseChangeLog: - sql: comment: Fixes the id sequence after data insert with predefined ids dbms: postgresql - sql: ALTER SEQUENCE IF EXISTS fragment_id_seq RESTART WITH 200
\ No newline at end of file + sql: ALTER SEQUENCE IF EXISTS fragment_id_seq RESTART WITH 200 diff --git a/cps-ri/src/main/resources/changelog/db/changes/07-update-yang-resource-checksums.yaml b/cps-ri/src/main/resources/changelog/db/changes/07-update-yang-resource-checksums.yaml index 59815fbb01..2ef1f16818 100644 --- a/cps-ri/src/main/resources/changelog/db/changes/07-update-yang-resource-checksums.yaml +++ b/cps-ri/src/main/resources/changelog/db/changes/07-update-yang-resource-checksums.yaml @@ -6,6 +6,7 @@ # 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. diff --git a/cps-ri/src/main/resources/changelog/db/changes/09-loadData-dmi-registry-schema-set.yaml b/cps-ri/src/main/resources/changelog/db/changes/09-loadData-dmi-registry-schema-set.yaml index d0977fbf38..7b56e6a65d 100644 --- a/cps-ri/src/main/resources/changelog/db/changes/09-loadData-dmi-registry-schema-set.yaml +++ b/cps-ri/src/main/resources/changelog/db/changes/09-loadData-dmi-registry-schema-set.yaml @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2021 Nordix Foundation. All rights reserved. +# Copyright (C) 2021 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/cps-ri/src/main/resources/hibernate.properties b/cps-ri/src/main/resources/hibernate.properties index a350db0ab3..fa268bc2b6 100644 --- a/cps-ri/src/main/resources/hibernate.properties +++ b/cps-ri/src/main/resources/hibernate.properties @@ -6,6 +6,7 @@ # 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. @@ -15,4 +16,4 @@ # SPDX-License-Identifier: Apache-2.0 # ============LICENSE_END========================================================= -hibernate.types.print.banner=false
\ No newline at end of file +hibernate.types.print.banner=false |