2 * Copyright (c) 2016 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.sal.connect.netconf.sal.tx;
11 import com.google.common.base.Preconditions;
12 import java.util.HashMap;
14 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainClosedException;
15 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
16 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
17 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
18 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
19 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
20 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * {@link DOMTransactionChain} implementation for Netconf connector.
27 public class TxChain implements DOMTransactionChain, TxListener {
29 private static final Logger LOG = LoggerFactory.getLogger(TxChain.class);
31 private final DOMDataBroker dataBroker;
32 private final TransactionChainListener listener;
34 * Submitted transactions that haven't completed yet.
36 private final Map<DOMDataWriteTransaction, AutoCloseable> pendingTransactions = new HashMap<>();
39 * Transaction created by this chain that hasn't been submitted or cancelled yet.
41 private AbstractWriteTx currentTransaction = null;
42 private boolean closed = false;
43 private boolean successful = true;
45 public TxChain(final DOMDataBroker dataBroker, final TransactionChainListener listener) {
46 this.dataBroker = dataBroker;
47 this.listener = listener;
51 public synchronized DOMDataReadOnlyTransaction newReadOnlyTransaction() {
52 checkOperationPermitted();
53 return dataBroker.newReadOnlyTransaction();
57 public synchronized AbstractWriteTx newWriteOnlyTransaction() {
58 checkOperationPermitted();
59 final DOMDataWriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
60 Preconditions.checkState(writeTransaction instanceof AbstractWriteTx);
61 final AbstractWriteTx pendingWriteTx = (AbstractWriteTx) writeTransaction;
62 pendingTransactions.put(pendingWriteTx, pendingWriteTx.addListener(this));
63 currentTransaction = pendingWriteTx;
64 return pendingWriteTx;
68 public synchronized DOMDataReadWriteTransaction newReadWriteTransaction() {
69 return new ReadWriteTx(dataBroker.newReadOnlyTransaction(), newWriteOnlyTransaction());
73 public synchronized void close() {
76 notifyChainListenerSuccess();
81 public synchronized void onTransactionSuccessful(final AbstractWriteTx transaction) {
82 removePendingTx(transaction);
83 notifyChainListenerSuccess();
87 public synchronized void onTransactionFailed(final AbstractWriteTx transaction, final Throwable cause) {
88 removePendingTx(transaction);
90 if (currentTransaction != null) {
91 currentTransaction.cancel();
93 listener.onTransactionChainFailed(this, transaction, cause);
97 public synchronized void onTransactionSubmitted(final AbstractWriteTx transaction) {
98 currentTransaction = null;
102 public synchronized void onTransactionCancelled(final AbstractWriteTx transaction) {
103 removePendingTx(transaction);
104 currentTransaction = null;
107 private void removePendingTx(final AbstractWriteTx transaction) {
109 pendingTransactions.remove(transaction).close();
110 } catch (final Exception e) {
111 LOG.error("Can't remove transaction listener registration", e);
116 * Checks, if chain isn't closed and if there is no not submitted write transaction waiting.
118 private void checkOperationPermitted() {
120 throw new TransactionChainClosedException("Transaction chain was closed");
122 Preconditions.checkState(currentTransaction == null, "Last write transaction has not finished yet");
125 private void notifyChainListenerSuccess() {
126 if (closed && pendingTransactions.isEmpty() && successful) {
127 listener.onTransactionChainSuccessful(this);