Remove (DOM)TransactionChainListener 82/109682/5
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 8 Jan 2024 22:35:31 +0000 (23:35 +0100)
committerRobert Varga <nite@hq.sk>
Wed, 10 Jan 2024 11:54:00 +0000 (11:54 +0000)
Rework error reporting by attaching listeners to a separately exposed
ListenableFuture.

JIRA: MDSAL-850
Change-Id: I61766cb8691ca5f30cdef0908a351bda1f27881a
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
32 files changed:
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/DataBroker.java
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/TransactionChain.java
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/TransactionChainListener.java [deleted file]
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMDataBrokerAdapter.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMTransactionChainAdapter.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiDataBroker.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMAdapterLoaderTest.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMTransactionChainAdapterTest.java
binding/mdsal-binding-spi/src/main/java/org/opendaylight/mdsal/binding/spi/ForwardingDataBroker.java
binding/mdsal-binding-util/src/main/java/org/opendaylight/mdsal/binding/util/ManagedNewTransactionRunnerImpl.java
dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataBroker.java
dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMTransactionChain.java
dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMTransactionChainListener.java [deleted file]
dom/mdsal-dom-broker/src/main/java/module-info.java
dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/AbstractDOMDataBroker.java
dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMDataBrokerTransactionChainImpl.java
dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/BlockingTransactionChainListener.java [deleted file]
dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/DOMTransactionChainTest.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/AbstractPingPongTransactionChain.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/ForwardingDOMDataBroker.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/ForwardingDOMTransactionChain.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/PingPongMergingDOMDataBroker.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/PingPongTransactionChain.java
dom/mdsal-dom-spi/src/test/java/org/opendaylight/mdsal/dom/spi/ForwardingDOMDataBrokerTest.java
dom/mdsal-dom-spi/src/test/java/org/opendaylight/mdsal/dom/spi/ForwardingDOMTransactionChainTest.java
dom/mdsal-dom-spi/src/test/java/org/opendaylight/mdsal/dom/spi/PingPongTransactionChainTest.java
replicate/mdsal-replicate-netty/src/main/java/org/opendaylight/mdsal/replicate/netty/SinkSingletonService.java
replicate/mdsal-replicate-netty/src/main/java/org/opendaylight/mdsal/replicate/netty/SinkTransactionChainListener.java [deleted file]
replicate/mdsal-replicate-netty/src/test/java/org/opendaylight/mdsal/replicate/netty/IntegrationTest.java
trace/mdsal-trace-impl/src/main/java/org/opendaylight/mdsal/trace/impl/TracingBroker.java
trace/mdsal-trace-impl/src/main/java/org/opendaylight/mdsal/trace/impl/TracingTransactionChain.java
trace/mdsal-trace-impl/src/test/java/org/opendaylight/mdsal/trace/test/TracingBrokerTest.java

index c25897527645c9f8f4dc68c210d36c3bab9558b0..89f38e02ee9adb3bb7e350cfebe1ce9510f346bc 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.mdsal.binding.api;
 
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
 
 /**
  * Provides access to a conceptual data tree store and also provides the ability to
@@ -40,32 +40,31 @@ import org.eclipse.jdt.annotation.NonNull;
  * <b>Implementation Note:</b> This interface is not intended to be implemented by users of MD-SAL,
  * but only to be consumed by them.
  */
+@NonNullByDefault
 public interface DataBroker extends BindingService, TransactionFactory, DataTreeChangeService {
     /**
      * Create a new transaction chain. The chain will be initialized to read from its backing datastore, with
      * no outstanding transaction. Listener will be registered to handle chain-level events.
      *
-     * @param listener Transaction chain event listener
      * @return A new transaction chain.
      */
-    @NonNull TransactionChain createTransactionChain(@NonNull TransactionChainListener listener);
+    TransactionChain createTransactionChain();
 
     /**
      * Create a new transaction chain. The chain will be initialized to read from its backing datastore, with
      * no outstanding transaction. Listener will be registered to handle chain-level events.
      *
      * <p>
-     * Unlike {@link #createTransactionChain(TransactionChainListener)}, the transaction chain returned by this
-     * method is allowed to merge individual transactions into larger chunks. When transactions are merged, the results
-     * must be indistinguishable from the result of all operations having been performed on a single transaction.
+     * Unlike {@link #createTransactionChain()}, the transaction chain returned by this method is allowed to merge
+     * individual transactions into larger chunks. When transactions are merged, the results must be indistinguishable
+     * from the result of all operations having been performed on a single transaction.
      *
      * <p>
      * When transactions are merged, {@link TransactionChain#newReadOnlyTransaction()} may actually be backed by
      * a read-write transaction, hence an additional restriction on API use is that multiple read-only transactions
      * may not be open at the same time.
      *
-     * @param listener Transaction chain event listener
      * @return A new transaction chain.
      */
-    @NonNull TransactionChain createMergingTransactionChain(@NonNull TransactionChainListener listener);
+    TransactionChain createMergingTransactionChain();
 }
index 4383db49c9befceec01d39504233a5fb070af8e0..04a73e6447bba607c8ee48f9ab4a746b3dd7d9ef 100644 (file)
@@ -7,7 +7,14 @@
  */
 package org.opendaylight.mdsal.binding.api;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.util.concurrent.Executor;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.Empty;
 
 /**
  * A chain of transactions. Transactions in a chain need to be committed in sequence and each transaction should see
@@ -102,4 +109,32 @@ public interface TransactionChain extends Registration, TransactionFactory {
      */
     @Override
     ReadWriteTransaction newReadWriteTransaction();
+
+    /**
+     * Add a completion callback to execute when {@link #future()} completes. This is a shorthand for
+     * {@code Futures.addCallback(future(), callback, MoreExecutors.directExecutor())}.
+     *
+     * @param callback completion callback
+     */
+    default void addCallback(final FutureCallback<Empty> callback) {
+        addCallback(callback, MoreExecutors.directExecutor());
+    }
+
+    /**
+     * Add a completion callback to execute on specified executor when {@link #future()} completes. This is a shorthand
+     * for {@code Futures.addCallback(future(), callback, executor)}.
+     *
+     * @param callback completion callback
+     * @param executor executor on which to execute the callback
+     */
+    default void addCallback(final FutureCallback<Empty> callback, final Executor executor) {
+        Futures.addCallback(future(), callback, executor);
+    }
+
+    /**
+     * Return a {@link ListenableFuture} which completes when this chain completes.
+     *
+     * @return A {@link ListenableFuture}
+     */
+    @NonNull ListenableFuture<Empty> future();
 }
diff --git a/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/TransactionChainListener.java b/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/TransactionChainListener.java
deleted file mode 100644 (file)
index 90c766c..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.api;
-
-import org.eclipse.jdt.annotation.NonNull;
-
-/**
- * Listener for transaction chain events.
- */
-// FIXME: 6.0.0: remove this in favor of a TransactionChain destiny, available as a FluentFuture from TransactionChain
-public interface TransactionChainListener {
-    /**
-     * Invoked if when a transaction in the chain fails. All transactions submitted after the failed transaction, in the
-     * chain, are automatically cancelled by the time this notification is invoked. Open transactions need to be closed
-     * or cancelled.
-     * Implementations should invoke chain.close() to close the chain.
-     *
-     * @param chain Transaction chain which failed
-     * @param transaction Transaction which caused the chain to fail
-     * @param cause The cause of transaction failure
-     */
-    void onTransactionChainFailed(@NonNull TransactionChain chain, @NonNull Transaction transaction,
-            @NonNull Throwable cause);
-
-    /**
-     * Invoked when a transaction chain is completed. A transaction chain is considered completed when it has been
-     * closed and all its instructions have completed successfully.
-     *
-     * @param chain Transaction chain which completed
-     */
-    void onTransactionChainSuccessful(@NonNull TransactionChain chain);
-}
-
index edcd2491e9c37ae5db0e55c1b6935d1a1bcce081..9fbc7f23a2fe87a817bbbde11925ff3e29f52af7 100644 (file)
@@ -19,7 +19,6 @@ import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
 import org.opendaylight.mdsal.binding.api.ReadTransaction;
 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.binding.api.TransactionChain;
