Search in sources :

Example 11 with Message

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());
}
Also used : RpcContext(org.apache.ignite.raft.jraft.rpc.RpcContext) Message(org.apache.ignite.raft.jraft.rpc.Message) RpcRequests(org.apache.ignite.raft.jraft.rpc.RpcRequests) RpcRequestClosure(org.apache.ignite.raft.jraft.rpc.RpcRequestClosure) Test(org.junit.jupiter.api.Test)

Example 12 with Message

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;
}
Also used : Status(org.apache.ignite.raft.jraft.Status) RecyclableByteBufferList(org.apache.ignite.raft.jraft.util.RecyclableByteBufferList) Message(org.apache.ignite.raft.jraft.rpc.Message) ByteString(org.apache.ignite.raft.jraft.util.ByteString) ArrayList(java.util.ArrayList) RpcResponseClosureAdapter(org.apache.ignite.raft.jraft.rpc.RpcResponseClosureAdapter) AppendEntriesRequest(org.apache.ignite.raft.jraft.rpc.RpcRequests.AppendEntriesRequest) ByteBuffer(java.nio.ByteBuffer) ByteBufferCollector(org.apache.ignite.raft.jraft.util.ByteBufferCollector) AppendEntriesRequestBuilder(org.apache.ignite.raft.jraft.rpc.AppendEntriesRequestBuilder) Recyclable(org.apache.ignite.raft.jraft.util.Recyclable) EntryMetaBuilder(org.apache.ignite.raft.jraft.entity.EntryMetaBuilder)

Example 13 with Message

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();
    }
}
Also used : Status(org.apache.ignite.raft.jraft.Status) AppendEntriesResponse(org.apache.ignite.raft.jraft.rpc.RpcRequests.AppendEntriesResponse) AppendEntriesRequestBuilder(org.apache.ignite.raft.jraft.rpc.AppendEntriesRequestBuilder) Message(org.apache.ignite.raft.jraft.rpc.Message) AppendEntriesRequest(org.apache.ignite.raft.jraft.rpc.RpcRequests.AppendEntriesRequest)

Example 14 with Message

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();
        }
    }
}
Also used : Status(org.apache.ignite.raft.jraft.Status) RaftException(org.apache.ignite.raft.jraft.error.RaftException) Message(org.apache.ignite.raft.jraft.rpc.Message) RaftOutter(org.apache.ignite.raft.jraft.entity.RaftOutter) InstallSnapshotRequest(org.apache.ignite.raft.jraft.rpc.RpcRequests.InstallSnapshotRequest) ByteString(org.apache.ignite.raft.jraft.util.ByteString) InstallSnapshotResponse(org.apache.ignite.raft.jraft.rpc.RpcRequests.InstallSnapshotResponse)

Example 15 with Message

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;
        }
    });
}
Also used : Message(org.apache.ignite.raft.jraft.rpc.Message) RpcRequests(org.apache.ignite.raft.jraft.rpc.RpcRequests) RpcClient(org.apache.ignite.raft.jraft.rpc.RpcClient) ErrorResponse(org.apache.ignite.raft.jraft.rpc.RpcRequests.ErrorResponse)

Aggregations

Message (org.apache.ignite.raft.jraft.rpc.Message)35 Status (org.apache.ignite.raft.jraft.Status)18 RpcRequests (org.apache.ignite.raft.jraft.rpc.RpcRequests)16 Test (org.junit.jupiter.api.Test)15 PeerId (org.apache.ignite.raft.jraft.entity.PeerId)12 JRaftException (org.apache.ignite.raft.jraft.error.JRaftException)11 CompletableFuture (java.util.concurrent.CompletableFuture)10 ByteString (org.apache.ignite.raft.jraft.util.ByteString)7 RpcRequestClosure (org.apache.ignite.raft.jraft.rpc.RpcRequestClosure)6 RpcResponseClosure (org.apache.ignite.raft.jraft.rpc.RpcResponseClosure)5 SnapshotReader (org.apache.ignite.raft.jraft.storage.snapshot.SnapshotReader)5 Endpoint (org.apache.ignite.raft.jraft.util.Endpoint)5 ByteBuffer (java.nio.ByteBuffer)3 ArrayList (java.util.ArrayList)3 Configuration (org.apache.ignite.raft.jraft.conf.Configuration)3 RemotingException (org.apache.ignite.raft.jraft.error.RemotingException)3 AppendEntriesRequestBuilder (org.apache.ignite.raft.jraft.rpc.AppendEntriesRequestBuilder)3 RpcContext (org.apache.ignite.raft.jraft.rpc.RpcContext)3 ErrorResponse (org.apache.ignite.raft.jraft.rpc.RpcRequests.ErrorResponse)3 ByteBufferCollector (org.apache.ignite.raft.jraft.util.ByteBufferCollector)3