Move netconf-console to apps/
[netconf.git] / plugins / sal-netconf-connector / src / main / java / org / opendaylight / netconf / sal / connect / netconf / sal / tx / AbstractTxChain.java
1 /*
2  * Copyright (c) 2016 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.sal.connect.netconf.sal.tx;
9
10 import static com.google.common.base.Preconditions.checkState;
11
12 import java.util.HashMap;
13 import java.util.Map;
14 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
15 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
16 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
17 import org.opendaylight.mdsal.dom.api.DOMTransactionChainClosedException;
18 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 /**
23  * {@link DOMTransactionChain} implementation for Netconf connector.
24  */
25 abstract class AbstractTxChain implements DOMTransactionChain, TxListener {
26     private static final Logger LOG = LoggerFactory.getLogger(AbstractTxChain.class);
27
28     /**
29      * Submitted transactions that haven't completed yet.
30      */
31     private final Map<DOMDataTreeWriteTransaction, AutoCloseable> pendingTransactions = new HashMap<>();
32
33     final DOMDataBroker dataBroker;
34     final DOMTransactionChainListener listener;
35
36     /**
37      * Transaction created by this chain that hasn't been submitted or cancelled yet.
38      */
39     private AbstractWriteTx currentTransaction = null;
40     private boolean closed = false;
41     private boolean successful = true;
42
43     AbstractTxChain(final DOMDataBroker dataBroker, final DOMTransactionChainListener listener) {
44         this.dataBroker = dataBroker;
45         this.listener = listener;
46     }
47
48     @Override
49     public final synchronized AbstractWriteTx newWriteOnlyTransaction() {
50         checkOperationPermitted();
51         final DOMDataTreeWriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
52         checkState(writeTransaction instanceof AbstractWriteTx);
53         final AbstractWriteTx pendingWriteTx = (AbstractWriteTx) writeTransaction;
54         pendingTransactions.put(pendingWriteTx, pendingWriteTx.addListener(this));
55         currentTransaction = pendingWriteTx;
56         return pendingWriteTx;
57     }
58
59     @Override
60     public final synchronized void close() {
61         if (!closed) {
62             closed = true;
63             notifyChainListenerSuccess();
64         }
65     }
66
67     @Override
68     public final synchronized void onTransactionSuccessful(final AbstractWriteTx transaction) {
69         removePendingTx(transaction);
70         notifyChainListenerSuccess();
71     }
72
73     @Override
74     public final synchronized void onTransactionFailed(final AbstractWriteTx transaction, final Throwable cause) {
75         removePendingTx(transaction);
76         successful = false;
77         if (currentTransaction != null) {
78             currentTransaction.cancel();
79         }
80         listener.onTransactionChainFailed(this, transaction, cause);
81     }
82
83     @Override
84     public final synchronized void onTransactionSubmitted(final AbstractWriteTx transaction) {
85         currentTransaction = null;
86     }
87
88     @Override
89     public final synchronized void onTransactionCancelled(final AbstractWriteTx transaction) {
90         removePendingTx(transaction);
91         currentTransaction = null;
92     }
93
94     /**
95      * Checks, if chain isn't closed and if there is no not submitted write transaction waiting.
96      */
97     final void checkOperationPermitted() {
98         if (closed) {
99             throw new DOMTransactionChainClosedException("Transaction chain was closed");
100         }
101         checkState(currentTransaction == null, "Last write transaction has not finished yet");
102     }
103
104     @SuppressWarnings("checkstyle:IllegalCatch")
105     private void removePendingTx(final AbstractWriteTx transaction) {
106         try {
107             pendingTransactions.remove(transaction).close();
108         } catch (final Exception e) {
109             LOG.error("Can't remove transaction listener registration", e);
110         }
111     }
112
113     private void notifyChainListenerSuccess() {
114         if (closed && pendingTransactions.isEmpty() && successful) {
115             listener.onTransactionChainSuccessful(this);
116         }
117     }
118 }