@Override
public ListenableFuture<Void> abort() {
- if (candidate != null) {
- candidate.close();
- candidate = null;
- }
-
- return Futures.<Void> immediateFuture(null);
+ candidate = null;
+ return Futures.immediateFuture(null);
}
@Override
}
}
- return Futures.<Void> immediateFuture(null);
+ return Futures.immediateFuture(null);
}
}
}
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.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Node;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
private final ListenerTree listenerRoot;
public ResolveDataChangeEventsTask(DataTreeCandidate candidate, ListenerTree listenerTree) {
- this.candidate = Preconditions.checkNotNull(candidate);
- this.listenerRoot = Preconditions.checkNotNull(listenerTree);
- }
+ this.candidate = Preconditions.checkNotNull(candidate);
+ this.listenerRoot = Preconditions.checkNotNull(listenerTree);
+ }
/**
* Resolves and creates Notification Tasks
@Override
public Iterable<ChangeListenerNotifyTask> call() {
try (final Walker w = listenerRoot.getWalker()) {
- resolveAnyChangeEvent(candidate.getRootPath(), Collections.singleton(w.getRootNode()),
- candidate.getModificationRoot(), Optional.fromNullable(candidate.getBeforeRoot()),
- Optional.fromNullable(candidate.getAfterRoot()));
+ resolveAnyChangeEvent(candidate.getRootPath(), Collections.singleton(w.getRootNode()), candidate.getRootNode());
return createNotificationTasks();
}
}
* @return Data Change Event of this node and all it's children
*/
private DOMImmutableDataChangeEvent resolveAnyChangeEvent(final InstanceIdentifier path,
- final Collection<ListenerTree.Node> listeners, final NodeModification modification,
- final Optional<StoreMetadataNode> before, final Optional<StoreMetadataNode> after) {
- // No listeners are present in listener registration subtree
- // no before and after state is present
- if (!before.isPresent() && !after.isPresent()) {
+ final Collection<ListenerTree.Node> listeners, final DataTreeCandidateNode node) {
+
+ if (node.getModificationType() != ModificationType.UNMODIFIED &&
+ !node.getDataAfter().isPresent() && !node.getDataBefore().isPresent()) {
+ LOG.debug("Modification at {} has type {}, but no before- and after-data. Assuming unchanged.",
+ path, node.getModificationType());
return NO_CHANGE;
}
- switch (modification.getModificationType()) {
+
+ // no before and after state is present
+
+ switch (node.getModificationType()) {
case SUBTREE_MODIFIED:
- return resolveSubtreeChangeEvent(path, listeners, modification, before.get(), after.get());
+ return resolveSubtreeChangeEvent(path, listeners, node);
case MERGE:
case WRITE:
- if (before.isPresent()) {
- return resolveReplacedEvent(path, listeners, before.get().getData(), after.get().getData());
+ Preconditions.checkArgument(node.getDataAfter().isPresent(),
+ "Modification at {} has type {} but no after-data", path, node.getModificationType());
+ if (node.getDataBefore().isPresent()) {
+ return resolveReplacedEvent(path, listeners, node.getDataBefore().get(), node.getDataAfter().get());
} else {
- return resolveCreateEvent(path, listeners, after.get());
+ return resolveCreateEvent(path, listeners, node.getDataAfter().get());
}
case DELETE:
- return resolveDeleteEvent(path, listeners, before.get());
- default:
+ Preconditions.checkArgument(node.getDataBefore().isPresent(),
+ "Modification at {} has type {} but no before-data", path, node.getModificationType());
+ return resolveDeleteEvent(path, listeners, node.getDataBefore().get());
+ case UNMODIFIED:
return NO_CHANGE;
}
+ throw new IllegalStateException(String.format("Unhandled node state %s at %s", node.getModificationType(), path));
}
private DOMImmutableDataChangeEvent resolveReplacedEvent(final InstanceIdentifier path,
private DOMImmutableDataChangeEvent resolveNodeContainerReplaced(final InstanceIdentifier path,
final Collection<Node> listeners,
final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont,
- final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
+ final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
final Set<PathArgument> alreadyProcessed = new HashSet<>();
final List<DOMImmutableDataChangeEvent> childChanges = new LinkedList<>();
* @return
*/
private DOMImmutableDataChangeEvent resolveCreateEvent(final InstanceIdentifier path,
- final Collection<ListenerTree.Node> listeners, final StoreMetadataNode afterState) {
+ final Collection<ListenerTree.Node> listeners, final NormalizedNode<?, ?> afterState) {
@SuppressWarnings({ "unchecked", "rawtypes" })
- final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState.getData();
+ final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState;
return resolveSameEventRecursivelly(path, listeners, node, DOMImmutableDataChangeEvent.getCreateEventFactory());
}
private DOMImmutableDataChangeEvent resolveDeleteEvent(final InstanceIdentifier path,
- final Collection<ListenerTree.Node> listeners, final StoreMetadataNode beforeState) {
+ final Collection<ListenerTree.Node> listeners, final NormalizedNode<?, ?> beforeState) {
@SuppressWarnings({ "unchecked", "rawtypes" })
- final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState.getData();
+ final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState;
return resolveSameEventRecursivelly(path, listeners, node, DOMImmutableDataChangeEvent.getRemoveEventFactory());
}
final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
DOMImmutableDataChangeEvent propagateEvent = event;
// We have listeners for this node or it's children, so we will try
- // to do additional processing
+ // to do additional processing
if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
LOG.trace("Resolving subtree recursive event for {}, type {}", path, eventFactory);
}
private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path,
- final Collection<ListenerTree.Node> listeners, final NodeModification modification,
- final StoreMetadataNode before, final StoreMetadataNode after) {
+ final Collection<ListenerTree.Node> listeners, final DataTreeCandidateNode modification) {
- Builder one = builder(DataChangeScope.ONE).setBefore(before.getData()).setAfter(after.getData());
+ Preconditions.checkArgument(modification.getDataBefore().isPresent(), "Subtree change with before-data not present at path %s", path);
+ Preconditions.checkArgument(modification.getDataAfter().isPresent(), "Subtree change with after-data not present at path %s", path);
- Builder subtree = builder(DataChangeScope.SUBTREE).setBefore(before.getData()).setAfter(after.getData());
+ Builder one = builder(DataChangeScope.ONE).
+ setBefore(modification.getDataBefore().get()).
+ setAfter(modification.getDataAfter().get());
+ Builder subtree = builder(DataChangeScope.SUBTREE).
+ setBefore(modification.getDataBefore().get()).
+ setAfter(modification.getDataAfter().get());
- for (NodeModification childMod : modification.getModifications()) {
+ for (DataTreeCandidateNode childMod : modification.getChildNodes()) {
PathArgument childId = childMod.getIdentifier();
InstanceIdentifier childPath = append(path, childId);
Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
- Optional<StoreMetadataNode> childBefore = before.getChild(childId);
- Optional<StoreMetadataNode> childAfter = after.getChild(childId);
-
switch (childMod.getModificationType()) {
case WRITE:
case MERGE:
case DELETE:
- one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod, childBefore, childAfter));
+ one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod));
break;
case SUBTREE_MODIFIED:
- subtree.merge(resolveSubtreeChangeEvent(childPath, childListeners, childMod, childBefore.get(),
- childAfter.get()));
+ subtree.merge(resolveSubtreeChangeEvent(childPath, childListeners, childMod));
break;
case UNMODIFIED:
// no-op
}
}
- public static ResolveDataChangeEventsTask create(DataTreeCandidate candidate, ListenerTree listenerTree) {
+ public static ResolveDataChangeEventsTask create(DataTreeCandidate candidate, ListenerTree listenerTree) {
return new ResolveDataChangeEventsTask(candidate, listenerTree);
- }
+ }
}
*/
package org.opendaylight.controller.md.sal.dom.store.impl.tree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.StoreMetadataNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-public interface DataTreeCandidate extends AutoCloseable {
- @Override
- void close();
-
- InstanceIdentifier getRootPath();
-
- @Deprecated
- NodeModification getModificationRoot();
-
- @Deprecated
- StoreMetadataNode getBeforeRoot();
-
- @Deprecated
- StoreMetadataNode getAfterRoot();
+public interface DataTreeCandidate {
+ DataTreeCandidateNode getRootNode();
+ InstanceIdentifier getRootPath();
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+public interface DataTreeCandidateNode {
+ PathArgument getIdentifier();
+ Iterable<DataTreeCandidateNode> getChildNodes();
+
+ ModificationType getModificationType();
+ Optional<NormalizedNode<?, ?>> getDataAfter();
+ Optional<NormalizedNode<?, ?>> getDataBefore();
+}
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
public enum ModificationType {
import com.google.common.base.Preconditions;
abstract class AbstractDataTreeCandidate implements DataTreeCandidate {
- private final InstanceIdentifier rootPath;
- private final NodeModification modificationRoot;
+ private final InstanceIdentifier rootPath;
- protected AbstractDataTreeCandidate(final InstanceIdentifier rootPath, NodeModification modificationRoot) {
- this.rootPath = Preconditions.checkNotNull(rootPath);
- this.modificationRoot = Preconditions.checkNotNull(modificationRoot);
- }
+ protected AbstractDataTreeCandidate(final InstanceIdentifier rootPath) {
+ this.rootPath = Preconditions.checkNotNull(rootPath);
+ }
- @Override
- public final InstanceIdentifier getRootPath() {
- return rootPath;
- }
+ @Override
+ public final InstanceIdentifier getRootPath() {
+ return rootPath;
+ }
- @Override
- public final NodeModification getModificationRoot() {
- return modificationRoot;
- }
}
import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
rwLock.writeLock().lock();
try {
Preconditions.checkState(c.getBeforeRoot() == rootNode,
- String.format("Store snapshot %s and transaction snapshot %s differ.", rootNode, c.getBeforeRoot()));
+ String.format("Store tree %s and candidate base %s differ.", rootNode, c.getBeforeRoot()));
this.rootNode = c.getAfterRoot();
} finally {
rwLock.writeLock().unlock();
package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
- private final StoreMetadataNode newRoot;
- private final StoreMetadataNode oldRoot;
-
- InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot,
- final StoreMetadataNode oldRoot, final StoreMetadataNode newRoot) {
- super(rootPath, modificationRoot);
- this.newRoot = Preconditions.checkNotNull(newRoot);
- this.oldRoot = Preconditions.checkNotNull(oldRoot);
- }
-
- @Override
- public void close() {
- // FIXME: abort operation here :)
- }
-
- @Override
- public StoreMetadataNode getBeforeRoot() {
- return oldRoot;
- }
-
- @Override
- public StoreMetadataNode getAfterRoot() {
- return newRoot;
- }
+ private static abstract class AbstractNode implements DataTreeCandidateNode {
+ private final StoreMetadataNode newMeta;
+ private final StoreMetadataNode oldMeta;
+ private final NodeModification mod;
+
+ protected AbstractNode(final NodeModification mod,
+ final StoreMetadataNode oldMeta, final StoreMetadataNode newMeta) {
+ this.newMeta = newMeta;
+ this.oldMeta = oldMeta;
+ this.mod = Preconditions.checkNotNull(mod);
+ }
+
+ protected final NodeModification getMod() {
+ return mod;
+ }
+
+ protected final StoreMetadataNode getNewMeta() {
+ return newMeta;
+ }
+
+ protected final StoreMetadataNode getOldMeta() {
+ return oldMeta;
+ }
+
+ private static final StoreMetadataNode childMeta(final StoreMetadataNode parent, final PathArgument id) {
+ return parent == null ? null : parent.getChild(id).orNull();
+ }
+
+ @Override
+ public Iterable<DataTreeCandidateNode> getChildNodes() {
+ return Iterables.transform(mod.getModifications(), new Function<NodeModification, DataTreeCandidateNode>() {
+ @Override
+ public DataTreeCandidateNode apply(final NodeModification input) {
+ final PathArgument id = input.getIdentifier();
+ return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
+ }
+ });
+ }
+
+ @Override
+ public ModificationType getModificationType() {
+ return mod.getModificationType();
+ }
+
+ private Optional<NormalizedNode<?, ?>> optionalData(StoreMetadataNode meta) {
+ if (meta == null) {
+ return Optional.absent();
+ }
+ return Optional.<NormalizedNode<?,?>>of(meta.getData());
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> getDataAfter() {
+ return optionalData(newMeta);
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> getDataBefore() {
+ return optionalData(oldMeta);
+ }
+ }
+
+ private static final class ChildNode extends AbstractNode {
+ public ChildNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) {
+ super(mod, oldMeta, newMeta);
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ return getMod().getIdentifier();
+ }
+ }
+
+ private static final class RootNode extends AbstractNode {
+ public RootNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) {
+ super(mod, oldMeta, newMeta);
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ throw new IllegalStateException("Attempted to get identifier of the root node");
+ }
+ }
+
+ private final RootNode root;
+
+ InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot,
+ final StoreMetadataNode oldRoot, final StoreMetadataNode newRoot) {
+ super(rootPath);
+ this.root = new RootNode(modificationRoot, oldRoot, newRoot);
+ }
+
+ StoreMetadataNode getAfterRoot() {
+ return root.getNewMeta();
+ }
+
+ StoreMetadataNode getBeforeRoot() {
+ return root.getOldMeta();
+ }
+
+ @Override
+ public DataTreeCandidateNode getRootNode() {
+ return root;
+ }
}
import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
*
* This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
* and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
- *
*/
-// FIXME: hide this class
-public class NodeModification implements StoreTreeNode<NodeModification>, Identifiable<PathArgument> {
+final class NodeModification implements StoreTreeNode<NodeModification>, Identifiable<PathArgument> {
public static final Predicate<NodeModification> IS_TERMINAL_PREDICATE = new Predicate<NodeModification>() {
@Override
*/
package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
final class NoopDataTreeCandidate extends AbstractDataTreeCandidate {
- protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot) {
- super(rootPath, modificationRoot);
- }
-
- @Override
- public void close() {
- // NO-OP
- }
-
- @Override
- public StoreMetadataNode getBeforeRoot() {
- return null;
- }
-
- @Override
- public StoreMetadataNode getAfterRoot() {
- return null;
- }
+ private static final DataTreeCandidateNode ROOT = new DataTreeCandidateNode() {
+ @Override
+ public ModificationType getModificationType() {
+ return ModificationType.UNMODIFIED;
+ }
+
+ @Override
+ public Iterable<DataTreeCandidateNode> getChildNodes() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ throw new IllegalStateException("Attempted to read identifier of the no-operation change");
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> getDataAfter() {
+ return Optional.absent();
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> getDataBefore() {
+ return Optional.absent();
+ }
+ };
+
+ protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot) {
+ super(rootPath);
+ Preconditions.checkArgument(modificationRoot.getModificationType() == ModificationType.UNMODIFIED);
+ }
+
+ @Override
+ public DataTreeCandidateNode getRootNode() {
+ return ROOT;
+ }
}
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import com.google.common.base.Preconditions;
import com.google.common.primitives.UnsignedLong;
-// FIXME: this should not be public
-public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>, StoreTreeNode<StoreMetadataNode> {
-
+class StoreMetadataNode implements Immutable, Identifiable<PathArgument>, StoreTreeNode<StoreMetadataNode> {
+ private final Map<PathArgument, StoreMetadataNode> children;
private final UnsignedLong nodeVersion;
private final UnsignedLong subtreeVersion;
private final NormalizedNode<?, ?> data;
- private final Map<PathArgument, StoreMetadataNode> children;
-
/**
*
* @param data
*/
protected StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
final UnsignedLong subtreeVersion, final Map<PathArgument, StoreMetadataNode> children) {
- this.nodeVersion = nodeVersion;
- this.subtreeVersion = subtreeVersion;
- this.data = data;
+ this.nodeVersion = Preconditions.checkNotNull(nodeVersion);
+ this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+ this.data = Preconditions.checkNotNull(data);
this.children = Preconditions.checkNotNull(children);
}