use of org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry in project controller by opendaylight.
the class RaftActorRecoverySupportTest method testServerConfigurationPayloadApplied.
@Test
public void testServerConfigurationPayloadApplied() {
String follower1 = "follower1";
String follower2 = "follower2";
String follower3 = "follower3";
context.addToPeers(follower1, null, VotingState.VOTING);
context.addToPeers(follower2, null, VotingState.VOTING);
// add new Server
ServerConfigurationPayload obj = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(localId, true), new ServerInfo(follower1, true), new ServerInfo(follower2, false), new ServerInfo(follower3, true)));
sendMessageToSupport(new SimpleReplicatedLogEntry(0, 1, obj));
// verify new peers
assertTrue("Dynamic server configuration", context.isDynamicServerConfigurationInUse());
assertEquals("New peer Ids", Sets.newHashSet(follower1, follower2, follower3), Sets.newHashSet(context.getPeerIds()));
assertEquals("follower1 isVoting", true, context.getPeerInfo(follower1).isVoting());
assertEquals("follower2 isVoting", false, context.getPeerInfo(follower2).isVoting());
assertEquals("follower3 isVoting", true, context.getPeerInfo(follower3).isVoting());
sendMessageToSupport(new ApplyJournalEntries(0));
verify(mockCohort, never()).startLogRecoveryBatch(anyInt());
verify(mockCohort, never()).appendRecoveredLogEntry(any(Payload.class));
// remove existing follower1
obj = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(localId, true), new ServerInfo("follower2", true), new ServerInfo("follower3", true)));
sendMessageToSupport(new SimpleReplicatedLogEntry(1, 1, obj));
// verify new peers
assertTrue("Dynamic server configuration", context.isDynamicServerConfigurationInUse());
assertEquals("New peer Ids", Sets.newHashSet(follower2, follower3), Sets.newHashSet(context.getPeerIds()));
}
use of org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry in project controller by opendaylight.
the class RaftActorRecoverySupportTest method testOnRecoveryCompletedWithRemainingBatch.
@Test
public void testOnRecoveryCompletedWithRemainingBatch() {
ReplicatedLog replicatedLog = context.getReplicatedLog();
replicatedLog.append(new SimpleReplicatedLogEntry(0, 1, new MockRaftActorContext.MockPayload("0")));
replicatedLog.append(new SimpleReplicatedLogEntry(1, 1, new MockRaftActorContext.MockPayload("1")));
sendMessageToSupport(new ApplyJournalEntries(1));
sendMessageToSupport(RecoveryCompleted.getInstance(), true);
assertEquals("Last applied", 1, context.getLastApplied());
assertEquals("Commit index", 1, context.getCommitIndex());
InOrder inOrder = Mockito.inOrder(mockCohort);
inOrder.verify(mockCohort).startLogRecoveryBatch(anyInt());
for (int i = 0; i < replicatedLog.size(); i++) {
inOrder.verify(mockCohort).appendRecoveredLogEntry(replicatedLog.get(i).getData());
}
inOrder.verify(mockCohort).applyCurrentLogRecoveryBatch();
inOrder.verify(mockCohort).getRestoreFromSnapshot();
inOrder.verifyNoMoreInteractions();
}
use of org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry in project controller by opendaylight.
the class RaftActorRecoverySupportTest method testOnSnapshotOffer.
@Test
public void testOnSnapshotOffer() {
ReplicatedLog replicatedLog = context.getReplicatedLog();
replicatedLog.append(new SimpleReplicatedLogEntry(1, 1, new MockRaftActorContext.MockPayload("1")));
replicatedLog.append(new SimpleReplicatedLogEntry(2, 1, new MockRaftActorContext.MockPayload("2")));
replicatedLog.append(new SimpleReplicatedLogEntry(3, 1, new MockRaftActorContext.MockPayload("3")));
ReplicatedLogEntry unAppliedEntry1 = new SimpleReplicatedLogEntry(4, 1, new MockRaftActorContext.MockPayload("4", 4));
ReplicatedLogEntry unAppliedEntry2 = new SimpleReplicatedLogEntry(5, 1, new MockRaftActorContext.MockPayload("5", 5));
long lastAppliedDuringSnapshotCapture = 3;
long lastIndexDuringSnapshotCapture = 5;
long electionTerm = 2;
String electionVotedFor = "member-2";
MockSnapshotState snapshotState = new MockSnapshotState(Arrays.asList(new MockPayload("1")));
Snapshot snapshot = Snapshot.create(snapshotState, Arrays.asList(unAppliedEntry1, unAppliedEntry2), lastIndexDuringSnapshotCapture, 1, lastAppliedDuringSnapshotCapture, 1, electionTerm, electionVotedFor, null);
SnapshotMetadata metadata = new SnapshotMetadata("test", 6, 12345);
SnapshotOffer snapshotOffer = new SnapshotOffer(metadata, snapshot);
sendMessageToSupport(snapshotOffer);
assertEquals("Journal log size", 2, context.getReplicatedLog().size());
assertEquals("Journal data size", 9, context.getReplicatedLog().dataSize());
assertEquals("Last index", lastIndexDuringSnapshotCapture, context.getReplicatedLog().lastIndex());
assertEquals("Last applied", lastAppliedDuringSnapshotCapture, context.getLastApplied());
assertEquals("Commit index", lastAppliedDuringSnapshotCapture, context.getCommitIndex());
assertEquals("Snapshot term", 1, context.getReplicatedLog().getSnapshotTerm());
assertEquals("Snapshot index", lastAppliedDuringSnapshotCapture, context.getReplicatedLog().getSnapshotIndex());
assertEquals("Election term", electionTerm, context.getTermInformation().getCurrentTerm());
assertEquals("Election votedFor", electionVotedFor, context.getTermInformation().getVotedFor());
assertFalse("Dynamic server configuration", context.isDynamicServerConfigurationInUse());
verify(mockCohort).applyRecoverySnapshot(snapshotState);
}
use of org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry in project controller by opendaylight.
the class RaftActorRecoverySupportTest method testServerConfigurationPayloadAppliedWithPersistenceDisabled.
@Test
public void testServerConfigurationPayloadAppliedWithPersistenceDisabled() {
doReturn(false).when(mockPersistence).isRecoveryApplicable();
String follower = "follower";
ServerConfigurationPayload obj = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(localId, true), new ServerInfo(follower, true)));
sendMessageToSupport(new SimpleReplicatedLogEntry(0, 1, obj));
// verify new peers
assertEquals("New peer Ids", Sets.newHashSet(follower), Sets.newHashSet(context.getPeerIds()));
}
use of org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testChangeToVotingWithNoLeaderAndForwardedToOtherNodeAfterElectionTimeout.
@Test
public void testChangeToVotingWithNoLeaderAndForwardedToOtherNodeAfterElectionTimeout() {
LOG.info("testChangeToVotingWithNoLeaderAndForwardedToOtherNodeAfterElectionTimeout starting");
final String node1ID = "node1";
final String node2ID = "node2";
final PeerAddressResolver peerAddressResolver = peerId -> peerId.equals(node1ID) ? actorFactory.createTestActorPath(node1ID) : peerId.equals(node2ID) ? actorFactory.createTestActorPath(node2ID) : null;
DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
configParams.setHeartBeatInterval(new FiniteDuration(100, TimeUnit.MILLISECONDS));
configParams.setElectionTimeoutFactor(3);
configParams.setPeerAddressResolver(peerAddressResolver);
ServerConfigurationPayload persistedServerConfig = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(node1ID, false), new ServerInfo(node2ID, false)));
SimpleReplicatedLogEntry persistedServerConfigEntry = new SimpleReplicatedLogEntry(0, 1, persistedServerConfig);
InMemoryJournal.addEntry(node1ID, 1, new UpdateElectionTerm(1, "node1"));
InMemoryJournal.addEntry(node1ID, 2, persistedServerConfigEntry);
InMemoryJournal.addEntry(node2ID, 1, new UpdateElectionTerm(1, "node1"));
InMemoryJournal.addEntry(node2ID, 2, persistedServerConfigEntry);
InMemoryJournal.addEntry(node2ID, 3, new SimpleReplicatedLogEntry(1, 1, new MockRaftActorContext.MockPayload("2")));
InMemoryJournal.addEntry(node2ID, 4, new ApplyJournalEntries(1));
ActorRef node1Collector = actorFactory.createActor(MessageCollectorActor.props(), actorFactory.generateActorId("collector"));
TestActorRef<CollectingMockRaftActor> node1RaftActorRef = actorFactory.createTestActor(CollectingMockRaftActor.props(node1ID, ImmutableMap.<String, String>of(), configParams, PERSISTENT, node1Collector).withDispatcher(Dispatchers.DefaultDispatcherId()), node1ID);
final CollectingMockRaftActor node1RaftActor = node1RaftActorRef.underlyingActor();
ActorRef node2Collector = actorFactory.createActor(MessageCollectorActor.props(), actorFactory.generateActorId("collector"));
TestActorRef<CollectingMockRaftActor> node2RaftActorRef = actorFactory.createTestActor(CollectingMockRaftActor.props(node2ID, ImmutableMap.<String, String>of(), configParams, PERSISTENT, node2Collector).withDispatcher(Dispatchers.DefaultDispatcherId()), node2ID);
final CollectingMockRaftActor node2RaftActor = node2RaftActorRef.underlyingActor();
// Send a ChangeServersVotingStatus message to node1 to change mode1 to voting. This should cause
// node1 to try to elect itself as leader in order to apply the new server config. However node1's log
// is behind node2's so node2 should not grant node1's vote. This should cause node1 to time out and
// forward the request to node2.
ChangeServersVotingStatus changeServers = new ChangeServersVotingStatus(ImmutableMap.of(node1ID, true, node2ID, true));
node1RaftActorRef.tell(changeServers, testKit.getRef());
ServerChangeReply reply = testKit.expectMsgClass(testKit.duration("5 seconds"), ServerChangeReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, reply.getStatus());
MessageCollectorActor.expectFirstMatching(node2Collector, ApplyJournalEntries.class);
verifyServerConfigurationPayloadEntry(node2RaftActor.getRaftActorContext().getReplicatedLog(), votingServer(node1ID), votingServer(node2ID));
assertEquals("getRaftState", RaftState.Leader, node2RaftActor.getRaftState());
MessageCollectorActor.expectFirstMatching(node1Collector, ApplyJournalEntries.class);
verifyServerConfigurationPayloadEntry(node1RaftActor.getRaftActorContext().getReplicatedLog(), votingServer(node1ID), votingServer(node2ID));
assertEquals("isVotingMember", true, node1RaftActor.getRaftActorContext().isVotingMember());
assertEquals("getRaftState", RaftState.Follower, node1RaftActor.getRaftState());
LOG.info("testChangeToVotingWithNoLeaderAndForwardedToOtherNodeAfterElectionTimeout ending");
}
Aggregations