From f17c5ab39d43de758c3f3c7bd642d7fa436a6983 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 20 Sep 2016 20:48:05 +0200 Subject: [PATCH 1/1] Move transaction-invariants into producer Instead of re-calculating the context, cache most of the information required in the InMemoryDOMDataTreeShardProducer, so it can be quickly reused when creating transactions. This information is calculated when a producer is created or when the sharding layout changes. Change-Id: Id2bcab420cf6d1635aba6cd97bf68f1860533780 Signed-off-by: Robert Varga (cherry picked from commit 5a9368fc20a5a6d403a63fe405b79c55a0a647cc) --- ...rdedDOMDataTreeProducerMultiShardTest.java | 6 +- .../inmemory/InMemoryDOMDataTreeShard.java | 132 ++++++++++-------- .../InMemoryDOMDataTreeShardProducer.java | 15 +- .../ModificationContextNodeBuilder.java | 22 ++- .../store/inmemory/ShardDataModification.java | 11 -- .../ShardDataModificationBuilder.java | 59 -------- .../ShardDataModificationFactory.java | 44 ++++++ .../ShardDataModificationFactoryBuilder.java | 63 +++++++++ .../InMemoryDOMDataTreeShardProducerTest.java | 12 +- .../InMemoryDOMDataTreeShardTest.java | 16 ++- ...yDOMDataTreeShardWriteTransactionTest.java | 2 +- .../ModificationContextNodeBuilderTest.java | 9 -- .../ShardDataModificationCursorTest.java | 6 +- .../inmemory/ShardDataModificationTest.java | 2 +- .../mdsal/dom/store/inmemory/TestUtils.java | 17 ++- 15 files changed, 244 insertions(+), 172 deletions(-) delete mode 100644 dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationBuilder.java create mode 100644 dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationFactory.java create mode 100644 dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationFactoryBuilder.java diff --git a/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/ShardedDOMDataTreeProducerMultiShardTest.java b/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/ShardedDOMDataTreeProducerMultiShardTest.java index 46ab94cc36..cd5a7169cd 100644 --- a/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/ShardedDOMDataTreeProducerMultiShardTest.java +++ b/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/ShardedDOMDataTreeProducerMultiShardTest.java @@ -286,13 +286,13 @@ public class ShardedDOMDataTreeProducerMultiShardTest { @Test public void testMockedSubshards() throws Exception { final WriteableDOMDataTreeShard mockedInnerShard = Mockito.mock(WriteableDOMDataTreeShard.class); + final DOMDataTreeShardProducer mockedProducer = Mockito.mock(DOMDataTreeShardProducer.class); + doReturn(mockedProducer).when(mockedInnerShard).createProducer(anyCollection()); final ShardedDOMDataTreeProducer shardRegProducer = Mockito.mock(ShardedDOMDataTreeProducer.class); doReturn(Collections.singleton(INNER_CONTAINER_ID)).when(shardRegProducer).getSubtrees(); doNothing().when(shardRegProducer).subshardAdded(anyMap()); dataTreeService.registerDataTreeShard(INNER_CONTAINER_ID, mockedInnerShard, shardRegProducer); - final DOMDataTreeShardProducer mockedProducer = Mockito.mock(DOMDataTreeShardProducer.class); - doReturn(mockedProducer).when(mockedInnerShard).createProducer(any(Collection.class)); final DOMDataTreeShardProducer producer = rootShard.createProducer(Collections.singletonList(TEST_ID)); @@ -351,7 +351,7 @@ public class ShardedDOMDataTreeProducerMultiShardTest { } - private ContainerNode createCrossShardContainer() { + private static ContainerNode createCrossShardContainer() { final LeafNode shardedValue1 = ImmutableLeafNodeBuilder.create().withNodeIdentifier( new NodeIdentifier(TestModel.SHARDED_VALUE_1)).withValue("sharded value 1").build(); diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShard.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShard.java index 97b2354f9a..127821fc09 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShard.java +++ b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShard.java @@ -18,6 +18,7 @@ import com.google.common.util.concurrent.MoreExecutors; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; @@ -39,12 +40,11 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType; import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @Beta public class InMemoryDOMDataTreeShard implements ReadableWriteableDOMDataTreeShard, SchemaContextListener { - - private static final int DEFAULT_SUBMIT_QUEUE_SIZE = 1000; - private static final class SubshardProducerSpecification { private final Collection prefixes = new ArrayList<>(1); private final ChildShardContext shard; @@ -61,17 +61,21 @@ public class InMemoryDOMDataTreeShard implements ReadableWriteableDOMDataTreeSha return shard.getShard().createProducer(prefixes); } - public DOMDataTreeIdentifier getPrefix() { + DOMDataTreeIdentifier getPrefix() { return shard.getPrefix(); } } + private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataTreeShard.class); + private static final int DEFAULT_SUBMIT_QUEUE_SIZE = 1000; + private final DOMDataTreePrefixTable childShardsTable = DOMDataTreePrefixTable.create(); private final Map childShards = new HashMap<>(); - private final DOMDataTreeIdentifier prefix; - private final DataTree dataTree; + private final Collection producers = new HashSet<>(); private final InMemoryDOMDataTreeShardChangePublisher shardChangePublisher; private final ListeningExecutorService executor; + private final DOMDataTreeIdentifier prefix; + private final DataTree dataTree; private InMemoryDOMDataTreeShard(final DOMDataTreeIdentifier prefix, final Executor dataTreeChangeExecutor, final int maxDataChangeListenerQueueSize, final int submitQueueSize) { @@ -112,13 +116,59 @@ public class InMemoryDOMDataTreeShard implements ReadableWriteableDOMDataTreeSha public void onChildAttached(final DOMDataTreeIdentifier prefix, final DOMDataTreeShard child) { Preconditions.checkArgument(child != this, "Attempted to attach child %s onto self", this); reparentChildShards(prefix, child); - addChildShard(prefix, child); + + final ChildShardContext context = createContextFor(prefix, child); + childShards.put(prefix, context); + childShardsTable.store(prefix, context); + updateProducers(); } @Override public void onChildDetached(final DOMDataTreeIdentifier prefix, final DOMDataTreeShard child) { childShards.remove(prefix); childShardsTable.remove(prefix); + updateProducers(); + } + + private void updateProducers() { + for (InMemoryDOMDataTreeShardProducer p : producers) { + p.setModificationFactory(createModificationFactory(p.getPrefixes())); + } + } + + @VisibleForTesting + ShardDataModificationFactory createModificationFactory(final Collection prefixes) { + final Map affected = new HashMap<>(); + for (final DOMDataTreeIdentifier producerPrefix : prefixes) { + for (final ChildShardContext child : childShards.values()) { + final DOMDataTreeIdentifier bindPath; + if (producerPrefix.contains(child.getPrefix())) { + bindPath = child.getPrefix(); + } else if (child.getPrefix().contains(producerPrefix)) { + // Bound path is inside subshard + bindPath = producerPrefix; + } else { + continue; + } + + SubshardProducerSpecification spec = affected.get(child.getPrefix()); + if (spec == null) { + spec = new SubshardProducerSpecification(child); + affected.put(child.getPrefix(), spec); + } + spec.addPrefix(bindPath); + } + } + + final ShardDataModificationFactoryBuilder builder = new ShardDataModificationFactoryBuilder(prefix); + for (final SubshardProducerSpecification spec : affected.values()) { + final ForeignShardModificationContext foreignContext = + new ForeignShardModificationContext(spec.getPrefix(), spec.createProducer()); + builder.addSubshard(foreignContext); + builder.addSubshard(spec.getPrefix(), foreignContext); + } + + return builder.build(); } @Override @@ -127,7 +177,17 @@ public class InMemoryDOMDataTreeShard implements ReadableWriteableDOMDataTreeSha Preconditions.checkArgument(prefix.contains(prodPrefix), "Prefix %s is not contained under shart root", prodPrefix, prefix); } - return new InMemoryDOMDataTreeShardProducer(this, prefixes); + + final InMemoryDOMDataTreeShardProducer ret = new InMemoryDOMDataTreeShardProducer(this, prefixes, + createModificationFactory(prefixes)); + producers.add(ret); + return ret; + } + + void closeProducer(final InMemoryDOMDataTreeShardProducer producer) { + if (!producers.remove(producer)) { + LOG.warn("Producer {} not found in shard {}", producer, this); + } } @Nonnull @@ -137,12 +197,6 @@ public class InMemoryDOMDataTreeShard implements ReadableWriteableDOMDataTreeSha return shardChangePublisher.registerTreeChangeListener(treeId, listener); } - private void addChildShard(final DOMDataTreeIdentifier prefix, final DOMDataTreeShard child) { - final ChildShardContext context = createContextFor(prefix, child); - childShards.put(prefix, context); - childShardsTable.store(prefix, context); - } - private void reparentChildShards(final DOMDataTreeIdentifier newChildPrefix, final DOMDataTreeShard newChild) { final Iterator> actualChildren = childShards.entrySet().iterator(); @@ -200,51 +254,11 @@ public class InMemoryDOMDataTreeShard implements ReadableWriteableDOMDataTreeSha } InmemoryDOMDataTreeShardWriteTransaction createTransaction(final String transactionId, - final InMemoryDOMDataTreeShardProducer producer, - final Collection prefixes, - final DataTreeSnapshot snapshot) { - - return createTxForSnapshot(producer, prefixes, (CursorAwareDataTreeSnapshot) snapshot); - } - - private InmemoryDOMDataTreeShardWriteTransaction createTxForSnapshot( - final InMemoryDOMDataTreeShardProducer producer, - final Collection prefixes, - final CursorAwareDataTreeSnapshot snapshot) { - - final Map affectedSubshards = new HashMap<>(); - for (final DOMDataTreeIdentifier producerPrefix : prefixes) { - for (final ChildShardContext maybeAffected : childShards.values()) { - final DOMDataTreeIdentifier bindPath; - if (producerPrefix.contains(maybeAffected.getPrefix())) { - bindPath = maybeAffected.getPrefix(); - } else if (maybeAffected.getPrefix().contains(producerPrefix)) { - // Bound path is inside subshard - bindPath = producerPrefix; - } else { - continue; - } - - SubshardProducerSpecification spec = affectedSubshards.get(maybeAffected.getPrefix()); - if (spec == null) { - spec = new SubshardProducerSpecification(maybeAffected); - affectedSubshards.put(maybeAffected.getPrefix(), spec); - } - spec.addPrefix(bindPath); - } - } + final InMemoryDOMDataTreeShardProducer producer, final DataTreeSnapshot snapshot) { + Preconditions.checkArgument(snapshot instanceof CursorAwareDataTreeSnapshot); - final ShardRootModificationContext rootContext = new ShardRootModificationContext(prefix, snapshot); - final ShardDataModificationBuilder builder = new ShardDataModificationBuilder(rootContext); - for (final SubshardProducerSpecification spec : affectedSubshards.values()) { - final ForeignShardModificationContext foreignContext = - new ForeignShardModificationContext(spec.getPrefix(), spec.createProducer()); - builder.addSubshard(foreignContext); - builder.addSubshard(spec.getPrefix(), foreignContext); - } - - return new InmemoryDOMDataTreeShardWriteTransaction(producer, builder.build(), - dataTree, shardChangePublisher, executor); + return new InmemoryDOMDataTreeShardWriteTransaction(producer, + producer.getModificationFactory().createModification((CursorAwareDataTreeSnapshot)snapshot), dataTree, + shardChangePublisher, executor); } - } diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardProducer.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardProducer.java index 348c46df33..f2b5ac0427 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardProducer.java +++ b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardProducer.java @@ -103,10 +103,13 @@ class InMemoryDOMDataTreeShardProducer implements DOMDataTreeShardProducer { AtomicReferenceFieldUpdater.newUpdater(InMemoryDOMDataTreeShardProducer.class, State.class, "state"); private volatile State state; + private ShardDataModificationFactory modificationFactory; + InMemoryDOMDataTreeShardProducer(final InMemoryDOMDataTreeShard parentShard, - final Collection prefixes) { + final Collection prefixes, final ShardDataModificationFactory modificationFactory) { this.parentShard = Preconditions.checkNotNull(parentShard); this.prefixes = ImmutableSet.copyOf(prefixes); + this.modificationFactory = Preconditions.checkNotNull(modificationFactory); state = idleState; } @@ -118,7 +121,7 @@ class InMemoryDOMDataTreeShardProducer implements DOMDataTreeShardProducer { InmemoryDOMDataTreeShardWriteTransaction ret; do { localState = state; - ret = parentShard.createTransaction(transactionId, this, prefixes, localState.getSnapshot(transactionId)); + ret = parentShard.createTransaction(transactionId, this, localState.getSnapshot(transactionId)); } while (!STATE_UPDATER.compareAndSet(this, localState, new Allocated(ret))); return ret; @@ -197,4 +200,12 @@ class InMemoryDOMDataTreeShardProducer implements DOMDataTreeShardProducer { public Collection getPrefixes() { return prefixes; } + + ShardDataModificationFactory getModificationFactory() { + return modificationFactory; + } + + void setModificationFactory(final ShardDataModificationFactory modificationFactory) { + this.modificationFactory = Preconditions.checkNotNull(modificationFactory); + } } diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ModificationContextNodeBuilder.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ModificationContextNodeBuilder.java index a98205df02..b35aae1903 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ModificationContextNodeBuilder.java +++ b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ModificationContextNodeBuilder.java @@ -8,16 +8,17 @@ package org.opendaylight.mdsal.dom.store.inmemory; +import com.google.common.base.Preconditions; import java.util.HashMap; import java.util.Map; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; -abstract class ModificationContextNodeBuilder { +abstract class ModificationContextNodeBuilder { private final Map interiorChildren = new HashMap<>(); private final Map boundaryChildren = new HashMap<>(); - protected InteriorNodeBuilder getInterior(final PathArgument arg) { + protected ModificationContextNodeBuilder getInterior(final PathArgument arg) { InteriorNodeBuilder potential = interiorChildren.get(arg); if (potential == null) { potential = new InteriorNodeBuilder(arg); @@ -30,30 +31,25 @@ abstract class ModificationContextNodeBuilder buildChildren() { final Map builtChildren = new HashMap<>(boundaryChildren); for (InteriorNodeBuilder interiorNode : interiorChildren.values()) { WriteableModificationNode builded = interiorNode.build(); builtChildren.put(builded.getIdentifier(), builded); } - return build(builtChildren); + return builtChildren; } - abstract T build(Map children); - - private static class InteriorNodeBuilder extends ModificationContextNodeBuilder { - + private static final class InteriorNodeBuilder extends ModificationContextNodeBuilder { private final PathArgument arg; InteriorNodeBuilder(final PathArgument arg) { - this.arg = arg; + this.arg = Preconditions.checkNotNull(arg); } - @Override - WritableInteriorNode build(final Map children) { - return new WritableInteriorNode(arg, children); + WritableInteriorNode build() { + return new WritableInteriorNode(arg, buildChildren()); } } - } \ No newline at end of file diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModification.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModification.java index 33d596bfec..514cc1133a 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModification.java +++ b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModification.java @@ -13,7 +13,6 @@ import com.google.common.collect.ImmutableMap; import java.util.Map; import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteCursor; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; @@ -45,16 +44,6 @@ final class ShardDataModification extends WriteableNodeWithSubshard { return rootContext.getIdentifier().getRootIdentifier().getLastPathArgument(); } - static ShardDataModification from(final ShardRootModificationContext root, - final Map shards) { - - ShardDataModificationBuilder builder = new ShardDataModificationBuilder(root); - for (ForeignShardModificationContext subshard : shards.values()) { - builder.addSubshard(subshard); - } - return builder.build(); - } - DOMDataTreeIdentifier getPrefix() { return rootContext.getIdentifier(); } diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationBuilder.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationBuilder.java deleted file mode 100644 index 1ea21a02c9..0000000000 --- a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationBuilder.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2016 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.mdsal.dom.store.inmemory; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; - -class ShardDataModificationBuilder extends ModificationContextNodeBuilder { - - private final ShardRootModificationContext root; - private final Map childShards = - new HashMap<>(); - - ShardDataModificationBuilder(final ShardRootModificationContext root) { - this.root = root; - } - - public void addSubshard(final ForeignShardModificationContext value) { - WriteableSubshardBoundaryNode leafNode = WriteableSubshardBoundaryNode.from(value); - putNode(value.getIdentifier().getRootIdentifier(), leafNode); - } - - public void addSubshard(final DOMDataTreeIdentifier prefix, final ForeignShardModificationContext value) { - childShards.put(prefix, value); - } - - private void putNode(final YangInstanceIdentifier key, final WriteableSubshardBoundaryNode subshardNode) { - ModificationContextNodeBuilder current = this; - Iterator toBoundary = toRelative(key).getPathArguments().iterator(); - while (toBoundary.hasNext()) { - PathArgument nextArg = toBoundary.next(); - if (toBoundary.hasNext()) { - current = getInterior(nextArg); - } else { - current.addBoundary(nextArg, subshardNode); - } - } - } - - - @Override - ShardDataModification build(final Map children) { - return new ShardDataModification(root, children, childShards); - } - - private YangInstanceIdentifier toRelative(final YangInstanceIdentifier key) { - return key.relativeTo(root.getIdentifier().getRootIdentifier()).get(); - } -} \ No newline at end of file diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationFactory.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationFactory.java new file mode 100644 index 0000000000..9b1881510f --- /dev/null +++ b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationFactory.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 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.mdsal.dom.store.inmemory; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.tree.CursorAwareDataTreeSnapshot; + +final class ShardDataModificationFactory { + private final Map childShards; + private final Map children; + private final DOMDataTreeIdentifier root; + + ShardDataModificationFactory(final DOMDataTreeIdentifier root, + final Map children, + final Map childShards) { + this.root = Preconditions.checkNotNull(root); + this.children = ImmutableMap.copyOf(children); + this.childShards = ImmutableMap.copyOf(childShards); + } + + @VisibleForTesting + Map getChildren() { + return children; + } + + @VisibleForTesting + Map getChildShards() { + return childShards; + } + + ShardDataModification createModification(final CursorAwareDataTreeSnapshot snapshot) { + return new ShardDataModification(new ShardRootModificationContext(root, snapshot), children, childShards); + } +} diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationFactoryBuilder.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationFactoryBuilder.java new file mode 100644 index 0000000000..5c7541953c --- /dev/null +++ b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationFactoryBuilder.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016 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.mdsal.dom.store.inmemory; + +import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; + +class ShardDataModificationFactoryBuilder extends ModificationContextNodeBuilder + implements Builder { + + private final Map childShards = new HashMap<>(); + private final DOMDataTreeIdentifier root; + + ShardDataModificationFactoryBuilder(final DOMDataTreeIdentifier root) { + this.root = Preconditions.checkNotNull(root); + } + + void addSubshard(final ForeignShardModificationContext value) { + WriteableSubshardBoundaryNode leafNode = WriteableSubshardBoundaryNode.from(value); + putNode(value.getIdentifier().getRootIdentifier(), leafNode); + } + + void addSubshard(final DOMDataTreeIdentifier prefix, final ForeignShardModificationContext value) { + childShards.put(prefix, value); + } + + private void putNode(final YangInstanceIdentifier key, final WriteableSubshardBoundaryNode subshardNode) { + final Iterator toBoundary = toRelative(key).getPathArguments().iterator(); + if (toBoundary.hasNext()) { + ModificationContextNodeBuilder current = this; + while (true) { + final PathArgument nextArg = toBoundary.next(); + if (!toBoundary.hasNext()) { + current.addBoundary(nextArg, subshardNode); + break; + } + + current = getInterior(nextArg); + } + } + } + + @Override + public ShardDataModificationFactory build() { + return new ShardDataModificationFactory(root, buildChildren(), childShards); + } + + private YangInstanceIdentifier toRelative(final YangInstanceIdentifier key) { + return key.relativeTo(root.getRootIdentifier()).get(); + } +} \ No newline at end of file diff --git a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardProducerTest.java b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardProducerTest.java index 0115866eb4..2286082a9f 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardProducerTest.java +++ b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardProducerTest.java @@ -9,16 +9,15 @@ package org.opendaylight.mdsal.dom.store.inmemory; import static org.junit.Assert.assertNotNull; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyCollectionOf; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.opendaylight.mdsal.dom.store.inmemory.TestUtils.DOM_DATA_TREE_IDENTIFIER; import static org.opendaylight.mdsal.dom.store.inmemory.TestUtils.resetMocks; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import org.junit.Test; -import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.tree.CursorAwareDataTreeSnapshot; public class InMemoryDOMDataTreeShardProducerTest { @@ -33,18 +32,19 @@ public class InMemoryDOMDataTreeShardProducerTest { doReturn(inmemoryDOMDataTreeShardWriteTransaction).when(inMemoryDOMDataTreeShard) .createTransaction(any(String.class), any(InMemoryDOMDataTreeShardProducer.class), - anyCollectionOf((DOMDataTreeIdentifier.class)), any(CursorAwareDataTreeSnapshot.class)); + any(CursorAwareDataTreeSnapshot.class)); final InMemoryDOMDataTreeShardProducer inMemoryDOMDataTreeShardProducer = new InMemoryDOMDataTreeShardProducer(inMemoryDOMDataTreeShard, - ImmutableSet.of(DOM_DATA_TREE_IDENTIFIER)); + ImmutableSet.of(DOM_DATA_TREE_IDENTIFIER), + new ShardDataModificationFactory(DOM_DATA_TREE_IDENTIFIER, ImmutableMap.of(), + ImmutableMap.of())); assertNotNull(inMemoryDOMDataTreeShardProducer.createTransaction()); verify(inMemoryDOMDataTreeShard).createTransaction( any(String.class), any(InMemoryDOMDataTreeShardProducer.class), - anyCollectionOf(DOMDataTreeIdentifier.class), any(CursorAwareDataTreeSnapshot.class)); resetMocks(); } -} \ No newline at end of file +} diff --git a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardTest.java b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardTest.java index f9b4d4ee04..72cbf4a6c4 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardTest.java +++ b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InMemoryDOMDataTreeShardTest.java @@ -41,7 +41,7 @@ public class InMemoryDOMDataTreeShardTest { public void basicTest() throws Exception { final InMemoryDOMDataTreeShard inMemoryDOMDataTreeShard = InMemoryDOMDataTreeShard.create(DOM_DATA_TREE_IDENTIFIER, - MoreExecutors.newDirectExecutorService(), 1); + MoreExecutors.directExecutor(), 1); final DOMDataTreeIdentifier domDataTreeIdentifier = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, @@ -60,12 +60,15 @@ public class InMemoryDOMDataTreeShardTest { assertEquals(prefixes.toString(), inMemoryDOMDataTreeShard.createProducer(prefixes).getPrefixes().toString()); final InMemoryDOMDataTreeShardProducer mockProducer = mock(InMemoryDOMDataTreeShardProducer.class); + doReturn(prefixes).when(mockProducer).getPrefixes(); + doReturn(inMemoryDOMDataTreeShard.createModificationFactory(prefixes)) + .when(mockProducer).getModificationFactory(); inMemoryDOMDataTreeShard.onGlobalContextUpdated(createTestContext()); - inMemoryDOMDataTreeShard.createTransaction("", mockProducer, prefixes, mock(CursorAwareDataTreeSnapshot.class)); + inMemoryDOMDataTreeShard.createTransaction("", mockProducer, mock(CursorAwareDataTreeSnapshot.class)); final DOMDataTreeChangeListener domDataTreeChangeListener = mock(DOMDataTreeChangeListener.class); - final ListenerRegistration listenerRegistration = mock(ListenerRegistration.class); + final ListenerRegistration listenerRegistration = mock(ListenerRegistration.class); doReturn(listenerRegistration).when(domDataTreeShard).registerTreeChangeListener(any(), any()); doNothing().when(domDataTreeChangeListener).onDataTreeChanged(any()); inMemoryDOMDataTreeShard.registerTreeChangeListener(YangInstanceIdentifier.EMPTY, domDataTreeChangeListener); @@ -88,10 +91,13 @@ public class InMemoryDOMDataTreeShardTest { final InmemoryDOMDataTreeShardWriteTransaction inmemoryDOMDataTreeShardWriteTransaction = mock(InmemoryDOMDataTreeShardWriteTransaction.class); doReturn(dataTreeModification).when(inmemoryDOMDataTreeShardWriteTransaction).getRootModification(); - final InMemoryDOMDataTreeShardProducer mockProducer = mock(InMemoryDOMDataTreeShardProducer.class); final Collection prefixes = ImmutableList.of(DOM_DATA_TREE_IDENTIFIER); + final InMemoryDOMDataTreeShardProducer mockProducer = mock(InMemoryDOMDataTreeShardProducer.class); + doReturn(prefixes).when(mockProducer).getPrefixes(); + doReturn(inMemoryDOMDataTreeShard.createModificationFactory(prefixes)) + .when(mockProducer).getModificationFactory(); - inMemoryDOMDataTreeShard.createTransaction("", mockProducer, prefixes, mock(CursorAwareDataTreeSnapshot.class)); + inMemoryDOMDataTreeShard.createTransaction("", mockProducer, mock(CursorAwareDataTreeSnapshot.class)); } @After diff --git a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InmemoryDOMDataTreeShardWriteTransactionTest.java b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InmemoryDOMDataTreeShardWriteTransactionTest.java index 9d63ce294f..39f3277212 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InmemoryDOMDataTreeShardWriteTransactionTest.java +++ b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/InmemoryDOMDataTreeShardWriteTransactionTest.java @@ -66,7 +66,7 @@ public class InmemoryDOMDataTreeShardWriteTransactionTest { doReturn("testDataTreeModification").when(dataTreeModification).toString(); doReturn(dataTreeModification).when(SHARD_ROOT_MODIFICATION_CONTEXT).ready(); doReturn(DOM_DATA_TREE_IDENTIFIER).when(SHARD_ROOT_MODIFICATION_CONTEXT).getIdentifier(); - shardDataModification = ShardDataModification.from(SHARD_ROOT_MODIFICATION_CONTEXT, + shardDataModification = TestUtils.createModification(SHARD_ROOT_MODIFICATION_CONTEXT, ImmutableMap.of(YANG_INSTANCE_IDENTIFIER, FOREIGN_SHARD_MODIFICATION_CONTEXT)); final DataTreeModificationCursor dataTreeModificationCursor = mock(DataTreeModificationCursor.class); doReturn(DataTreeModificationCursorAdaptor.of( dataTreeModificationCursor)) diff --git a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ModificationContextNodeBuilderTest.java b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ModificationContextNodeBuilderTest.java index aacbcfb2a3..e2282a410e 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ModificationContextNodeBuilderTest.java +++ b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ModificationContextNodeBuilderTest.java @@ -7,14 +7,11 @@ */ package org.opendaylight.mdsal.dom.store.inmemory; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.opendaylight.mdsal.dom.store.inmemory.TestUtils.DOM_DATA_TREE_IDENTIFIER; import static org.opendaylight.mdsal.dom.store.inmemory.TestUtils.DOM_DATA_TREE_SHARD_PRODUCER; import static org.opendaylight.mdsal.dom.store.inmemory.TestUtils.PATH_ARGUMENT; -import static org.opendaylight.mdsal.dom.store.inmemory.TestUtils.WRITEABLE_MODIFICATION_NODE; -import java.util.Map; import org.junit.Test; public class ModificationContextNodeBuilderTest extends ModificationContextNodeBuilder { @@ -28,11 +25,5 @@ public class ModificationContextNodeBuilderTest extends ModificationContextNodeB super.addBoundary(PATH_ARGUMENT, writeableSubshardBoundaryNode); assertNotNull(super.getInterior(PATH_ARGUMENT)); - assertEquals(WRITEABLE_MODIFICATION_NODE, super.build()); - } - - @Override - WriteableModificationNode build(Map children) { - return WRITEABLE_MODIFICATION_NODE; } } \ No newline at end of file diff --git a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationCursorTest.java b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationCursorTest.java index 380ff29d2a..e64842f139 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationCursorTest.java +++ b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationCursorTest.java @@ -19,6 +19,7 @@ import static org.opendaylight.mdsal.dom.store.inmemory.TestUtils.WRITE_CURSOR_S import static org.opendaylight.mdsal.dom.store.inmemory.TestUtils.resetMocks; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.lang.reflect.Field; import java.util.Deque; import java.util.HashMap; @@ -38,8 +39,9 @@ public class ShardDataModificationCursorTest { final ShardRootModificationContext shardRootModificationContext = mock(ShardRootModificationContext.class); final Map children = new HashMap<>(); children.put(PATH_ARGUMENT, WRITEABLE_MODIFICATION_NODE); - final ShardDataModification root = - new ShardDataModificationBuilder(shardRootModificationContext).build(children); + final ShardDataModification root = new ShardDataModification(shardRootModificationContext, children, + ImmutableMap.of()); + doReturn(dataTreeModificationCursorAdaptor).when(shardRootModificationContext).cursor(); InmemoryDOMDataTreeShardWriteTransaction inmemoryDOMDataTreeShardWriteTransaction = mock(InmemoryDOMDataTreeShardWriteTransaction.class); diff --git a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationTest.java b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationTest.java index ed529a0361..0939bc0454 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationTest.java +++ b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/ShardDataModificationTest.java @@ -43,7 +43,7 @@ public class ShardDataModificationTest { @Before public void setUp() throws Exception { doReturn(DOM_DATA_TREE_IDENTIFIER).when(SHARD_ROOT_MODIFICATION_CONTEXT).getIdentifier(); - shardDataModification = ShardDataModification.from(SHARD_ROOT_MODIFICATION_CONTEXT, + shardDataModification = TestUtils.createModification(SHARD_ROOT_MODIFICATION_CONTEXT, ImmutableMap.of(YangInstanceIdentifier.of(QName.create("test")), FOREIGN_SHARD_MODIFICATION_CONTEXT)); final Map children = diff --git a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/TestUtils.java b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/TestUtils.java index 7f05d7acb7..649c9947df 100644 --- a/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/TestUtils.java +++ b/dom/mdsal-dom-inmemory-datastore/src/test/java/org/opendaylight/mdsal/dom/store/inmemory/TestUtils.java @@ -13,6 +13,7 @@ import static org.mockito.Mockito.reset; import com.google.common.util.concurrent.ListenableFuture; import java.util.Collection; import java.util.HashSet; +import java.util.Map; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteCursor; @@ -67,4 +68,18 @@ final class TestUtils { private TestUtils() throws UnsupportedOperationException { throw new UnsupportedOperationException("Utility class should not be instantiated"); } -} \ No newline at end of file + + static ShardDataModification createModification(final ShardRootModificationContext root, + final Map shards) { + + final ShardDataModificationFactoryBuilder builder = new ShardDataModificationFactoryBuilder( + root.getIdentifier()); + for (ForeignShardModificationContext subshard : shards.values()) { + builder.addSubshard(subshard); + } + + final ShardDataModificationFactory factory = builder.build(); + return new ShardDataModification(root, factory.getChildren(), factory.getChildShards()); + } + +} -- 2.36.6