Search in sources :

Example 1 with AppendEntriesRequest

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);
}
Also used : PeerPair(com.alipay.sofa.jraft.rpc.impl.core.AppendEntriesRequestProcessor.PeerPair) PeerRequestContext(com.alipay.sofa.jraft.rpc.impl.core.AppendEntriesRequestProcessor.PeerRequestContext) AppendEntriesRequest(com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest)

Example 2 with AppendEntriesRequest

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());
}
Also used : AppendEntriesRequestHeader(com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequestHeader) AppendEntriesRequest(com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest) RpcCommandFactory(com.alipay.remoting.rpc.RpcCommandFactory) RpcRequestCommand(com.alipay.remoting.rpc.protocol.RpcRequestCommand) Test(org.junit.Test)

Example 3 with AppendEntriesRequest

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();
    }
}
Also used : Status(com.alipay.sofa.jraft.Status) AppendEntriesResponse(com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesResponse) Message(com.google.protobuf.Message) AppendEntriesRequest(com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest)

Example 4 with AppendEntriesRequest

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;
}
Also used : Status(com.alipay.sofa.jraft.Status) RecyclableByteBufferList(com.alipay.sofa.jraft.util.RecyclableByteBufferList) Message(com.google.protobuf.Message) RpcResponseClosureAdapter(com.alipay.sofa.jraft.rpc.RpcResponseClosureAdapter) AppendEntriesRequest(com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest) ByteBuffer(java.nio.ByteBuffer) ByteBufferCollector(com.alipay.sofa.jraft.util.ByteBufferCollector) Recyclable(com.alipay.sofa.jraft.util.Recyclable)

Aggregations

AppendEntriesRequest (com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest)4 Status (com.alipay.sofa.jraft.Status)2 Message (com.google.protobuf.Message)2 RpcCommandFactory (com.alipay.remoting.rpc.RpcCommandFactory)1 RpcRequestCommand (com.alipay.remoting.rpc.protocol.RpcRequestCommand)1 AppendEntriesRequestHeader (com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequestHeader)1 AppendEntriesResponse (com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesResponse)1 RpcResponseClosureAdapter (com.alipay.sofa.jraft.rpc.RpcResponseClosureAdapter)1 PeerPair (com.alipay.sofa.jraft.rpc.impl.core.AppendEntriesRequestProcessor.PeerPair)1 PeerRequestContext (com.alipay.sofa.jraft.rpc.impl.core.AppendEntriesRequestProcessor.PeerRequestContext)1 ByteBufferCollector (com.alipay.sofa.jraft.util.ByteBufferCollector)1 Recyclable (com.alipay.sofa.jraft.util.Recyclable)1 RecyclableByteBufferList (com.alipay.sofa.jraft.util.RecyclableByteBufferList)1 ByteBuffer (java.nio.ByteBuffer)1 Test (org.junit.Test)1