import com.typesafe.config.ConfigFactory;
import java.net.URI;
import java.util.AbstractMap;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
-import org.apache.commons.lang3.SerializationUtils;
-import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
import org.opendaylight.controller.cluster.access.concepts.MemberName;
-import org.opendaylight.controller.cluster.datastore.AbstractActorTest;
+import org.opendaylight.controller.cluster.datastore.AbstractShardManagerTest;
import org.opendaylight.controller.cluster.datastore.ClusterWrapperImpl;
import org.opendaylight.controller.cluster.datastore.DataStoreVersions;
import org.opendaylight.controller.cluster.datastore.DatastoreContext;
import org.opendaylight.controller.cluster.datastore.DatastoreContextFactory;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStore;
import org.opendaylight.controller.cluster.datastore.Shard;
import org.opendaylight.controller.cluster.datastore.ShardManager.SchemaContextModules;
-import org.opendaylight.controller.cluster.datastore.config.Configuration;
import org.opendaylight.controller.cluster.datastore.config.ConfigurationImpl;
import org.opendaylight.controller.cluster.datastore.config.EmptyModuleShardConfigProvider;
import org.opendaylight.controller.cluster.datastore.config.ModuleShardConfiguration;
import org.opendaylight.controller.cluster.datastore.messages.AddShardReplica;
import org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus;
import org.opendaylight.controller.cluster.datastore.messages.CreateShard;
-import org.opendaylight.controller.cluster.datastore.messages.DatastoreSnapshot;
-import org.opendaylight.controller.cluster.datastore.messages.DatastoreSnapshot.ShardSnapshot;
import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard;
import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
import org.opendaylight.controller.cluster.datastore.messages.LocalPrimaryShardFound;
import org.opendaylight.controller.cluster.datastore.messages.RemoveShardReplica;
import org.opendaylight.controller.cluster.datastore.messages.ShardLeaderStateChanged;
import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+import org.opendaylight.controller.cluster.datastore.persisted.DatastoreSnapshot;
+import org.opendaylight.controller.cluster.datastore.persisted.DatastoreSnapshot.ShardSnapshot;
+import org.opendaylight.controller.cluster.datastore.persisted.ShardManagerSnapshot;
import org.opendaylight.controller.cluster.datastore.utils.ForwardingActor;
import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper;
import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration;
import org.opendaylight.controller.cluster.notifications.RegisterRoleChangeListener;
import org.opendaylight.controller.cluster.notifications.RoleChangeNotification;
import org.opendaylight.controller.cluster.raft.RaftState;
-import org.opendaylight.controller.cluster.raft.TestActorFactory;
import org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus;
import org.opendaylight.controller.cluster.raft.base.messages.SwitchBehavior;
import org.opendaylight.controller.cluster.raft.client.messages.GetSnapshot;
import scala.concurrent.Future;
import scala.concurrent.duration.FiniteDuration;
-public class ShardManagerTest extends AbstractActorTest {
+public class ShardManagerTest extends AbstractShardManagerTest {
private static final Logger LOG = LoggerFactory.getLogger(ShardManagerTest.class);
- private static final MemberName MEMBER_1 = MemberName.forName("member-1");
private static final MemberName MEMBER_2 = MemberName.forName("member-2");
private static final MemberName MEMBER_3 = MemberName.forName("member-3");
- private static int ID_COUNTER = 1;
-
- private final String shardMrgIDSuffix = "config" + ID_COUNTER++;
private final String shardMgrID = ShardManagerIdentifier.builder().type(shardMrgIDSuffix).build().toString();
- @Mock
- private static CountDownLatch ready;
-
- private static ShardIdentifier mockShardName = ShardIdentifier.create(Shard.DEFAULT_NAME, MEMBER_1, "config");
-
- private static TestActorRef<MessageCollectorActor> mockShardActor = TestActorRef.create(getSystem(),
- Props.create(MessageCollectorActor.class), mockShardName.toString());
-
- private final DatastoreContext.Builder datastoreContextBuilder = DatastoreContext.newBuilder()
- .dataStoreName(shardMrgIDSuffix).shardInitializationTimeout(600, TimeUnit.MILLISECONDS)
- .shardHeartbeatIntervalInMillis(100).shardElectionTimeoutFactor(6);
-
- private final Collection<ActorSystem> actorSystems = new ArrayList<>();
-
- private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- InMemoryJournal.clear();
- InMemorySnapshotStore.clear();
-
- mockShardActor.underlyingActor().clear();
- }
-
- @After
- public void tearDown() {
- InMemoryJournal.clear();
- InMemorySnapshotStore.clear();
-
- for (ActorSystem system: actorSystems) {
- JavaTestKit.shutdownActorSystem(system, null, Boolean.TRUE);
- }
-
- actorFactory.close();
- }
-
private ActorSystem newActorSystem(String config) {
ActorSystem system = ActorSystem.create("cluster-test", ConfigFactory.load().getConfig(config));
actorSystems.add(system);
return newShardMgrProps(new MockConfiguration());
}
- private Props newShardMgrProps(Configuration config) {
- return newTestShardMgrBuilder(config).props();
- }
-
private static DatastoreContextFactory newDatastoreContextFactory(DatastoreContext datastoreContext) {
DatastoreContextFactory mockFactory = mock(DatastoreContextFactory.class);
Mockito.doReturn(datastoreContext).when(mockFactory).getBaseDatastoreContext();
return mockFactory;
}
- private TestShardManager.Builder newTestShardMgrBuilder() {
- return TestShardManager.builder(datastoreContextBuilder);
- }
-
- private TestShardManager.Builder newTestShardMgrBuilder(Configuration config) {
- return TestShardManager.builder(datastoreContextBuilder).configuration(config);
- }
-
private TestShardManager.Builder newTestShardMgrBuilderWithMockShardActor() {
return newTestShardMgrBuilderWithMockShardActor(mockShardActor);
}
private TestShardManager.Builder newTestShardMgrBuilderWithMockShardActor(ActorRef shardActor) {
- return TestShardManager.builder(datastoreContextBuilder).shardActor(shardActor);
+ return TestShardManager.builder(datastoreContextBuilder).shardActor(shardActor)
+ .distributedDataStore(mock(DistributedDataStore.class));
}
// Create an ActorSystem ShardManager actor for member-1.
final ActorSystem system1 = newActorSystem("Member1");
- Cluster.get(system1).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system1).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
final TestActorRef<TestShardManager> shardManager1 = TestActorRef.create(system1,
newTestShardMgrBuilderWithMockShardActor().cluster(
final ActorSystem system2 = newActorSystem("Member2");
- Cluster.get(system2).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system2).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
final ActorRef mockShardActor2 = newMockShardActor(system2, "astronauts", "member-2");
shardManager2.underlyingActor().verifyFindPrimary();
- Cluster.get(system2).down(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system2).down(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
shardManager1.underlyingActor().waitForMemberRemoved();
// Create an ActorSystem ShardManager actor for member-1.
final ActorSystem system1 = newActorSystem("Member1");
- Cluster.get(system1).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system1).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
final ActorRef mockShardActor1 = newMockShardActor(system1, Shard.DEFAULT_NAME, "member-1");
final ActorSystem system2 = newActorSystem("Member2");
- Cluster.get(system2).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system2).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
final ActorRef mockShardActor2 = newMockShardActor(system2, Shard.DEFAULT_NAME, "member-2");
assertTrue("Unexpected primary path " + path, path.contains("member-2-shard-default-config"));
shardManager1.tell(MockClusterWrapper.createUnreachableMember("member-2",
- "akka.tcp://cluster-test@127.0.0.1:2558"), getRef());
+ "akka://cluster-test@127.0.0.1:2558"), getRef());
shardManager1.underlyingActor().waitForUnreachableMember();
MessageCollectorActor.clearMessages(mockShardActor1);
shardManager1.tell(
- MockClusterWrapper.createMemberRemoved("member-2", "akka.tcp://cluster-test@127.0.0.1:2558"),
+ MockClusterWrapper.createMemberRemoved("member-2", "akka://cluster-test@127.0.0.1:2558"),
getRef());
MessageCollectorActor.expectFirstMatching(mockShardActor1, PeerDown.class);
expectMsgClass(duration("5 seconds"), NoShardLeaderException.class);
shardManager1.tell(
- MockClusterWrapper.createReachableMember("member-2", "akka.tcp://cluster-test@127.0.0.1:2558"),
+ MockClusterWrapper.createReachableMember("member-2", "akka://cluster-test@127.0.0.1:2558"),
getRef());
shardManager1.underlyingActor().waitForReachableMember();
assertTrue("Unexpected primary path " + path1, path1.contains("member-2-shard-default-config"));
shardManager1.tell(
- MockClusterWrapper.createMemberUp("member-2", "akka.tcp://cluster-test@127.0.0.1:2558"),
+ MockClusterWrapper.createMemberUp("member-2", "akka://cluster-test@127.0.0.1:2558"),
getRef());
MessageCollectorActor.expectFirstMatching(mockShardActor1, PeerUp.class);
// Test FindPrimary wait succeeds after reachable member event.
shardManager1.tell(MockClusterWrapper.createUnreachableMember("member-2",
- "akka.tcp://cluster-test@127.0.0.1:2558"), getRef());
+ "akka://cluster-test@127.0.0.1:2558"), getRef());
shardManager1.underlyingActor().waitForUnreachableMember();
shardManager1.tell(new FindPrimary("default", true), getRef());
shardManager1.tell(
- MockClusterWrapper.createReachableMember("member-2", "akka.tcp://cluster-test@127.0.0.1:2558"),
+ MockClusterWrapper.createReachableMember("member-2", "akka://cluster-test@127.0.0.1:2558"),
getRef());
RemotePrimaryShardFound found2 = expectMsgClass(duration("5 seconds"), RemotePrimaryShardFound.class);
// Create an ActorSystem ShardManager actor for member-1.
final ActorSystem system1 = newActorSystem("Member1");
- Cluster.get(system1).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system1).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
final ActorRef mockShardActor1 = newMockShardActor(system1, Shard.DEFAULT_NAME, "member-1");
final ActorSystem system2 = newActorSystem("Member2");
- Cluster.get(system2).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system2).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
final ActorRef mockShardActor2 = newMockShardActor(system2, Shard.DEFAULT_NAME, "member-2");
system1.actorSelection(mockShardActor1.path()), DataStoreVersions.CURRENT_VERSION));
shardManager1.tell(MockClusterWrapper.createUnreachableMember("member-2",
- "akka.tcp://cluster-test@127.0.0.1:2558"), getRef());
+ "akka://cluster-test@127.0.0.1:2558"), getRef());
shardManager1.underlyingActor().waitForUnreachableMember();
assertEquals("Shard names", Sets.newHashSet("shard1", "shard2", "astronauts"), Sets.newHashSet(
Lists.transform(datastoreSnapshot.getShardSnapshots(), shardNameTransformer)));
- byte[] snapshotBytes = datastoreSnapshot.getShardManagerSnapshot();
- assertNotNull("Expected ShardManagerSnapshot", snapshotBytes);
- ShardManagerSnapshot snapshot = SerializationUtils.deserialize(snapshotBytes);
+ ShardManagerSnapshot snapshot = datastoreSnapshot.getShardManagerSnapshot();
+ assertNotNull("Expected ShardManagerSnapshot", snapshot);
assertEquals("Shard names", Sets.newHashSet("shard1", "shard2", "astronauts"),
Sets.newHashSet(snapshot.getShardList()));
.put("shard1", Collections.<String>emptyList()).put("shard2", Collections.<String>emptyList())
.put("astronauts", Collections.<String>emptyList()).build());
- ShardManagerSnapshot snapshot = new ShardManagerSnapshot(Arrays.asList("shard1", "shard2", "astronauts"));
- DatastoreSnapshot restoreFromSnapshot = new DatastoreSnapshot(shardMrgIDSuffix,
- SerializationUtils.serialize(snapshot), Collections.<ShardSnapshot>emptyList());
+ ShardManagerSnapshot snapshot =
+ new ShardManagerSnapshot(Arrays.asList("shard1", "shard2", "astronauts"), Collections.emptyMap());
+ DatastoreSnapshot restoreFromSnapshot = new DatastoreSnapshot(shardMrgIDSuffix, snapshot,
+ Collections.<ShardSnapshot>emptyList());
TestActorRef<TestShardManager> shardManager = actorFactory.createTestActor(newTestShardMgrBuilder(mockConfig)
.restoreFromSnapshot(restoreFromSnapshot).props().withDispatcher(Dispatchers.DefaultDispatcherId()));
assertEquals("getType", shardMrgIDSuffix, datastoreSnapshot.getType());
- byte[] snapshotBytes = datastoreSnapshot.getShardManagerSnapshot();
- assertNotNull("Expected ShardManagerSnapshot", snapshotBytes);
- snapshot = SerializationUtils.deserialize(snapshotBytes);
+ assertNotNull("Expected ShardManagerSnapshot", datastoreSnapshot.getShardManagerSnapshot());
assertEquals("Shard names", Sets.newHashSet("shard1", "shard2", "astronauts"),
- Sets.newHashSet(snapshot.getShardList()));
+ Sets.newHashSet(datastoreSnapshot.getShardManagerSnapshot().getShardList()));
LOG.info("testRestoreFromSnapshot ending");
}
// Create an ActorSystem ShardManager actor for member-1.
final ActorSystem system1 = newActorSystem("Member1");
- Cluster.get(system1).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system1).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
ActorRef mockDefaultShardActor = newMockShardActor(system1, Shard.DEFAULT_NAME, "member-1");
final TestActorRef<TestShardManager> newReplicaShardManager = TestActorRef.create(system1,
newTestShardMgrBuilder(mockConfig).shardActor(mockDefaultShardActor)
// Create an ActorSystem ShardManager actor for member-2.
final ActorSystem system2 = newActorSystem("Member2");
- Cluster.get(system2).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system2).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
String memberId2 = "member-2-shard-astronauts-" + shardMrgIDSuffix;
String name = ShardIdentifier.create("astronauts", MEMBER_2, "config").toString();
// Have a dummy snapshot to be overwritten by the new data
// persisted.
String[] restoredShards = { "default", "people" };
- ShardManagerSnapshot snapshot = new ShardManagerSnapshot(Arrays.asList(restoredShards));
+ ShardManagerSnapshot snapshot =
+ new ShardManagerSnapshot(Arrays.asList(restoredShards), Collections.emptyMap());
InMemorySnapshotStore.addSnapshot(shardManagerID, snapshot);
Uninterruptibles.sleepUninterruptibly(2, TimeUnit.MILLISECONDS);
newReplicaShardManager.tell(new UpdateSchemaContext(TestModel.createTestContext()), getRef());
MockClusterWrapper.sendMemberUp(newReplicaShardManager, "member-2",
- AddressFromURIString.parse("akka.tcp://non-existent@127.0.0.1:5").toString());
+ AddressFromURIString.parse("akka://non-existent@127.0.0.1:5").toString());
newReplicaShardManager.tell(new AddShardReplica("astronauts"), getRef());
Status.Failure resp = expectMsgClass(duration("5 seconds"), Status.Failure.class);
// Create an ActorSystem ShardManager actor for member-1.
final ActorSystem system1 = newActorSystem("Member1");
- Cluster.get(system1).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system1).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
ActorRef mockDefaultShardActor = newMockShardActor(system1, Shard.DEFAULT_NAME, "member-1");
final TestActorRef<TestShardManager> newReplicaShardManager = TestActorRef.create(system1,
// Create an ActorSystem ShardManager actor for member-2.
final ActorSystem system2 = newActorSystem("Member2");
- Cluster.get(system2).join(AddressFromURIString.parse("akka.tcp://cluster-test@127.0.0.1:2558"));
+ Cluster.get(system2).join(AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558"));
String name = ShardIdentifier.create("default", MEMBER_2, shardMrgIDSuffix).toString();
String memberId2 = "member-2-shard-default-" + shardMrgIDSuffix;
shardManagerID);
// Because mockShardLeaderActor is created at the top level of the actor system it has an address like so,
- // akka.tcp://cluster-test@127.0.0.1:2559/user/member-2-shard-default-config1
+ // akka://cluster-test@127.0.0.1:2559/user/member-2-shard-default-config1
// However when a shard manager has a local shard which is a follower and a leader that is remote it will
// try to compute an address for the remote shard leader using the ShardPeerAddressResolver. This address will
// look like so,
- // akka.tcp://cluster-test@127.0.0.1:2559/user/shardmanager-config1/member-2-shard-default-config1
+ // akka://cluster-test@127.0.0.1:2559/user/shardmanager-config1/member-2-shard-default-config1
// In this specific case if we did a FindPrimary for shard default from member-1 we would come up
// with the address of an actor which does not exist, therefore any message sent to that actor would go to
// dead letters.
LOG.info("testShardPersistenceWithRestoredData starting");
new JavaTestKit(getSystem()) {
{
- MockConfiguration mockConfig = new MockConfiguration(ImmutableMap.<String, List<String>>builder()
- .put("default", Arrays.asList("member-1", "member-2"))
- .put("astronauts", Arrays.asList("member-2"))
- .put("people", Arrays.asList("member-1", "member-2")).build());
- String[] restoredShards = { "default", "astronauts" };
- ShardManagerSnapshot snapshot = new ShardManagerSnapshot(Arrays.asList(restoredShards));
+ MockConfiguration mockConfig =
+ new MockConfiguration(ImmutableMap.<String, List<String>>builder()
+ .put("default", Arrays.asList("member-1", "member-2"))
+ .put("astronauts", Arrays.asList("member-2"))
+ .put("people", Arrays.asList("member-1", "member-2")).build());
+ String[] restoredShards = {"default", "astronauts"};
+ ShardManagerSnapshot snapshot =
+ new ShardManagerSnapshot(Arrays.asList(restoredShards), Collections.emptyMap());
InMemorySnapshotStore.addSnapshot("shard-manager-" + shardMrgIDSuffix, snapshot);
// create shardManager to come up with restored data
};
}
- private static class TestShardManager extends ShardManager {
+ public static class TestShardManager extends ShardManager {
private final CountDownLatch recoveryComplete = new CountDownLatch(1);
private final CountDownLatch snapshotPersist = new CountDownLatch(1);
private ShardManagerSnapshot snapshot;
Uninterruptibles.awaitUninterruptibly(recoveryComplete, 5, TimeUnit.SECONDS));
}
- void waitForMemberUp() {
+ public void waitForMemberUp() {
assertEquals("MemberUp received", true,
Uninterruptibles.awaitUninterruptibly(memberUpReceived, 5, TimeUnit.SECONDS));
memberUpReceived = new CountDownLatch(1);
return new Builder(datastoreContextBuilder);
}
- private static class Builder extends AbstractGenericCreator<Builder, TestShardManager> {
+ public static class Builder extends AbstractGenericCreator<Builder, TestShardManager> {
private ActorRef shardActor;
private final Map<String, ActorRef> shardActors = new HashMap<>();