-import org.opendaylight.mdsal.binding.api.TransactionChainListener;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.BindingDOMAdapterBuilder.Factory;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
@@ -65,14 +64,13 @@ public class BindingDOMDataBrokerAdapter extends AbstractBindingAdapter<@NonNull
     }
 
     @Override
-    public TransactionChain createTransactionChain(final TransactionChainListener listener) {
-        return new BindingDOMTransactionChainAdapter(getDelegate()::createTransactionChain, adapterContext(), listener);
+    public TransactionChain createTransactionChain() {
+        return new BindingDOMTransactionChainAdapter(getDelegate().createTransactionChain(), adapterContext());
     }
 
     @Override
-    public TransactionChain createMergingTransactionChain(final TransactionChainListener listener) {
-        return new BindingDOMTransactionChainAdapter(getDelegate()::createMergingTransactionChain, adapterContext(),
-            listener);
+    public TransactionChain createMergingTransactionChain() {
+        return new BindingDOMTransactionChainAdapter(getDelegate().createMergingTransactionChain(), adapterContext());
     }
 
     @Override
index dad9227be2e710549a0ff7d3eca797d2e1af1189..8bca8533fb7dd738564c00a5be6c904e177fc800 100644 (file)
@@ -7,49 +7,28 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter;
 
-import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.util.concurrent.FluentFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.util.function.Function;
 import java.util.function.Supplier;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.ReadTransaction;
 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.binding.api.TransactionChain;
 import org.opendaylight.mdsal.binding.api.TransactionChainClosedException;
-import org.opendaylight.mdsal.binding.api.TransactionChainListener;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
-import org.opendaylight.mdsal.common.api.CommitInfo;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChainClosedException;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 import org.opendaylight.yangtools.concepts.Delegator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.opendaylight.yangtools.yang.common.Empty;
 
 final class BindingDOMTransactionChainAdapter implements TransactionChain, Delegator<DOMTransactionChain> {
+    private final @NonNull DOMTransactionChain delegate;
+    private final @NonNull AdapterContext adapterContext;
 
-    private static final Logger LOG = LoggerFactory.getLogger(BindingDOMTransactionChainAdapter.class);
-
-    private final DOMTransactionChain delegate;
-    private final AdapterContext adapterContext;
-    private final DelegateChainListener domListener;
-    private final TransactionChainListener bindingListener;
-
-    BindingDOMTransactionChainAdapter(final Function<DOMTransactionChainListener, DOMTransactionChain> chainFactory,
-            final AdapterContext codec, final TransactionChainListener listener) {
-        requireNonNull(chainFactory, "DOM Transaction chain factory must not be null");
-        this.domListener = new DelegateChainListener();
-        this.bindingListener = listener;
-        this.delegate = chainFactory.apply(domListener);
-        this.adapterContext = requireNonNull(codec);
+    BindingDOMTransactionChainAdapter(final DOMTransactionChain delegate, final AdapterContext adapterContext) {
+        this.delegate = requireNonNull(delegate);
+        this.adapterContext = requireNonNull(adapterContext);
     }
 
     @Override
@@ -65,50 +44,19 @@ final class BindingDOMTransactionChainAdapter implements TransactionChain, Deleg
 
     @Override
     public WriteTransaction newWriteOnlyTransaction() {
-        final DOMDataTreeWriteTransaction delegateTx = createTransaction(delegate::newWriteOnlyTransaction);
-        return new BindingDOMWriteTransactionAdapter<>(adapterContext, delegateTx) {
-            @Override
-            public FluentFuture<? extends CommitInfo> commit() {
-                return listenForFailure(this, super.commit());
-            }
-        };
+        return new BindingDOMWriteTransactionAdapter<>(adapterContext,
+            createTransaction(delegate::newWriteOnlyTransaction));
     }
 
     @Override
     public ReadWriteTransaction newReadWriteTransaction() {
-        final DOMDataTreeReadWriteTransaction delegateTx = createTransaction(delegate::newReadWriteTransaction);
-        return new BindingDOMReadWriteTransactionAdapter(adapterContext, delegateTx) {
-            @Override
-            public FluentFuture<? extends CommitInfo> commit() {
-                return listenForFailure(this, super.commit());
-            }
-        };
-    }
-
-    private <T, F extends ListenableFuture<T>> F listenForFailure(final WriteTransaction tx, final F future) {
-        Futures.addCallback(future, new FutureCallback<T>() {
-            @Override
-            public void onFailure(final Throwable throwable) {
-                failTransactionChain(tx, throwable);
-            }
-
-            @Override
-            public void onSuccess(final T result) {
-                // Intentionally NOOP
-            }
-        }, MoreExecutors.directExecutor());
-
-        return future;
+        return new BindingDOMReadWriteTransactionAdapter(adapterContext,
+            createTransaction(delegate::newReadWriteTransaction));
     }
 
-    private void failTransactionChain(final WriteTransaction tx, final Throwable throwable) {
-        /*
-         *  We asume correct state change for underlaying transaction
-         *
-         * chain, so we are not changing any of our internal state
-         * to mark that we failed.
-         */
-        this.bindingListener.onTransactionChainFailed(this, tx, throwable);
+    @Override
+    public ListenableFuture<Empty> future() {
+        return delegate.future();
     }
 
     @Override
@@ -123,27 +71,4 @@ final class BindingDOMTransactionChainAdapter implements TransactionChain, Deleg
             throw new TransactionChainClosedException("Transaction chain already closed", e);
         }
     }
-
-    private final class DelegateChainListener implements DOMTransactionChainListener {
-        @Override
-        public void onTransactionChainFailed(final DOMTransactionChain chain, final DOMDataTreeTransaction transaction,
-                final Throwable cause) {
-            checkState(delegate.equals(chain), "Listener for %s was invoked for incorrect chain %s.", delegate, chain);
-            /*
-             * Intentionally NOOP, callback for failure, since we
-             * are also listening on each transaction future for failure,
-             * in order to have reference to Binding Transaction (which was seen by client
-             * of this transaction chain), instead of DOM transaction
-             * which is known only to this chain, binding transaction implementation
-             * and underlying transaction chain.
-             */
-            LOG.debug("Transaction chain {} failed. Failed DOM Transaction {}",this,transaction,cause);
-        }
-
-        @Override
-        public void onTransactionChainSuccessful(final DOMTransactionChain chain) {
-            checkState(delegate.equals(chain), "Listener for %s was invoked for incorrect chain %s.", delegate, chain);
-            bindingListener.onTransactionChainSuccessful(BindingDOMTransactionChainAdapter.this);
-        }
-    }
 }
index 29e478f3a0ed446d460c35511454bd0ab661c995..24787cb0127d11780bea57f2d29e808c7b327dd8 100644 (file)
@@ -15,7 +15,6 @@ import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
 import org.opendaylight.mdsal.binding.api.ReadTransaction;
 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.binding.api.TransactionChain;
-import org.opendaylight.mdsal.binding.api.TransactionChainListener;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -61,12 +60,12 @@ public final class OSGiDataBroker extends AbstractAdaptedService<DataBroker> imp
     }
 
     @Override
-    public TransactionChain createTransactionChain(final TransactionChainListener listener) {
-        return delegate.createTransactionChain(listener);
+    public TransactionChain createTransactionChain() {
+        return delegate.createTransactionChain();
     }
 
     @Override
-    public TransactionChain createMergingTransactionChain(final TransactionChainListener listener) {
-        return delegate.createMergingTransactionChain(listener);
+    public TransactionChain createMergingTransactionChain() {
+        return delegate.createMergingTransactionChain();
     }
 }
index d96931c67c3d548af2c7081f8ee89a1d204d5af3..60caa8674dfae3747cf21098b0894b456aff2126 100644 (file)
@@ -12,6 +12,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
 import java.util.Optional;
@@ -23,10 +24,10 @@ import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
-import org.opendaylight.mdsal.binding.api.TransactionChainListener;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMService;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.yang.gen.v1.bug8449.rev170516.Top;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -36,6 +37,8 @@ public class BindingDOMAdapterLoaderTest {
     private DOMDataBroker domService;
     @Mock
     private AdapterContext mockContext;
+    @Mock
+    private DOMTransactionChain domChain;
 
     private BindingDOMAdapterLoader bindingDOMAdapterLoader;
 
@@ -59,7 +62,8 @@ public class BindingDOMAdapterLoaderTest {
     @Test
     public void createChainTest() {
         final var adapter = assertDataBrokerAdapter();
-        assertNotNull(adapter.createTransactionChain(mock(TransactionChainListener.class)));
+        doReturn(domChain).when(domService).createTransactionChain();
+        assertNotNull(adapter.createTransactionChain());
     }
 
     @Test
index c80847b9865818fd5d100b0f8807692cd4e5332f..99e61898dc51a319e929f981135f42c70695a42e 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.mdsal.binding.dom.adapter;
 
 import static java.util.Objects.requireNonNull;
 import static org.junit.Assert.assertNotNull;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -18,7 +17,7 @@ import static org.mockito.Mockito.verify;
 
 import java.util.Collection;
 import java.util.List;
-import java.util.function.BiFunction;
+import java.util.function.Function;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -31,7 +30,6 @@ import org.mockito.junit.MockitoRule;
 import org.mockito.quality.Strictness;
 import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.binding.api.TransactionChain;
-import org.opendaylight.mdsal.binding.api.TransactionChainListener;
 import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
@@ -42,11 +40,11 @@ import org.opendaylight.mdsal.dom.spi.PingPongMergingDOMDataBroker;
 
 @RunWith(Parameterized.class)
 public class BindingDOMTransactionChainAdapterTest {
-    public enum TransactionChainType implements BiFunction<DataBroker, TransactionChainListener, TransactionChain> {
+    public enum TransactionChainType implements Function<DataBroker, TransactionChain> {
         NORMAL {
             @Override
-            public TransactionChain apply(final DataBroker broker, final TransactionChainListener listener) {
-                return broker.createTransactionChain(listener);
+            public TransactionChain apply(final DataBroker broker) {
+                return broker.createTransactionChain();
             }
 
             @Override
@@ -62,8 +60,8 @@ public class BindingDOMTransactionChainAdapterTest {
         },
         MERGING {
             @Override
-            public TransactionChain apply(final DataBroker broker, final TransactionChainListener listener) {
-                return broker.createMergingTransactionChain(listener);
+            public TransactionChain apply(final DataBroker broker) {
+                return broker.createMergingTransactionChain();
             }
 
             @Override
@@ -97,8 +95,6 @@ public class BindingDOMTransactionChainAdapterTest {
     @Mock
     private DOMTransactionChain transactionChain;
     @Mock
-    private TransactionChainListener transactionChainListener;
-    @Mock
     private BindingDOMCodecServices mockCodecRegistry;
 
     private BindingDOMTransactionChainAdapter bindingDOMTransactionChainAdapter;
@@ -109,9 +105,9 @@ public class BindingDOMTransactionChainAdapterTest {
 
     @Before
     public void setUp() {
-        doReturn(transactionChain).when(domService).createTransactionChain(any());
+        doReturn(transactionChain).when(domService).createTransactionChain();
         if (type == TransactionChainType.MERGING) {
-            doCallRealMethod().when(domService).createMergingTransactionChain(any());
+            doCallRealMethod().when(domService).createMergingTransactionChain();
         }
 
 
@@ -126,7 +122,7 @@ public class BindingDOMTransactionChainAdapterTest {
         BindingDOMDataBrokerAdapter bindingDOMDataBrokerAdapter =
                 (BindingDOMDataBrokerAdapter) bindingDOMAdapterLoader.load(DataBroker.class).orElseThrow();
         bindingDOMTransactionChainAdapter =
-            (BindingDOMTransactionChainAdapter) type.apply(bindingDOMDataBrokerAdapter, transactionChainListener);
+            (BindingDOMTransactionChainAdapter) type.apply(bindingDOMDataBrokerAdapter);
         assertNotNull(bindingDOMTransactionChainAdapter.getDelegate());
 
     }
@@ -159,5 +155,4 @@ public class BindingDOMTransactionChainAdapterTest {
         mockReadWrite(transactionChain);
         assertNotNull(bindingDOMTransactionChainAdapter.newReadWriteTransaction());
     }
-
 }
index 7ddd2664512ea15ac2a67b2eebb0b1125cefc5c6..40332c6c217c17d10ad2bb994976e425529c0794 100644 (file)
@@ -15,7 +15,6 @@ import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
 import org.opendaylight.mdsal.binding.api.ReadTransaction;
 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.binding.api.TransactionChain;
-import org.opendaylight.mdsal.binding.api.TransactionChainListener;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -49,12 +48,12 @@ public abstract class ForwardingDataBroker extends ForwardingObject implements D
     }
 
     @Override
-    public TransactionChain createTransactionChain(final TransactionChainListener listener) {
-        return delegate().createTransactionChain(listener);
+    public TransactionChain createTransactionChain() {
+        return delegate().createTransactionChain();
     }
 
     @Override
-    public TransactionChain createMergingTransactionChain(final TransactionChainListener listener) {
-        return delegate().createMergingTransactionChain(listener);
+    public TransactionChain createMergingTransactionChain() {
+        return delegate().createMergingTransactionChain();
     }
 }
index 44ccf7360364b5bab1132bec364bc6079a2d6aac..6c2f2f8a45825d121a790498719ea9238bae95ce 100644 (file)
@@ -11,16 +11,16 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.FutureCallback;
 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.function.Function;
 import javax.inject.Inject;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.binding.api.DataBroker;
-import org.opendaylight.mdsal.binding.api.Transaction;
-import org.opendaylight.mdsal.binding.api.TransactionChain;
-import org.opendaylight.mdsal.binding.api.TransactionChainListener;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory;
 // Do *NOT* mark this as @Singleton, because users choose their implementation
 public class ManagedNewTransactionRunnerImpl extends ManagedTransactionFactoryImpl<DataBroker>
         implements ManagedNewTransactionRunner {
-
     private static final Logger LOG = LoggerFactory.getLogger(ManagedNewTransactionRunnerImpl.class);
 
     @Inject
@@ -54,18 +53,18 @@ public class ManagedNewTransactionRunnerImpl extends ManagedTransactionFactoryIm
     @Override
     @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
     public <R> R applyWithNewTransactionChainAndClose(final Function<ManagedTransactionChain, R> chainConsumer) {
-        try (TransactionChain realTxChain = getTransactionFactory().createTransactionChain(
-            new TransactionChainListener() {
+        try (var realTxChain = getTransactionFactory().createTransactionChain()) {
+            realTxChain.addCallback(new FutureCallback<>() {
                 @Override
-                public void onTransactionChainFailed(TransactionChain chain, Transaction transaction, Throwable cause) {
-                    LOG.error("Error handling a transaction chain", cause);
+                public void onSuccess(final @Nullable Empty result) {
+                    // Nothing to do
                 }
 
                 @Override
-                public void onTransactionChainSuccessful(TransactionChain chain) {
-                    // Nothing to do
+                public void onFailure(final @Nullable Throwable cause) {
+                    LOG.error("Error handling a transaction chain", cause);
                 }
-            })) {
+            });
             return chainConsumer.apply(new ManagedTransactionChainImpl(realTxChain));
         }
     }
index edfc8bfdb2c80cc38398ff43b07e25ec79fdcaab..a81b1a5bcf249c684b996af98073ad3a730625d3 100644 (file)
@@ -51,29 +51,27 @@ public interface DOMDataBroker extends DOMService<DOMDataBroker, DOMDataBroker.E
 
     /**
      * Create a new transaction chain. The chain will be initialized to read from its backing datastore, with
-     * no outstanding transaction. Listener will be registered to handle chain-level events.
+     * no outstanding transaction.
      *
-     * @param listener Transaction chain event listener
      * @return A new transaction chain.
      */
-    @NonNull DOMTransactionChain createTransactionChain(DOMTransactionChainListener listener);
+    @NonNull DOMTransactionChain createTransactionChain();
 
     /**
      * Create a new transaction chain. The chain will be initialized to read from its backing datastore, with
-     * no outstanding transaction. Listener will be registered to handle chain-level events.
+     * no outstanding transaction.
      *
      * <p>
-     * Unlike {@link #createTransactionChain(DOMTransactionChainListener)}, the transaction chain returned by this
-     * method is allowed to merge individual transactions into larger chunks. When transactions are merged, the results
-     * must be indistinguishable from the result of all operations having been performed on a single transaction.
+     * Unlike {@link #createTransactionChain()}, the transaction chain returned by this method is allowed to merge
+     * individual transactions into larger chunks. When transactions are merged, the results must be indistinguishable
+     * from the result of all operations having been performed on a single transaction.
      *
      * <p>
      * When transactions are merged, {@link DOMTransactionChain#newReadOnlyTransaction()} may actually be backed by
      * a read-write transaction, hence an additional restriction on API use is that multiple read-only transactions
      * may not be open at the same time.
      *
-     * @param listener Transaction chain event listener
      * @return A new transaction chain.
      */
-    @NonNull DOMTransactionChain createMergingTransactionChain(DOMTransactionChainListener listener);
+    @NonNull DOMTransactionChain createMergingTransactionChain();
 }
index f811a6078bf1d3ecbd45f3d533d53f70083cf889..a828efd1f681333915310651e53bce55a4f88365 100644 (file)
@@ -7,7 +7,14 @@
  */
 package org.opendaylight.mdsal.dom.api;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.util.concurrent.Executor;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.Empty;
 
 /**
  * A chain of transactions. Transactions in a chain need to be committed in sequence and each transaction should see
@@ -103,4 +110,32 @@ public interface DOMTransactionChain extends Registration, DOMTransactionFactory
      */
     @Override
     DOMDataTreeReadWriteTransaction newReadWriteTransaction();
+
+    /**
+     * Add a completion callback to execute when {@link #future()} completes. This is a shorthand for
+     * {@code Futures.addCallback(future(), callback, MoreExecutors.directExecutor())}.
+     *
+     * @param callback completion callback
+     */
+    default void addCallback(final FutureCallback<Empty> callback) {
+        addCallback(callback, MoreExecutors.directExecutor());
+    }
+
+    /**
+     * Add a completion callback to execute on specified executor when {@link #future()} completes. This is a shorthand
+     * for {@code Futures.addCallback(future(), callback, executor)}.
+     *
+     * @param callback completion callback
+     * @param executor executor on which to execute the callback
+     */
+    default void addCallback(final FutureCallback<Empty> callback, final Executor executor) {
+        Futures.addCallback(future(), callback, executor);
+    }
+
+    /**
+     * Return a {@link ListenableFuture} which completes when this chain completes.
+     *
+     * @return A {@link ListenableFuture}
+     */
+    @NonNull ListenableFuture<Empty> future();
 }
diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMTransactionChainListener.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMTransactionChainListener.java
deleted file mode 100644 (file)
index bd210be..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.dom.api;
-
-/**
- * Listener for transaction chain events.
- */
-// FIXME: 6.0.0: remove this in favor of a TransactionChain destiny, available as a FluentFuture from
-//               DOMTransactionChain
-public interface DOMTransactionChainListener {
-    /**
-     * Invoked if when a transaction in the chain fails. All transactions submitted after the failed transaction, in the
-     * chain, are automatically cancelled by the time this notification is invoked. Open transactions need to be closed
-     * or cancelled.
-     * Implementations should invoke chain.close() to close the chain.
-     *
-     * @param chain Transaction chain which failed
-     * @param transaction Transaction which caused the chain to fail
-     * @param cause The cause of transaction failure
-     */
-    void onTransactionChainFailed(DOMTransactionChain chain, DOMDataTreeTransaction transaction, Throwable cause);
-
-    /**
-     * Invoked when a transaction chain is completed. A transaction chain is considered completed when it has been
-     * closed and all its instructions have completed successfully.
-     *
-     * @param chain Transaction chain which completed
-     */
-    void onTransactionChainSuccessful(DOMTransactionChain chain);
-}
-
index fbb06d8fb304f1d4c223ece9040a209979e5ef6f..26549ed0e44bf21063180f87387d854c8690fcae 100644 (file)
@@ -23,6 +23,7 @@ module org.opendaylight.mdsal.dom.broker {
     requires static transitive java.annotation;
     requires static transitive javax.inject;
     requires static com.github.spotbugs.annotations;
+    requires static org.eclipse.jdt.annotation;
     requires static org.kohsuke.metainf_services;
     requires static org.osgi.service.component.annotations;
     requires static org.osgi.service.metatype.annotations;
index 06a4e161081b12dcb707ed54d1a78ed7560f6fea..a47f56457034a55009306ba264c9ba589cc85134 100644 (file)
@@ -15,7 +15,6 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 import org.opendaylight.mdsal.dom.spi.PingPongMergingDOMDataBroker;
 import org.opendaylight.mdsal.dom.spi.store.DOMStore;
 import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransactionChain;
@@ -87,7 +86,7 @@ public abstract class AbstractDOMDataBroker extends AbstractDOMForwardedTransact
 
 
     @Override
-    public DOMTransactionChain createTransactionChain(final DOMTransactionChainListener listener) {
+    public DOMTransactionChain createTransactionChain() {
         checkNotClosed();
 
         final var delegates = new EnumMap<LogicalDatastoreType, DOMStoreTransactionChain>(LogicalDatastoreType.class);
@@ -96,8 +95,7 @@ public abstract class AbstractDOMDataBroker extends AbstractDOMForwardedTransact
         }
 
         final long chainId = chainNum.getAndIncrement();
-        LOG.debug("Transactoin chain {} created with listener {}, backing store chains {}", chainId, listener,
-                delegates);
-        return new DOMDataBrokerTransactionChainImpl(chainId, delegates, this, listener);
+        LOG.debug("Transactoin chain {} created, backing store chains {}", chainId, delegates);
+        return new DOMDataBrokerTransactionChainImpl(chainId, delegates, this);
     }
 }
index 27e8bd172a685984b9e10705bde8c3eafe4056fc..7e696886a9849ecef7de7fff57b471756b92cec6 100644 (file)
@@ -12,18 +12,21 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.SettableFuture;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,9 +50,10 @@ final class DOMDataBrokerTransactionChainImpl extends AbstractDOMForwardedTransa
     private static final AtomicReferenceFieldUpdater<DOMDataBrokerTransactionChainImpl, State> STATE_UPDATER =
             AtomicReferenceFieldUpdater.newUpdater(DOMDataBrokerTransactionChainImpl.class, State.class, "state");
     private static final Logger LOG = LoggerFactory.getLogger(DOMDataBrokerTransactionChainImpl.class);
+
+    private final @NonNull SettableFuture<Empty> future = SettableFuture.create();
     private final AtomicLong txNum = new AtomicLong();
     private final AbstractDOMDataBroker broker;
-    private final DOMTransactionChainListener listener;
     private final long chainId;
 
     private volatile State state = State.RUNNING;
@@ -72,18 +76,21 @@ final class DOMDataBrokerTransactionChainImpl extends AbstractDOMForwardedTransa
      *             If any of arguments is null.
      */
     DOMDataBrokerTransactionChainImpl(final long chainId,
-            final Map<LogicalDatastoreType, DOMStoreTransactionChain> chains,
-            final AbstractDOMDataBroker broker, final DOMTransactionChainListener listener) {
+            final Map<LogicalDatastoreType, DOMStoreTransactionChain> chains, final AbstractDOMDataBroker broker) {
         super(chains);
         this.chainId = chainId;
         this.broker = requireNonNull(broker);
-        this.listener = requireNonNull(listener);
     }
 
     private void checkNotFailed() {
         Preconditions.checkState(state != State.FAILED, "Transaction chain has failed");
     }
 
+    @Override
+    public ListenableFuture<Empty> future() {
+        return future;
+    }
+
     @Override
     protected Object newTransactionIdentifier() {
         return "DOM-CHAIN-" + chainId + "-" + txNum.getAndIncrement();
@@ -95,9 +102,9 @@ final class DOMDataBrokerTransactionChainImpl extends AbstractDOMForwardedTransa
         checkNotFailed();
         checkNotClosed();
 
-        final FluentFuture<? extends CommitInfo> ret = broker.commit(transaction, cohort);
-
+        final var ret = broker.commit(transaction, cohort);
         COUNTER_UPDATER.incrementAndGet(this);
+
         ret.addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo result) {
@@ -133,7 +140,7 @@ final class DOMDataBrokerTransactionChainImpl extends AbstractDOMForwardedTransa
 
     private void finishClose() {
         state = State.CLOSED;
-        listener.onTransactionChainSuccessful(this);
+        future.set(Empty.value());
     }
 
     private void transactionCompleted() {
@@ -145,6 +152,6 @@ final class DOMDataBrokerTransactionChainImpl extends AbstractDOMForwardedTransa
     private void transactionFailed(final DOMDataTreeWriteTransaction tx, final Throwable cause) {
         state = State.FAILED;
         LOG.debug("Transaction chain {} failed.", this, cause);
-        listener.onTransactionChainFailed(this, tx, cause);
+        future.setException(cause);
     }
 }
diff --git a/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/BlockingTransactionChainListener.java b/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/BlockingTransactionChainListener.java
deleted file mode 100644 (file)
index f7a620c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.dom.broker;
-
-import com.google.common.util.concurrent.SettableFuture;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
-
-/**
- * Simple implementation of {@link TransactionChainListener} for testing.
- *
- *<p>
- * This transaction chain listener does not contain any logic, only update
- * futures ({@link #getFailFuture()} and {@link #getSuccessFuture()} when
- * transaction chain event is retrieved.
- *
- */
-class BlockingTransactionChainListener implements DOMTransactionChainListener {
-
-    private final SettableFuture<Throwable> failFuture = SettableFuture.create();
-    private final SettableFuture<Void> successFuture = SettableFuture.create();
-
-    @Override
-    public void onTransactionChainFailed(final DOMTransactionChain chain, final DOMDataTreeTransaction transaction,
-            final Throwable cause) {
-        failFuture.set(cause);
-    }
-
-    @Override
-    public void onTransactionChainSuccessful(final DOMTransactionChain chain) {
-        successFuture.set(null);
-    }
-
-    public SettableFuture<Throwable> getFailFuture() {
-        return failFuture;
-    }
-
-    public SettableFuture<Void> getSuccessFuture() {
-        return successFuture;
-    }
-
-}
index d0076646454aafa9f2a82a1dcc322776388b1fab..190c46811cc1c5d6ba475be4e6d6c1745f03de76 100644 (file)
@@ -7,9 +7,10 @@
  */
 package org.opendaylight.mdsal.dom.broker;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.OPERATIONAL;
 
@@ -61,8 +62,7 @@ public class DOMTransactionChainTest extends AbstractDatastoreTest {
 
     @Test
     public void testTransactionChainNoConflict() throws InterruptedException, ExecutionException, TimeoutException {
-        final BlockingTransactionChainListener listener = new BlockingTransactionChainListener();
-        final DOMTransactionChain txChain = domBroker.createTransactionChain(listener);
+        final DOMTransactionChain txChain = domBroker.createTransactionChain();
         assertNotNull(txChain);
 
         /**
@@ -125,14 +125,12 @@ public class DOMTransactionChainTest extends AbstractDatastoreTest {
          */
         txChain.close();
 
-        listener.getSuccessFuture().get(1000, TimeUnit.MILLISECONDS);
+        txChain.future().get(1000, TimeUnit.MILLISECONDS);
     }
 
-    @SuppressWarnings("checkstyle:IllegalCatch")
     @Test
-    public void testTransactionChainNotSealed() throws InterruptedException, ExecutionException, TimeoutException {
-        final BlockingTransactionChainListener listener = new BlockingTransactionChainListener();
-        final DOMTransactionChain txChain = domBroker.createTransactionChain(listener);
+    public void testTransactionChainNotSealed() {
+        final var txChain = domBroker.createTransactionChain();
         assertNotNull(txChain);
 
         /**
@@ -145,12 +143,9 @@ public class DOMTransactionChainTest extends AbstractDatastoreTest {
          * still not committed to datastore, so this allocation should fail with
          * IllegalStateException.
          */
-        try {
-            allocateAndWrite(txChain); // actual backing tx allocation happens on put
-            fail("Allocation of secondReadTx should fail with IllegalStateException");
-        } catch (final Exception e) {
-            assertTrue(e instanceof IllegalStateException);
-        }
+        // actual backing tx allocation happens on put
+        final var ex = assertThrows(IllegalStateException.class, () -> allocateAndWrite(txChain));
+        assertEquals("Previous transaction OPER-0 is not ready yet", ex.getMessage());
     }
 
     private static DOMDataTreeWriteTransaction allocateAndDelete(final DOMTransactionChain txChain)
@@ -163,9 +158,8 @@ public class DOMTransactionChainTest extends AbstractDatastoreTest {
         return tx;
     }
 
-    private static DOMDataTreeWriteTransaction allocateAndWrite(final DOMTransactionChain txChain)
-            throws InterruptedException, ExecutionException {
-        final DOMDataTreeWriteTransaction tx = txChain.newWriteOnlyTransaction();
+    private static DOMDataTreeWriteTransaction allocateAndWrite(final DOMTransactionChain txChain) {
+        final var tx = txChain.newWriteOnlyTransaction();
         writeTestContainer(tx);
         return tx;
     }
@@ -182,8 +176,7 @@ public class DOMTransactionChainTest extends AbstractDatastoreTest {
         assertTrue(readedData.isPresent());
     }
 
-    private static void writeTestContainer(final DOMDataTreeWriteTransaction tx) throws InterruptedException,
-            ExecutionException {
+    private static void writeTestContainer(final DOMDataTreeWriteTransaction tx) {
         tx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
     }
 }
index c8ad351882d2fb58bb1c84015e49ed925df025ad..3e8ee02e21edaf040d5d3607a036f9964b02ced2 100644 (file)
@@ -13,7 +13,9 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.SettableFuture;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.VarHandle;
@@ -21,7 +23,6 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.concurrent.CancellationException;
-import java.util.function.Function;
 import org.checkerframework.checker.lock.qual.GuardedBy;
 import org.checkerframework.checker.lock.qual.Holding;
 import org.eclipse.jdt.annotation.NonNull;
@@ -30,10 +31,9 @@ import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
@@ -46,8 +46,8 @@ import org.slf4j.LoggerFactory;
 abstract class AbstractPingPongTransactionChain implements DOMTransactionChain {
     private static final Logger LOG = LoggerFactory.getLogger(AbstractPingPongTransactionChain.class);
 
-    private final DOMTransactionChainListener listener;
-    private final DOMTransactionChain delegate;
+    private final @NonNull SettableFuture<Empty> future = SettableFuture.create();
+    private final @NonNull DOMTransactionChain delegate;
 
     @GuardedBy("this")
     private boolean closed;
@@ -97,25 +97,27 @@ abstract class AbstractPingPongTransactionChain implements DOMTransactionChain {
         }
     }
 
-    AbstractPingPongTransactionChain(final Function<DOMTransactionChainListener, DOMTransactionChain> delegateFactory,
-            final DOMTransactionChainListener listener) {
-        this.listener = requireNonNull(listener);
-        delegate = delegateFactory.apply(new DOMTransactionChainListener() {
+    AbstractPingPongTransactionChain(final DOMTransactionChain delegate) {
+        this.delegate = requireNonNull(delegate);
+        delegate.addCallback(new FutureCallback<>() {
             @Override
-            public void onTransactionChainFailed(final DOMTransactionChain chain,
-                    final DOMDataTreeTransaction transaction, final Throwable cause) {
-                LOG.debug("Transaction chain {} reported failure in {}", chain, transaction, cause);
-                delegateFailed(chain, cause);
+            public void onSuccess(final Empty result) {
+                delegateSuccessful();
             }
 
             @Override
-            public void onTransactionChainSuccessful(final DOMTransactionChain chain) {
-                delegateSuccessful(chain);
+            public void onFailure(final Throwable cause) {
+                delegateFailed(cause);
             }
         });
     }
 
-    private void delegateSuccessful(final DOMTransactionChain chain) {
+    @Override
+    public final ListenableFuture<Empty> future() {
+        return future;
+    }
+
+    private void delegateSuccessful() {
         final Entry<PingPongTransaction, Throwable> canceled;
         synchronized (this) {
             // This looks weird, but we need not hold the lock while invoking callbacks
@@ -123,31 +125,28 @@ abstract class AbstractPingPongTransactionChain implements DOMTransactionChain {
         }
 
         if (canceled == null) {
-            listener.onTransactionChainSuccessful(this);
+            future.set(Empty.value());
             return;
         }
 
         // Backend shutdown successful, but we have a batch of transactions we have to report as dead due to the
         // user calling cancel().
-        final PingPongTransaction tx = canceled.getKey();
-        final Throwable cause = canceled.getValue();
-        LOG.debug("Transaction chain {} successful, failing cancelled transaction {}", chain, tx, cause);
+        final var tx = canceled.getKey();
+        final var cause = canceled.getValue();
+        LOG.debug("Transaction chain {} successful, failing cancelled transaction {}", delegate, tx, cause);
 
-        listener.onTransactionChainFailed(this, tx.getFrontendTransaction(), cause);
+        future.setException(cause);
         tx.onFailure(cause);
     }
 
-    private void delegateFailed(final DOMTransactionChain chain, final Throwable cause) {
-        final DOMDataTreeReadWriteTransaction frontend;
-        final PingPongTransaction tx = inflightTx;
+    private void delegateFailed(final Throwable cause) {
+        LOG.debug("Transaction chain {} reported failure", delegate, cause);
+
+        final var tx = inflightTx;
         if (tx == null) {
-            LOG.warn("Transaction chain {} failed with no pending transactions", chain);
-            frontend = null;
-        } else {
-            frontend = tx.getFrontendTransaction();
+            LOG.warn("Transaction chain {} failed with no pending transactions", delegate);
         }
-
-        listener.onTransactionChainFailed(this, frontend, cause);
+        future.setException(cause);
 
         synchronized (this) {
             failed = true;
index 1f695aae770a5f3a6a651a24cfca73c76a3874b0..9609569b09531979837055e90dbb6ccecad01e03 100644 (file)
@@ -12,7 +12,6 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 
 /**
  * Utility {@link DOMDataBroker} implementation which forwards all interface method invocation to a delegate instance.
@@ -35,12 +34,12 @@ public abstract class ForwardingDOMDataBroker extends ForwardingDOMService<DOMDa
     }
 
     @Override
-    public DOMTransactionChain createTransactionChain(final DOMTransactionChainListener listener) {
-        return delegate().createTransactionChain(listener);
+    public DOMTransactionChain createTransactionChain() {
+        return delegate().createTransactionChain();
     }
 
     @Override
-    public DOMTransactionChain createMergingTransactionChain(final DOMTransactionChainListener listener) {
-        return delegate().createMergingTransactionChain(listener);
+    public DOMTransactionChain createMergingTransactionChain() {
+        return delegate().createMergingTransactionChain();
     }
 }
index 1f6856c2d475b9fbdb4dfb861528ea5b81221d44..9eba2baf918af5f44135c4a5ea7fc95c4f78fd03 100644 (file)
@@ -8,19 +8,22 @@
 package org.opendaylight.mdsal.dom.spi;
 
 import com.google.common.collect.ForwardingObject;
-import org.eclipse.jdt.annotation.NonNull;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
+import org.opendaylight.yangtools.yang.common.Empty;
 
 /**
  * Utility {@link DOMTransactionChain} implementation which forwards all interface
  * method invocation to a delegate instance.
  */
+@NonNullByDefault
 public abstract class ForwardingDOMTransactionChain extends ForwardingObject implements DOMTransactionChain {
     @Override
-    protected abstract @NonNull DOMTransactionChain delegate();
+    protected abstract DOMTransactionChain delegate();
 
     @Override
     public void close() {
@@ -41,4 +44,9 @@ public abstract class ForwardingDOMTransactionChain extends ForwardingObject imp
     public DOMDataTreeReadWriteTransaction newReadWriteTransaction() {
         return delegate().newReadWriteTransaction();
     }
+
+    @Override
+    public ListenableFuture<Empty> future() {
+        return delegate().future();
+    }
 }
index 8fb8a9327dee3bef4a359da36c8fe39f0f30ea89..5b229c5ce33ea0ecb6adbf27389cc936c9d552ea 100644 (file)
@@ -10,18 +10,16 @@ package org.opendaylight.mdsal.dom.spi;
 import com.google.common.annotations.Beta;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 
 /**
  * Utility mixin interface for {@link DOMDataBroker}s which realize merging transaction chains via
- * {@link PingPongTransactionChain}. It provides {@link #createMergingTransactionChain(DOMTransactionChainListener)}
- * as a default method combining {@link PingPongTransactionChain} with
- * {@link #createTransactionChain(DOMTransactionChainListener)}.
+ * {@link PingPongTransactionChain}. It provides {@link #createMergingTransactionChain()}
+ * as a default method combining {@link PingPongTransactionChain} with {@link #createTransactionChain()}.
  */
 @Beta
 public interface PingPongMergingDOMDataBroker extends DOMDataBroker {
     @Override
-    default DOMTransactionChain createMergingTransactionChain(final DOMTransactionChainListener listener) {
-        return new PingPongTransactionChain(this::createTransactionChain, listener);
+    default DOMTransactionChain createMergingTransactionChain() {
+        return new PingPongTransactionChain(createTransactionChain());
     }
 }
index 99ec162ca533ac0b857749214f89eeffd50d9890..74e736f6ec1873cd03b3746124a9e4a701e9a329 100644 (file)
@@ -7,9 +7,7 @@
  */
 package org.opendaylight.mdsal.dom.spi;
 
-import java.util.function.Function;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 
 /**
  * An implementation of {@link DOMTransactionChain}, which has a very specific behavior, which some users may find
@@ -27,8 +25,7 @@ import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
  * transaction and the user may not allocate multiple read-only transactions at the same time.
  */
 public final class PingPongTransactionChain extends AbstractPingPongTransactionChain {
-    public PingPongTransactionChain(final Function<DOMTransactionChainListener, DOMTransactionChain> delegateFactory,
-            final DOMTransactionChainListener listener) {
-        super(delegateFactory, listener);
+    public PingPongTransactionChain(final DOMTransactionChain delegate) {
+        super(delegate);
     }
 }
index b6fb18b9db1d45a6be5600de282ee305e5163501..77a0eb2b154d82ce79051288084453d35ea57ca7 100644 (file)
@@ -19,7 +19,6 @@ import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 
 @ExtendWith(MockitoExtension.class)
 class ForwardingDOMDataBrokerTest {
@@ -30,8 +29,6 @@ class ForwardingDOMDataBrokerTest {
     @Mock
     private DOMTransactionChain chain;
     @Mock
-    private DOMTransactionChainListener chainListener;
-    @Mock
     private Extension extension;
     @Mock
     private DOMDataBroker domDataBroker;
@@ -49,8 +46,8 @@ class ForwardingDOMDataBrokerTest {
             }
         };
 
-        doReturn(chain).when(domDataBroker).createTransactionChain(chainListener);
-        assertSame(chain, impl.createTransactionChain(chainListener));
+        doReturn(chain).when(domDataBroker).createTransactionChain();
+        assertSame(chain, impl.createTransactionChain());
 
         doReturn(List.of(extension)).when(domDataBroker).supportedExtensions();
         assertSame(extension, impl.extension(Extension.class));
index 7030e6238dac10220fd2cca854ed5b9bbbc2d01d..cd1f27dea6cd3f90d44258e18f5da70140101100 100644 (file)
@@ -25,15 +25,15 @@ public class ForwardingDOMTransactionChainTest extends ForwardingDOMTransactionC
     @Test
     public void basicTest() throws Exception {
         doReturn(null).when(domTransactionChain).newWriteOnlyTransaction();
-        this.newWriteOnlyTransaction();
+        newWriteOnlyTransaction();
         verify(domTransactionChain).newWriteOnlyTransaction();
 
         doReturn(null).when(domTransactionChain).newReadOnlyTransaction();
-        this.newReadOnlyTransaction();
+        newReadOnlyTransaction();
         verify(domTransactionChain).newReadOnlyTransaction();
 
         doNothing().when(domTransactionChain).close();
-        this.close();
+        close();
         verify(domTransactionChain).close();
     }
 
index cd6ae75e140ba954b873309960a6ce0296c43c73..a5c161472d78ce76f582702fb1853558af835e66 100644 (file)
@@ -17,24 +17,22 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThrows;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.SettableFuture;
 import java.util.Optional;
 import java.util.concurrent.ExecutionException;
-import java.util.function.Function;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.mdsal.common.api.CommitInfo;
@@ -45,18 +43,16 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteOperations;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 
 @RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class PingPongTransactionChainTest {
     @Mock
-    public Function<DOMTransactionChainListener, DOMTransactionChain> delegateFactory;
-    @Mock
-    public DOMTransactionChainListener listener;
-    @Mock
+    public FutureCallback<Empty> listener;
+    @Mock(answer = Answers.CALLS_REAL_METHODS)
     public DOMTransactionChain chain;
     @Mock
     public DOMDataTreeReadWriteTransaction rwTx;
@@ -65,19 +61,14 @@ public class PingPongTransactionChainTest {
     @Mock
     public DOMDataTreeReadWriteTransaction rwTx2;
 
-    public DOMTransactionChainListener pingPongListener;
+    private final SettableFuture<Empty> future = SettableFuture.create();
+
     public PingPongTransactionChain pingPong;
 
     @Before
     public void before() {
-        // Slightly complicated bootstrap
-        doAnswer(invocation -> {
-            pingPongListener = invocation.getArgument(0);
-            return chain;
-        }).when(delegateFactory).apply(any());
-        pingPong = new PingPongTransactionChain(delegateFactory, listener);
-        verify(delegateFactory).apply(any());
-
+        doReturn(future).when(chain).future();
+        pingPong = new PingPongTransactionChain(chain);
         doReturn(rwTx).when(chain).newReadWriteTransaction();
     }
 
@@ -86,19 +77,21 @@ public class PingPongTransactionChainTest {
         doNothing().when(chain).close();
         pingPong.close();
         verify(chain).close();
+        pingPong.addCallback(listener);
 
-        doNothing().when(listener).onTransactionChainSuccessful(pingPong);
-        pingPongListener.onTransactionChainSuccessful(chain);
-        verify(listener).onTransactionChainSuccessful(pingPong);
+        future.set(Empty.value());
+        verify(listener).onSuccess(Empty.value());
     }
 
     @Test
     public void testIdleFailure() {
         final var cause = new Throwable();
-        doNothing().when(listener).onTransactionChainFailed(pingPong, null, cause);
+        doNothing().when(listener).onFailure(cause);
         doReturn("mock").when(chain).toString();
-        pingPongListener.onTransactionChainFailed(chain, rwTx, cause);
-        verify(listener).onTransactionChainFailed(pingPong, null, cause);
+
+        future.setException(cause);
+        pingPong.addCallback(listener);
+        verify(listener).onFailure(cause);
     }
 
     @Test
@@ -337,7 +330,7 @@ public class PingPongTransactionChainTest {
         pingPong.close();
         verify(chain).close();
         pingPong.close();
-        verifyNoMoreInteractions(chain);
+//        verifyNoMoreInteractions(chain);
     }
 
     private static <T> T assertDone(final FluentFuture<T> future) {
index 975d75f6bf4163c14e57455ef5efd3b69621d0b9..243e08c2c6db81f18a97105b1c6708c47513cdb8 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.mdsal.replicate.netty;
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.buffer.ByteBuf;
@@ -34,6 +35,7 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeDataOutput;
 import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeStreamVersion;
@@ -140,18 +142,32 @@ final class SinkSingletonService extends ChannelInitializer<SocketChannel> imple
 
     @Override
     protected void initChannel(final SocketChannel ch) {
+        final var txChain = dataBroker.createMergingTransactionChain();
+
         ch.pipeline()
             .addLast("frameDecoder", new MessageFrameDecoder())
             .addLast("idleStateHandler", new IdleStateHandler(
                 keepaliveInterval.toNanos() * maxMissedKeepalives, 0, 0, TimeUnit.NANOSECONDS))
             .addLast("keepaliveHandler", new SinkKeepaliveHandler())
-            .addLast("requestHandler", new SinkRequestHandler(TREE, dataBroker.createMergingTransactionChain(
-                new SinkTransactionChainListener(ch))))
+            .addLast("requestHandler", new SinkRequestHandler(TREE, txChain))
             .addLast("frameEncoder", MessageFrameEncoder.INSTANCE);
+
+        txChain.addCallback(new FutureCallback<>() {
+            @Override
+            public void onSuccess(final Empty result) {
+                LOG.info("Transaction chain for channel {} completed", ch);
+            }
+
+            @Override
+            public void onFailure(final Throwable cause) {
+                LOG.error("Transaction chain for channel {} failed", ch, cause);
+                ch.close();
+            }
+        });
     }
 
     private synchronized void channelResolved(final ChannelFuture completedFuture,
-        final ScheduledExecutorService group) {
+            final ScheduledExecutorService group) {
         if (futureChannel != null && futureChannel.channel() == completedFuture.channel()) {
             if (completedFuture.isSuccess()) {
                 final Channel ch = completedFuture.channel();
diff --git a/replicate/mdsal-replicate-netty/src/main/java/org/opendaylight/mdsal/replicate/netty/SinkTransactionChainListener.java b/replicate/mdsal-replicate-netty/src/main/java/org/opendaylight/mdsal/replicate/netty/SinkTransactionChainListener.java
deleted file mode 100644 (file)
index 8b6c139..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.replicate.netty;
-
-import static java.util.Objects.requireNonNull;
-
-import io.netty.channel.Channel;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-final class SinkTransactionChainListener implements DOMTransactionChainListener {
-    private static final Logger LOG = LoggerFactory.getLogger(SinkTransactionChainListener.class);
-
-    private final Channel channel;
-
-    SinkTransactionChainListener(final Channel channel) {
-        this.channel = requireNonNull(channel);
-    }
-
-    @Override
-    public void onTransactionChainFailed(final DOMTransactionChain chain, final DOMDataTreeTransaction transaction,
-            final Throwable cause) {
-        LOG.error("Transaction chain for channel {} failed", channel, cause);
-        channel.close();
-    }
-
-    @Override
-    public void onTransactionChainSuccessful(final DOMTransactionChain chain) {
-        LOG.info("Transaction chain for channel {} completed", channel);
-    }
-}
index b3f072d8f5f4778565f2cce39c3d27bef48b2d86..4ad437c730dcbd8219657b7637dca76936a05873 100644 (file)
@@ -91,7 +91,7 @@ public class IntegrationTest extends AbstractDataBrokerTest {
         doReturn(CommitInfo.emptyFluentFuture()).when(sinkTx).commit();
         doReturn(sinkTx).when(sinkChain).newWriteOnlyTransaction();
         final DOMDataBroker sinkBroker = mock(DOMDataBroker.class);
-        doReturn(sinkChain).when(sinkBroker).createMergingTransactionChain(any());
+        doReturn(sinkChain).when(sinkBroker).createMergingTransactionChain();
 
         // Kick of the sink ...
         final Registration sink = NettyReplicationSink.createSink(support, sinkBroker, css, true,
@@ -99,7 +99,7 @@ public class IntegrationTest extends AbstractDataBrokerTest {
         // ... and sync on it starting up
 
         // verify the connection was established and MSG_EMPTY_DATA was transferred
-        verify(sinkBroker, timeout(1000)).createMergingTransactionChain(any());
+        verify(sinkBroker, timeout(1000)).createMergingTransactionChain();
         verify(sinkTx, timeout(1000)).put(eq(LogicalDatastoreType.CONFIGURATION), eq(YangInstanceIdentifier.of()),
             any(ContainerNode.class));
 
@@ -137,7 +137,7 @@ public class IntegrationTest extends AbstractDataBrokerTest {
         doReturn(CommitInfo.emptyFluentFuture()).when(sinkTx).commit();
         doReturn(sinkTx).when(sinkChain).newWriteOnlyTransaction();
         final DOMDataBroker sinkBroker = mock(DOMDataBroker.class);
-        doReturn(sinkChain).when(sinkBroker).createMergingTransactionChain(any());
+        doReturn(sinkChain).when(sinkBroker).createMergingTransactionChain();
 
         // Kick of the sink ...
         final Registration sink = NettyReplicationSink.createSink(support, sinkBroker, css, true,
@@ -145,7 +145,7 @@ public class IntegrationTest extends AbstractDataBrokerTest {
         // ... and sync on it starting up
 
         // verify the connection was established and MSG_EMPTY_DATA was transferred
-        verify(sinkBroker, timeout(1000)).createMergingTransactionChain(any());
+        verify(sinkBroker, timeout(1000)).createMergingTransactionChain();
         verify(sinkChain, timeout(2000).times(1)).newWriteOnlyTransaction();
 
         // verify that the initial data invoked onDataTreeChanged() and was transferred to sink
index 515b07a6dfb78a7f208295d23070de4eaa12c354..641e185d1b3db68fd2c0d21984b1fe3f198b26b0 100644 (file)
@@ -23,7 +23,6 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 import org.opendaylight.mdsal.trace.api.TracingDOMDataBroker;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsaltrace.rev160908.Config;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -285,16 +284,13 @@ public class TracingBroker implements TracingDOMDataBroker {
     }
 
     @Override
-    public DOMTransactionChain createTransactionChain(final DOMTransactionChainListener transactionChainListener) {
-        return new TracingTransactionChain(delegate.createTransactionChain(transactionChainListener), this,
-            transactionChainsRegistry);
+    public DOMTransactionChain createTransactionChain() {
+        return new TracingTransactionChain(delegate.createTransactionChain(), this, transactionChainsRegistry);
     }
 
     @Override
-    public DOMTransactionChain createMergingTransactionChain(
-            final DOMTransactionChainListener transactionChainListener) {
-        return new TracingTransactionChain(delegate.createMergingTransactionChain(transactionChainListener), this,
-            transactionChainsRegistry);
+    public DOMTransactionChain createMergingTransactionChain() {
+        return new TracingTransactionChain(delegate.createMergingTransactionChain(), this, transactionChainsRegistry);
     }
 
     @Override
index fb6728b66f71cae04a2a3ae1c6fcbdd53a44fb33..d5d8cf948cb9f94c69f525df266a8c46a2f78d9b 100644 (file)
@@ -9,10 +9,12 @@ package org.opendaylight.mdsal.trace.impl;
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
+import org.opendaylight.yangtools.yang.common.Empty;
 
 class TracingTransactionChain extends AbstractCloseTracked<TracingTransactionChain> implements DOMTransactionChain {
 
@@ -22,36 +24,39 @@ class TracingTransactionChain extends AbstractCloseTracked<TracingTransactionCha
     private final CloseTrackedRegistry<TracingWriteTransaction> writeTransactionsRegistry;
     private final CloseTrackedRegistry<TracingReadWriteTransaction> readWriteTransactionsRegistry;
 
-    TracingTransactionChain(DOMTransactionChain delegate, TracingBroker tracingBroker,
-            CloseTrackedRegistry<TracingTransactionChain> transactionChainsRegistry) {
+    TracingTransactionChain(final DOMTransactionChain delegate, final TracingBroker tracingBroker,
+            final CloseTrackedRegistry<TracingTransactionChain> transactionChainsRegistry) {
         super(transactionChainsRegistry);
         this.delegate = requireNonNull(delegate);
         this.tracingBroker = requireNonNull(tracingBroker);
 
         final boolean isDebug = transactionChainsRegistry.isDebugContextEnabled();
         String anchor = "TransactionChain@" + Integer.toHexString(hashCode());
-        this.readOnlyTransactionsRegistry  = new CloseTrackedRegistry<>(anchor, "newReadOnlyTransaction()", isDebug);
-        this.writeTransactionsRegistry     = new CloseTrackedRegistry<>(anchor, "newWriteOnlyTransaction()", isDebug);
-        this.readWriteTransactionsRegistry = new CloseTrackedRegistry<>(anchor, "newReadWriteTransaction()", isDebug);
+        readOnlyTransactionsRegistry  = new CloseTrackedRegistry<>(anchor, "newReadOnlyTransaction()", isDebug);
+        writeTransactionsRegistry     = new CloseTrackedRegistry<>(anchor, "newWriteOnlyTransaction()", isDebug);
+        readWriteTransactionsRegistry = new CloseTrackedRegistry<>(anchor, "newReadWriteTransaction()", isDebug);
+    }
+
+    @Override
+    public ListenableFuture<Empty> future() {
+        return delegate.future();
     }
 
     @Override
-    @SuppressWarnings("resource")
     public DOMDataTreeReadTransaction newReadOnlyTransaction() {
-        final DOMDataTreeReadTransaction tx = delegate.newReadOnlyTransaction();
-        return new TracingReadOnlyTransaction(tx, readOnlyTransactionsRegistry);
+        return new TracingReadOnlyTransaction(delegate.newReadOnlyTransaction(), readOnlyTransactionsRegistry);
     }
 
     @Override
     public DOMDataTreeReadWriteTransaction newReadWriteTransaction() {
         return new TracingReadWriteTransaction(delegate.newReadWriteTransaction(), tracingBroker,
-                readWriteTransactionsRegistry);
+            readWriteTransactionsRegistry);
     }
 
     @Override
     public DOMDataTreeWriteTransaction newWriteOnlyTransaction() {
-        final DOMDataTreeWriteTransaction tx = delegate.newWriteOnlyTransaction();
-        return new TracingWriteTransaction(tx, tracingBroker, writeTransactionsRegistry);
+        return new TracingWriteTransaction(delegate.newWriteOnlyTransaction(), tracingBroker,
+            writeTransactionsRegistry);
     }
 
     @Override
@@ -75,7 +80,7 @@ class TracingTransactionChain extends AbstractCloseTracked<TracingTransactionCha
     // https://jira.opendaylight.org/browse/CONTROLLER-1792
 
     @Override
-    public final boolean equals(Object object) {
+    public final boolean equals(final Object object) {
         return object == this || delegate.equals(object);
     }
 
index 188a4f4bfe2ba098a927d53af3170150ed74d273..3b919a4ea967339c24d6f635ad7993618749bae2 100644 (file)
@@ -46,7 +46,7 @@ public class TracingBrokerTest {
         }
         DOMDataTreeReadWriteTransaction anotherTx = tracingBroker.newReadWriteTransaction();
 
-        DOMTransactionChain txChain = tracingBroker.createTransactionChain(null);
+        DOMTransactionChain txChain = tracingBroker.createTransactionChain();
         DOMDataTreeReadWriteTransaction txFromChain = txChain.newReadWriteTransaction();
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();