Search in sources :

Example 1 with BeginQuorumEpochResponseData

use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.

the class RaftClientTestContext method assertSentBeginQuorumEpochResponse.

void assertSentBeginQuorumEpochResponse(Errors partitionError, int epoch, OptionalInt leaderId) {
    List<RaftResponse.Outbound> sentMessages = drainSentResponses(ApiKeys.BEGIN_QUORUM_EPOCH);
    assertEquals(1, sentMessages.size());
    RaftMessage raftMessage = sentMessages.get(0);
    assertTrue(raftMessage.data() instanceof BeginQuorumEpochResponseData);
    BeginQuorumEpochResponseData response = (BeginQuorumEpochResponseData) raftMessage.data();
    assertEquals(Errors.NONE, Errors.forCode(response.errorCode()));
    BeginQuorumEpochResponseData.PartitionData partitionResponse = response.topics().get(0).partitions().get(0);
    assertEquals(epoch, partitionResponse.leaderEpoch());
    assertEquals(leaderId.orElse(-1), partitionResponse.leaderId());
    assertEquals(partitionError, Errors.forCode(partitionResponse.errorCode()));
}
Also used : BeginQuorumEpochResponseData(org.apache.kafka.common.message.BeginQuorumEpochResponseData)

Example 2 with BeginQuorumEpochResponseData

use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.

the class RaftClientTestContext method assertSentBeginQuorumEpochResponse.

void assertSentBeginQuorumEpochResponse(Errors responseError) {
    List<RaftResponse.Outbound> sentMessages = drainSentResponses(ApiKeys.BEGIN_QUORUM_EPOCH);
    assertEquals(1, sentMessages.size());
    RaftMessage raftMessage = sentMessages.get(0);
    assertTrue(raftMessage.data() instanceof BeginQuorumEpochResponseData);
    BeginQuorumEpochResponseData response = (BeginQuorumEpochResponseData) raftMessage.data();
    assertEquals(responseError, Errors.forCode(response.errorCode()));
}
Also used : BeginQuorumEpochResponseData(org.apache.kafka.common.message.BeginQuorumEpochResponseData)

Example 3 with BeginQuorumEpochResponseData

use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.

the class KafkaRaftClient method handleBeginQuorumEpochResponse.

private boolean handleBeginQuorumEpochResponse(RaftResponse.Inbound responseMetadata, long currentTimeMs) {
    int remoteNodeId = responseMetadata.sourceId();
    BeginQuorumEpochResponseData response = (BeginQuorumEpochResponseData) responseMetadata.data;
    Errors topLevelError = Errors.forCode(response.errorCode());
    if (topLevelError != Errors.NONE) {
        return handleTopLevelError(topLevelError, responseMetadata);
    }
    if (!hasValidTopicPartition(response, log.topicPartition())) {
        return false;
    }
    BeginQuorumEpochResponseData.PartitionData partitionResponse = response.topics().get(0).partitions().get(0);
    Errors partitionError = Errors.forCode(partitionResponse.errorCode());
    OptionalInt responseLeaderId = optionalLeaderId(partitionResponse.leaderId());
    int responseEpoch = partitionResponse.leaderEpoch();
    Optional<Boolean> handled = maybeHandleCommonResponse(partitionError, responseLeaderId, responseEpoch, currentTimeMs);
    if (handled.isPresent()) {
        return handled.get();
    } else if (partitionError == Errors.NONE) {
        if (quorum.isLeader()) {
            LeaderState<T> state = quorum.leaderStateOrThrow();
            state.addAcknowledgementFrom(remoteNodeId);
        } else {
            logger.debug("Ignoring BeginQuorumEpoch response {} since " + "this node is not the leader anymore", response);
        }
        return true;
    } else {
        return handleUnexpectedError(partitionError, responseMetadata);
    }
}
Also used : Errors(org.apache.kafka.common.protocol.Errors) OptionalInt(java.util.OptionalInt) BeginQuorumEpochResponseData(org.apache.kafka.common.message.BeginQuorumEpochResponseData)

Example 4 with BeginQuorumEpochResponseData

use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.

