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%2FInMemoryDOMDataStore.java;h=7476d4c1c43bc97fef6ce6a6441eedc8d5b66cb4;hp=7e4056a1900b99a777096910b32e6b37d0012574;hb=401577076374485afea34caeb33bce474563f752;hpb=07c40ad2904d0e9aa03828ba0ba9336e1560d0ec diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java index 7e4056a190..7476d4c1c4 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java @@ -7,21 +7,17 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl; -import static com.google.common.base.Preconditions.checkState; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; +import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener; -import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree; -import org.opendaylight.controller.sal.core.spi.data.AbstractDOMStoreTransaction; +import org.opendaylight.controller.sal.core.compat.DataChangeListenerRegistration; +import org.opendaylight.controller.sal.core.compat.ListenerTree; import org.opendaylight.controller.sal.core.spi.data.DOMStore; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction; @@ -40,9 +36,9 @@ import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager; import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager.Invoker; 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.ConflictingModificationAppliedException; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; @@ -55,34 +51,32 @@ import org.slf4j.LoggerFactory; /** * In-memory DOM Data Store * + *

* Implementation of {@link DOMStore} which uses {@link DataTree} and other * classes such as {@link SnapshotBackedWriteTransaction}. - * {@link org.opendaylight.controller.sal.core.spi.data.SnapshotBackedReadTransaction} and {@link ResolveDataChangeEventsTask} + * {@link org.opendaylight.controller.sal.core.spi.data.SnapshotBackedReadTransaction} and + * {@link ResolveDataChangeEventsTask} * to implement {@link DOMStore} contract. * */ -public class InMemoryDOMDataStore extends TransactionReadyPrototype implements DOMStore, Identifiable, SchemaContextListener, AutoCloseable, DOMStoreTreeChangePublisher { +public class InMemoryDOMDataStore extends TransactionReadyPrototype + implements DOMStore, Identifiable, SchemaContextListener, AutoCloseable, DOMStoreTreeChangePublisher { private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class); - private static final ListenableFuture SUCCESSFUL_FUTURE = Futures.immediateFuture(null); - private static final ListenableFuture CAN_COMMIT_FUTURE = Futures.immediateFuture(Boolean.TRUE); - - private static final Invoker, DOMImmutableDataChangeEvent> DCL_NOTIFICATION_MGR_INVOKER = - new Invoker, DOMImmutableDataChangeEvent>() { - @Override - public void invokeListener(final DataChangeListenerRegistration listener, - final DOMImmutableDataChangeEvent notification ) { - final AsyncDataChangeListener> inst = listener.getInstance(); - if (inst != null) { - inst.onDataChanged(notification); - } - } + + private static final Invoker, DOMImmutableDataChangeEvent> + DCL_NOTIFICATION_MGR_INVOKER = + (listener, notification) -> { + final AsyncDataChangeListener> inst = + listener.getInstance(); + inst.onDataChanged(notification); }; - private final DataTree dataTree = InMemoryDataTreeFactory.getInstance().create(); + private final DataTree dataTree; private final ListenerTree listenerTree = ListenerTree.create(); private final AtomicLong txCounter = new AtomicLong(0); - private final QueuedNotificationManager, DOMImmutableDataChangeEvent> dataChangeListenerNotificationManager; + private final QueuedNotificationManager, DOMImmutableDataChangeEvent> + dataChangeListenerNotificationManager; private final InMemoryDOMStoreTreeChangePublisher changePublisher; private final ExecutorService dataChangeListenerExecutor; private final boolean debugTransactions; @@ -91,10 +85,12 @@ public class InMemoryDOMDataStore extends TransactionReadyPrototype impl private volatile AutoCloseable closeable; public InMemoryDOMDataStore(final String name, final ExecutorService dataChangeListenerExecutor) { - this(name, dataChangeListenerExecutor, InMemoryDOMDataStoreConfigProperties.DEFAULT_MAX_DATA_CHANGE_LISTENER_QUEUE_SIZE, false); + this(name, LogicalDatastoreType.OPERATIONAL, dataChangeListenerExecutor, + InMemoryDOMDataStoreConfigProperties.DEFAULT_MAX_DATA_CHANGE_LISTENER_QUEUE_SIZE, false); } - public InMemoryDOMDataStore(final String name, final ExecutorService dataChangeListenerExecutor, + public InMemoryDOMDataStore(final String name, final LogicalDatastoreType type, + final ExecutorService dataChangeListenerExecutor, final int maxDataChangeListenerQueueSize, final boolean debugTransactions) { this.name = Preconditions.checkNotNull(name); this.dataChangeListenerExecutor = Preconditions.checkNotNull(dataChangeListenerExecutor); @@ -104,7 +100,19 @@ public class InMemoryDOMDataStore extends TransactionReadyPrototype impl new QueuedNotificationManager<>(this.dataChangeListenerExecutor, DCL_NOTIFICATION_MGR_INVOKER, maxDataChangeListenerQueueSize, "DataChangeListenerQueueMgr"); - changePublisher = new InMemoryDOMStoreTreeChangePublisher(this.dataChangeListenerExecutor, maxDataChangeListenerQueueSize); + changePublisher = new InMemoryDOMStoreTreeChangePublisher(this.dataChangeListenerExecutor, + maxDataChangeListenerQueueSize); + + switch (type) { + case CONFIGURATION: + dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION); + break; + case OPERATIONAL: + dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL); + break; + default: + throw new IllegalArgumentException("Data store " + type + " not supported"); + } } public void setCloseable(final AutoCloseable closeable) { @@ -122,17 +130,20 @@ public class InMemoryDOMDataStore extends TransactionReadyPrototype impl @Override public DOMStoreReadTransaction newReadOnlyTransaction() { - return SnapshotBackedTransactions.newReadTransaction(nextIdentifier(), debugTransactions, dataTree.takeSnapshot()); + return SnapshotBackedTransactions.newReadTransaction(nextIdentifier(), debugTransactions, + dataTree.takeSnapshot()); } @Override public DOMStoreReadWriteTransaction newReadWriteTransaction() { - return SnapshotBackedTransactions.newReadWriteTransaction(nextIdentifier(), debugTransactions, dataTree.takeSnapshot(), this); + return SnapshotBackedTransactions.newReadWriteTransaction(nextIdentifier(), debugTransactions, + dataTree.takeSnapshot(), this); } @Override public DOMStoreWriteTransaction newWriteOnlyTransaction() { - return SnapshotBackedTransactions.newWriteTransaction(nextIdentifier(), debugTransactions, dataTree.takeSnapshot(), this); + return SnapshotBackedTransactions.newWriteTransaction(nextIdentifier(), debugTransactions, + dataTree.takeSnapshot(), this); } @Override @@ -146,13 +157,14 @@ public class InMemoryDOMDataStore extends TransactionReadyPrototype impl } @Override + @SuppressWarnings("checkstyle:IllegalCatch") public void close() { ExecutorServiceUtil.tryGracefulShutdown(dataChangeListenerExecutor, 30, TimeUnit.SECONDS); - if(closeable != null) { + if (closeable != null) { try { closeable.close(); - } catch(Exception e) { + } catch (Exception e) { LOG.debug("Error closing instance", e); } } @@ -167,8 +179,8 @@ public class InMemoryDOMDataStore extends TransactionReadyPrototype impl } @Override - public >> ListenerRegistration registerChangeListener( - final YangInstanceIdentifier path, final L listener, final DataChangeScope scope) { + public >> ListenerRegistration + registerChangeListener(final YangInstanceIdentifier path, final L listener, final DataChangeScope scope) { /* * Make sure commit is not occurring right now. Listener has to be @@ -207,7 +219,8 @@ public class InMemoryDOMDataStore extends TransactionReadyPrototype impl } @Override - public synchronized ListenerRegistration registerTreeChangeListener(final YangInstanceIdentifier treeId, final L listener) { + public synchronized ListenerRegistration registerTreeChangeListener( + final YangInstanceIdentifier treeId, final L listener) { /* * Make sure commit is not occurring right now. Listener has to be * registered and its state capture enqueued at a consistent point. @@ -221,94 +234,28 @@ public class InMemoryDOMDataStore extends TransactionReadyPrototype impl } @Override - protected DOMStoreThreePhaseCommitCohort transactionReady(final SnapshotBackedWriteTransaction tx, final DataTreeModification tree) { - LOG.debug("Tx: {} is submitted. Modifications: {}", tx.getIdentifier(), tree); - return new ThreePhaseCommitImpl(tx, tree); + protected DOMStoreThreePhaseCommitCohort transactionReady(final SnapshotBackedWriteTransaction tx, + final DataTreeModification modification, + final Exception readyError) { + LOG.debug("Tx: {} is submitted. Modifications: {}", tx.getIdentifier(), modification); + return new InMemoryDOMStoreThreePhaseCommitCohort(this, tx, modification, readyError); } String nextIdentifier() { return name + "-" + txCounter.getAndIncrement(); } - private static void warnDebugContext(final AbstractDOMStoreTransaction transaction) { - final Throwable ctx = transaction.getDebugContext(); - if (ctx != null) { - LOG.warn("Transaction {} has been allocated in the following context", transaction.getIdentifier(), ctx); - } + void validate(final DataTreeModification modification) throws DataValidationFailedException { + dataTree.validate(modification); } - private final class ThreePhaseCommitImpl implements DOMStoreThreePhaseCommitCohort { - private final SnapshotBackedWriteTransaction transaction; - private final DataTreeModification modification; - - private ResolveDataChangeEventsTask listenerResolver; - private DataTreeCandidate candidate; - - public ThreePhaseCommitImpl(final SnapshotBackedWriteTransaction writeTransaction, final DataTreeModification modification) { - this.transaction = writeTransaction; - this.modification = modification; - } - - @Override - public ListenableFuture canCommit() { - try { - dataTree.validate(modification); - LOG.debug("Store Transaction: {} can be committed", transaction.getIdentifier()); - return CAN_COMMIT_FUTURE; - } catch (ConflictingModificationAppliedException e) { - LOG.warn("Store Tx: {} Conflicting modification for {}.", transaction.getIdentifier(), - e.getPath()); - warnDebugContext(transaction); - return Futures.immediateFailedFuture(new OptimisticLockFailedException("Optimistic lock failed.", e)); - } catch (DataValidationFailedException e) { - LOG.warn("Store Tx: {} Data Precondition failed for {}.", transaction.getIdentifier(), - e.getPath(), e); - warnDebugContext(transaction); - - // For debugging purposes, allow dumping of the modification. Coupled with the above - // precondition log, it should allow us to understand what went on. - LOG.trace("Store Tx: {} modifications: {} tree: {}", modification, dataTree); - - return Futures.immediateFailedFuture(new TransactionCommitFailedException("Data did not pass validation.", e)); - } catch (Exception e) { - LOG.warn("Unexpected failure in validation phase", e); - return Futures.immediateFailedFuture(e); - } - } - - @Override - public ListenableFuture preCommit() { - try { - candidate = dataTree.prepare(modification); - listenerResolver = ResolveDataChangeEventsTask.create(candidate, listenerTree); - return SUCCESSFUL_FUTURE; - } catch (Exception e) { - LOG.warn("Unexpected failure in pre-commit phase", e); - return Futures.immediateFailedFuture(e); - } - } - - @Override - public ListenableFuture abort() { - candidate = null; - return SUCCESSFUL_FUTURE; - } - - @Override - public ListenableFuture commit() { - checkState(candidate != null, "Proposed subtree must be computed"); - - /* - * The commit has to occur atomically with regard to listener - * registrations. - */ - synchronized (InMemoryDOMDataStore.this) { - dataTree.commit(candidate); - changePublisher.publishChange(candidate); - listenerResolver.resolve(dataChangeListenerNotificationManager); - } + DataTreeCandidate prepare(final DataTreeModification modification) { + return dataTree.prepare(modification); + } - return SUCCESSFUL_FUTURE; - } + synchronized void commit(final DataTreeCandidate candidate) { + dataTree.commit(candidate); + changePublisher.publishChange(candidate); + ResolveDataChangeEventsTask.create(candidate, listenerTree).resolve(dataChangeListenerNotificationManager); } }