*/
FiniteDuration getElectionTimeOutInterval();
+ /**
+ * Returns the number by which a candidate should divide the election timeout it has calculated. This serves
+ * to speed up retries when elections result in a stalemate.
+ *
+ * @return the interval as a FiniteDuration.
+ */
+ long getCandidateElectionTimeoutDivisor();
+
/**
* Returns the maximum election time variance. The election is scheduled using both the election timeout
* and variance.
private int snapshotChunkSize = SNAPSHOT_CHUNK_SIZE;
private long electionTimeoutFactor = 2;
+ private long candidateElectionTimeoutDivisor = 1;
private String customRaftPolicyImplementationClass;
private PeerAddressResolver peerAddressResolver = NoopPeerAddressResolver.INSTANCE;
electionTimeOutInterval = null;
}
+ public void setCandidateElectionTimeoutDivisor(final long candidateElectionTimeoutDivisor) {
+ this.candidateElectionTimeoutDivisor = candidateElectionTimeoutDivisor;
+ }
+
public void setTempFileDirectory(final String tempFileDirectory) {
this.tempFileDirectory = tempFileDirectory;
}
return snapshotDataThresholdPercentage;
}
-
@Override
public FiniteDuration getHeartBeatInterval() {
return heartBeatInterval;
return electionTimeOutInterval;
}
+ @Override
+ public long getCandidateElectionTimeoutDivisor() {
+ return candidateElectionTimeoutDivisor;
+ }
+
@Override
public int getElectionTimeVariance() {
return ELECTION_TIME_MAX_VARIANCE;
import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
import org.opendaylight.controller.cluster.raft.messages.RequestVote;
import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
+import scala.concurrent.duration.FiniteDuration;
/**
* The behavior of a RaftActor when it is in the Candidate raft state.
return this;
}
+ @Override
+ protected FiniteDuration electionDuration() {
+ return super.electionDuration().$div(context.getConfigParams().getCandidateElectionTimeoutDivisor());
+ }
+
@Override
public RaftActorBehavior handleMessage(ActorRef sender, Object message) {
if (message instanceof ElectionTimeout) {
# The interval at which a shard will send a heart beat message to its remote shard.
#shard-heartbeat-interval-in-millis=500
+# The amount by which to divide election timeout in case of a candidate. This serves as a counter-balance
+# to shard-election-timeout-factor. The default value is 1, i.e. election timeout is the same in all
+# situations.
+#shard-candidate-election-timeout-divisor=1
+
# The maximum amount of time to wait for a shard to elect a leader before failing an operation (eg transaction create).
#shard-leader-election-timeout-in-seconds=30
public static final FileAkkaConfigurationReader DEFAULT_CONFIGURATION_READER = new FileAkkaConfigurationReader();
public static final int DEFAULT_SHARD_SNAPSHOT_DATA_THRESHOLD_PERCENTAGE = 12;
public static final int DEFAULT_SHARD_ELECTION_TIMEOUT_FACTOR = 2;
+ public static final int DEFAULT_SHARD_CANDIDATE_ELECTION_TIMEOUT_DIVISOR = 1;
public static final int DEFAULT_TX_CREATION_INITIAL_RATE_LIMIT = 100;
public static final String UNKNOWN_DATA_STORE_TYPE = "unknown";
public static final int DEFAULT_SHARD_BATCHED_MODIFICATION_COUNT = 1000;
setIsolatedLeaderCheckInterval(DEFAULT_ISOLATED_LEADER_CHECK_INTERVAL_IN_MILLIS);
setSnapshotDataThresholdPercentage(DEFAULT_SHARD_SNAPSHOT_DATA_THRESHOLD_PERCENTAGE);
setElectionTimeoutFactor(DEFAULT_SHARD_ELECTION_TIMEOUT_FACTOR);
+ setCandidateElectionTimeoutDivisor(DEFAULT_SHARD_CANDIDATE_ELECTION_TIMEOUT_DIVISOR);
setSyncIndexThreshold(DEFAULT_SYNC_INDEX_THRESHOLD);
setMaximumMessageSliceSize(DEFAULT_MAX_MESSAGE_SLICE_SIZE);
}
setIsolatedLeaderCheckInterval(other.raftConfig.getIsolatedCheckIntervalInMillis());
setSnapshotDataThresholdPercentage(other.raftConfig.getSnapshotDataThresholdPercentage());
setElectionTimeoutFactor(other.raftConfig.getElectionTimeoutFactor());
+ setCandidateElectionTimeoutDivisor(other.raftConfig.getCandidateElectionTimeoutDivisor());
setCustomRaftPolicyImplementation(other.raftConfig.getCustomRaftPolicyImplementationClass());
setMaximumMessageSliceSize(other.getMaximumMessageSliceSize());
setShardSnapshotChunkSize(other.raftConfig.getSnapshotChunkSize());
raftConfig.setElectionTimeoutFactor(shardElectionTimeoutFactor);
}
+ private void setCandidateElectionTimeoutDivisor(final long candidateElectionTimeoutDivisor) {
+ raftConfig.setCandidateElectionTimeoutDivisor(candidateElectionTimeoutDivisor);
+ }
+
private void setCustomRaftPolicyImplementation(final String customRaftPolicyImplementation) {
raftConfig.setCustomRaftPolicyImplementationClass(customRaftPolicyImplementation);
}
return this;
}
+ public Builder shardCandidateElectionTimeoutDivisor(final long candidateElectionTimeoutDivisor) {
+ datastoreContext.setCandidateElectionTimeoutDivisor(candidateElectionTimeoutDivisor);
+ return this;
+ }
+
public Builder transactionCreationInitialRateLimit(final long initialRateLimit) {
datastoreContext.transactionCreationInitialRateLimit = initialRateLimit;
return this;