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
8 package org.opendaylight.netconf.client.mdsal.spi;
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.util.HashMap;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
19 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
20 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
21 import org.opendaylight.mdsal.dom.api.DOMTransactionChainClosedException;
22 import org.opendaylight.yangtools.concepts.Registration;
23 import org.opendaylight.yangtools.yang.common.Empty;
26 * {@link DOMTransactionChain} implementation for Netconf connector.
28 abstract class AbstractTxChain implements DOMTransactionChain, TxListener {
29 // Submitted transactions that haven't completed yet.
30 private final Map<DOMDataTreeWriteTransaction, Registration> pendingTransactions = new HashMap<>();
31 private final @NonNull SettableFuture<Empty> future = SettableFuture.create();
33 final DOMDataBroker dataBroker;
36 * Transaction created by this chain that hasn't been submitted or cancelled yet.
38 private AbstractWriteTx currentTransaction = null;
39 private boolean closed = false;
40 private boolean successful = true;
42 AbstractTxChain(final DOMDataBroker dataBroker) {
43 this.dataBroker = requireNonNull(dataBroker);
47 public final ListenableFuture<Empty> future() {
52 public final synchronized AbstractWriteTx newWriteOnlyTransaction() {
53 checkOperationPermitted();
55 final var writeTransaction = dataBroker.newWriteOnlyTransaction();
56 if (!(writeTransaction instanceof AbstractWriteTx pendingWriteTx)) {
57 throw new IllegalStateException("Unexpected transaction " + writeTransaction);
59 pendingTransactions.put(pendingWriteTx, pendingWriteTx.addListener(this));
60 currentTransaction = pendingWriteTx;
61 return pendingWriteTx;
65 public final synchronized void close() {
68 notifyChainListenerSuccess();
73 public final synchronized void onTransactionSuccessful(final AbstractWriteTx transaction) {
74 removePendingTx(transaction);
75 notifyChainListenerSuccess();
79 public final synchronized void onTransactionFailed(final AbstractWriteTx transaction, final Throwable cause) {
80 removePendingTx(transaction);
82 if (currentTransaction != null) {
83 currentTransaction.cancel();
85 future.setException(cause);
89 public final synchronized void onTransactionSubmitted(final AbstractWriteTx transaction) {
90 currentTransaction = null;
94 public final synchronized void onTransactionCancelled(final AbstractWriteTx transaction) {
95 removePendingTx(transaction);
96 currentTransaction = null;
100 * Checks, if chain isn't closed and if there is no not submitted write transaction waiting.
102 final void checkOperationPermitted() {
104 throw new DOMTransactionChainClosedException("Transaction chain was closed");
106 checkState(currentTransaction == null, "Last write transaction has not finished yet");
109 private void removePendingTx(final AbstractWriteTx transaction) {
110 pendingTransactions.remove(transaction).close();
113 private void notifyChainListenerSuccess() {
114 if (closed && pendingTransactions.isEmpty() && successful) {
115 future.set(Empty.value());