X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=dom%2Fmdsal-dom-spi%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fdom%2Fspi%2FAbstractPingPongTransactionChain.java;h=ce4da1b258e8b509425179d31899ed13a4855628;hb=94fb90ab450470ee1b3225d737cd394f034ea932;hp=b68deb6e092f1ebda99012fd614407cc5460bf60;hpb=2d26c8383f8c6cbd1e54a8ed215cb90269100415;p=mdsal.git diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/AbstractPingPongTransactionChain.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/AbstractPingPongTransactionChain.java index b68deb6e09..ce4da1b258 100644 --- a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/AbstractPingPongTransactionChain.java +++ b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/AbstractPingPongTransactionChain.java @@ -13,14 +13,16 @@ 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; 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; @@ -29,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; @@ -45,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 future = SettableFuture.create(); + private final @NonNull DOMTransactionChain delegate; @GuardedBy("this") private boolean closed; @@ -60,6 +61,7 @@ abstract class AbstractPingPongTransactionChain implements DOMTransactionChain { // This VarHandle is used to manipulate the "ready" transaction. We perform only atomic get-and-set on it. private static final VarHandle READY_TX; @SuppressWarnings("unused") + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749") private volatile PingPongTransaction readyTx; /* @@ -68,6 +70,8 @@ abstract class AbstractPingPongTransactionChain implements DOMTransactionChain { * detect when a user is attempting to allocated multiple transactions concurrently. */ private static final VarHandle LOCKED_TX; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", + justification = "https://github.com/spotbugs/spotbugs/issues/2749") private volatile PingPongTransaction lockedTx; /* @@ -75,6 +79,8 @@ abstract class AbstractPingPongTransactionChain implements DOMTransactionChain { * time. We perform only compare-and-swap on these. */ private static final VarHandle INFLIGHT_TX; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", + justification = "https://github.com/spotbugs/spotbugs/issues/2749") private volatile PingPongTransaction inflightTx; static { @@ -91,25 +97,27 @@ abstract class AbstractPingPongTransactionChain implements DOMTransactionChain { } } - AbstractPingPongTransactionChain(final Function 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 future() { + return future; + } + + private void delegateSuccessful() { final Entry canceled; synchronized (this) { // This looks weird, but we need not hold the lock while invoking callbacks @@ -117,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; @@ -484,7 +489,7 @@ abstract class AbstractPingPongTransactionChain implements DOMTransactionChain { public FluentFuture commit() { readyTransaction(tx); isOpen = false; - return tx.getCommitFuture().transform(ignored -> CommitInfo.empty(), MoreExecutors.directExecutor()); + return tx.completionFuture(); } @Override