2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.netconf.confignetconfconnector.transactions;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import org.opendaylight.controller.config.api.ValidationException;
14 import org.opendaylight.controller.config.api.jmx.CommitStatus;
15 import org.opendaylight.controller.config.util.ConfigRegistryClient;
16 import org.opendaylight.controller.config.util.ConfigTransactionClient;
17 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
21 import javax.management.InstanceNotFoundException;
22 import javax.management.ObjectName;
23 import java.util.ArrayList;
24 import java.util.List;
27 public class TransactionProvider implements AutoCloseable {
28 private static final Logger logger = LoggerFactory.getLogger(TransactionProvider.class);
30 private final ConfigRegistryClient configRegistryClient;
32 private final String netconfSessionIdForReporting;
33 private ObjectName transaction;
34 private final List<ObjectName> allOpenedTransactions = new ArrayList<>();
36 public TransactionProvider(ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) {
37 this.configRegistryClient = configRegistryClient;
38 this.netconfSessionIdForReporting = netconfSessionIdForReporting;
42 public synchronized void close() {
43 for (ObjectName tx : allOpenedTransactions) {
45 if (isStillOpenTransaction(tx)) {
46 configRegistryClient.getConfigTransactionClient(tx).abortConfig();
48 } catch (Exception e) {
49 logger.debug("Ignoring exception while closing transaction {}", tx, e);
52 allOpenedTransactions.clear();
55 public Optional<ObjectName> getTransaction() {
57 if (transaction == null)
58 return Optional.absent();
60 // Transaction was already closed somehow
61 if (isStillOpenTransaction(transaction) == false) {
62 logger.warn("Fixing illegal state: transaction {} was closed in {}", transaction,
63 netconfSessionIdForReporting);
65 return Optional.absent();
67 return Optional.of(transaction);
70 private boolean isStillOpenTransaction(ObjectName transaction) {
71 boolean isStillOpenTransaction = configRegistryClient.getOpenConfigs().contains(transaction);
72 return isStillOpenTransaction;
75 public synchronized ObjectName getOrCreateTransaction() {
76 Optional<ObjectName> ta = getTransaction();
80 transaction = configRegistryClient.beginConfig();
81 allOpenedTransactions.add(transaction);
86 * Used for editConfig test option
88 public synchronized ObjectName getTestTransaction() {
89 ObjectName testTx = configRegistryClient.beginConfig();
90 allOpenedTransactions.add(testTx);
95 * Commit and notification send must be atomic
97 public synchronized CommitStatus commitTransaction() throws NetconfDocumentedException {
98 final Optional<ObjectName> maybeTaON = getTransaction();
99 Preconditions.checkState(maybeTaON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
100 ObjectName taON = maybeTaON.get();
102 CommitStatus status = configRegistryClient.commitConfig(taON);
104 allOpenedTransactions.remove(transaction);
107 } catch (ValidationException validationException) {
108 // no clean up: user can reconfigure and recover this transaction
109 logger.warn("Transaction {} failed on {}", taON, validationException.toString());
110 throw validationException;
111 } catch (Exception e) {
112 logger.error("Exception while commit of {}, aborting transaction", taON, e);
119 public synchronized void abortTransaction() {
120 logger.debug("Aborting current transaction");
121 Optional<ObjectName> taON = getTransaction();
122 Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
124 ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get());
125 transactionClient.abortConfig();
126 allOpenedTransactions.remove(transaction);
130 public synchronized void abortTestTransaction(ObjectName testTx) {
131 logger.debug("Aborting transaction {}", testTx);
132 ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(testTx);
133 allOpenedTransactions.remove(testTx);
134 transactionClient.abortConfig();
137 public void validateTransaction() throws ValidationException {
138 Optional<ObjectName> taON = getTransaction();
139 Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
141 ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get());
142 transactionClient.validateConfig();
145 public void validateTestTransaction(ObjectName taON) {
146 ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON);
147 transactionClient.validateConfig();
150 public void wipeTestTransaction(ObjectName taON) {
151 wipeInternal(taON, true, null);
155 * Wiping means removing all module instances keeping the transaction open + service references.
157 synchronized void wipeInternal(ObjectName taON, boolean isTest, String moduleName) {
158 ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON);
160 Set<ObjectName> lookupConfigBeans = moduleName == null ? transactionClient.lookupConfigBeans()
161 : transactionClient.lookupConfigBeans(moduleName);
162 int i = lookupConfigBeans.size();
163 for (ObjectName instance : lookupConfigBeans) {
165 transactionClient.destroyModule(instance);
166 } catch (InstanceNotFoundException e) {
168 logger.debug("Unable to clean configuration in transactiom {}", taON, e);
170 logger.warn("Unable to clean configuration in transactiom {}", taON, e);
172 throw new IllegalStateException("Unable to clean configuration in transactiom " + taON, e);
175 logger.debug("Transaction {} wiped clean of {} config beans", taON, i);
177 transactionClient.removeAllServiceReferences();
178 logger.debug("Transaction {} wiped clean of all service references", taON);
181 public void wipeTransaction() {
182 Optional<ObjectName> taON = getTransaction();
183 Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
184 wipeInternal(taON.get(), false, null);