use of org.apache.ignite.raft.jraft.rpc.Message in project ignite-3 by apache.
the class FileServiceTest method testGetFileNotFoundReader.
@Test
public void testGetFileNotFoundReader() {
RpcRequests.GetFileRequest request = msgFactory.getFileRequest().count(Integer.MAX_VALUE).filename("data").offset(0).readerId(1).build();
RpcContext asyncContext = Mockito.mock(RpcContext.class);
Message msg = FileService.getInstance().handleGetFile(request, new RpcRequestClosure(asyncContext, msgFactory));
assertTrue(msg instanceof RpcRequests.ErrorResponse);
RpcRequests.ErrorResponse response = (RpcRequests.ErrorResponse) msg;
assertEquals(RaftError.ENOENT.getNumber(), response.errorCode());
assertEquals("Fail to find reader=1", response.errorMsg());
}
use of org.apache.ignite.raft.jraft.rpc.Message in project ignite-3 by apache.
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 AppendEntriesRequestBuilder rb = raftOptions.getRaftMessagesFactory().appendEntriesRequest();
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 {
List<RaftOutter.EntryMeta> entries = new ArrayList<>();
for (int i = 0; i < maxEntriesSize; i++) {
final EntryMetaBuilder emb = raftOptions.getRaftMessagesFactory().entryMeta();
if (!prepareEntry(nextSendingIndex, i, emb, byteBufList)) {
break;
}
entries.add(emb.build());
}
rb.entriesList(entries);
if (entries.isEmpty()) {
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.data(new ByteString(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.committedIndex(), request.prevLogIndex(), request.prevLogTerm(), nextSendingIndex, Utils.size(request.entriesList()));
}
this.statInfo.runningState = RunningState.APPENDING_ENTRIES;
this.statInfo.firstLogIndex = request.prevLogIndex() + 1;
this.statInfo.lastLogIndex = request.prevLogIndex() + Utils.size(request.entriesList());
final Recyclable recyclable = dataBuf;
final int v = this.version;
final long monotonicSendTimeMs = Utils.monotonicMs();
final int seq = getAndIncrementReqSeq();
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) {
if (status.isOk()) {
// TODO: recycle on send success, not response received IGNITE-14832.
// Also, this closure can be executed when rpcFuture was cancelled, but the request was not sent (meaning
// it's too early to recycle byte buffer)
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, Utils.size(request.entriesList()), request.data() == null ? 0 : request.data().size(), seq, rpcFuture);
return true;
}
use of org.apache.ignite.raft.jraft.rpc.Message in project ignite-3 by apache.
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 AppendEntriesRequestBuilder rb = raftOptions.getRaftMessagesFactory().appendEntriesRequest();
if (!fillCommonFields(rb, this.nextIndex - 1, isHeartbeat)) {
// id is unlock in installSnapshot
installSnapshot();
if (isHeartbeat && heartBeatClosure != null) {
Utils.runClosureInThread(options.getCommonExecutor(), heartBeatClosure, new Status(RaftError.EAGAIN, "Fail to send heartbeat to peer %s", this.options.getPeerId()));
}
return;
}
try {
final long monotonicSendTimeMs = Utils.monotonicMs();
final AppendEntriesRequest request;
if (isHeartbeat) {
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 refactor, adds a new flag field? https://issues.apache.org/jira/browse/IGNITE-14832
rb.data(ByteString.EMPTY);
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.appendEntriesCounter++;
this.state = 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(), request.committedIndex());
} finally {
this.id.unlock();
}
}
use of org.apache.ignite.raft.jraft.rpc.Message in project ignite-3 by apache.
the class Replicator method installSnapshot.
void installSnapshot() {
if (this.state == State.Snapshot) {
LOG.warn("Replicator {} is installing snapshot, ignore the new request.", this.options.getPeerId());
this.id.unlock();
return;
}
boolean doUnlock = true;
try {
Requires.requireTrue(this.reader == null, "Replicator %s already has a snapshot reader, current state is %s", this.options.getPeerId(), this.state);
this.reader = this.options.getSnapshotStorage().open();
if (this.reader == null) {
final NodeImpl node = this.options.getNode();
final RaftException error = new RaftException(EnumOutter.ErrorType.ERROR_TYPE_SNAPSHOT);
error.setStatus(new Status(RaftError.EIO, "Fail to open snapshot"));
this.id.unlock();
doUnlock = false;
node.onError(error);
return;
}
final String uri = this.reader.generateURIForCopy();
if (uri == null) {
final NodeImpl node = this.options.getNode();
final RaftException error = new RaftException(EnumOutter.ErrorType.ERROR_TYPE_SNAPSHOT);
error.setStatus(new Status(RaftError.EIO, "Fail to generate uri for snapshot reader"));
releaseReader();
this.id.unlock();
doUnlock = false;
node.onError(error);
return;
}
final RaftOutter.SnapshotMeta meta = this.reader.load();
if (meta == null) {
final String snapshotPath = this.reader.getPath();
final NodeImpl node = this.options.getNode();
final RaftException error = new RaftException(EnumOutter.ErrorType.ERROR_TYPE_SNAPSHOT);
error.setStatus(new Status(RaftError.EIO, "Fail to load meta from %s", snapshotPath));
releaseReader();
this.id.unlock();
doUnlock = false;
node.onError(error);
return;
}
final InstallSnapshotRequest request = raftOptions.getRaftMessagesFactory().installSnapshotRequest().term(options.getTerm()).groupId(options.getGroupId()).serverId(options.getServerId().toString()).peerId(options.getPeerId().toString()).meta(meta).uri(uri).build();
this.statInfo.runningState = RunningState.INSTALLING_SNAPSHOT;
this.statInfo.lastLogIncluded = meta.lastIncludedIndex();
this.statInfo.lastTermIncluded = meta.lastIncludedTerm();
this.state = State.Snapshot;
// noinspection NonAtomicOperationOnVolatileField
this.installSnapshotCounter++;
final long monotonicSendTimeMs = Utils.monotonicMs();
final int stateVersion = this.version;
final int seq = getAndIncrementReqSeq();
final Future<Message> rpcFuture = this.rpcService.installSnapshot(this.options.getPeerId().getEndpoint(), request, new RpcResponseClosureAdapter<InstallSnapshotResponse>() {
@Override
public void run(final Status status) {
onRpcReturned(Replicator.this.id, RequestType.Snapshot, status, request, getResponse(), seq, stateVersion, monotonicSendTimeMs);
}
});
addInflight(RequestType.Snapshot, this.nextIndex, 0, 0, seq, rpcFuture);
} finally {
if (doUnlock) {
this.id.unlock();
}
}
}
use of org.apache.ignite.raft.jraft.rpc.Message in project ignite-3 by apache.
the class AbstractClientService method connectAsync.
@Override
public CompletableFuture<Boolean> connectAsync(Endpoint endpoint) {
final RpcClient rc = this.rpcClient;
if (rc == null) {
throw new IllegalStateException("Client service is uninitialized.");
}
// Remote node is alive and pinged, safe to continue.
if (readyAddresses.contains(endpoint.toString())) {
return CompletableFuture.completedFuture(true);
}
final RpcRequests.PingRequest req = rpcOptions.getRaftMessagesFactory().pingRequest().sendTimestamp(System.currentTimeMillis()).build();
CompletableFuture<Message> fut = invokeWithDone(endpoint, req, null, null, rpcOptions.getRpcConnectTimeoutMs(), rpcExecutor);
return fut.thenApply(msg -> {
ErrorResponse resp = (ErrorResponse) msg;
if (resp != null && resp.errorCode() == 0) {
readyAddresses.add(endpoint.toString());
return true;
} else {
return false;
}
});
}
Aggregations