From 98f72d6e38e62500bbad181acf522511d384565c Mon Sep 17 00:00:00 2001 From: Moiz Raja Date: Wed, 9 Jul 2014 20:18:14 -0700 Subject: [PATCH] Modify the FindPrimary implementation so that it works correctly with a configuration Change-Id: Ie41b688adf54de06332bbe5add7aba8107eb4264 Signed-off-by: Moiz Raja --- .../cluster/datastore/Configuration.java | 1 + .../cluster/datastore/ConfigurationImpl.java | 12 ++++ .../cluster/datastore/ShardManager.java | 51 ++++++++++++--- .../DistributedDataStoreIntegrationTest.java | 64 ++++++++++++++++++- .../datastore/utils/MockConfiguration.java | 6 ++ .../cluster/datastore/model/PeopleModel.java | 5 +- 6 files changed, 127 insertions(+), 12 deletions(-) diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Configuration.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Configuration.java index 1c3a82a790..a67f58c760 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Configuration.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Configuration.java @@ -19,4 +19,5 @@ public interface Configuration { Optional getModuleNameFromNameSpace(String nameSpace); Map getModuleNameToShardStrategyMap(); List getShardNamesFromModuleName(String moduleName); + List getMembersFromShardName(String shardName); } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ConfigurationImpl.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ConfigurationImpl.java index 1b8bf3e160..9a9ac2c725 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ConfigurationImpl.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ConfigurationImpl.java @@ -85,6 +85,18 @@ public class ConfigurationImpl implements Configuration { return Collections.EMPTY_LIST; } + @Override public List getMembersFromShardName(String shardName) { + List shards = new ArrayList(); + for(ModuleShard ms : moduleShards){ + for(Shard s : ms.getShards()) { + if(s.getName().equals(shardName)){ + return s.getReplicas(); + } + } + } + return Collections.EMPTY_LIST; + } + private void readModules(Config modulesConfig) { diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java index 8fd13bd45a..3e0c97f6af 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java @@ -67,22 +67,28 @@ public class ShardManager extends AbstractUntypedActor { private final Map localShards = new HashMap<>(); + private final String type; + private final ClusterWrapper cluster; + private final Configuration configuration; + /** * @param type defines the kind of data that goes into shards created by this shard manager. Examples of type would be * configuration or operational */ private ShardManager(String type, ClusterWrapper cluster, Configuration configuration) { + this.type = type; this.cluster = cluster; + this.configuration = configuration; String memberName = cluster.getCurrentMemberName(); List memberShardNames = configuration.getMemberShardNames(memberName); for(String shardName : memberShardNames){ + String shardActorName = getShardActorName(memberName, shardName); ActorRef actor = getContext() - .actorOf(Shard.props(memberName + "-shard-" + shardName + "-" + type), - memberName + "-shard-" + shardName + "-" + type); + .actorOf(Shard.props(shardActorName), shardActorName); ActorPath path = actor.path(); localShards.put(shardName, path); } @@ -106,16 +112,37 @@ public class ShardManager extends AbstractUntypedActor { FindPrimary msg = ((FindPrimary) message); String shardName = msg.getShardName(); - if (Shard.DEFAULT_NAME.equals(shardName)) { - ActorPath defaultShardPath = localShards.get(shardName); - if(defaultShardPath == null){ - throw new IllegalStateException("local default shard not found"); + List members = + configuration.getMembersFromShardName(shardName); + + for(String memberName : members) { + if (memberName.equals(cluster.getCurrentMemberName())) { + // This is a local shard + ActorPath shardPath = localShards.get(shardName); + // FIXME: This check may be redundant + if (shardPath == null) { + getSender() + .tell(new PrimaryNotFound(shardName), getSelf()); + return; + } + getSender().tell(new PrimaryFound(shardPath.toString()), + getSelf()); + return; + } else { + Address address = memberNameToAddress.get(shardName); + if(address != null){ + String path = + address.toString() + "/user/" + getShardActorName( + memberName, shardName); + getSender().tell(new PrimaryFound(path), getSelf()); + } + + } - getSender().tell(new PrimaryFound(defaultShardPath.toString()), - getSelf()); - } else { - getSender().tell(new PrimaryNotFound(shardName), getSelf()); } + + getSender().tell(new PrimaryNotFound(shardName), getSelf()); + } else if (message instanceof UpdateSchemaContext) { for(ActorPath path : localShards.values()){ getContext().system().actorSelection(path) @@ -125,5 +152,9 @@ public class ShardManager extends AbstractUntypedActor { } } + private String getShardActorName(String memberName, String shardName){ + return memberName + "-shard-" + shardName + "-" + this.type; + } + } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java index 6a25328a4d..116e5e75b5 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java @@ -1,21 +1,48 @@ package org.opendaylight.controller.cluster.datastore; +import akka.actor.ActorSystem; +import akka.testkit.JavaTestKit; import com.google.common.base.Optional; import com.google.common.util.concurrent.ListenableFuture; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory; import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper; import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration; +import org.opendaylight.controller.md.cluster.datastore.model.CarsModel; +import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel; +import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper; import org.opendaylight.controller.md.cluster.datastore.model.TestModel; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction; import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import java.util.concurrent.ExecutionException; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; -public class DistributedDataStoreIntegrationTest extends AbstractActorTest { +public class DistributedDataStoreIntegrationTest{ + + private static ActorSystem system; + + @Before + public void setUp() { + System.setProperty("shard.persistent", "false"); + system = ActorSystem.create("test"); + } + + @After + public void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + protected ActorSystem getSystem() { + return system; + } @Test public void integrationTest() throws Exception { @@ -55,4 +82,39 @@ public class DistributedDataStoreIntegrationTest extends AbstractActorTest { } + + @Test + public void integrationTestWithMultiShardConfiguration() + throws ExecutionException, InterruptedException { + Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf"); + + ShardStrategyFactory.setConfiguration(configuration); + DistributedDataStore distributedDataStore = + new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration); + + + distributedDataStore.onGlobalContextUpdated(SchemaContextHelper.full()); + + DOMStoreReadWriteTransaction transaction = + distributedDataStore.newReadWriteTransaction(); + + transaction.write(CarsModel.BASE_PATH, CarsModel.emptyContainer()); + transaction.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer()); + + DOMStoreThreePhaseCommitCohort ready = transaction.ready(); + + ListenableFuture canCommit = ready.canCommit(); + + assertTrue(canCommit.get()); + + ListenableFuture preCommit = ready.preCommit(); + + preCommit.get(); + + ListenableFuture commit = ready.commit(); + + commit.get(); + + } + } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MockConfiguration.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MockConfiguration.java index 470726e56a..2597dda04c 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MockConfiguration.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MockConfiguration.java @@ -38,4 +38,10 @@ public class MockConfiguration implements Configuration{ String moduleName) { return Collections.EMPTY_LIST; } + + @Override public List getMembersFromShardName(String shardName) { + List shardNames = new ArrayList<>(); + shardNames.add("member-1"); + return shardNames; + } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java index 9ccb054623..14b02a222a 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java @@ -22,12 +22,14 @@ public class PeopleModel { public static final QName BASE_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:people", "2014-03-13", "people"); + public static final InstanceIdentifier BASE_PATH = InstanceIdentifier.of(BASE_QNAME); public static final QName PEOPLE_QNAME = QName.create(BASE_QNAME, "people"); public static final QName PERSON_QNAME = QName.create(PEOPLE_QNAME, "person"); public static final QName PERSON_NAME_QNAME = QName.create(PERSON_QNAME, "name"); public static final QName PERSON_AGE_QNAME = QName.create(PERSON_QNAME, "age"); + public static NormalizedNode create(){ // Create a list builder @@ -62,7 +64,8 @@ public class PeopleModel { public static NormalizedNode emptyContainer(){ return ImmutableContainerNodeBuilder.create() - .withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(BASE_QNAME)) + .withNodeIdentifier( + new InstanceIdentifier.NodeIdentifier(BASE_QNAME)) .build(); } -- 2.36.6