X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fconfig-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fconfignetconfconnector%2Ftransactions%2FTransactionProvider.java;h=b2ee63a987836102fa31ae8c97e8dac899a33198;hp=b8113a090313d270c4b1a391777d0d6e2e7d759e;hb=662f3629fea2904f8c14526ef412ef1650961e83;hpb=ea7f0e0e25c7c41c314f10d9587b050c24d27344 diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java index b8113a0903..b2ee63a987 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java @@ -10,28 +10,30 @@ package org.opendaylight.controller.netconf.confignetconfconnector.transactions; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.CommitStatus; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.exception.NoTransactionFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - public class TransactionProvider implements AutoCloseable { - private static final Logger logger = LoggerFactory.getLogger(TransactionProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(TransactionProvider.class); private final ConfigRegistryClient configRegistryClient; private final String netconfSessionIdForReporting; private ObjectName transaction; private final List allOpenedTransactions = new ArrayList<>(); + private static final String NO_TRANSACTION_FOUND_FOR_SESSION = "No transaction found for session "; public TransactionProvider(ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) { this.configRegistryClient = configRegistryClient; @@ -46,20 +48,21 @@ public class TransactionProvider implements AutoCloseable { configRegistryClient.getConfigTransactionClient(tx).abortConfig(); } } catch (Exception e) { - logger.debug("Ignoring exception while closing transaction {}", tx, e); + LOG.debug("Ignoring exception while closing transaction {}", tx, e); } } allOpenedTransactions.clear(); } - public Optional getTransaction() { + public synchronized Optional getTransaction() { - if (transaction == null) + if (transaction == null){ return Optional.absent(); + } // Transaction was already closed somehow - if (isStillOpenTransaction(transaction) == false) { - logger.warn("Fixing illegal state: transaction {} was closed in {}", transaction, + if (!isStillOpenTransaction(transaction)) { + LOG.warn("Fixing illegal state: transaction {} was closed in {}", transaction, netconfSessionIdForReporting); transaction = null; return Optional.absent(); @@ -68,15 +71,15 @@ public class TransactionProvider implements AutoCloseable { } private boolean isStillOpenTransaction(ObjectName transaction) { - boolean isStillOpenTransaction = configRegistryClient.getOpenConfigs().contains(transaction); - return isStillOpenTransaction; + return configRegistryClient.getOpenConfigs().contains(transaction); } public synchronized ObjectName getOrCreateTransaction() { Optional ta = getTransaction(); - if (ta.isPresent()) + if (ta.isPresent()) { return ta.get(); + } transaction = configRegistryClient.beginConfig(); allOpenedTransactions.add(transaction); return transaction; @@ -94,18 +97,37 @@ public class TransactionProvider implements AutoCloseable { /** * Commit and notification send must be atomic */ - public synchronized CommitStatus commitTransaction() throws NetconfDocumentedException { - final Optional taON = getTransaction(); - Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting); - CommitStatus status = configRegistryClient.commitConfig(taON.get()); - allOpenedTransactions.remove(transaction); - transaction = null; - return status; + public synchronized CommitStatus commitTransaction() throws ValidationException, ConflictingVersionException, NoTransactionFoundException { + if (!getTransaction().isPresent()){ + throw new NoTransactionFoundException("No transaction found for session " + netconfSessionIdForReporting, + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_failed, + NetconfDocumentedException.ErrorSeverity.error); + } + final Optional maybeTaON = getTransaction(); + ObjectName taON = maybeTaON.get(); + try { + CommitStatus status = configRegistryClient.commitConfig(taON); + // clean up + allOpenedTransactions.remove(transaction); + transaction = null; + return status; + } catch (ValidationException validationException) { + // no clean up: user can reconfigure and recover this transaction + LOG.warn("Transaction {} failed on {}", taON, validationException.toString()); + throw validationException; + } catch (ConflictingVersionException e) { + LOG.error("Exception while commit of {}, aborting transaction", taON, e); + // clean up + abortTransaction(); + throw e; + } } public synchronized void abortTransaction() { + LOG.debug("Aborting current transaction"); Optional taON = getTransaction(); - Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting); + Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting); ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get()); transactionClient.abortConfig(); @@ -114,6 +136,7 @@ public class TransactionProvider implements AutoCloseable { } public synchronized void abortTestTransaction(ObjectName testTx) { + LOG.debug("Aborting transaction {}", testTx); ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(testTx); allOpenedTransactions.remove(testTx); transactionClient.abortConfig(); @@ -121,48 +144,52 @@ public class TransactionProvider implements AutoCloseable { public void validateTransaction() throws ValidationException { Optional taON = getTransaction(); - Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting); + Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting); ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get()); transactionClient.validateConfig(); } - public void validateTestTransaction(ObjectName taON) { + public void validateTestTransaction(ObjectName taON) throws ValidationException { ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON); transactionClient.validateConfig(); } public void wipeTestTransaction(ObjectName taON) { - wipeInternal(taON, true, null); + wipeInternal(taON, true); } /** - * Wiping means removing all module instances keeping the transaction open. + * Wiping means removing all module instances keeping the transaction open + service references. */ - synchronized void wipeInternal(ObjectName taON, boolean isTest, String moduleName) { + synchronized void wipeInternal(ObjectName taON, boolean isTest) { ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON); - Set lookupConfigBeans = moduleName == null ? transactionClient.lookupConfigBeans() - : transactionClient.lookupConfigBeans(moduleName); + Set lookupConfigBeans = transactionClient.lookupConfigBeans(); + int i = lookupConfigBeans.size(); for (ObjectName instance : lookupConfigBeans) { try { transactionClient.destroyModule(instance); } catch (InstanceNotFoundException e) { - if (isTest) - logger.debug("Unable to clean configuration in transactiom {}", taON, e); - else - logger.warn("Unable to clean configuration in transactiom {}", taON, e); + if (isTest){ + LOG.debug("Unable to clean configuration in transactiom {}", taON, e); + } else { + LOG.warn("Unable to clean configuration in transactiom {}", taON, e); + } throw new IllegalStateException("Unable to clean configuration in transactiom " + taON, e); } } - logger.debug("Transaction {} wiped clean", taON); + LOG.debug("Transaction {} wiped clean of {} config beans", taON, i); + + transactionClient.removeAllServiceReferences(); + LOG.debug("Transaction {} wiped clean of all service references", taON); } public void wipeTransaction() { Optional taON = getTransaction(); - Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting); - wipeInternal(taON.get(), false, null); + Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting); + wipeInternal(taON.get(), false); } }