From: Moiz Raja Date: Fri, 13 Jun 2014 23:11:18 +0000 (-0700) Subject: Introducing ShardManager X-Git-Tag: release/helium~638^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=63ef05ffdad1413ffb6882db9b662435390e1015 Introducing ShardManager Change-Id: I6bf6955ece55d1a1bdcc150a3fec77f8aff22d6e Signed-off-by: Moiz Raja --- diff --git a/opendaylight/md-sal/sal-distributed-datastore/pom.xml b/opendaylight/md-sal/sal-distributed-datastore/pom.xml index e7fcd83328..62647bdf89 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/pom.xml +++ b/opendaylight/md-sal/sal-distributed-datastore/pom.xml @@ -92,7 +92,6 @@ org.osgi.core - org.scala-lang scala-library @@ -109,6 +108,13 @@ mockito-all test + + + com.typesafe.akka + akka-testkit_2.11 + 2.3.2 + + org.slf4j slf4j-simple 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 new file mode 100644 index 0000000000..f5e46852e3 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java @@ -0,0 +1,53 @@ +package org.opendaylight.controller.cluster.datastore; + +import akka.actor.Address; +import akka.actor.UntypedActor; +import akka.event.Logging; +import akka.event.LoggingAdapter; +import org.opendaylight.controller.cluster.datastore.messages.FindPrimary; +import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * The ShardManager has the following jobs, + * + * - Create all the local shard replicas that belong on this cluster member + * - Find the primary replica for any given shard + * - Engage in shard replica elections which decide which replica should be the primary + * + * Creation of Shard replicas + * ========================== + * When the ShardManager is constructed it reads the cluster configuration to find out which shard replicas + * belong on this member. It finds out the name of the current cluster member from the Akka Clustering Service. + * + * Replica Elections + * ================= + * The Shard Manager uses multiple cues to initiate election. + * - When a member of the cluster dies + * - When a local shard replica dies + * - When a local shard replica comes alive + */ +public class ShardManager extends UntypedActor { + + // Stores a mapping between a shard name and the address of the current primary + private final Map shardNameToPrimaryAddress = new HashMap<>(); + + // Stores a mapping between a member name and the address of the member + private final Map memberNameToAddress = new HashMap<>(); + + // Stores a mapping between the shard name and all the members on which a replica of that shard are available + private final Map> shardNameToMembers = new HashMap<>(); + + LoggingAdapter log = Logging.getLogger(getContext().system(), this); + + @Override + public void onReceive(Object message) throws Exception { + if(message instanceof FindPrimary ){ + FindPrimary msg = ((FindPrimary) message); + getSender().tell(new PrimaryNotFound(msg.getShardName()), getSelf()); + } + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimary.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimary.java new file mode 100644 index 0000000000..0920c284ad --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimary.java @@ -0,0 +1,23 @@ +package org.opendaylight.controller.cluster.datastore.messages; + +import com.google.common.base.Preconditions; + +/** + * The FindPrimary message is used to locate the primary of any given shard + * + * TODO : Make this serializable + */ +public class FindPrimary{ + private final String shardName; + + public FindPrimary(String shardName){ + + Preconditions.checkNotNull(shardName, "shardName should not be null"); + + this.shardName = shardName; + } + + public String getShardName() { + return shardName; + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryFound.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryFound.java new file mode 100644 index 0000000000..1326898b0f --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryFound.java @@ -0,0 +1,12 @@ +/* + * 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.cluster.datastore.messages; + +public class PrimaryFound { +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryNotFound.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryNotFound.java new file mode 100644 index 0000000000..c66e12cb39 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryNotFound.java @@ -0,0 +1,40 @@ +/* + * 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.cluster.datastore.messages; + +import com.google.common.base.Preconditions; + +public class PrimaryNotFound { + + private final String shardName; + + public PrimaryNotFound(String shardName){ + + Preconditions.checkNotNull(shardName, "shardName should not be null"); + + this.shardName = shardName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PrimaryNotFound that = (PrimaryNotFound) o; + + if (shardName != null ? !shardName.equals(that.shardName) : that.shardName != null) return false; + + return true; + } + + @Override + public int hashCode() { + return shardName != null ? shardName.hashCode() : 0; + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardManagerTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardManagerTest.java new file mode 100644 index 0000000000..9c1ea70fdb --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardManagerTest.java @@ -0,0 +1,52 @@ +package org.opendaylight.controller.cluster.datastore; + +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.testkit.JavaTestKit; +import akka.testkit.TestActorRef; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.cluster.datastore.messages.FindPrimary; +import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound; +import scala.concurrent.duration.Duration; + +public class ShardManagerTest { + private static ActorSystem system; + + @BeforeClass + public static void setUp(){ + system = ActorSystem.create("test"); + } + + @AfterClass + public static void tearDown(){ + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + @Test + public void testOnReceiveFindPrimary() throws Exception { + + new JavaTestKit(system) {{ + final Props props = Props.create(ShardManager.class); + final TestActorRef subject = TestActorRef.create(system, props, "test"); + + // can also use JavaTestKit “from the outside” + final JavaTestKit probe = new JavaTestKit(system); + + // the run() method needs to finish within 3 seconds + new Within(duration("3 seconds")) { + protected void run() { + + subject.tell(new FindPrimary("inventory"), getRef()); + + expectMsgEquals(Duration.Zero(), new PrimaryNotFound("inventory")); + + // Will wait for the rest of the 3 seconds + expectNoMsg(); + } + }; + }}; + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimaryTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimaryTest.java new file mode 100644 index 0000000000..7e4ec10501 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimaryTest.java @@ -0,0 +1,21 @@ +package org.opendaylight.controller.cluster.datastore.messages; + +import org.junit.Test; + +public class FindPrimaryTest { + + @Test + public void testNewBuilderForType() throws Exception { + + } + + @Test + public void testToBuilder() throws Exception { + + } + + @Test + public void testGetDefaultInstanceForType() throws Exception { + + } +} \ No newline at end of file