2 * Copyright (c) 2015 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.netconf.mdsal.connector;
11 import static org.opendaylight.netconf.mdsal.connector.DOMDataTransactionValidator.ValidationFailedException;
13 import com.google.common.base.Optional;
14 import com.google.common.base.Preconditions;
15 import com.google.common.util.concurrent.CheckedFuture;
16 import java.util.ArrayList;
17 import java.util.List;
18 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
19 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
20 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
21 import org.opendaylight.netconf.api.DocumentedException;
22 import org.opendaylight.netconf.api.DocumentedException.ErrorSeverity;
23 import org.opendaylight.netconf.api.DocumentedException.ErrorTag;
24 import org.opendaylight.netconf.api.DocumentedException.ErrorType;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
28 public class TransactionProvider implements AutoCloseable {
30 private static final Logger LOG = LoggerFactory.getLogger(TransactionProvider.class);
32 private final DOMDataBroker dataBroker;
34 private DOMDataReadWriteTransaction candidateTransaction = null;
35 private DOMDataReadWriteTransaction runningTransaction = null;
36 private final List<DOMDataReadWriteTransaction> allOpenReadWriteTransactions = new ArrayList<>();
37 private final DOMDataTransactionValidator transactionValidator;
39 private final String netconfSessionIdForReporting;
41 private static final String NO_TRANSACTION_FOUND_FOR_SESSION = "No candidateTransaction found for session ";
43 public TransactionProvider(final DOMDataBroker dataBroker, final String netconfSessionIdForReporting) {
44 this.dataBroker = dataBroker;
45 this.netconfSessionIdForReporting = netconfSessionIdForReporting;
46 this.transactionValidator = (DOMDataTransactionValidator)dataBroker.getSupportedExtensions()
47 .get(DOMDataTransactionValidator.class);
51 public synchronized void close() {
52 for (final DOMDataReadWriteTransaction rwt : allOpenReadWriteTransactions) {
56 allOpenReadWriteTransactions.clear();
59 public synchronized Optional<DOMDataReadWriteTransaction> getCandidateTransaction() {
60 if (candidateTransaction == null) {
61 return Optional.absent();
64 return Optional.of(candidateTransaction);
67 public synchronized DOMDataReadWriteTransaction getOrCreateTransaction() {
68 if (getCandidateTransaction().isPresent()) {
69 return getCandidateTransaction().get();
72 candidateTransaction = dataBroker.newReadWriteTransaction();
73 allOpenReadWriteTransactions.add(candidateTransaction);
74 return candidateTransaction;
77 public synchronized void validateTransaction() throws DocumentedException {
78 if (transactionValidator == null) {
79 LOG.error("Validate capability is not supported");
80 throw new DocumentedException("Validate capability is not supported",
81 ErrorType.PROTOCOL, ErrorTag.OPERATION_NOT_SUPPORTED, ErrorSeverity.ERROR);
84 if (!getCandidateTransaction().isPresent()) {
85 // Validating empty transaction, just return true
86 LOG.debug("Validating empty candidate transaction for session {}", netconfSessionIdForReporting);
91 transactionValidator.validate(candidateTransaction).checkedGet();
92 } catch (final ValidationFailedException e) {
93 LOG.debug("Candidate transaction validation {} failed on session {}", candidateTransaction,
94 netconfSessionIdForReporting, e);
95 final String cause = e.getCause() != null ? (" Cause: " + e.getCause().getMessage()) : "";
96 throw new DocumentedException(
97 "Candidate transaction validate failed on " + e.getMessage() + " " + netconfSessionIdForReporting
98 + cause, e, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, ErrorSeverity.ERROR);
103 public synchronized boolean commitTransaction() throws DocumentedException {
104 if (!getCandidateTransaction().isPresent()) {
105 //making empty commit without prior opened transaction, just return true
106 LOG.debug("Making commit without open candidate transaction for session {}", netconfSessionIdForReporting);
110 final CheckedFuture<Void, TransactionCommitFailedException> future = candidateTransaction.submit();
113 } catch (final TransactionCommitFailedException e) {
114 LOG.debug("Transaction {} failed on", candidateTransaction, e);
115 final String cause = e.getCause() != null ? " Cause: " + e.getCause().getMessage() : "";
116 throw new DocumentedException(
117 "Transaction commit failed on " + e.getMessage() + " " + netconfSessionIdForReporting + cause, e,
118 ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, ErrorSeverity.ERROR);
120 allOpenReadWriteTransactions.remove(candidateTransaction);
121 candidateTransaction = null;
127 public synchronized void abortTransaction() {
128 LOG.debug("Aborting current candidateTransaction");
129 final Optional<DOMDataReadWriteTransaction> otx = getCandidateTransaction();
130 if (!otx.isPresent()) {
131 LOG.warn("discard-changes triggerd on an empty transaction for session: {}", netconfSessionIdForReporting);
134 candidateTransaction.cancel();
135 allOpenReadWriteTransactions.remove(candidateTransaction);
136 candidateTransaction = null;
139 public synchronized DOMDataReadWriteTransaction createRunningTransaction() {
140 runningTransaction = dataBroker.newReadWriteTransaction();
141 allOpenReadWriteTransactions.add(runningTransaction);
142 return runningTransaction;
145 public synchronized void abortRunningTransaction(final DOMDataReadWriteTransaction tx) {
146 LOG.debug("Aborting current running Transaction");
147 Preconditions.checkState(runningTransaction != null,
148 NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
150 allOpenReadWriteTransactions.remove(tx);