X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=dom%2Fmdsal-dom-broker%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fdom%2Fbroker%2FShardedDOMDataTreeTest.java;h=6e5a41e7d17f442c6085790657a1a9d38610da7a;hb=dca009bba2d4ceb2e13537f3ac6f9a5f1b05302f;hp=70111ec7d24f579ec9ddf130424aa494e8e3b127;hpb=ee9319dbb6dc9afe7f5f69ac2afd782d9dcfdfe6;p=mdsal.git diff --git a/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/ShardedDOMDataTreeTest.java b/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/ShardedDOMDataTreeTest.java index 70111ec7d2..6e5a41e7d1 100644 --- a/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/ShardedDOMDataTreeTest.java +++ b/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/ShardedDOMDataTreeTest.java @@ -1,3 +1,10 @@ +/* + * 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.broker; import static org.junit.Assert.assertEquals; @@ -11,6 +18,8 @@ import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import com.google.common.util.concurrent.CheckedFuture; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -24,6 +33,7 @@ import org.mockito.Captor; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.TransactionCommitFailedException; import org.opendaylight.mdsal.dom.api.DOMDataTreeCursorAwareTransaction; import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; import org.opendaylight.mdsal.dom.api.DOMDataTreeListener; @@ -32,14 +42,20 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteCursor; import org.opendaylight.mdsal.dom.broker.util.TestModel; import org.opendaylight.mdsal.dom.store.inmemory.InMemoryDOMDataTreeShard; import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; import org.slf4j.Logger; @@ -85,7 +101,7 @@ public class ShardedDOMDataTreeTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - rootShard = InMemoryDOMDataTreeShard.create(ROOT_ID, executor, 1, 1); + rootShard = InMemoryDOMDataTreeShard.create(ROOT_ID, executor, 1); rootShard.onGlobalContextUpdated(schemaContext); final ShardedDOMDataTree dataTree = new ShardedDOMDataTree(); @@ -98,8 +114,42 @@ public class ShardedDOMDataTreeTest { @Test(expected = IllegalArgumentException.class) public void testProducerPathContention() throws Exception { - final DOMDataTreeProducer p1 = dataTreeService.createProducer(Collections.singletonList(ROOT_ID)); - final DOMDataTreeProducer p2 = dataTreeService.createProducer(Collections.singletonList(TEST_ID)); + dataTreeService.createProducer(Collections.singletonList(ROOT_ID)); + dataTreeService.createProducer(Collections.singletonList(TEST_ID)); + } + + @Test + public void testShardRegistrationClose() throws Exception { + rootShardReg.close(); + + final InMemoryDOMDataTreeShard newRootShard = InMemoryDOMDataTreeShard.create(ROOT_ID, executor, 1); + newRootShard.onGlobalContextUpdated(schemaContext); + final DOMDataTreeProducer shardRegProducer = dataTreeService.createProducer(Collections.singletonList(ROOT_ID)); + + final ListenerRegistration newRootShardReg = + dataTreeService.registerDataTreeShard(ROOT_ID, rootShard, shardRegProducer); + shardRegProducer.close(); + + final InMemoryDOMDataTreeShard innerShard = InMemoryDOMDataTreeShard.create(INNER_CONTAINER_ID, executor, 1); + innerShard.onGlobalContextUpdated(schemaContext); + final DOMDataTreeProducer shardRegProducer2 = + dataTreeService.createProducer(Collections.singletonList(INNER_CONTAINER_ID)); + ListenerRegistration innerShardReg = + dataTreeService.registerDataTreeShard(INNER_CONTAINER_ID, innerShard, shardRegProducer2); + + innerShardReg.close(); + // try to register the shard again + innerShardReg = dataTreeService.registerDataTreeShard(INNER_CONTAINER_ID, innerShard, shardRegProducer2); + final DOMDataTreeCursorAwareTransaction tx = shardRegProducer2.createTransaction(false); + final DOMDataTreeWriteCursor cursor = tx.createCursor(INNER_CONTAINER_ID); + assertNotNull(cursor); + + cursor.close(); + tx.cancel(); + shardRegProducer2.close(); + + innerShardReg.close(); + newRootShardReg.close(); } @Test @@ -107,7 +157,8 @@ public class ShardedDOMDataTreeTest { final DOMDataTreeListener mockedDataTreeListener = Mockito.mock(DOMDataTreeListener.class); doNothing().when(mockedDataTreeListener).onDataTreeChanged(anyCollection(), anyMap()); - dataTreeService.registerListener(mockedDataTreeListener, Collections.singletonList(INNER_CONTAINER_ID), true, Collections.emptyList()); + dataTreeService.registerListener(mockedDataTreeListener, Collections.singletonList(INNER_CONTAINER_ID), + true, Collections.emptyList()); final DOMDataTreeProducer producer = dataTreeService.createProducer(Collections.singletonList(ROOT_ID)); DOMDataTreeCursorAwareTransaction tx = producer.createTransaction(false); @@ -134,17 +185,83 @@ public class ShardedDOMDataTreeTest { cursor.close(); tx.submit().checkedGet(); - verify(mockedDataTreeListener, timeout(1000).times(2)).onDataTreeChanged(captorForChanges.capture(), captorForSubtrees.capture()); + verify(mockedDataTreeListener, timeout(1000).times(3)).onDataTreeChanged(captorForChanges.capture(), + captorForSubtrees.capture()); final List> capturedValue = captorForChanges.getAllValues(); - assertTrue(capturedValue.size() == 2); + assertTrue(capturedValue.size() == 3); - final ContainerNode capturedChange = (ContainerNode) capturedValue.get(0).iterator().next().getRootNode().getDataAfter().get(); - final ContainerNode innerContainerVerify = (ContainerNode) crossShardContainer.getChild(TestModel.INNER_CONTAINER_PATH.getLastPathArgument()).get(); + final ContainerNode capturedChange = + (ContainerNode) capturedValue.get(1).iterator().next().getRootNode().getDataAfter().get(); + final ContainerNode innerContainerVerify = (ContainerNode) crossShardContainer.getChild( + TestModel.INNER_CONTAINER_PATH.getLastPathArgument()).get(); assertEquals(innerContainerVerify, capturedChange); verifyNoMoreInteractions(mockedDataTreeListener); } + @Test + public void testMultipleWritesIntoSingleMapEntry() throws Exception { + + final YangInstanceIdentifier oid1 = TestModel.OUTER_LIST_PATH.node(new NodeIdentifierWithPredicates( + TestModel.OUTER_LIST_QNAME, QName.create(TestModel.OUTER_LIST_QNAME, "id"), 0)); + final DOMDataTreeIdentifier outerListPath = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, oid1); + + final DOMDataTreeProducer shardProducer = dataTreeService.createProducer( + Collections.singletonList(outerListPath)); + final InMemoryDOMDataTreeShard outerListShard = InMemoryDOMDataTreeShard.create(outerListPath, executor, 1000); + outerListShard.onGlobalContextUpdated(schemaContext); + + final ListenerRegistration oid1ShardRegistration = + dataTreeService.registerDataTreeShard(outerListPath, outerListShard, shardProducer); + + final DOMDataTreeCursorAwareTransaction tx = shardProducer.createTransaction(false); + final DOMDataTreeWriteCursor cursor = + tx.createCursor(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, oid1)); + assertNotNull(cursor); + + MapNode innerList = ImmutableMapNodeBuilder + .create() + .withNodeIdentifier(new NodeIdentifier(TestModel.INNER_LIST_QNAME)) + .build(); + + cursor.write(new NodeIdentifier(TestModel.INNER_LIST_QNAME), innerList); + cursor.close(); + tx.submit().checkedGet(); + + final ArrayList> futures = new ArrayList<>(); + for (int i = 0; i < 1000; i++) { + final Collection innerListMapEntries = createInnerListMapEntries(1000, "run-" + i); + for (final MapEntryNode innerListMapEntry : innerListMapEntries) { + final DOMDataTreeCursorAwareTransaction tx1 = shardProducer.createTransaction(false); + final DOMDataTreeWriteCursor cursor1 = tx1.createCursor( + new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, + oid1.node(new NodeIdentifier(TestModel.INNER_LIST_QNAME)))); + cursor1.write(innerListMapEntry.getIdentifier(), innerListMapEntry); + cursor1.close(); + futures.add(tx1.submit()); + } + } + + futures.get(futures.size() - 1).checkedGet(); + + } + + private Collection createInnerListMapEntries(int amount, String valuePrefix) { + final Collection ret = new ArrayList<>(); + for (int i = 0; i < amount; i++) { + ret.add(ImmutableNodes.mapEntryBuilder() + .withNodeIdentifier(new NodeIdentifierWithPredicates(TestModel.INNER_LIST_QNAME, + QName.create(TestModel.OUTER_LIST_QNAME, "name"), Integer.toString(i))) + .withChild(ImmutableNodes + .leafNode(QName.create(TestModel.INNER_LIST_QNAME, "name"), Integer.toString(i))) + .withChild(ImmutableNodes + .leafNode(QName.create(TestModel.INNER_LIST_QNAME, "value"), valuePrefix + "-" + i)) + .build()); + } + + return ret; + } + @Test public void testMultipleProducerCursorCreation() throws Exception { @@ -164,7 +281,8 @@ public class ShardedDOMDataTreeTest { assertTrue(rootTx.cancel()); - final DOMDataTreeProducer innerContainerProducer = rootProducer.createProducer(Collections.singletonList(INNER_CONTAINER_ID)); + final DOMDataTreeProducer innerContainerProducer = rootProducer.createProducer( + Collections.singletonList(INNER_CONTAINER_ID)); rootTx = rootProducer.createTransaction(false); try { @@ -200,9 +318,11 @@ public class ShardedDOMDataTreeTest { private ContainerNode createCrossShardContainer() { final LeafNode shardedValue1 = - ImmutableLeafNodeBuilder.create().withNodeIdentifier(new NodeIdentifier(TestModel.SHARDED_VALUE_1)).withValue("sharded value 1").build(); + ImmutableLeafNodeBuilder.create().withNodeIdentifier(new NodeIdentifier( + TestModel.SHARDED_VALUE_1)).withValue("sharded value 1").build(); final LeafNode shardedValue2 = - ImmutableLeafNodeBuilder.create().withNodeIdentifier(new NodeIdentifier(TestModel.SHARDED_VALUE_2)).withValue("sharded value 2").build(); + ImmutableLeafNodeBuilder.create().withNodeIdentifier(new NodeIdentifier( + TestModel.SHARDED_VALUE_2)).withValue("sharded value 2").build(); final ContainerNode lowerShardContainer = ImmutableContainerNodeBuilder.create()