* 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.raft.base.messages;
import akka.actor.ActorRef;
-import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
import org.opendaylight.yangtools.concepts.Identifier;
-public class Replicate {
- private final ActorRef clientActor;
- private final Identifier identifier;
- private final ReplicatedLogEntry replicatedLogEntry;
- private final boolean sendImmediate;
-
- public Replicate(ActorRef clientActor, Identifier identifier, ReplicatedLogEntry replicatedLogEntry,
- boolean sendImmediate) {
- this.clientActor = clientActor;
- this.identifier = identifier;
- this.replicatedLogEntry = replicatedLogEntry;
- this.sendImmediate = sendImmediate;
- }
-
- public ActorRef getClientActor() {
- return clientActor;
- }
-
- public Identifier getIdentifier() {
- return identifier;
- }
-
- public ReplicatedLogEntry getReplicatedLogEntry() {
- return replicatedLogEntry;
- }
-
- public boolean isSendImmediate() {
- return sendImmediate;
- }
+public record Replicate(long logIndex, boolean sendImmediate, ActorRef clientActor, Identifier identifier) {
+ // Nothing else here
}
}
private void replicate(final Replicate replicate) {
- long logIndex = replicate.getReplicatedLogEntry().getIndex();
+ final long logIndex = replicate.logIndex();
- log.debug("{}: Replicate message: identifier: {}, logIndex: {}, payload: {}, isSendImmediate: {}", logName(),
- replicate.getIdentifier(), logIndex, replicate.getReplicatedLogEntry().getData().getClass(),
- replicate.isSendImmediate());
+ log.debug("{}: Replicate message: identifier: {}, logIndex: {}, isSendImmediate: {}", logName(),
+ replicate.identifier(), logIndex, replicate.sendImmediate());
// Create a tracker entry we will use this later to notify the
// client actor
- final var clientActor = replicate.getClientActor();
+ final var clientActor = replicate.clientActor();
if (clientActor != null) {
- trackers.add(new ClientRequestTrackerImpl(clientActor, replicate.getIdentifier(), logIndex));
+ trackers.add(new ClientRequestTrackerImpl(clientActor, replicate.identifier(), logIndex));
}
boolean applyModificationToState = !context.anyVotingPeers()
applyLogToStateMachine(logIndex);
}
- if (replicate.isSendImmediate() && !followerToLog.isEmpty()) {
+ if (replicate.sendImmediate() && !followerToLog.isEmpty()) {
sendAppendEntries(0, false);
}
}
private RaftActorBehavior sendReplicate(final MockRaftActorContext actorContext, final long term, final long index,
final Payload payload) {
- SimpleReplicatedLogEntry newEntry = new SimpleReplicatedLogEntry(index, term, payload);
- actorContext.getReplicatedLog().append(newEntry);
- return leader.handleMessage(leaderActor, new Replicate(null, null, newEntry, true));
+ actorContext.getReplicatedLog().append(new SimpleReplicatedLogEntry(index, term, payload));
+ return leader.handleMessage(leaderActor, new Replicate(index, true, null, null));
}
@Test
actorContext.setLastApplied(0);
- long newLogIndex = actorContext.getReplicatedLog().lastIndex() + 1;
- long term = actorContext.getTermInformation().getCurrentTerm();
- ReplicatedLogEntry newEntry = new SimpleReplicatedLogEntry(
- newLogIndex, term, new MockRaftActorContext.MockPayload("foo"));
+ final long newLogIndex = actorContext.getReplicatedLog().lastIndex() + 1;
+ final long term = actorContext.getTermInformation().getCurrentTerm();
+ final var data = new MockRaftActorContext.MockPayload("foo");
- actorContext.getReplicatedLog().append(newEntry);
+ actorContext.getReplicatedLog().append(new SimpleReplicatedLogEntry(newLogIndex, term, data));
final Identifier id = new MockIdentifier("state-id");
- RaftActorBehavior raftBehavior = leader.handleMessage(leaderActor,
- new Replicate(leaderActor, id, newEntry, true));
+ final var raftBehavior = leader.handleMessage(leaderActor, new Replicate(newLogIndex, true, leaderActor, id));
// State should not change
assertTrue(raftBehavior instanceof Leader);
// We should get 2 ApplyState messages - 1 for new log entry and 1 for the previous
// one since lastApplied state is 0.
- List<ApplyState> applyStateList = MessageCollectorActor.getAllMatching(
- leaderActor, ApplyState.class);
+ final var applyStateList = MessageCollectorActor.getAllMatching(leaderActor, ApplyState.class);
assertEquals("ApplyState count", newLogIndex, applyStateList.size());
for (int i = 0; i <= newLogIndex - 1; i++) {
}
ApplyState last = applyStateList.get((int) newLogIndex - 1);
- assertEquals("getData", newEntry.getData(), last.getReplicatedLogEntry().getData());
+ assertEquals("getData", data, last.getReplicatedLogEntry().getData());
assertEquals("getIdentifier", id, last.getIdentifier());
}
MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
// new entry
- SimpleReplicatedLogEntry entry =
- new SimpleReplicatedLogEntry(newEntryIndex, currentTerm,
- new MockRaftActorContext.MockPayload("D"));
-
- actorContext.getReplicatedLog().append(entry);
+ actorContext.getReplicatedLog().append(
+ new SimpleReplicatedLogEntry(newEntryIndex, currentTerm, new MockRaftActorContext.MockPayload("D")));
//update follower timestamp
leader.markFollowerActive(FOLLOWER_ID);
// this should invoke a sendinstallsnapshot as followersLastIndex < snapshotIndex
RaftActorBehavior raftBehavior = leader.handleMessage(
- leaderActor, new Replicate(null, new MockIdentifier("state-id"), entry, true));
+ leaderActor, new Replicate(newEntryIndex, true, null, new MockIdentifier("state-id")));
assertTrue(raftBehavior instanceof Leader);
leader.setSnapshotHolder(null);
// new entry
- SimpleReplicatedLogEntry entry = new SimpleReplicatedLogEntry(newEntryIndex, currentTerm,
- new MockRaftActorContext.MockPayload("D"));
-
- actorContext.getReplicatedLog().append(entry);
+ actorContext.getReplicatedLog().append(
+ new SimpleReplicatedLogEntry(newEntryIndex, currentTerm, new MockRaftActorContext.MockPayload("D")));
//update follower timestamp
leader.markFollowerActive(FOLLOWER_ID);
- leader.handleMessage(leaderActor, new Replicate(null, new MockIdentifier("state-id"), entry, true));
+ leader.handleMessage(leaderActor, new Replicate(newEntryIndex, true, null, new MockIdentifier("state-id")));
assertEquals("isCapturing", true, actorContext.getSnapshotManager().isCapturing());
assertEquals(2, cs.getLastTerm());
// if an initiate is started again when first is in progress, it shouldnt initiate Capture
- leader.handleMessage(leaderActor, new Replicate(null, new MockIdentifier("state-id"), entry, true));
+ leader.handleMessage(leaderActor, new Replicate(newEntryIndex, true, null, new MockIdentifier("state-id")));
assertSame("CaptureSnapshot instance", cs, actorContext.getSnapshotManager().getCaptureSnapshot());
}
}
// new entry
- SimpleReplicatedLogEntry entry = new SimpleReplicatedLogEntry(newEntryIndex, currentTerm,
- new MockRaftActorContext.MockPayload("D"));
-
- actorContext.getReplicatedLog().append(entry);
+ actorContext.getReplicatedLog().append(
+ new SimpleReplicatedLogEntry(newEntryIndex, currentTerm, new MockRaftActorContext.MockPayload("D")));
//update follower timestamp
leader.markFollowerActive(FOLLOWER_ID);
MessageCollectorActor.clearMessages(followerActor);
// Sending Replicate message should not initiate another capture since the first is in progress.
- leader.handleMessage(leaderActor, new Replicate(null, new MockIdentifier("state-id"), entry, true));
+ leader.handleMessage(leaderActor, new Replicate(newEntryIndex, true, null, new MockIdentifier("state-id")));
assertSame("CaptureSnapshot instance", cs, actorContext.getSnapshotManager().getCaptureSnapshot());
// Similarly sending another AppendEntriesReply to force a snapshot should not initiate another capture.