use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.
the class Replicator method onHeartbeatReturned.
static void onHeartbeatReturned(final ThreadId id, final Status status, final AppendEntriesRequest request, final AppendEntriesResponse response, final long rpcSendTime) {
if (id == null) {
// replicator already was destroyed.
return;
}
final long startTimeMs = Utils.nowMs();
Replicator r;
if ((r = (Replicator) id.lock()) == null) {
return;
}
boolean doUnlock = true;
try {
final boolean isLogDebugEnabled = LOG.isDebugEnabled();
StringBuilder sb = null;
if (isLogDebugEnabled) {
sb = //
new StringBuilder("Node ").append(//
r.options.getGroupId()).append(//
':').append(//
r.options.getServerId()).append(//
" received HeartbeatResponse from ").append(//
r.options.getPeerId()).append(//
" prevLogIndex=").append(//
request.getPrevLogIndex()).append(//
" prevLogTerm=").append(request.getPrevLogTerm());
}
if (!status.isOk()) {
if (isLogDebugEnabled) {
//
sb.append(" fail, sleep, status=").append(status);
LOG.debug(sb.toString());
}
r.setState(State.Probe);
notifyReplicatorStatusListener(r, ReplicatorEvent.ERROR, status);
if (++r.consecutiveErrorTimes % 10 == 0) {
LOG.warn("Fail to issue RPC to {}, consecutiveErrorTimes={}, error={}", r.options.getPeerId(), r.consecutiveErrorTimes, status);
}
r.startHeartbeatTimer(startTimeMs);
return;
}
r.consecutiveErrorTimes = 0;
if (response.getTerm() > r.options.getTerm()) {
if (isLogDebugEnabled) {
//
sb.append(" fail, greater term ").append(//
response.getTerm()).append(//
" expect term ").append(r.options.getTerm());
LOG.debug(sb.toString());
}
final NodeImpl node = r.options.getNode();
r.notifyOnCaughtUp(RaftError.EPERM.getNumber(), true);
r.destroy();
node.increaseTermTo(response.getTerm(), new Status(RaftError.EHIGHERTERMRESPONSE, "Leader receives higher term heartbeat_response from peer:%s", r.options.getPeerId()));
return;
}
if (!response.getSuccess() && response.hasLastLogIndex()) {
if (isLogDebugEnabled) {
//
sb.append(" fail, response term ").append(//
response.getTerm()).append(//
" lastLogIndex ").append(response.getLastLogIndex());
LOG.debug(sb.toString());
}
LOG.warn("Heartbeat to peer {} failure, try to send a probe request.", r.options.getPeerId());
doUnlock = false;
r.sendProbeRequest();
r.startHeartbeatTimer(startTimeMs);
return;
}
if (isLogDebugEnabled) {
LOG.debug(sb.toString());
}
if (rpcSendTime > r.lastRpcSendTimestamp) {
r.lastRpcSendTimestamp = rpcSendTime;
}
r.startHeartbeatTimer(startTimeMs);
} finally {
if (doUnlock) {
id.unlock();
}
}
}
use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.
the class CliServiceImpl method transferLeader.
@Override
public Status transferLeader(final String groupId, final Configuration conf, final PeerId peer) {
Requires.requireTrue(!StringUtils.isBlank(groupId), "Blank group id");
Requires.requireNonNull(conf, "Null configuration");
Requires.requireNonNull(peer, "Null peer");
final PeerId leaderId = new PeerId();
final Status st = checkLeaderAndConnect(groupId, conf, leaderId);
if (!st.isOk()) {
return st;
}
final TransferLeaderRequest.Builder rb = //
TransferLeaderRequest.newBuilder().setGroupId(//
groupId).setLeaderId(leaderId.toString());
if (!peer.isEmpty()) {
rb.setPeerId(peer.toString());
}
try {
final Message result = this.cliClientService.transferLeader(leaderId.getEndpoint(), rb.build(), null).get();
return statusFromResponse(result);
} catch (final Exception e) {
return new Status(-1, e.getMessage());
}
}
use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.
the class CliServiceImpl method getLeader.
@Override
public Status getLeader(final String groupId, final Configuration conf, final PeerId leaderId) {
Requires.requireTrue(!StringUtils.isBlank(groupId), "Blank group id");
Requires.requireNonNull(leaderId, "Null leader id");
if (conf == null || conf.isEmpty()) {
return new Status(RaftError.EINVAL, "Empty group configuration");
}
final Status st = new Status(-1, "Fail to get leader of group %s", groupId);
for (final PeerId peer : conf) {
if (!this.cliClientService.connect(peer.getEndpoint())) {
LOG.error("Fail to connect peer {} to get leader for group {}.", peer, groupId);
continue;
}
final GetLeaderRequest.Builder rb = //
GetLeaderRequest.newBuilder().setGroupId(//
groupId).setPeerId(peer.toString());
final Future<Message> result = this.cliClientService.getLeader(peer.getEndpoint(), rb.build(), null);
try {
final Message msg = result.get(this.cliOptions.getTimeoutMs() <= 0 ? this.cliOptions.getRpcDefaultTimeout() : this.cliOptions.getTimeoutMs(), TimeUnit.MILLISECONDS);
if (msg instanceof ErrorResponse) {
if (st.isOk()) {
st.setError(-1, ((ErrorResponse) msg).getErrorMsg());
} else {
final String savedMsg = st.getErrorMsg();
st.setError(-1, "%s, %s", savedMsg, ((ErrorResponse) msg).getErrorMsg());
}
} else {
final GetLeaderResponse response = (GetLeaderResponse) msg;
if (leaderId.parse(response.getLeaderId())) {
break;
}
}
} catch (final Exception e) {
if (st.isOk()) {
st.setError(-1, e.getMessage());
} else {
final String savedMsg = st.getErrorMsg();
st.setError(-1, "%s, %s", savedMsg, e.getMessage());
}
}
}
if (leaderId.isEmpty()) {
return st;
}
return Status.OK();
}
use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.
the class CliServiceImpl method getPeers.
private List<PeerId> getPeers(final String groupId, final Configuration conf, final boolean returnLearners, final boolean onlyGetAlive) {
Requires.requireTrue(!StringUtils.isBlank(groupId), "Blank group id");
Requires.requireNonNull(conf, "Null conf");
final PeerId leaderId = new PeerId();
final Status st = getLeader(groupId, conf, leaderId);
if (!st.isOk()) {
throw new IllegalStateException(st.getErrorMsg());
}
if (!this.cliClientService.connect(leaderId.getEndpoint())) {
throw new IllegalStateException("Fail to init channel to leader " + leaderId);
}
final GetPeersRequest.Builder rb = //
GetPeersRequest.newBuilder().setGroupId(//
groupId).setLeaderId(//
leaderId.toString()).setOnlyAlive(onlyGetAlive);
try {
final Message result = this.cliClientService.getPeers(leaderId.getEndpoint(), rb.build(), null).get(this.cliOptions.getTimeoutMs() <= 0 ? this.cliOptions.getRpcDefaultTimeout() : this.cliOptions.getTimeoutMs(), TimeUnit.MILLISECONDS);
if (result instanceof GetPeersResponse) {
final GetPeersResponse resp = (GetPeersResponse) result;
final List<PeerId> peerIdList = new ArrayList<>();
final ProtocolStringList responsePeers = returnLearners ? resp.getLearnersList() : resp.getPeersList();
for (final String peerIdStr : responsePeers) {
final PeerId newPeer = new PeerId();
newPeer.parse(peerIdStr);
peerIdList.add(newPeer);
}
return peerIdList;
} else {
final ErrorResponse resp = (ErrorResponse) result;
throw new JRaftException(resp.getErrorMsg());
}
} catch (final JRaftException e) {
throw e;
} catch (final Exception e) {
throw new JRaftException(e);
}
}
use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.
the class CliServiceImpl method removeLearners.
@Override
public Status removeLearners(final String groupId, final Configuration conf, final List<PeerId> learners) {
checkLearnersOpParams(groupId, conf, learners);
final PeerId leaderId = new PeerId();
final Status st = getLeader(groupId, conf, leaderId);
if (!st.isOk()) {
return st;
}
if (!this.cliClientService.connect(leaderId.getEndpoint())) {
return new Status(-1, "Fail to init channel to leader %s", leaderId);
}
final RemoveLearnersRequest.Builder rb = //
RemoveLearnersRequest.newBuilder().setGroupId(//
groupId).setLeaderId(leaderId.toString());
for (final PeerId peer : learners) {
rb.addLearners(peer.toString());
}
try {
final Message result = this.cliClientService.removeLearners(leaderId.getEndpoint(), rb.build(), null).get();
return processLearnersOpResponse(groupId, result, "removing learners: %s", learners);
} catch (final Exception e) {
return new Status(-1, e.getMessage());
}
}
Aggregations