From 005b1cad87fab6695a53b1085893fbb7f0efb5e9 Mon Sep 17 00:00:00 2001 From: Moiz Raja Date: Tue, 3 Mar 2015 15:49:48 -0800 Subject: [PATCH] Handle FollowerInitialSyncStatus message in Shard/ShardManager Both Shard and ShardManager updated the status in their respective MBeans so that the status can be queried from there Change-Id: I9e9fd6c93ad6a1b4d260f6ecd9a7fd1d63f70a12 Signed-off-by: Moiz Raja --- .../messages/FollowerInitialSyncUpStatus.java | 8 +- .../behaviors/AbstractRaftActorBehavior.java | 4 + .../cluster/raft/behaviors/Follower.java | 6 +- .../controller/cluster/datastore/Shard.java | 4 + .../cluster/datastore/ShardManager.java | 55 +++++++- .../jmx/mbeans/shard/ShardStats.java | 11 ++ .../jmx/mbeans/shard/ShardStatsMXBean.java | 2 + .../mbeans/shardmanager/ShardManagerInfo.java | 11 ++ .../shardmanager/ShardManagerInfoMBean.java | 1 + .../cluster/datastore/ShardManagerTest.java | 129 ++++++++++++++++++ .../cluster/datastore/ShardTest.java | 21 ++- 11 files changed, 244 insertions(+), 8 deletions(-) diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/FollowerInitialSyncUpStatus.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/FollowerInitialSyncUpStatus.java index 3ce1f5d1e8..72b5ac9515 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/FollowerInitialSyncUpStatus.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/FollowerInitialSyncUpStatus.java @@ -18,12 +18,18 @@ package org.opendaylight.controller.cluster.raft.base.messages; */ public class FollowerInitialSyncUpStatus { private final boolean initialSyncDone; + private final String name; - public FollowerInitialSyncUpStatus(boolean initialSyncDone){ + public FollowerInitialSyncUpStatus(boolean initialSyncDone, String name){ this.initialSyncDone = initialSyncDone; + this.name = name; } public boolean isInitialSyncDone() { return initialSyncDone; } + + public String getName() { + return name; + } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java index ef5f11e37a..e814cd000d 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java @@ -476,4 +476,8 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior { } } + protected String getId(){ + return context.getId(); + } + } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java index 618865cb88..0f251a3012 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java @@ -352,7 +352,7 @@ public class Follower extends AbstractRaftActorBehavior { return snapshotTracker; } - private static class InitialSyncStatusTracker { + private class InitialSyncStatusTracker { private static final long INVALID_LOG_INDEX = -2L; private long initialLeaderCommit = INVALID_LOG_INDEX; @@ -374,10 +374,10 @@ public class Follower extends AbstractRaftActorBehavior { if(!initialSyncUpDone){ if(initialLeaderCommit == INVALID_LOG_INDEX){ - actor.tell(new FollowerInitialSyncUpStatus(false), ActorRef.noSender()); + actor.tell(new FollowerInitialSyncUpStatus(false, getId()), ActorRef.noSender()); initialLeaderCommit = leaderCommit; } else if(commitIndex >= initialLeaderCommit){ - actor.tell(new FollowerInitialSyncUpStatus(true), ActorRef.noSender()); + actor.tell(new FollowerInitialSyncUpStatus(true, getId()), ActorRef.noSender()); initialSyncUpDone = true; } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java index a5abd2fc69..764679ec87 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java @@ -67,6 +67,7 @@ import org.opendaylight.controller.cluster.notifications.RegisterRoleChangeListe import org.opendaylight.controller.cluster.notifications.RoleChangeNotifier; import org.opendaylight.controller.cluster.raft.RaftActor; import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry; +import org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus; import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply; import org.opendaylight.controller.cluster.raft.protobuff.client.messages.CompositeModificationByteStringPayload; import org.opendaylight.controller.cluster.raft.protobuff.client.messages.CompositeModificationPayload; @@ -291,6 +292,9 @@ public class Shard extends RaftActor { onDatastoreContext((DatastoreContext)message); } else if(message instanceof RegisterRoleChangeListener){ roleChangeNotifier.get().forward(message, context()); + } else if (message instanceof FollowerInitialSyncUpStatus){ + shardMBean.setFollowerInitialSyncStatus(((FollowerInitialSyncUpStatus) message).isInitialSyncDone()); + context().parent().tell(message, self()); } else { super.onReceiveCommand(message); } 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 d836a347c5..aba8ae8c7e 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 @@ -41,6 +41,7 @@ import org.opendaylight.controller.cluster.common.actor.AbstractUntypedPersisten import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier; import org.opendaylight.controller.cluster.datastore.identifiers.ShardManagerIdentifier; import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shardmanager.ShardManagerInfo; +import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shardmanager.ShardManagerInfoMBean; import org.opendaylight.controller.cluster.datastore.messages.ActorInitialized; import org.opendaylight.controller.cluster.datastore.messages.ActorNotInitialized; import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard; @@ -55,6 +56,7 @@ import org.opendaylight.controller.cluster.datastore.utils.Dispatchers; 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.base.messages.FollowerInitialSyncUpStatus; import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.slf4j.Logger; @@ -166,16 +168,31 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { ignoreMessage(message); } else if(message instanceof DatastoreContext) { onDatastoreContext((DatastoreContext)message); - } else if(message instanceof RoleChangeNotification){ + } else if(message instanceof RoleChangeNotification) { onRoleChangeNotification((RoleChangeNotification) message); + } else if(message instanceof FollowerInitialSyncUpStatus){ + onFollowerInitialSyncStatus((FollowerInitialSyncUpStatus) message); } else{ unknownMessage(message); } } - private void onRoleChangeNotification(RoleChangeNotification message) { - RoleChangeNotification roleChanged = message; + private void onFollowerInitialSyncStatus(FollowerInitialSyncUpStatus status) { + LOG.info("Received follower initial sync status for {} status sync done {}", status.getName(), + status.isInitialSyncDone()); + + ShardInformation shardInformation = findShardInformation(status.getName()); + + if(shardInformation != null) { + shardInformation.setFollowerSyncStatus(status.isInitialSyncDone()); + + mBean.setSyncStatus(isInSync()); + } + + } + + private void onRoleChangeNotification(RoleChangeNotification roleChanged) { LOG.info("Received role changed for {} from {} to {}", roleChanged.getMemberId(), roleChanged.getOldRole(), roleChanged.getNewRole()); @@ -189,6 +206,8 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { waitTillReadyCountdownLatch.countDown(); } + + mBean.setSyncStatus(isInSync()); } } @@ -214,6 +233,15 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { return isReady; } + private boolean isInSync(){ + for (ShardInformation info : localShards.values()) { + if(!info.isInSync()){ + return false; + } + } + return true; + } + private void onActorInitialized(Object message) { final ActorRef sender = getSender(); @@ -519,6 +547,11 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { return dataPersistenceProvider; } + @VisibleForTesting + ShardManagerInfoMBean getMBean(){ + return mBean; + } + private class ShardInformation { private final ShardIdentifier shardId; private final String shardName; @@ -529,6 +562,8 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { // flag that determines if the actor is ready for business private boolean actorInitialized = false; + private boolean followerSyncStatus = false; + private final List runnablesOnInitialized = Lists.newArrayList(); private String role ; @@ -607,6 +642,20 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { return this.role; } + public void setFollowerSyncStatus(boolean syncStatus){ + this.followerSyncStatus = syncStatus; + } + + public boolean isInSync(){ + if(RaftState.Follower.name().equals(this.role)){ + return followerSyncStatus; + } else if(RaftState.Leader.name().equals(this.role)){ + return true; + } + + return false; + } + } private static class ShardManagerCreator implements Creator { diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java index 945ae0a478..6222d3be09 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStats.java @@ -67,6 +67,8 @@ public class ShardStats extends AbstractMXBean implements ShardStatsMXBean { private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + private boolean followerInitialSyncStatus = false; + public ShardStats(final String shardName, final String mxBeanType) { super(shardName, mxBeanType, JMX_CATEGORY_SHARD); } @@ -276,4 +278,13 @@ public class ShardStats extends AbstractMXBean implements ShardStatsMXBean { public void setDataStore(final InMemoryDOMDataStore store) { setNotificationManager(store.getDataChangeListenerNotificationManager()); } + + public void setFollowerInitialSyncStatus(boolean followerInitialSyncStatus) { + this.followerInitialSyncStatus = followerInitialSyncStatus; + } + + @Override + public boolean getFollowerInitialSyncStatus() { + return followerInitialSyncStatus; + } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java index 9698f6fe22..0281cdd8ce 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMXBean.java @@ -53,4 +53,6 @@ public interface ShardStatsMXBean { void resetTransactionCounters(); long getInMemoryJournalDataSize(); + + boolean getFollowerInitialSyncStatus(); } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shardmanager/ShardManagerInfo.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shardmanager/ShardManagerInfo.java index 99c8daf87d..8adc8b24b2 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shardmanager/ShardManagerInfo.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shardmanager/ShardManagerInfo.java @@ -18,6 +18,8 @@ public class ShardManagerInfo extends AbstractMXBean implements ShardManagerInfo private final List localShards; + private boolean syncStatus = false; + public ShardManagerInfo(String name, String mxBeanType, List localShards) { super(name, mxBeanType, JMX_CATEGORY_SHARD_MANAGER); this.localShards = localShards; @@ -36,4 +38,13 @@ public class ShardManagerInfo extends AbstractMXBean implements ShardManagerInfo public List getLocalShards() { return localShards; } + + @Override + public boolean getSyncStatus() { + return this.syncStatus; + } + + public void setSyncStatus(boolean syncStatus){ + this.syncStatus = syncStatus; + } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shardmanager/ShardManagerInfoMBean.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shardmanager/ShardManagerInfoMBean.java index 28ccc4f0b3..b64ba74782 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shardmanager/ShardManagerInfoMBean.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shardmanager/ShardManagerInfoMBean.java @@ -12,4 +12,5 @@ import java.util.List; public interface ShardManagerInfoMBean { List getLocalShards(); + boolean getSyncStatus(); } 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 index f0cdacc9ef..c005751380 100644 --- 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 @@ -20,8 +20,10 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Uninterruptibles; import java.net.URI; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; @@ -48,6 +50,7 @@ import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper; import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration; import org.opendaylight.controller.cluster.notifications.RoleChangeNotification; import org.opendaylight.controller.cluster.raft.RaftState; +import org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus; import org.opendaylight.controller.md.cluster.datastore.model.TestModel; import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -469,6 +472,132 @@ public class ShardManagerTest extends AbstractActorTest { } + @Test + public void testByDefaultSyncStatusIsFalse() throws Exception{ + final Props persistentProps = ShardManager.props( + new MockClusterWrapper(), + new MockConfiguration(), + DatastoreContext.newBuilder().persistent(true).build(), ready); + final TestActorRef shardManager = + TestActorRef.create(getSystem(), persistentProps); + + ShardManager shardManagerActor = shardManager.underlyingActor(); + + assertEquals(false, shardManagerActor.getMBean().getSyncStatus()); + } + + @Test + public void testWhenShardIsLeaderSyncStatusIsTrue() throws Exception{ + final Props persistentProps = ShardManager.props( + new MockClusterWrapper(), + new MockConfiguration(), + DatastoreContext.newBuilder().persistent(true).build(), ready); + final TestActorRef shardManager = + TestActorRef.create(getSystem(), persistentProps); + + ShardManager shardManagerActor = shardManager.underlyingActor(); + shardManagerActor.onReceiveCommand(new RoleChangeNotification("member-1-shard-default-unknown", + RaftState.Follower.name(), RaftState.Leader.name())); + + assertEquals(true, shardManagerActor.getMBean().getSyncStatus()); + } + + @Test + public void testWhenShardIsCandidateSyncStatusIsFalse() throws Exception{ + final Props persistentProps = ShardManager.props( + new MockClusterWrapper(), + new MockConfiguration(), + DatastoreContext.newBuilder().persistent(true).build(), ready); + final TestActorRef shardManager = + TestActorRef.create(getSystem(), persistentProps); + + ShardManager shardManagerActor = shardManager.underlyingActor(); + shardManagerActor.onReceiveCommand(new RoleChangeNotification("member-1-shard-default-unknown", + RaftState.Follower.name(), RaftState.Candidate.name())); + + assertEquals(false, shardManagerActor.getMBean().getSyncStatus()); + + // Send a FollowerInitialSyncStatus with status = true for the replica whose current state is candidate + shardManagerActor.onReceiveCommand(new FollowerInitialSyncUpStatus(true, "member-1-shard-default-unknown")); + + assertEquals(false, shardManagerActor.getMBean().getSyncStatus()); + } + + @Test + public void testWhenShardIsFollowerSyncStatusDependsOnFollowerInitialSyncStatus() throws Exception{ + final Props persistentProps = ShardManager.props( + new MockClusterWrapper(), + new MockConfiguration(), + DatastoreContext.newBuilder().persistent(true).build(), ready); + final TestActorRef shardManager = + TestActorRef.create(getSystem(), persistentProps); + + ShardManager shardManagerActor = shardManager.underlyingActor(); + shardManagerActor.onReceiveCommand(new RoleChangeNotification("member-1-shard-default-unknown", + RaftState.Candidate.name(), RaftState.Follower.name())); + + // Initially will be false + assertEquals(false, shardManagerActor.getMBean().getSyncStatus()); + + // Send status true will make sync status true + shardManagerActor.onReceiveCommand(new FollowerInitialSyncUpStatus(true, "member-1-shard-default-unknown")); + + assertEquals(true, shardManagerActor.getMBean().getSyncStatus()); + + // Send status false will make sync status false + shardManagerActor.onReceiveCommand(new FollowerInitialSyncUpStatus(false, "member-1-shard-default-unknown")); + + assertEquals(false, shardManagerActor.getMBean().getSyncStatus()); + + } + + @Test + public void testWhenMultipleShardsPresentSyncStatusMustBeTrueForAllShards() throws Exception{ + final Props persistentProps = ShardManager.props( + new MockClusterWrapper(), + new MockConfiguration() { + @Override + public List getMemberShardNames(String memberName) { + return Arrays.asList("default", "astronauts"); + } + }, + DatastoreContext.newBuilder().persistent(true).build(), ready); + final TestActorRef shardManager = + TestActorRef.create(getSystem(), persistentProps); + + ShardManager shardManagerActor = shardManager.underlyingActor(); + + // Initially will be false + assertEquals(false, shardManagerActor.getMBean().getSyncStatus()); + + // Make default shard leader + shardManagerActor.onReceiveCommand(new RoleChangeNotification("member-1-shard-default-unknown", + RaftState.Follower.name(), RaftState.Leader.name())); + + // default = Leader, astronauts is unknown so sync status remains false + assertEquals(false, shardManagerActor.getMBean().getSyncStatus()); + + // Make astronauts shard leader as well + shardManagerActor.onReceiveCommand(new RoleChangeNotification("member-1-shard-astronauts-unknown", + RaftState.Follower.name(), RaftState.Leader.name())); + + // Now sync status should be true + assertEquals(true, shardManagerActor.getMBean().getSyncStatus()); + + // Make astronauts a Follower + shardManagerActor.onReceiveCommand(new RoleChangeNotification("member-1-shard-astronauts-unknown", + RaftState.Leader.name(), RaftState.Follower.name())); + + // Sync status is not true + assertEquals(false, shardManagerActor.getMBean().getSyncStatus()); + + // Make the astronauts follower sync status true + shardManagerActor.onReceiveCommand(new FollowerInitialSyncUpStatus(true, "member-1-shard-astronauts-unknown")); + + // Sync status is now true + assertEquals(true, shardManagerActor.getMBean().getSyncStatus()); + + } private static class TestShardManager extends ShardManager { private final CountDownLatch recoveryComplete = new CountDownLatch(1); diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java index 7dfbd668b8..d930b2519e 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java @@ -84,6 +84,7 @@ import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot; import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot; import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout; +import org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus; import org.opendaylight.controller.cluster.raft.client.messages.FindLeader; import org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply; import org.opendaylight.controller.cluster.raft.protobuff.client.messages.CompositeModificationByteStringPayload; @@ -1618,7 +1619,25 @@ public class ShardTest extends AbstractActorTest { List allMatching = MessageCollectorActor.getAllMatching(listener, RegisterRoleChangeListenerReply.class); assertEquals(1, allMatching.size()); - }}; + } + }; + } + + @Test + public void testFollowerInitialSyncStatus() throws Exception { + final TestActorRef shard = TestActorRef.create(getSystem(), + newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()), + "testFollowerInitialSyncStatus"); + + shard.underlyingActor().onReceiveCommand(new FollowerInitialSyncUpStatus(false, "member-1-shard-inventory-operational")); + + assertEquals(false, shard.underlyingActor().getShardMBean().getFollowerInitialSyncStatus()); + + shard.underlyingActor().onReceiveCommand(new FollowerInitialSyncUpStatus(true, "member-1-shard-inventory-operational")); + + assertEquals(true, shard.underlyingActor().getShardMBean().getFollowerInitialSyncStatus()); + + shard.tell(PoisonPill.getInstance(), ActorRef.noSender()); } -- 2.36.6