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
8 package org.opendaylight.netconf.mdsal.connector;
10 import com.google.common.util.concurrent.FluentFuture;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Optional;
14 import java.util.concurrent.ExecutionException;
15 import org.opendaylight.mdsal.common.api.CommitInfo;
16 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
17 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
18 import org.opendaylight.netconf.api.DocumentedException;
19 import org.opendaylight.yangtools.yang.common.ErrorSeverity;
20 import org.opendaylight.yangtools.yang.common.ErrorTag;
21 import org.opendaylight.yangtools.yang.common.ErrorType;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
25 public final class TransactionProvider implements AutoCloseable {
26 private static final Logger LOG = LoggerFactory.getLogger(TransactionProvider.class);
28 private final List<DOMDataTreeReadWriteTransaction> allOpenReadWriteTransactions = new ArrayList<>();
29 private final DOMDataTransactionValidator transactionValidator;
30 private final DOMDataBroker dataBroker;
31 private final String netconfSessionIdForReporting;
33 private DOMDataTreeReadWriteTransaction candidateTransaction = null;
34 private DOMDataTreeReadWriteTransaction runningTransaction = null;
36 public TransactionProvider(final DOMDataBroker dataBroker, final String netconfSessionIdForReporting) {
37 this.dataBroker = dataBroker;
38 this.netconfSessionIdForReporting = netconfSessionIdForReporting;
39 transactionValidator = dataBroker.getExtensions().getInstance(DOMDataTransactionValidator.class);
43 public synchronized void close() {
44 for (var rwt : allOpenReadWriteTransactions) {
48 allOpenReadWriteTransactions.clear();
51 public synchronized Optional<DOMDataTreeReadWriteTransaction> getCandidateTransaction() {
52 return Optional.ofNullable(candidateTransaction);
55 public synchronized DOMDataTreeReadWriteTransaction getOrCreateTransaction() {
56 if (candidateTransaction == null) {
57 candidateTransaction = dataBroker.newReadWriteTransaction();
58 allOpenReadWriteTransactions.add(candidateTransaction);
60 return candidateTransaction;
63 public synchronized void validateTransaction() throws DocumentedException {
64 if (transactionValidator == null) {
65 LOG.error("Validate capability is not supported");
66 throw new DocumentedException("Validate capability is not supported",
67 ErrorType.PROTOCOL, ErrorTag.OPERATION_NOT_SUPPORTED, ErrorSeverity.ERROR);
70 if (candidateTransaction == null) {
71 // Validating empty transaction, just return true
72 LOG.debug("Validating empty candidate transaction for session {}", netconfSessionIdForReporting);
77 transactionValidator.validate(candidateTransaction).get();
78 } catch (final InterruptedException | ExecutionException e) {
79 LOG.debug("Candidate transaction validation {} failed on session {}", candidateTransaction,
80 netconfSessionIdForReporting, e);
81 final String cause = e.getCause() != null ? " Cause: " + e.getCause().getMessage() : "";
82 throw new DocumentedException("Candidate transaction validate failed [sessionId="
83 + netconfSessionIdForReporting + "]: " + e.getMessage() + cause, e, ErrorType.APPLICATION,
84 ErrorTag.OPERATION_FAILED, ErrorSeverity.ERROR);
88 public synchronized boolean commitTransaction() throws DocumentedException {
89 if (candidateTransaction == null) {
90 //making empty commit without prior opened transaction, just return true
91 LOG.debug("Making commit without open candidate transaction for session {}", netconfSessionIdForReporting);
95 final FluentFuture<? extends CommitInfo> future = candidateTransaction.commit();
98 } catch (final InterruptedException | ExecutionException e) {
99 LOG.debug("Transaction {} failed on", candidateTransaction, e);
100 final String cause = e.getCause() != null ? " Cause: " + e.getCause().getMessage() : "";
101 throw new DocumentedException("Transaction commit failed on " + e.getMessage() + " "
102 + netconfSessionIdForReporting + cause, e, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED,
103 ErrorSeverity.ERROR);
105 allOpenReadWriteTransactions.remove(candidateTransaction);
106 candidateTransaction = null;
112 public synchronized void abortTransaction() {
113 LOG.debug("Aborting current candidateTransaction");
114 if (candidateTransaction == null) {
115 LOG.warn("discard-changes triggerd on an empty transaction for session: {}", netconfSessionIdForReporting);
119 candidateTransaction.cancel();
120 allOpenReadWriteTransactions.remove(candidateTransaction);
121 candidateTransaction = null;
124 public synchronized DOMDataTreeReadWriteTransaction createRunningTransaction() {
125 runningTransaction = dataBroker.newReadWriteTransaction();
126 allOpenReadWriteTransactions.add(runningTransaction);
127 return runningTransaction;
130 public synchronized void abortRunningTransaction(final DOMDataTreeReadWriteTransaction tx) {
131 LOG.debug("Aborting current running Transaction");
132 if (runningTransaction == null) {
133 throw new IllegalStateException("No candidateTransaction found for session "
134 + netconfSessionIdForReporting);
137 allOpenReadWriteTransactions.remove(tx);