the class KafkaRaftClient method handleBeginQuorumEpochRequest.

/**
 * Handle a BeginEpoch request. This API may return the following errors:
 *
 * - {@link Errors#INCONSISTENT_CLUSTER_ID} if the cluster id is presented in request
 *      but different from this node
 * - {@link Errors#BROKER_NOT_AVAILABLE} if this node is currently shutting down
 * - {@link Errors#INCONSISTENT_VOTER_SET} if the request suggests inconsistent voter membership (e.g.
 *      if this node or the sender is not one of the current known voters)
 * - {@link Errors#FENCED_LEADER_EPOCH} if the epoch is smaller than this node's epoch
 */
private BeginQuorumEpochResponseData handleBeginQuorumEpochRequest(RaftRequest.Inbound requestMetadata, long currentTimeMs) {
    BeginQuorumEpochRequestData request = (BeginQuorumEpochRequestData) requestMetadata.data;
    if (!hasValidClusterId(request.clusterId())) {
        return new BeginQuorumEpochResponseData().setErrorCode(Errors.INCONSISTENT_CLUSTER_ID.code());
    }
    if (!hasValidTopicPartition(request, log.topicPartition())) {
        // Until we support multi-raft, we treat topic partition mismatches as invalid requests
        return new BeginQuorumEpochResponseData().setErrorCode(Errors.INVALID_REQUEST.code());
    }
    BeginQuorumEpochRequestData.PartitionData partitionRequest = request.topics().get(0).partitions().get(0);
    int requestLeaderId = partitionRequest.leaderId();
    int requestEpoch = partitionRequest.leaderEpoch();
    Optional<Errors> errorOpt = validateVoterOnlyRequest(requestLeaderId, requestEpoch);
    if (errorOpt.isPresent()) {
        return buildBeginQuorumEpochResponse(errorOpt.get());
    }
    maybeTransition(OptionalInt.of(requestLeaderId), requestEpoch, currentTimeMs);
    return buildBeginQuorumEpochResponse(Errors.NONE);
}
Also used : BeginQuorumEpochRequestData(org.apache.kafka.common.message.BeginQuorumEpochRequestData) Errors(org.apache.kafka.common.protocol.Errors) BeginQuorumEpochResponseData(org.apache.kafka.common.message.BeginQuorumEpochResponseData)

Example 5 with BeginQuorumEpochResponseData

use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.

the class KafkaRaftClientTest method testClusterAuthorizationFailedInBeginQuorumEpoch.

@Test
public void testClusterAuthorizationFailedInBeginQuorumEpoch() throws Exception {
    int localId = 0;
    int otherNodeId = 1;
    int epoch = 5;
    Set<Integer> voters = Utils.mkSet(localId, otherNodeId);
    RaftClientTestContext context = new RaftClientTestContext.Builder(localId, voters).updateRandom(r -> r.mockNextInt(DEFAULT_ELECTION_TIMEOUT_MS, 0)).withUnknownLeader(epoch - 1).build();
    context.time.sleep(context.electionTimeoutMs());
    context.expectAndGrantVotes(epoch);
    context.pollUntilRequest();
    int correlationId = context.assertSentBeginQuorumEpochRequest(epoch, 1);
    BeginQuorumEpochResponseData response = new BeginQuorumEpochResponseData().setErrorCode(Errors.CLUSTER_AUTHORIZATION_FAILED.code());
    context.deliverResponse(correlationId, otherNodeId, response);
    assertThrows(ClusterAuthorizationException.class, context.client::poll);
}
Also used : BeginQuorumEpochResponseData(org.apache.kafka.common.message.BeginQuorumEpochResponseData) Test(org.junit.jupiter.api.Test)

Aggregations

BeginQuorumEpochResponseData (org.apache.kafka.common.message.BeginQuorumEpochResponseData)6 Errors (org.apache.kafka.common.protocol.Errors)2 OptionalInt (java.util.OptionalInt)1 BeginQuorumEpochRequestData (org.apache.kafka.common.message.BeginQuorumEpochRequestData)1 Test (org.junit.jupiter.api.Test)1