From: Robert Varga Date: Wed, 8 May 2019 10:28:24 +0000 (+0200) Subject: Allow SnapshotBackedReadTransaction customization X-Git-Tag: release/sodium~91 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=a885056d2fddd17e3879aca9b75fe597e3be7953 Allow SnapshotBackedReadTransaction customization In some specific cases we need to customize abort-like handling, which is already implemented for write-like transactions, but is not present for read-only transaction. This patch adds the capability to attach a close() handler and makes sure AbstractSnapshotBackedTransactionChain takes advantage of it. JIRA: CONTROLLER-1879 Change-Id: Ic7027956556b5dd25120ee81613a6151e5dbc501 Signed-off-by: Robert Varga --- diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/AbstractSnapshotBackedTransactionChain.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/AbstractSnapshotBackedTransactionChain.java index f80c80001f..e0dc0dc8de 100644 --- a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/AbstractSnapshotBackedTransactionChain.java +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/AbstractSnapshotBackedTransactionChain.java @@ -12,6 +12,7 @@ import com.google.common.base.Preconditions; import java.util.AbstractMap.SimpleEntry; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +import org.opendaylight.controller.sal.core.spi.data.SnapshotBackedReadTransaction.TransactionClosePrototype; import org.opendaylight.controller.sal.core.spi.data.SnapshotBackedWriteTransaction.TransactionReadyPrototype; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; @@ -26,7 +27,7 @@ import org.slf4j.LoggerFactory; */ @Beta public abstract class AbstractSnapshotBackedTransactionChain extends TransactionReadyPrototype - implements DOMStoreTransactionChain { + implements DOMStoreTransactionChain, TransactionClosePrototype { private abstract static class State { /** * Allocate a new snapshot. @@ -129,7 +130,13 @@ public abstract class AbstractSnapshotBackedTransactionChain extends Transact protected DOMStoreReadTransaction newReadOnlyTransaction(T transactionId) { final Entry entry = getSnapshot(transactionId); - return SnapshotBackedTransactions.newReadTransaction(transactionId, getDebugTransactions(), entry.getValue()); + return SnapshotBackedTransactions.newReadTransaction(transactionId, getDebugTransactions(), entry.getValue(), + this); + } + + @Override + public void transactionClosed(final SnapshotBackedReadTransaction tx) { + // Defaults to no-op } @Override diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/SnapshotBackedReadTransaction.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/SnapshotBackedReadTransaction.java index 688d1e37e7..eaf3aa7913 100644 --- a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/SnapshotBackedReadTransaction.java +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/SnapshotBackedReadTransaction.java @@ -14,6 +14,7 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.Futures; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -34,6 +35,14 @@ import org.slf4j.LoggerFactory; public final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements DOMStoreReadTransaction { private static final Logger LOG = LoggerFactory.getLogger(SnapshotBackedReadTransaction.class); + + @SuppressWarnings("rawtypes") + private static final AtomicReferenceFieldUpdater SNAPSHOT_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(SnapshotBackedReadTransaction.class, DataTreeSnapshot.class, + "stableSnapshot"); + + // Guarded by stableSnapshot CAS, hence it does not need to be volatile + private TransactionClosePrototype closeImpl; private volatile DataTreeSnapshot stableSnapshot; /** @@ -43,16 +52,27 @@ public final class SnapshotBackedReadTransaction extends AbstractDOMStoreTran * @param debug Enable transaction debugging * @param snapshot Snapshot which will be modified. */ - SnapshotBackedReadTransaction(final T identifier, final boolean debug, final DataTreeSnapshot snapshot) { + SnapshotBackedReadTransaction(final T identifier, final boolean debug, final DataTreeSnapshot snapshot, + final TransactionClosePrototype closeImpl) { super(identifier, debug); this.stableSnapshot = Preconditions.checkNotNull(snapshot); + this.closeImpl = closeImpl; LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot); } @Override public void close() { + final DataTreeSnapshot prev = SNAPSHOT_UPDATER.getAndSet(this, null); + if (prev == null) { + LOG.debug("Store transaction: {} : previously closed", getIdentifier()); + return; + } + LOG.debug("Store transaction: {} : Closed", getIdentifier()); - stableSnapshot = null; + if (closeImpl != null) { + closeImpl.transactionClosed(this); + closeImpl = null; + } } @Override @@ -85,4 +105,23 @@ public final class SnapshotBackedReadTransaction extends AbstractDOMStoreTran return Futures.immediateFailedCheckedFuture(e); } } + + /** + * Prototype implementation of {@link SnapshotBackedReadTransaction#close()}. + * + *

+ * This class is intended to be implemented by Transaction factories responsible for allocation + * of {@link org.opendaylight.mdsal.dom.spi.store.SnapshotBackedReadTransaction} and + * providing underlying logic for applying implementation. + * + * @param identifier type + */ + public interface TransactionClosePrototype { + /** + * Called when a transaction is closed. This is not invoked at most once for every transaction. + * + * @param tx Transaction which got closed. + */ + void transactionClosed(SnapshotBackedReadTransaction tx); + } } diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/SnapshotBackedTransactions.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/SnapshotBackedTransactions.java index a82a65ea7e..7a775e8341 100644 --- a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/SnapshotBackedTransactions.java +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/SnapshotBackedTransactions.java @@ -7,7 +7,10 @@ */ package org.opendaylight.controller.sal.core.spi.data; +import static java.util.Objects.requireNonNull; + import com.google.common.annotations.Beta; +import org.opendaylight.controller.sal.core.spi.data.SnapshotBackedReadTransaction.TransactionClosePrototype; import org.opendaylight.controller.sal.core.spi.data.SnapshotBackedWriteTransaction.TransactionReadyPrototype; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; @@ -26,10 +29,25 @@ public final class SnapshotBackedTransactions { * @param identifier Transaction Identifier * @param debug Enable transaction debugging * @param snapshot Snapshot which will be modified. + * @return A new read-only transaction */ public static SnapshotBackedReadTransaction newReadTransaction(final T identifier, final boolean debug, final DataTreeSnapshot snapshot) { - return new SnapshotBackedReadTransaction<>(identifier, debug, snapshot); + return new SnapshotBackedReadTransaction<>(identifier, debug, snapshot, null); + } + + /** + * Creates a new read-only transaction. + * + * @param identifier Transaction Identifier + * @param debug Enable transaction debugging + * @param snapshot Snapshot which will be modified. + * @param closeImpl Implementation of close method + * @return A new read-only transaction + */ + public static SnapshotBackedReadTransaction newReadTransaction(final T identifier, + final boolean debug, final DataTreeSnapshot snapshot, final TransactionClosePrototype closeImpl) { + return new SnapshotBackedReadTransaction<>(identifier, debug, snapshot, requireNonNull(closeImpl)); } /** @@ -39,6 +57,7 @@ public final class SnapshotBackedTransactions { * @param debug Enable transaction debugging * @param snapshot Snapshot which will be modified. * @param readyImpl Implementation of ready method. + * @return A new read-write transaction */ public static SnapshotBackedReadWriteTransaction newReadWriteTransaction(final T identifier, final boolean debug, final DataTreeSnapshot snapshot, final TransactionReadyPrototype readyImpl) { @@ -52,6 +71,7 @@ public final class SnapshotBackedTransactions { * @param debug Enable transaction debugging * @param snapshot Snapshot which will be modified. * @param readyImpl Implementation of ready method. + * @return A new write transaction */ public static SnapshotBackedWriteTransaction newWriteTransaction(final T identifier, final boolean debug, final DataTreeSnapshot snapshot, final TransactionReadyPrototype readyImpl) {