use of com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest in project sofa-jraft by sofastack.
the class AppendEntriesRequestProcessorTest method verify.
@Override
public void verify(final String interest, final RaftServerService service, final NodeRequestProcessor<AppendEntriesRequest> processor) {
assertEquals(interest, AppendEntriesRequest.class.getName());
Mockito.verify(service).handleAppendEntriesRequest(eq(this.request), Mockito.any());
final PeerPair pair = ((AppendEntriesRequestProcessor) processor).pairOf(this.peerIdStr, this.serverId);
final PeerRequestContext ctx = ((AppendEntriesRequestProcessor) processor).getOrCreatePeerRequestContext(this.groupId, pair, this.conn);
assertNotNull(ctx);
}
use of com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest in project sofa-jraft by sofastack.
the class ProtobufSerializerTest method testEncodeDecodeAppendEntiresRequestHeader.
@Test
public void testEncodeDecodeAppendEntiresRequestHeader() throws Exception {
final AppendEntriesRequest reqObject = //
AppendEntriesRequest.newBuilder().setGroupId(//
"testGroup").setPeerId(//
"testPeer").setServerId(//
"testServer").setTerm(//
1).setPrevLogIndex(//
1).setPrevLogTerm(//
0).setCommittedIndex(1).build();
final RpcCommandFactory cmdFactory = new RpcCommandFactory();
final RpcRequestCommand request = cmdFactory.createRequestCommand(reqObject);
request.setRequestClass(AppendEntriesRequest.class.getName());
assertNull(request.getHeader());
assertTrue(serializer.serializeContent(request, null));
assertTrue(serializer.serializeHeader(request, null));
assertNull(request.getRequestHeader());
request.setRequestObject(null);
assertTrue(serializer.deserializeContent(request));
assertTrue(serializer.deserializeHeader(request));
assertNotNull(request.getRequestObject());
assertNotNull(request.getRequestHeader());
assertEquals(reqObject, request.getRequestObject());
assertNotSame(reqObject, request.getRequestObject());
final AppendEntriesRequestHeader header = (AppendEntriesRequestHeader) request.getRequestHeader();
assertEquals("testGroup", header.getGroupId());
assertEquals("testPeer", header.getPeerId());
assertEquals("testServer", header.getServerId());
}
use of com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest in project sofa-jraft by sofastack.
the class Replicator method sendEmptyEntries.
/**
* Send probe or heartbeat request
* @param isHeartbeat if current entries is heartbeat
* @param heartBeatClosure heartbeat callback
*/
@SuppressWarnings("NonAtomicOperationOnVolatileField")
private void sendEmptyEntries(final boolean isHeartbeat, final RpcResponseClosure<AppendEntriesResponse> heartBeatClosure) {
final AppendEntriesRequest.Builder rb = AppendEntriesRequest.newBuilder();
if (!fillCommonFields(rb, this.nextIndex - 1, isHeartbeat)) {
// id is unlock in installSnapshot
installSnapshot();
if (isHeartbeat && heartBeatClosure != null) {
RpcUtils.runClosureInThread(heartBeatClosure, new Status(RaftError.EAGAIN, "Fail to send heartbeat to peer %s", this.options.getPeerId()));
}
return;
}
try {
final long monotonicSendTimeMs = Utils.monotonicMs();
if (isHeartbeat) {
final AppendEntriesRequest request = rb.build();
// Sending a heartbeat request
this.heartbeatCounter++;
RpcResponseClosure<AppendEntriesResponse> heartbeatDone;
// Prefer passed-in closure.
if (heartBeatClosure != null) {
heartbeatDone = heartBeatClosure;
} else {
heartbeatDone = new RpcResponseClosureAdapter<AppendEntriesResponse>() {
@Override
public void run(final Status status) {
onHeartbeatReturned(Replicator.this.id, status, request, getResponse(), monotonicSendTimeMs);
}
};
}
this.heartbeatInFly = this.rpcService.appendEntries(this.options.getPeerId().getEndpoint(), request, this.options.getElectionTimeoutMs() / 2, heartbeatDone);
} else {
// No entries and has empty data means a probe request.
// TODO(boyan) refactor, adds a new flag field?
rb.setData(ByteString.EMPTY);
final AppendEntriesRequest request = rb.build();
// Sending a probe request.
this.statInfo.runningState = RunningState.APPENDING_ENTRIES;
this.statInfo.firstLogIndex = this.nextIndex;
this.statInfo.lastLogIndex = this.nextIndex - 1;
this.probeCounter++;
setState(State.Probe);
final int stateVersion = this.version;
final int seq = getAndIncrementReqSeq();
final Future<Message> rpcFuture = this.rpcService.appendEntries(this.options.getPeerId().getEndpoint(), request, -1, new RpcResponseClosureAdapter<AppendEntriesResponse>() {
@Override
public void run(final Status status) {
onRpcReturned(Replicator.this.id, RequestType.AppendEntries, status, request, getResponse(), seq, stateVersion, monotonicSendTimeMs);
}
});
addInflight(RequestType.AppendEntries, this.nextIndex, 0, 0, seq, rpcFuture);
}
LOG.debug("Node {} send HeartbeatRequest to {} term {} lastCommittedIndex {}", this.options.getNode().getNodeId(), this.options.getPeerId(), this.options.getTerm(), rb.getCommittedIndex());
} finally {
unlockId();
}
}
use of com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest in project sofa-jraft by sofastack.
the class Replicator method sendEntries.
/**
* Send log entries to follower, returns true when success, otherwise false and unlock the id.
*
* @param nextSendingIndex next sending index
* @return send result.
*/
private boolean sendEntries(final long nextSendingIndex) {
final AppendEntriesRequest.Builder rb = AppendEntriesRequest.newBuilder();
if (!fillCommonFields(rb, nextSendingIndex - 1, false)) {
// unlock id in installSnapshot
installSnapshot();
return false;
}
ByteBufferCollector dataBuf = null;
final int maxEntriesSize = this.raftOptions.getMaxEntriesSize();
final RecyclableByteBufferList byteBufList = RecyclableByteBufferList.newInstance();
try {
for (int i = 0; i < maxEntriesSize; i++) {
final RaftOutter.EntryMeta.Builder emb = RaftOutter.EntryMeta.newBuilder();
if (!prepareEntry(nextSendingIndex, i, emb, byteBufList)) {
break;
}
rb.addEntries(emb.build());
}
if (rb.getEntriesCount() == 0) {
if (nextSendingIndex < this.options.getLogManager().getFirstLogIndex()) {
installSnapshot();
return false;
}
// _id is unlock in _wait_more
waitMoreEntries(nextSendingIndex);
return false;
}
if (byteBufList.getCapacity() > 0) {
dataBuf = ByteBufferCollector.allocateByRecyclers(byteBufList.getCapacity());
for (final ByteBuffer b : byteBufList) {
dataBuf.put(b);
}
final ByteBuffer buf = dataBuf.getBuffer();
buf.flip();
rb.setData(ZeroByteStringHelper.wrap(buf));
}
} finally {
RecycleUtil.recycle(byteBufList);
}
final AppendEntriesRequest request = rb.build();
if (LOG.isDebugEnabled()) {
LOG.debug("Node {} send AppendEntriesRequest to {} term {} lastCommittedIndex {} prevLogIndex {} prevLogTerm {} logIndex {} count {}", this.options.getNode().getNodeId(), this.options.getPeerId(), this.options.getTerm(), request.getCommittedIndex(), request.getPrevLogIndex(), request.getPrevLogTerm(), nextSendingIndex, request.getEntriesCount());
}
this.statInfo.runningState = RunningState.APPENDING_ENTRIES;
this.statInfo.firstLogIndex = rb.getPrevLogIndex() + 1;
this.statInfo.lastLogIndex = rb.getPrevLogIndex() + rb.getEntriesCount();
final Recyclable recyclable = dataBuf;
final int v = this.version;
final long monotonicSendTimeMs = Utils.monotonicMs();
final int seq = getAndIncrementReqSeq();
this.appendEntriesCounter++;
Future<Message> rpcFuture = null;
try {
rpcFuture = this.rpcService.appendEntries(this.options.getPeerId().getEndpoint(), request, -1, new RpcResponseClosureAdapter<AppendEntriesResponse>() {
@Override
public void run(final Status status) {
// TODO: recycle on send success, not response received.
RecycleUtil.recycle(recyclable);
onRpcReturned(Replicator.this.id, RequestType.AppendEntries, status, request, getResponse(), seq, v, monotonicSendTimeMs);
}
});
} catch (final Throwable t) {
RecycleUtil.recycle(recyclable);
ThrowUtil.throwException(t);
}
addInflight(RequestType.AppendEntries, nextSendingIndex, request.getEntriesCount(), request.getData().size(), seq, rpcFuture);
return true;
}
Aggregations