BUG-2673: deprecate ListenerNode,Tree and Walker
[controller.git] / opendaylight / md-sal / sal-inmemory-datastore / src / main / java / org / opendaylight / controller / md / sal / dom / store / impl / ResolveDataChangeEventsTask.java
index a4e8c86aa83f1b10f084f86f81a10feb08178d58..4e650842789b23504fec0801b85c71708617381e 100644 (file)
@@ -11,19 +11,13 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
-
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map.Entry;
-import java.util.concurrent.Callable;
-
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.spi.RegistrationTreeSnapshot;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.SimpleEventFactory;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker;
 import org.opendaylight.yangtools.util.concurrent.NotificationManager;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -40,36 +34,24 @@ import org.slf4j.LoggerFactory;
  * Computes data change events for all affected registered listeners in data
  * tree.
  */
-final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListenerNotifyTask>> {
+final class ResolveDataChangeEventsTask {
     private static final Logger LOG = LoggerFactory.getLogger(ResolveDataChangeEventsTask.class);
 
-    @SuppressWarnings("rawtypes")
-    private final NotificationManager<AsyncDataChangeListener, AsyncDataChangeEvent> notificationMgr;
     private final DataTreeCandidate candidate;
     private final ListenerTree listenerRoot;
 
     private Multimap<DataChangeListenerRegistration<?>, DOMImmutableDataChangeEvent> collectedEvents;
 
-    @SuppressWarnings("rawtypes")
-    public ResolveDataChangeEventsTask(final DataTreeCandidate candidate, final ListenerTree listenerTree,
-            final NotificationManager<AsyncDataChangeListener, AsyncDataChangeEvent> notificationMgr) {
+    public ResolveDataChangeEventsTask(final DataTreeCandidate candidate, final ListenerTree listenerTree) {
         this.candidate = Preconditions.checkNotNull(candidate);
         this.listenerRoot = Preconditions.checkNotNull(listenerTree);
-        this.notificationMgr = Preconditions.checkNotNull(notificationMgr);
     }
 
     /**
-     * Resolves and creates Notification Tasks
-     *
-     * Implementation of done as Map-Reduce with two steps: 1. resolving events
-     * and their mapping to listeners 2. merging events affecting same listener
-     *
-     * @return An {@link Iterable} of Notification Tasks which needs to be executed in
-     *         order to delivery data change events.
+     * Resolves and submits notification tasks to the specified manager.
      */
-    @Override
-    public synchronized Iterable<ChangeListenerNotifyTask> call() {
-        try (final Walker w = listenerRoot.getWalker()) {
+    public synchronized void resolve(final NotificationManager<DataChangeListenerRegistration<?>, DOMImmutableDataChangeEvent> manager) {
+        try (final RegistrationTreeSnapshot<DataChangeListenerRegistration<?>> w = listenerRoot.takeSnapshot()) {
             // Defensive: reset internal state
             collectedEvents = ArrayListMultimap.create();
 
@@ -81,7 +63,6 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
              * Convert to tasks, but be mindful of multiple values -- those indicate multiple
              * wildcard matches, which need to be merged.
              */
-            final Collection<ChangeListenerNotifyTask> ret = new ArrayList<>();
             for (Entry<DataChangeListenerRegistration<?>, Collection<DOMImmutableDataChangeEvent>> e : collectedEvents.asMap().entrySet()) {
                 final Collection<DOMImmutableDataChangeEvent> col = e.getValue();
                 final DOMImmutableDataChangeEvent event;
@@ -98,12 +79,8 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
                     event = col.iterator().next();
                 }
 
-                ret.add(new ChangeListenerNotifyTask(e.getKey(), event, notificationMgr));
+                manager.submitNotification(e.getKey(), event);
             }
-
-            // FIXME: so now we have tasks to submit tasks... Inception-style!
-            LOG.debug("Created tasks {}", ret);
-            return ret;
         }
     }
 
@@ -141,7 +118,9 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             Preconditions.checkArgument(node.getDataAfter().isPresent(),
                     "Modification at {} has type {} but no after-data", state.getPath(), node.getModificationType());
             if (!node.getDataBefore().isPresent()) {
-                resolveCreateEvent(state, node.getDataAfter().get());
+                @SuppressWarnings({ "unchecked", "rawtypes" })
+                final NormalizedNode<PathArgument, ?> afterNode = (NormalizedNode)node.getDataAfter().get();
+                resolveSameEventRecursivelly(state, afterNode, DOMImmutableDataChangeEvent.getCreateEventFactory());
                 return true;
             }
 
@@ -149,7 +128,10 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
         case DELETE:
             Preconditions.checkArgument(node.getDataBefore().isPresent(),
                     "Modification at {} has type {} but no before-data", state.getPath(), node.getModificationType());
-            resolveDeleteEvent(state, node.getDataBefore().get());
+
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            final NormalizedNode<PathArgument, ?> beforeNode = (NormalizedNode)node.getDataBefore().get();
+            resolveSameEventRecursivelly(state, beforeNode, DOMImmutableDataChangeEvent.getRemoveEventFactory());
             return true;
         case UNMODIFIED:
             return false;
@@ -244,26 +226,6 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
         return true;
     }
 
-    /**
-     * Resolves create events deep down the interest listener tree.
-     *
-     * @param path
-     * @param listeners
-     * @param afterState
-     * @return
-     */
-    private void resolveCreateEvent(final ResolveDataChangeState state, final NormalizedNode<?, ?> afterState) {
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState;
-        resolveSameEventRecursivelly(state, node, DOMImmutableDataChangeEvent.getCreateEventFactory());
-    }
-
-    private void resolveDeleteEvent(final ResolveDataChangeState state, final NormalizedNode<?, ?> beforeState) {
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState;
-        resolveSameEventRecursivelly(state, node, DOMImmutableDataChangeEvent.getRemoveEventFactory());
-    }
-
     private void resolveSameEventRecursivelly(final ResolveDataChangeState state,
             final NormalizedNode<PathArgument, ?> node, final SimpleEventFactory eventFactory) {
         if (!state.needsProcessing()) {
@@ -298,6 +260,11 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
         Preconditions.checkArgument(modification.getDataBefore().isPresent(), "Subtree change with before-data not present at path %s", state.getPath());
         Preconditions.checkArgument(modification.getDataAfter().isPresent(), "Subtree change with after-data not present at path %s", state.getPath());
 
+        if (!state.needsProcessing()) {
+            LOG.trace("Not processing modified subtree {}", state.getPath());
+            return true;
+        }
+
         DataChangeScope scope = null;
         for (DataTreeCandidateNode childMod : modification.getChildNodes()) {
             final ResolveDataChangeState childState = state.child(childMod.getIdentifier());
@@ -333,10 +300,7 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
         return scope != null;
     }
 
-    @SuppressWarnings("rawtypes")
-    public static ResolveDataChangeEventsTask create(final DataTreeCandidate candidate,
-            final ListenerTree listenerTree,
-            final NotificationManager<AsyncDataChangeListener,AsyncDataChangeEvent> notificationMgr) {
-        return new ResolveDataChangeEventsTask(candidate, listenerTree, notificationMgr);
+    public static ResolveDataChangeEventsTask create(final DataTreeCandidate candidate, final ListenerTree listenerTree) {
+        return new ResolveDataChangeEventsTask(candidate, listenerTree);
     }
 }