From a5cc12f729f44ca0a5f8b7cb2e6912fdffe12e10 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Fri, 23 May 2014 13:11:39 +0200 Subject: [PATCH] BUG-509: use concurrent hash-trie Map This patch switches to using concurrent hash-trie map for metadata tracking. It has the nice feature of having O(1) concurrent snapshots, which should give us better performance when dealing with large children bases. This is a trade-off, please refer to yangtools.util.MapAdaptor for system properties which tune its behavior. Change-Id: I2ddb81a1296cc17528a605eeaeda1f303560fb55 Signed-off-by: Robert Varga --- opendaylight/commons/opendaylight/pom.xml | 7 +++++++ opendaylight/md-sal/sal-dom-broker/pom.xml | 6 ++++++ .../store/impl/tree/spi/ContainerNode.java | 20 ++++++++----------- .../store/impl/tree/spi/MutableTreeNode.java | 5 +++++ .../store/impl/tree/spi/TreeNodeFactory.java | 4 ++++ 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 47dbe123f8..c166f668cc 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -49,6 +49,7 @@ 0.5.2-SNAPSHOT 0.0.2-SNAPSHOT 7.0.42 + 0.2.0 0.4.2-SNAPSHOT 2.5.0 @@ -240,6 +241,11 @@ jackson-module-jaxb-annotations ${jackson.version} + + com.github.romix + java-concurrent-hash-trie-map + ${ctrie.version} + com.google.code.findbugs jsr305 @@ -255,6 +261,7 @@ guava ${guava.version} + com.sun.jersey jersey-client diff --git a/opendaylight/md-sal/sal-dom-broker/pom.xml b/opendaylight/md-sal/sal-dom-broker/pom.xml index 456af8353b..bac9146bf5 100644 --- a/opendaylight/md-sal/sal-dom-broker/pom.xml +++ b/opendaylight/md-sal/sal-dom-broker/pom.xml @@ -10,6 +10,10 @@ bundle + + com.github.romix + java-concurrent-hash-trie-map + com.google.guava guava @@ -50,6 +54,7 @@ org.opendaylight.yangtools yang-parser-impl + org.slf4j slf4j-api @@ -88,6 +93,7 @@ org.opendaylight.yangtools.yang.util, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.dom.impl.rev131028.* * + java-concurrent-hash-trie-map;inline=true diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java index 8f74f60498..3ca8db2405 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java @@ -7,10 +7,10 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi; -import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.opendaylight.yangtools.util.MapAdaptor; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; @@ -50,14 +50,14 @@ final class ContainerNode extends AbstractTreeNode { } private static final class Mutable implements MutableTreeNode { - private final Map children; private final Version version; + private Map children; private NormalizedNode data; private Version subtreeVersion; private Mutable(final ContainerNode parent) { this.data = parent.getData(); - this.children = new HashMap<>(parent.children); + this.children = MapAdaptor.getDefaultInstance().takeSnapshot(parent.children); this.subtreeVersion = parent.getSubtreeVersion(); this.version = parent.getVersion(); } @@ -84,15 +84,11 @@ final class ContainerNode extends AbstractTreeNode { @Override public TreeNode seal() { - final Map realChildren; + final TreeNode ret = new ContainerNode(data, version, MapAdaptor.getDefaultInstance().optimize(children), subtreeVersion); - if (children.isEmpty()) { - realChildren = Collections.emptyMap(); - } else { - realChildren = children; - } - - return new ContainerNode(data, version, realChildren, subtreeVersion); + // This forces a NPE if this class is accessed again. Better than corruption. + children = null; + return ret; } @Override @@ -103,8 +99,8 @@ final class ContainerNode extends AbstractTreeNode { private static ContainerNode create(final Version version, final NormalizedNode data, final Iterable> children) { - final Map map = new HashMap<>(); + final Map map = new HashMap<>(); for (NormalizedNode child : children) { map.put(child.getIdentifier(), TreeNodeFactory.createTreeNode(child, version)); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java index dd3672cf11..7ab309607b 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java @@ -11,6 +11,11 @@ import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +/** + * A mutable tree node. This is a transient view materialized from a pre-existing + * node. Modifications are isolated. Once this object is {@link #seal()}-ed, + * any interactions with it will result in undefined behavior. + */ public interface MutableTreeNode extends StoreTreeNode { void setData(NormalizedNode data); void setSubtreeVersion(Version subtreeVersion); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java index c5d174caad..9547628ae9 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java @@ -11,6 +11,10 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer; +/** + * Public entrypoint for other packages. Allows instantiating a tree node + * with specified version. + */ public final class TreeNodeFactory { private TreeNodeFactory() { throw new UnsupportedOperationException("Utility class should not be instantiated"); -- 2.36.6