All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.cp.internal.raft.impl.task.LeadershipTransferTask Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.cp.internal.raft.impl.task;

import com.hazelcast.cp.internal.raft.impl.RaftEndpoint;
import com.hazelcast.cp.internal.raft.impl.RaftNodeImpl;
import com.hazelcast.cp.internal.raft.impl.dto.AppendRequest;
import com.hazelcast.cp.internal.raft.impl.dto.TriggerLeaderElection;
import com.hazelcast.cp.internal.raft.impl.log.LogEntry;
import com.hazelcast.cp.internal.raft.impl.state.LeaderState;
import com.hazelcast.cp.internal.raft.impl.state.LeadershipTransferState;
import com.hazelcast.cp.internal.raft.impl.state.RaftState;
import com.hazelcast.logging.ILogger;

import static com.hazelcast.internal.util.Preconditions.checkTrue;
import static java.lang.Math.max;

/**
 * Sends a {@link TriggerLeaderElection} request to the endpoint given in
 * {@link LeadershipTransferState#endpoint()}. Before sending this request,
 * the append request backoff state of the endpoint is reset and
 * an {@link AppendRequest} is also sent.
 * 

* This task waits until all appended entries are committed in the current * leader before starting the leadership transfer, and reschedules itself if * the local Raft node is still leader or there are uncommitted log entries. */ public class LeadershipTransferTask implements Runnable { private final RaftNodeImpl raftNode; private final int retryCount; private final int maxRetryCount; LeadershipTransferTask(RaftNodeImpl raftNode, int maxRetryCount) { this(raftNode, 0, maxRetryCount); } private LeadershipTransferTask(RaftNodeImpl raftNode, int retryCount, int maxRetryCount) { this.raftNode = raftNode; this.retryCount = retryCount; this.maxRetryCount = maxRetryCount; } @Override public void run() { ILogger logger = raftNode.getLogger(getClass()); RaftState state = raftNode.state(); LeaderState leaderState = state.leaderState(); if (leaderState == null) { logger.fine("Not retrying leadership transfer since not leader..."); return; } LeadershipTransferState leadershipTransferState = state.leadershipTransferState(); checkTrue(leadershipTransferState != null, "No leadership transfer state!"); if (retryCount == maxRetryCount) { String msg = "Leadership transfer to " + leadershipTransferState.endpoint() + " timed out!"; logger.warning(msg); state.completeLeadershipTransfer(new IllegalStateException(msg)); return; } RaftEndpoint targetEndpoint = leadershipTransferState.endpoint(); if (state.commitIndex() < state.log().lastLogOrSnapshotIndex()) { logger.warning("Waiting until all appended entries to be committed before transferring leadership to " + targetEndpoint); reschedule(); return; } if (retryCount > 0) { logger.fine("Retrying leadership transfer to " + leadershipTransferState.endpoint()); } else { logger.info("Transferring leadership to " + leadershipTransferState.endpoint()); } leaderState.getFollowerState(targetEndpoint).appendRequestAckReceived(); raftNode.sendAppendRequest(targetEndpoint); LogEntry entry = state.log().lastLogOrSnapshotEntry(); raftNode.send(new TriggerLeaderElection(raftNode.getLocalMember(), state.term(), entry.term(), entry.index()), targetEndpoint); reschedule(); } private void reschedule() { long delayMillis = max(1, raftNode.getLeaderElectionTimeoutInMillis() * 2 / maxRetryCount); raftNode.schedule(new LeadershipTransferTask(raftNode, retryCount + 1, maxRetryCount), delayMillis); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy