Clean up mdsal-netconf-monitoring dependencies
[netconf.git] / netconf / mdsal-netconf-connector / src / main / java / org / opendaylight / netconf / mdsal / connector / TransactionProvider.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.mdsal.connector;
9
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;
24
25 public final class TransactionProvider implements AutoCloseable {
26     private static final Logger LOG = LoggerFactory.getLogger(TransactionProvider.class);
27
28     private final List<DOMDataTreeReadWriteTransaction> allOpenReadWriteTransactions = new ArrayList<>();
29     private final DOMDataTransactionValidator transactionValidator;
30     private final DOMDataBroker dataBroker;
31     private final String netconfSessionIdForReporting;
32
33     private DOMDataTreeReadWriteTransaction candidateTransaction = null;
34     private DOMDataTreeReadWriteTransaction runningTransaction = null;
35
36     public TransactionProvider(final DOMDataBroker dataBroker, final String netconfSessionIdForReporting) {
37         this.dataBroker = dataBroker;
38         this.netconfSessionIdForReporting = netconfSessionIdForReporting;
39         transactionValidator = dataBroker.getExtensions().getInstance(DOMDataTransactionValidator.class);
40     }
41
42     @Override
43     public synchronized void close() {
44         for (var rwt : allOpenReadWriteTransactions) {
45             rwt.cancel();
46         }
47
48         allOpenReadWriteTransactions.clear();
49     }
50
51     public synchronized Optional<DOMDataTreeReadWriteTransaction> getCandidateTransaction() {
52         return Optional.ofNullable(candidateTransaction);
53     }
54
55     public synchronized DOMDataTreeReadWriteTransaction getOrCreateTransaction() {
56         if (candidateTransaction == null) {
57             candidateTransaction = dataBroker.newReadWriteTransaction();
58             allOpenReadWriteTransactions.add(candidateTransaction);
59         }
60         return candidateTransaction;
61     }
62
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);
68         }
69
70         if (candidateTransaction == null) {
71             // Validating empty transaction, just return true
72             LOG.debug("Validating empty candidate transaction for session {}", netconfSessionIdForReporting);
73             return;
74         }
75
76         try {
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);
85         }
86     }
87
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);
92             return true;
93         }
94
95         final FluentFuture<? extends CommitInfo> future = candidateTransaction.commit();
96         try {
97             future.get();
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);
104         } finally {
105             allOpenReadWriteTransactions.remove(candidateTransaction);
106             candidateTransaction = null;
107         }
108
109         return true;
110     }
111
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);
116             return;
117         }
118
119         candidateTransaction.cancel();
120         allOpenReadWriteTransactions.remove(candidateTransaction);
121         candidateTransaction = null;
122     }
123
124     public synchronized DOMDataTreeReadWriteTransaction createRunningTransaction() {
125         runningTransaction = dataBroker.newReadWriteTransaction();
126         allOpenReadWriteTransactions.add(runningTransaction);
127         return runningTransaction;
128     }
129
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);
135         }
136         tx.cancel();
137         allOpenReadWriteTransactions.remove(tx);
138     }
139 }