From 52170568d84bc50ce0119249d387bbf342c2bc7a Mon Sep 17 00:00:00 2001 From: liamfallon Date: Sun, 10 May 2020 15:53:46 +0100 Subject: Policy DB contents removed on DB deadlock When a DB deadlock occurs, the DB contents can sometimes be deleted becasue the DB removes the Service Template object and recreates a new one in two separate DB transactions. This change makes sure that the object remove and re-create is in a sngle DB transaction, so the operation will either happen or not happen so the DB will not be cleared. Legacy policy handling must also use the SimpleToscaProvider rather than accessing the DB directly, as SimpleToscaProvider keeps the DB structure correct. Issue-ID: POLICY-2548 Change-Id: I263a41cd1d8bec5d7b421045b3b14aad6e6c66d3 Signed-off-by: liamfallon --- .../tosca/legacy/provider/LegacyProvider.java | 121 ++++++++------------- .../tosca/simple/provider/SimpleToscaProvider.java | 29 +++-- .../SimpleToscaServiceTemplateProvider.java | 63 ++++++----- 3 files changed, 101 insertions(+), 112 deletions(-) (limited to 'models-tosca/src/main/java') diff --git a/models-tosca/src/main/java/org/onap/policy/models/tosca/legacy/provider/LegacyProvider.java b/models-tosca/src/main/java/org/onap/policy/models/tosca/legacy/provider/LegacyProvider.java index 314c7728d..44c086dc4 100644 --- a/models-tosca/src/main/java/org/onap/policy/models/tosca/legacy/provider/LegacyProvider.java +++ b/models-tosca/src/main/java/org/onap/policy/models/tosca/legacy/provider/LegacyProvider.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2019 Nordix Foundation. + * Copyright (C) 2019-2020 Nordix Foundation. * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ package org.onap.policy.models.tosca.legacy.provider; -import java.util.List; +import java.util.Map; import javax.ws.rs.core.Response; @@ -33,11 +33,10 @@ import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.dao.PfDao; import org.onap.policy.models.tosca.legacy.concepts.LegacyOperationalPolicy; import org.onap.policy.models.tosca.legacy.mapping.LegacyOperationalPolicyMapper; -import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicies; import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicy; import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; -import org.onap.policy.models.tosca.simple.concepts.JpaToscaTopologyTemplate; import org.onap.policy.models.tosca.simple.provider.SimpleToscaProvider; +import org.onap.policy.models.tosca.utils.ToscaUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,15 +63,15 @@ public class LegacyProvider { * @throws PfModelException on errors getting policies */ public LegacyOperationalPolicy getOperationalPolicy(@NonNull final PfDao dao, @NonNull final String policyId, - final String policyVersion) throws PfModelException { + final String policyVersion) throws PfModelException { LOGGER.debug("->getOperationalPolicy: policyId={}, policyVersion={}", policyId, policyVersion); - LegacyOperationalPolicy legacyOperationalPolicy = new LegacyOperationalPolicyMapper() - .fromToscaServiceTemplate(getLegacyPolicy(dao, policyId, policyVersion)); + LegacyOperationalPolicy legacyOperationalPolicy = + new LegacyOperationalPolicyMapper().fromToscaServiceTemplate(getLegacyPolicy(dao, policyId, policyVersion)); LOGGER.debug("<-getOperationalPolicy: policyId={}, policyVersion={}, legacyOperationalPolicy={}", policyId, - policyVersion, legacyOperationalPolicy); + policyVersion, legacyOperationalPolicy); return legacyOperationalPolicy; } @@ -85,17 +84,17 @@ public class LegacyProvider { * @throws PfModelException on errors creating policies */ public LegacyOperationalPolicy createOperationalPolicy(@NonNull final PfDao dao, - @NonNull final LegacyOperationalPolicy legacyOperationalPolicy) throws PfModelException { + @NonNull final LegacyOperationalPolicy legacyOperationalPolicy) throws PfModelException { LOGGER.debug("->createOperationalPolicy: legacyOperationalPolicy={}", legacyOperationalPolicy); JpaToscaServiceTemplate legacyOperationalServiceTemplate = - new LegacyOperationalPolicyMapper().toToscaServiceTemplate(legacyOperationalPolicy); + new LegacyOperationalPolicyMapper().toToscaServiceTemplate(legacyOperationalPolicy); new SimpleToscaProvider().createPolicies(dao, legacyOperationalServiceTemplate); LegacyOperationalPolicy createdLegacyOperationalPolicy = - new LegacyOperationalPolicyMapper().fromToscaServiceTemplate(legacyOperationalServiceTemplate); + new LegacyOperationalPolicyMapper().fromToscaServiceTemplate(legacyOperationalServiceTemplate); LOGGER.debug("<-createOperationalPolicy: createdLegacyOperationalPolicy={}", createdLegacyOperationalPolicy); return createdLegacyOperationalPolicy; @@ -110,16 +109,16 @@ public class LegacyProvider { * @throws PfModelException on errors updating policies */ public LegacyOperationalPolicy updateOperationalPolicy(@NonNull final PfDao dao, - @NonNull final LegacyOperationalPolicy legacyOperationalPolicy) throws PfModelException { + @NonNull final LegacyOperationalPolicy legacyOperationalPolicy) throws PfModelException { LOGGER.debug("->updateOperationalPolicy: legacyOperationalPolicy={}", legacyOperationalPolicy); JpaToscaServiceTemplate incomingServiceTemplate = - new LegacyOperationalPolicyMapper().toToscaServiceTemplate(legacyOperationalPolicy); + new LegacyOperationalPolicyMapper().toToscaServiceTemplate(legacyOperationalPolicy); JpaToscaServiceTemplate outgoingingServiceTemplate = - new SimpleToscaProvider().updatePolicies(dao, incomingServiceTemplate); + new SimpleToscaProvider().updatePolicies(dao, incomingServiceTemplate); LegacyOperationalPolicy updatedLegacyOperationalPolicy = - new LegacyOperationalPolicyMapper().fromToscaServiceTemplate(outgoingingServiceTemplate); + new LegacyOperationalPolicyMapper().fromToscaServiceTemplate(outgoingingServiceTemplate); LOGGER.debug("<-updateOperationalPolicy: updatedLegacyOperationalPolicy={}", updatedLegacyOperationalPolicy); return updatedLegacyOperationalPolicy; @@ -135,15 +134,17 @@ public class LegacyProvider { * @throws PfModelException on errors deleting policies */ public LegacyOperationalPolicy deleteOperationalPolicy(@NonNull final PfDao dao, @NonNull final String policyId, - @NonNull final String policyVersion) throws PfModelException { + @NonNull final String policyVersion) throws PfModelException { LOGGER.debug("->deleteOperationalPolicy: policyId={}, policyVersion={}", policyId, policyVersion); - LegacyOperationalPolicy legacyOperationalPolicy = new LegacyOperationalPolicyMapper() - .fromToscaServiceTemplate(deleteLegacyPolicy(dao, policyId, policyVersion)); + JpaToscaServiceTemplate deleteServiceTemplate = new SimpleToscaProvider().deletePolicy(dao, + new PfConceptKey(policyId, policyVersion + LEGACY_MINOR_PATCH_SUFFIX)); + LegacyOperationalPolicy legacyOperationalPolicy = + new LegacyOperationalPolicyMapper().fromToscaServiceTemplate(deleteServiceTemplate); LOGGER.debug("<-deleteOperationalPolicy: policyId={}, policyVersion={}, legacyOperationalPolicy={}", policyId, - policyVersion, legacyOperationalPolicy); + policyVersion, legacyOperationalPolicy); return legacyOperationalPolicy; } @@ -154,63 +155,25 @@ public class LegacyProvider { * @param policyId the policy ID to search for * @param policyVersion the policy version to search for * @return the JPA policy found - * @throws PfModelRuntimeException if a policy is not found + * @throws PfModelException if a policy is not found */ - private JpaToscaServiceTemplate getLegacyPolicy(final PfDao dao, final String policyId, - final String policyVersion) { - JpaToscaPolicy foundPolicy = null; + private JpaToscaServiceTemplate getLegacyPolicy(final PfDao dao, final String policyId, final String policyVersion) + throws PfModelException { + JpaToscaServiceTemplate foundPolicyServiceTemplate = null; if (policyVersion == null) { - foundPolicy = getLatestPolicy(dao, policyId); + foundPolicyServiceTemplate = getLatestPolicy(dao, policyId); } else { - foundPolicy = dao.get(JpaToscaPolicy.class, - new PfConceptKey(policyId, policyVersion + LEGACY_MINOR_PATCH_SUFFIX)); + foundPolicyServiceTemplate = + new SimpleToscaProvider().getPolicies(dao, policyId, policyVersion + LEGACY_MINOR_PATCH_SUFFIX); } - if (foundPolicy == null) { + if (foundPolicyServiceTemplate == null) { String errorMessage = NO_POLICY_FOUND_FOR_POLICY + policyId + ':' + policyVersion; LOGGER.warn(errorMessage); throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, errorMessage); } - // Create the structure of the TOSCA service template to contain the policy type - JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate(); - serviceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate()); - serviceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies()); - serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(foundPolicy.getKey(), foundPolicy); - - return serviceTemplate; - } - - /** - * Delete a legacy policy. - * - * @param dao the DAO to use for the deletion - * @param policyId the policy ID - * @param policyVersion the policy version - * @return a service template containing the policy that has been deleted - */ - private JpaToscaServiceTemplate deleteLegacyPolicy(final PfDao dao, final String policyId, - final String policyVersion) { - - final JpaToscaPolicy deletePolicy = - dao.get(JpaToscaPolicy.class, new PfConceptKey(policyId, policyVersion + LEGACY_MINOR_PATCH_SUFFIX)); - - if (deletePolicy == null) { - String errorMessage = NO_POLICY_FOUND_FOR_POLICY + policyId + ':' + policyVersion; - LOGGER.warn(errorMessage); - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, errorMessage); - } - - // Delete the policy - dao.delete(deletePolicy); - - // Create the structure of the TOSCA service template to contain the policy type - JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate(); - serviceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate()); - serviceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies()); - serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(deletePolicy.getKey(), deletePolicy); - - return serviceTemplate; + return foundPolicyServiceTemplate; } /** @@ -219,26 +182,36 @@ public class LegacyProvider { * @param dao The DAO to read from * @param policyId the ID of the policy * @return the policy + * @throws PfModelException on exceptions getting the policies */ - private JpaToscaPolicy getLatestPolicy(final PfDao dao, final String policyId) { + private JpaToscaServiceTemplate getLatestPolicy(final PfDao dao, final String policyId) throws PfModelException { // Get all the policies in the database and check the policy ID against the policies returned - List policyList = dao.getAll(JpaToscaPolicy.class); + JpaToscaServiceTemplate serviceTemplate = new SimpleToscaProvider().getPolicies(dao, policyId, null); + + if (!ToscaUtils.doPoliciesExist(serviceTemplate)) { + return null; + } // Find the latest policy that matches the ID - JpaToscaPolicy newestPolicy = null; + final Map policyMap = + serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap(); + PfConceptKey newestPolicyKey = null; - for (JpaToscaPolicy policy : policyList) { + for (JpaToscaPolicy policy : policyMap.values()) { if (!policyId.equals(policy.getKey().getName())) { continue; } // We found a matching policy - if (newestPolicy == null || policy.getKey().isNewerThan(newestPolicy.getKey())) { + if (newestPolicyKey == null || policy.getKey().isNewerThan(newestPolicyKey)) { // First policy found - newestPolicy = policy; + newestPolicyKey = policy.getKey(); } } - return newestPolicy; - } + final PfConceptKey newestPolicyFinalKey = newestPolicyKey; + policyMap.keySet().removeIf(key -> !key.equals(newestPolicyFinalKey)); + + return serviceTemplate; + } } diff --git a/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/provider/SimpleToscaProvider.java b/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/provider/SimpleToscaProvider.java index 4dbbc2dd5..f12f9884f 100644 --- a/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/provider/SimpleToscaProvider.java +++ b/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/provider/SimpleToscaProvider.java @@ -276,10 +276,16 @@ public class SimpleToscaProvider { } } - dao.delete(JpaToscaDataType.class, dataTypeKey); + serviceTemplate.getDataTypes().getConceptMap().remove(dataTypeKey); + new SimpleToscaServiceTemplateProvider().write(dao, serviceTemplate); + dao.delete(dataType4Deletion); - LOGGER.debug("<-deleteDataType: key={}, serviceTempalate={}", dataTypeKey, serviceTemplate); - return serviceTemplate; + JpaToscaServiceTemplate deletedServiceTemplate = new JpaToscaServiceTemplate(); + deletedServiceTemplate.setDataTypes(new JpaToscaDataTypes()); + deletedServiceTemplate.getDataTypes().getConceptMap().put(dataTypeKey, dataType4Deletion); + + LOGGER.debug("<-deleteDataType: key={}, serviceTempalate={}", dataTypeKey, deletedServiceTemplate); + return deletedServiceTemplate; } /** @@ -427,8 +433,7 @@ public class SimpleToscaProvider { throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policy types found"); } - JpaToscaEntityType policyType4Deletion = - serviceTemplate.getPolicyTypes().get(policyTypeKey); + JpaToscaPolicyType policyType4Deletion = serviceTemplate.getPolicyTypes().get(policyTypeKey); if (policyType4Deletion == null) { throw new PfModelRuntimeException(Response.Status.NOT_FOUND, POLICY_TYPE + policyTypeKey.getId() + NOT_FOUND); @@ -453,12 +458,13 @@ public class SimpleToscaProvider { } } - dao.delete(JpaToscaPolicyType.class, policyTypeKey); + serviceTemplate.getPolicyTypes().getConceptMap().remove(policyTypeKey); + new SimpleToscaServiceTemplateProvider().write(dao, serviceTemplate); + dao.delete(policyType4Deletion); JpaToscaServiceTemplate deletedServiceTemplate = new JpaToscaServiceTemplate(); deletedServiceTemplate.setPolicyTypes(new JpaToscaPolicyTypes()); - deletedServiceTemplate.getPolicyTypes().getConceptMap().put(policyTypeKey, - serviceTemplate.getPolicyTypes().getConceptMap().get(policyTypeKey)); + deletedServiceTemplate.getPolicyTypes().getConceptMap().put(policyTypeKey, policyType4Deletion); LOGGER.debug("<-deletePolicyType: key={}, serviceTempalate={}", policyTypeKey, deletedServiceTemplate); return deletedServiceTemplate; @@ -604,13 +610,14 @@ public class SimpleToscaProvider { throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "policy " + policyKey.getId() + NOT_FOUND); } - dao.delete(JpaToscaPolicy.class, policyKey); + serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().remove(policyKey); + new SimpleToscaServiceTemplateProvider().write(dao, serviceTemplate); + dao.delete(policy4Deletion); JpaToscaServiceTemplate deletedServiceTemplate = new JpaToscaServiceTemplate(); deletedServiceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate()); deletedServiceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies()); - deletedServiceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(policyKey, - serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().get(policyKey)); + deletedServiceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(policyKey, policy4Deletion); LOGGER.debug("<-deletePolicy: key={}, serviceTempalate={}", policyKey, deletedServiceTemplate); return deletedServiceTemplate; diff --git a/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/provider/SimpleToscaServiceTemplateProvider.java b/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/provider/SimpleToscaServiceTemplateProvider.java index a971b9af3..34a7e2cee 100644 --- a/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/provider/SimpleToscaServiceTemplateProvider.java +++ b/models-tosca/src/main/java/org/onap/policy/models/tosca/simple/provider/SimpleToscaServiceTemplateProvider.java @@ -20,6 +20,8 @@ package org.onap.policy.models.tosca.simple.provider; +import javax.ws.rs.core.Response.Status; + import lombok.NonNull; import org.onap.policy.models.base.PfConceptKey; @@ -40,7 +42,7 @@ public class SimpleToscaServiceTemplateProvider { // There is only one service template in the database becasue TOSCA does not specify names and versions on service // templates. private static final PfConceptKey DEFAULT_SERVICE_TEMPLATE_KEY = - new PfConceptKey(JpaToscaServiceTemplate.DEFAULT_NAME, JpaToscaServiceTemplate.DEFAULT_VERSION); + new PfConceptKey(JpaToscaServiceTemplate.DEFAULT_NAME, JpaToscaServiceTemplate.DEFAULT_VERSION); /** * Get a service template from the database. @@ -49,14 +51,20 @@ public class SimpleToscaServiceTemplateProvider { * @return the Service Template read from the database * @throws PfModelException on errors getting the service template */ - public JpaToscaServiceTemplate read(@NonNull final PfDao dao) throws PfModelException { + protected JpaToscaServiceTemplate read(@NonNull final PfDao dao) throws PfModelException { LOGGER.debug("->read"); - // Get the service template - JpaToscaServiceTemplate serviceTemplate = dao.get(JpaToscaServiceTemplate.class, DEFAULT_SERVICE_TEMPLATE_KEY); + try { + // Get the service template + JpaToscaServiceTemplate serviceTemplate = + dao.get(JpaToscaServiceTemplate.class, DEFAULT_SERVICE_TEMPLATE_KEY); - LOGGER.debug("<-read: serviceTemplate={}", serviceTemplate); - return serviceTemplate; + LOGGER.debug("<-read: serviceTemplate={}", serviceTemplate); + return serviceTemplate; + } catch (Exception dbException) { + throw new PfModelException(Status.INTERNAL_SERVER_ERROR, "database read error on service tempalate" + + DEFAULT_SERVICE_TEMPLATE_KEY.getId() + "\n" + dbException.getMessage(), dbException); + } } /** @@ -67,21 +75,18 @@ public class SimpleToscaServiceTemplateProvider { * @return the TOSCA service template overwritten by this method * @throws PfModelException on errors writing the service template */ - public JpaToscaServiceTemplate write(@NonNull final PfDao dao, - @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException { - LOGGER.debug("->write: serviceTempalate={}", serviceTemplate); - - JpaToscaServiceTemplate overwrittenServiceTemplate = - dao.get(JpaToscaServiceTemplate.class, serviceTemplate.getKey()); - - if (overwrittenServiceTemplate != null) { - dao.delete(overwrittenServiceTemplate); + protected JpaToscaServiceTemplate write(@NonNull final PfDao dao, + @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException { + + try { + LOGGER.debug("->write: serviceTempalate={}", serviceTemplate); + JpaToscaServiceTemplate overwrittenServiceTemplate = dao.update(serviceTemplate); + LOGGER.debug("<-write: overwrittenServiceTemplate={}", overwrittenServiceTemplate); + return overwrittenServiceTemplate; + } catch (Exception dbException) { + throw new PfModelException(Status.INTERNAL_SERVER_ERROR, "database write error on service tempalate" + + serviceTemplate.getKey().getId() + "\n" + dbException.getMessage(), dbException); } - - dao.create(serviceTemplate); - - LOGGER.debug("<-write: overwrittenServiceTemplate={}", overwrittenServiceTemplate); - return overwrittenServiceTemplate; } /** @@ -91,16 +96,20 @@ public class SimpleToscaServiceTemplateProvider { * @return the Service Template stored in the database * @throws PfModelException on errors getting the service template */ - public JpaToscaServiceTemplate delete(@NonNull final PfDao dao) throws PfModelException { - LOGGER.debug("->delete"); + protected JpaToscaServiceTemplate delete(@NonNull final PfDao dao) throws PfModelException { + try { + LOGGER.debug("->delete"); - JpaToscaServiceTemplate serviceTemplateToBeDeleted = + JpaToscaServiceTemplate serviceTemplateToBeDeleted = dao.get(JpaToscaServiceTemplate.class, DEFAULT_SERVICE_TEMPLATE_KEY); - dao.delete(serviceTemplateToBeDeleted); + dao.delete(serviceTemplateToBeDeleted); - LOGGER.debug("<-delete: serviceTemplate={}", serviceTemplateToBeDeleted); - return serviceTemplateToBeDeleted; + LOGGER.debug("<-delete: serviceTemplate={}", serviceTemplateToBeDeleted); + return serviceTemplateToBeDeleted; + } catch (Exception dbException) { + throw new PfModelException(Status.INTERNAL_SERVER_ERROR, "database delete error on service tempalate" + + DEFAULT_SERVICE_TEMPLATE_KEY.getId() + "\n" + dbException.getMessage(), dbException); + } } - } -- cgit 1.2.3-korg