use of org.apache.ignite.raft.jraft.util.ByteString 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.util.ByteString in project ignite-3 by apache.
the class FileService method handleGetFile.
/**
* Handle GetFileRequest, run the response or set the response with done.
*/
public Message handleGetFile(final GetFileRequest request, final RpcRequestClosure done) {
if (request.count() <= 0 || request.offset() < 0) {
return //
RaftRpcFactory.DEFAULT.newResponse(msgFactory, RaftError.EREQUEST, "Invalid request: %s", request);
}
final FileReader reader = this.fileReaderMap.get(request.readerId());
if (LOG.isDebugEnabled()) {
LOG.info("handleGetFile id={}, name={}, offset={}, cnt={}", request.readerId(), request.filename(), request.offset(), request.count());
}
if (reader == null) {
return //
RaftRpcFactory.DEFAULT.newResponse(msgFactory, RaftError.ENOENT, "Fail to find reader=%d", request.readerId());
}
if (LOG.isDebugEnabled()) {
LOG.debug("GetFile from {} path={} filename={} offset={} count={}", done.getRpcCtx().getRemoteAddress(), reader.getPath(), request.filename(), request.offset(), request.count());
}
final ByteBufferCollector dataBuffer = ByteBufferCollector.allocate();
final GetFileResponseBuilder responseBuilder = msgFactory.getFileResponse();
try {
final int read = reader.readFile(dataBuffer, request.filename(), request.offset(), request.count());
responseBuilder.readSize(read);
responseBuilder.eof(read == FileReader.EOF);
final ByteBuffer buf = dataBuffer.getBuffer();
buf.flip();
if (!buf.hasRemaining()) {
// skip empty data
responseBuilder.data(ByteString.EMPTY);
} else {
// TODO check hole https://issues.apache.org/jira/browse/IGNITE-14832
responseBuilder.data(new ByteString(buf));
}
return responseBuilder.build();
} catch (final RetryAgainException e) {
return //
RaftRpcFactory.DEFAULT.newResponse(msgFactory, RaftError.EAGAIN, "Fail to read from path=%s filename=%s with error: %s", reader.getPath(), request.filename(), e.getMessage());
} catch (final IOException e) {
LOG.error("Fail to read file path={} filename={}", e, reader.getPath(), request.filename());
return //
RaftRpcFactory.DEFAULT.newResponse(msgFactory, RaftError.EIO, "Fail to read from path=%s filename=%s", reader.getPath(), request.filename());
}
}
use of org.apache.ignite.raft.jraft.util.ByteString in project ignite-3 by apache.
the class ReadOnlyServiceImpl method executeReadIndexEvents.
private void executeReadIndexEvents(final List<ReadIndexEvent> events) {
if (events.isEmpty())
return;
ReadIndexRequestBuilder rb = raftOptions.getRaftMessagesFactory().readIndexRequest().groupId(this.node.getGroupId()).serverId(this.node.getServerId().toString());
List<ReadIndexState> states = new ArrayList<>(events.size());
List<ByteString> entries = new ArrayList<>(events.size());
for (ReadIndexEvent event : events) {
byte[] ctx = event.requestContext.get();
entries.add(ctx == null ? ByteString.EMPTY : new ByteString(ctx));
states.add(new ReadIndexState(event.requestContext, event.done, event.startTime));
}
ReadIndexRequest request = rb.entriesList(entries).build();
this.node.handleReadIndexRequest(request, new ReadIndexResponseClosure(states, request));
}
use of org.apache.ignite.raft.jraft.util.ByteString in project ignite-3 by apache.
the class SnapshotExecutorTest method testInstallSnapshot.
@Test
public void testInstallSnapshot() throws Exception {
RaftMessagesFactory msgFactory = raftOptions.getRaftMessagesFactory();
final RpcRequests.InstallSnapshotRequest irb = msgFactory.installSnapshotRequest().groupId("test").peerId(addr.toString()).serverId("localhost:8080").uri("remote://localhost:8080/99").term(0).meta(msgFactory.snapshotMeta().lastIncludedIndex(1).lastIncludedTerm(2).build()).build();
Mockito.when(raftClientService.connect(new Endpoint("localhost", 8080))).thenReturn(true);
final CompletableFuture<Message> fut = new CompletableFuture<>();
final GetFileRequestBuilder rb = msgFactory.getFileRequest().readerId(99).filename(Snapshot.JRAFT_SNAPSHOT_META_FILE).count(Integer.MAX_VALUE).offset(0).readPartly(true);
// Mock get metadata
ArgumentCaptor<RpcResponseClosure> argument = ArgumentCaptor.forClass(RpcResponseClosure.class);
Mockito.when(raftClientService.getFile(eq(new Endpoint("localhost", 8080)), eq(rb.build()), eq(copyOpts.getTimeoutMs()), argument.capture())).thenReturn(fut);
Future<?> snapFut = Utils.runInThread(ForkJoinPool.commonPool(), () -> executor.installSnapshot(irb, msgFactory.installSnapshotResponse(), new RpcRequestClosure(asyncCtx, msgFactory)));
assertTrue(TestUtils.waitForArgumentCapture(argument, 5_000));
RpcResponseClosure<RpcRequests.GetFileResponse> closure = argument.getValue();
final ByteBuffer metaBuf = table.saveToByteBufferAsRemote();
closure.setResponse(msgFactory.getFileResponse().readSize(metaBuf.remaining()).eof(true).data(new ByteString(metaBuf)).build());
// Mock get file
argument = ArgumentCaptor.forClass(RpcResponseClosure.class);
rb.filename("testFile");
rb.count(raftOptions.getMaxByteCountPerRpc());
Mockito.when(raftClientService.getFile(eq(new Endpoint("localhost", 8080)), eq(rb.build()), eq(copyOpts.getTimeoutMs()), argument.capture())).thenReturn(fut);
closure.run(Status.OK());
assertTrue(TestUtils.waitForArgumentCapture(argument, 5_000));
closure = argument.getValue();
closure.setResponse(msgFactory.getFileResponse().readSize(100).eof(true).data(new ByteString(new byte[100])).build());
ArgumentCaptor<LoadSnapshotClosure> loadSnapshotArg = ArgumentCaptor.forClass(LoadSnapshotClosure.class);
Mockito.when(fSMCaller.onSnapshotLoad(loadSnapshotArg.capture())).thenReturn(true);
closure.run(Status.OK());
assertTrue(TestUtils.waitForArgumentCapture(loadSnapshotArg, 5_000));
final LoadSnapshotClosure done = loadSnapshotArg.getValue();
final SnapshotReader reader = done.start();
assertNotNull(reader);
assertEquals(1, reader.listFiles().size());
assertTrue(reader.listFiles().contains("testFile"));
done.run(Status.OK());
executor.join();
assertTrue(snapFut.isDone());
assertEquals(2, executor.getLastSnapshotTerm());
assertEquals(1, executor.getLastSnapshotIndex());
}
use of org.apache.ignite.raft.jraft.util.ByteString in project ignite-3 by apache.
the class CopySessionTest method testOnRpcReturnedEOF.
@Test
public void testOnRpcReturnedEOF() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
Thread t = new Thread(() -> {
try {
// test join, should return
session.join();
latch.countDown();
} catch (final InterruptedException e) {
// No-op.
}
});
try {
t.start();
assertNull(this.session.getRpcCall());
final ByteBufferCollector bufRef = ByteBufferCollector.allocate(0);
this.session.setDestBuf(bufRef);
this.session.onRpcReturned(Status.OK(), raftOpts.getRaftMessagesFactory().getFileResponse().readSize(100).eof(true).data(new ByteString(new byte[100])).build());
assertEquals(100, bufRef.capacity());
// should be flip
assertEquals(0, bufRef.getBuffer().position());
assertEquals(100, bufRef.getBuffer().remaining());
assertNull(this.session.getRpcCall());
latch.await();
} finally {
t.join();
}
}
Aggregations