X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=dom%2Fmdsal-dom-inmemory-datastore%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fdom%2Fstore%2Finmemory%2FInMemoryDOMStoreTreeChangePublisher.java;h=d98697ecde6c679e29e7973643f3420a6429f00a;hb=11408d627adca7eb71ac956c3ad01f75b6b91596;hp=919f888f024121f577285eb2a7e31cff04615d56;hpb=099ae98f4694007d7edf76c695a901766521f45f;p=mdsal.git diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMStoreTreeChangePublisher.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMStoreTreeChangePublisher.java index 919f888f02..d98697ecde 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMStoreTreeChangePublisher.java +++ b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMStoreTreeChangePublisher.java @@ -7,58 +7,58 @@ */ package org.opendaylight.mdsal.dom.store.inmemory; -import com.google.common.base.Optional; -import java.util.Collection; -import java.util.Collections; +import static com.google.common.base.Preconditions.checkState; + +import java.util.List; +import java.util.Optional; import java.util.concurrent.ExecutorService; -import javax.annotation.Nonnull; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener; import org.opendaylight.mdsal.dom.spi.AbstractDOMDataTreeChangeListenerRegistration; import org.opendaylight.mdsal.dom.spi.store.AbstractDOMStoreTreeChangePublisher; import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager; -import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager.Invoker; +import org.opendaylight.yangtools.util.concurrent.EqualityQueuedNotificationManager; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; +import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate; +import org.opendaylight.yangtools.yang.data.tree.api.DataTreeSnapshot; +import org.opendaylight.yangtools.yang.data.tree.spi.DataTreeCandidates; import org.slf4j.Logger; import org.slf4j.LoggerFactory; final class InMemoryDOMStoreTreeChangePublisher extends AbstractDOMStoreTreeChangePublisher { - private static final Invoker, DataTreeCandidate> MANAGER_INVOKER = - new Invoker, DataTreeCandidate>() { - @Override - public void invokeListener(final AbstractDOMDataTreeChangeListenerRegistration listener, - final DataTreeCandidate notification) { - // FIXME: this is inefficient, as we could grab the entire queue for the listener and post it - final DOMDataTreeChangeListener inst = listener.getInstance(); - if (inst != null) { - inst.onDataTreeChanged(Collections.singletonList(notification)); - } - } - }; private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMStoreTreeChangePublisher.class); - private final QueuedNotificationManager, DataTreeCandidate> + // Registrations use identity for equality, hence we can skip wrapping them + private final EqualityQueuedNotificationManager, DataTreeCandidate> notificationManager; - InMemoryDOMStoreTreeChangePublisher(final ExecutorService listenerExecutor, final int maxQueueSize) { - notificationManager = new QueuedNotificationManager<>(listenerExecutor, MANAGER_INVOKER, maxQueueSize, - "DataTreeChangeListenerQueueMgr"); + InMemoryDOMStoreTreeChangePublisher(final String dsName, final ExecutorService listenerExecutor, + final int maxQueueSize) { + notificationManager = new EqualityQueuedNotificationManager<>("DataTreeChangeListenerQueueMgr + dsName", + listenerExecutor, maxQueueSize, + (listener, notifications) -> { + if (!listener.isClosed()) { + listener.getInstance().onDataTreeChanged(notifications); + } + }); } - @Override - protected void notifyListeners(final Collection> registrations, - final YangInstanceIdentifier path, final DataTreeCandidateNode node) { - final DataTreeCandidate candidate = DataTreeCandidates.newDataTreeCandidate(path, node); + private InMemoryDOMStoreTreeChangePublisher(final EqualityQueuedNotificationManager< + AbstractDOMDataTreeChangeListenerRegistration, DataTreeCandidate> notificationManager) { + this.notificationManager = notificationManager; + } - for (AbstractDOMDataTreeChangeListenerRegistration reg : registrations) { - LOG.debug("Enqueueing candidate {} to registration {}", candidate, registrations); - notificationManager.submitNotification(reg, candidate); - } + EqualityQueuedNotificationManager getNotificationManager() { + return notificationManager; + } + + @Override + protected void notifyListener(final AbstractDOMDataTreeChangeListenerRegistration registration, + final List changes) { + LOG.debug("Enqueueing candidates {} for registration {}", changes, registration); + notificationManager.submitNotifications(registration, changes); } @Override @@ -72,18 +72,40 @@ final class InMemoryDOMStoreTreeChangePublisher extends AbstractDOMStoreTreeChan ListenerRegistration registerTreeChangeListener( final YangInstanceIdentifier treeId, final L listener, final DataTreeSnapshot snapshot) { final AbstractDOMDataTreeChangeListenerRegistration reg = registerTreeChangeListener(treeId, listener); + final Optional preExistingData = snapshot.readNode(YangInstanceIdentifier.empty()); + if (!preExistingData.isPresent()) { + listener.onInitialData(); + return reg; + } + + final NormalizedNode data = preExistingData.get(); + if (treeId.isEmpty()) { + checkState(data instanceof DataContainerNode, "Unexpected root node %s", data); + if (((DataContainerNode) data).isEmpty()) { + // If we are listening on root of data tree we still get empty normalized node, root is always present, + // we should filter this out separately and notify it by 'onInitialData()' once. + // Otherwise, it is just a valid data node with empty value which also should be notified by + // "onDataTreeChanged(List)". + listener.onInitialData(); + return reg; + } + } - final Optional> node = snapshot.readNode(treeId); - if (node.isPresent()) { - final DataTreeCandidate candidate = DataTreeCandidates.fromNormalizedNode(treeId, node.get()); - notificationManager.submitNotification(reg, candidate); + final DataTreeCandidate candidate = DataTreeCandidates.fromNormalizedNode(YangInstanceIdentifier.empty(), data); + final InMemoryDOMStoreTreeChangePublisher publisher = new InMemoryDOMStoreTreeChangePublisher( + notificationManager); + publisher.registerTreeChangeListener(treeId, listener); + if (!publisher.publishChange(candidate)) { + // There is no data in the conceptual data tree then + // notify with 'onInitialData()'. + listener.onInitialData(); } return reg; } - synchronized void publishChange(@Nonnull final DataTreeCandidate candidate) { + synchronized boolean publishChange(final @NonNull DataTreeCandidate candidate) { // Runs synchronized with registrationRemoved() - processCandidateTree(candidate); + return processCandidateTree(candidate); } }