X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-inmemory-datastore%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fdom%2Fstore%2Fimpl%2FSnapshotBackedWriteTransaction.java;h=faddbae850ce50753dc7ca1e7298bdc6e77c0f21;hp=16675d3a8563f0a4142d86e248243c790085e940;hb=3997099eb61b0f2adc47f7a85952c324e9de223f;hpb=b2e6c299fad844633c8b40a2e180780f5774a4ae diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java index 16675d3a85..faddbae850 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java @@ -8,21 +8,20 @@ package org.opendaylight.controller.md.sal.dom.store.impl; import static com.google.common.base.Preconditions.checkState; - - +import com.google.common.base.MoreObjects.ToStringHelper; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort; import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Objects.ToStringHelper; -import com.google.common.base.Preconditions; -import com.google.common.base.Throwables; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; - /** * Implementation of Write transaction which is backed by * {@link DataTreeSnapshot} and executed according to @@ -30,11 +29,16 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification * */ class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements DOMStoreWriteTransaction { - private static final Logger LOG = LoggerFactory.getLogger(SnapshotBackedWriteTransaction.class); - private DataTreeModification mutableTree; - private boolean ready = false; - private TransactionReadyPrototype readyImpl; + private static final AtomicReferenceFieldUpdater READY_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(SnapshotBackedWriteTransaction.class, TransactionReadyPrototype.class, "readyImpl"); + private static final AtomicReferenceFieldUpdater TREE_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(SnapshotBackedWriteTransaction.class, DataTreeModification.class, "mutableTree"); + + // non-null when not ready + private volatile TransactionReadyPrototype readyImpl; + // non-null when not committed/closed + private volatile DataTreeModification mutableTree; /** * Creates new write-only transaction. @@ -46,30 +50,26 @@ class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction impleme * @param readyImpl * Implementation of ready method. */ - public SnapshotBackedWriteTransaction(final Object identifier, final DataTreeSnapshot snapshot, - final TransactionReadyPrototype readyImpl) { - super(identifier); - mutableTree = snapshot.newModification(); + public SnapshotBackedWriteTransaction(final Object identifier, final boolean debug, + final DataTreeSnapshot snapshot, final TransactionReadyPrototype readyImpl) { + super(identifier, debug); this.readyImpl = Preconditions.checkNotNull(readyImpl, "readyImpl must not be null."); + mutableTree = snapshot.newModification(); LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot); } @Override - public void close() { - LOG.debug("Store transaction: {} : Closed", getIdentifier()); - this.mutableTree = null; - this.readyImpl = null; - } - - @Override - public void write(final InstanceIdentifier path, final NormalizedNode data) { + public void write(final YangInstanceIdentifier path, final NormalizedNode data) { checkNotReady(); + + final DataTreeModification tree = mutableTree; + LOG.debug("Tx: {} Write: {}:{}", getIdentifier(), path, data); + try { - LOG.debug("Tx: {} Write: {}:{}", getIdentifier(), path, data); - mutableTree.write(path, data); + tree.write(path, data); // FIXME: Add checked exception } catch (Exception e) { - LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, mutableTree, e); + LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, tree, e); // Rethrow original ones if they are subclasses of RuntimeException // or Error Throwables.propagateIfPossible(e); @@ -79,14 +79,17 @@ class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction impleme } @Override - public void merge(final InstanceIdentifier path, final NormalizedNode data) { + public void merge(final YangInstanceIdentifier path, final NormalizedNode data) { checkNotReady(); + + final DataTreeModification tree = mutableTree; + LOG.debug("Tx: {} Merge: {}:{}", getIdentifier(), path, data); + try { - LOG.debug("Tx: {} Merge: {}:{}", getIdentifier(), path, data); - mutableTree.merge(path, data); + tree.merge(path, data); // FIXME: Add checked exception } catch (Exception e) { - LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, mutableTree, e); + LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, tree, e); // Rethrow original ones if they are subclasses of RuntimeException // or Error Throwables.propagateIfPossible(e); @@ -96,14 +99,17 @@ class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction impleme } @Override - public void delete(final InstanceIdentifier path) { + public void delete(final YangInstanceIdentifier path) { checkNotReady(); + + final DataTreeModification tree = mutableTree; + LOG.debug("Tx: {} Delete: {}", getIdentifier(), path); + try { - LOG.debug("Tx: {} Delete: {}", getIdentifier(), path); - mutableTree.delete(path); + tree.delete(path); // FIXME: Add checked exception } catch (Exception e) { - LOG.error("Tx: {}, failed to delete {} in {}", getIdentifier(), path, mutableTree, e); + LOG.error("Tx: {}, failed to delete {} in {}", getIdentifier(), path, tree, e); // Rethrow original ones if they are subclasses of RuntimeException // or Error Throwables.propagateIfPossible(e); @@ -112,30 +118,49 @@ class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction impleme } } - protected final boolean isReady() { - return ready; + /** + * Exposed for {@link SnapshotBackedReadWriteTransaction}'s sake only. The contract does + * not allow data access after the transaction has been closed or readied. + * + * @param path Path to read + * @return null if the the transaction has been closed; + */ + protected final Optional> readSnapshotNode(final YangInstanceIdentifier path) { + return readyImpl == null ? null : mutableTree.readNode(path); } - protected final void checkNotReady() { - checkState(!ready, "Transaction %s is ready. No further modifications allowed.", getIdentifier()); + private final void checkNotReady() { + checkState(readyImpl != null, "Transaction %s is no longer open. No further modifications allowed.", getIdentifier()); } @Override - public synchronized DOMStoreThreePhaseCommitCohort ready() { - checkState(!ready, "Transaction %s is already ready.", getIdentifier()); - ready = true; + public DOMStoreThreePhaseCommitCohort ready() { + final TransactionReadyPrototype wasReady = READY_UPDATER.getAndSet(this, null); + checkState(wasReady != null, "Transaction %s is no longer open", getIdentifier()); + LOG.debug("Store transaction: {} : Ready", getIdentifier()); - mutableTree.ready(); - return readyImpl.ready(this); + + final DataTreeModification tree = mutableTree; + TREE_UPDATER.lazySet(this, null); + tree.ready(); + return wasReady.transactionReady(this, tree); } - protected DataTreeModification getMutatedView() { - return mutableTree; + @Override + public void close() { + final TransactionReadyPrototype wasReady = READY_UPDATER.getAndSet(this, null); + if (wasReady != null) { + LOG.debug("Store transaction: {} : Closed", getIdentifier()); + TREE_UPDATER.lazySet(this, null); + wasReady.transactionAborted(this); + } else { + LOG.debug("Store transaction: {} : Closed after submit", getIdentifier()); + } } @Override protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { - return toStringHelper.add("ready", isReady()); + return toStringHelper.add("ready", readyImpl == null); } /** @@ -147,7 +172,14 @@ class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction impleme * providing underlying logic for applying implementation. * */ - public static interface TransactionReadyPrototype { + abstract static class TransactionReadyPrototype { + /** + * Called when a transaction is closed without being readied. This is not invoked for + * transactions which are ready. + * + * @param tx Transaction which got aborted. + */ + protected abstract void transactionAborted(final SnapshotBackedWriteTransaction tx); /** * Returns a commit coordinator associated with supplied transactions. @@ -156,8 +188,10 @@ class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction impleme * * @param tx * Transaction on which ready was invoked. + * @param tree + * Modified data tree which has been constructed. * @return DOMStoreThreePhaseCommitCohort associated with transaction */ - DOMStoreThreePhaseCommitCohort ready(SnapshotBackedWriteTransaction tx); + protected abstract DOMStoreThreePhaseCommitCohort transactionReady(SnapshotBackedWriteTransaction tx, DataTreeModification tree); } } \ No newline at end of file