When we insert a new subtree, we need to make sure to call serialization
on the entire, such that any new elements which appear have their
classed attached to paths.
This reuses a previous code path, which pruned the walk tree as soon as
it encountered a node which did not have any listeners attached (thus
improving performance when we're gathering listeners).
In this specific case, though, this check is not correct: we need to
walk the path because it may be placing new data in the subtree.
At the same time add debug statements which made pinpointing this
problem possible.
Change-Id: I1687ba45817a84ea4a888496a90defc5896216c9
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
Signed-off-by: Robert Varga <rovarga@cisco.com>
final Collection<Node> listeners, final NormalizedNode<?, ?> beforeData,
final NormalizedNode<?, ?> afterData) {
final Collection<Node> listeners, final NormalizedNode<?, ?> beforeData,
final NormalizedNode<?, ?> afterData) {
- if (beforeData instanceof NormalizedNodeContainer<?, ?, ?> && !listeners.isEmpty()) {
+ if (beforeData instanceof NormalizedNodeContainer<?, ?, ?>) {
// Node is container (contains child) and we have interested
// listeners registered for it, that means we need to do
// resolution of changes on children level and can not
// shortcut resolution.
// Node is container (contains child) and we have interested
// listeners registered for it, that means we need to do
// resolution of changes on children level and can not
// shortcut resolution.
+ LOG.trace("Resolving subtree replace event for {} before {}, after {}",path,beforeData,afterData);
@SuppressWarnings("unchecked")
NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) beforeData;
@SuppressWarnings("unchecked")
@SuppressWarnings("unchecked")
NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) beforeData;
@SuppressWarnings("unchecked")
// Node is either of Leaf type (does not contain child nodes)
// or we do not have listeners, so normal equals method is
// sufficient for determining change.
// Node is either of Leaf type (does not contain child nodes)
// or we do not have listeners, so normal equals method is
// sufficient for determining change.
+ LOG.trace("Resolving leaf replace event for {} , before {}, after {}",path,beforeData,afterData);
DOMImmutableDataChangeEvent event = builder(DataChangeScope.BASE).setBefore(beforeData).setAfter(afterData)
.addUpdated(path, beforeData, afterData).build();
addPartialTask(listeners, event);
DOMImmutableDataChangeEvent event = builder(DataChangeScope.BASE).setBefore(beforeData).setAfter(afterData)
.addUpdated(path, beforeData, afterData).build();
addPartialTask(listeners, event);
private DOMImmutableDataChangeEvent resolveSameEventRecursivelly(final InstanceIdentifier path,
final Collection<Node> listeners, final NormalizedNode<PathArgument, ?> node,
final SimpleEventFactory eventFactory) {
private DOMImmutableDataChangeEvent resolveSameEventRecursivelly(final InstanceIdentifier path,
final Collection<Node> listeners, final NormalizedNode<PathArgument, ?> node,
final SimpleEventFactory eventFactory) {
final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
DOMImmutableDataChangeEvent propagateEvent = event;
final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
DOMImmutableDataChangeEvent propagateEvent = event;
- // We have listeners for this node or it's children, so we will try
+ // We have listeners for this node or it's children, so we will try
// to do additional processing
if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
// to do additional processing
if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
+ LOG.trace("Resolving subtree recursive event for {}, type {}", path, eventFactory);
+
Builder eventBuilder = builder(DataChangeScope.BASE);
eventBuilder.merge(event);
eventBuilder.setBefore(event.getOriginalSubtree());
Builder eventBuilder = builder(DataChangeScope.BASE);
eventBuilder.merge(event);
eventBuilder.setBefore(event.getOriginalSubtree());
NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> container = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) node;
for (NormalizedNode<PathArgument, ?> child : container.getValue()) {
PathArgument childId = child.getIdentifier();
NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> container = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) node;
for (NormalizedNode<PathArgument, ?> child : container.getValue()) {
PathArgument childId = child.getIdentifier();
+ LOG.trace("Resolving event for child {}", childId);
Collection<Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
eventBuilder.merge(resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory));
}
Collection<Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
eventBuilder.merge(resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory));
}
propagateEvent = builder(DataChangeScope.BASE).build();
}
if (!listeners.isEmpty()) {
propagateEvent = builder(DataChangeScope.BASE).build();
}
if (!listeners.isEmpty()) {
- addPartialTask(listeners, event);
+ addPartialTask(listeners, propagateEvent);
}
return propagateEvent;
}
}
return propagateEvent;
}
private DOMImmutableDataChangeEvent addPartialTask(final Collection<ListenerTree.Node> listeners,
final DOMImmutableDataChangeEvent event) {
private DOMImmutableDataChangeEvent addPartialTask(final Collection<ListenerTree.Node> listeners,
final DOMImmutableDataChangeEvent event) {
for (ListenerTree.Node listenerNode : listeners) {
if (!listenerNode.getListeners().isEmpty()) {
for (ListenerTree.Node listenerNode : listeners) {
if (!listenerNode.getListeners().isEmpty()) {
+ LOG.trace("Adding event {} for listeners {}",event,listenerNode);
events.put(listenerNode, event);
}
}
events.put(listenerNode, event);
}
}