Search in sources :

Example 81 with Uuid

use of org.apache.kafka.common.Uuid in project kafka by apache.

the class ReplicationControlManager method electLeader.

ApiError electLeader(String topic, int partitionId, ElectionType electionType, List<ApiMessageAndVersion> records) {
    Uuid topicId = topicsByName.get(topic);
    if (topicId == null) {
        return new ApiError(UNKNOWN_TOPIC_OR_PARTITION, "No such topic as " + topic);
    }
    TopicControlInfo topicInfo = topics.get(topicId);
    if (topicInfo == null) {
        return new ApiError(UNKNOWN_TOPIC_OR_PARTITION, "No such topic id as " + topicId);
    }
    PartitionRegistration partition = topicInfo.parts.get(partitionId);
    if (partition == null) {
        return new ApiError(UNKNOWN_TOPIC_OR_PARTITION, "No such partition as " + topic + "-" + partitionId);
    }
    if ((electionType == ElectionType.PREFERRED && partition.hasPreferredLeader()) || (electionType == ElectionType.UNCLEAN && partition.hasLeader())) {
        return new ApiError(Errors.ELECTION_NOT_NEEDED);
    }
    PartitionChangeBuilder builder = new PartitionChangeBuilder(partition, topicId, partitionId, r -> clusterControl.unfenced(r), () -> electionType == ElectionType.UNCLEAN);
    builder.setAlwaysElectPreferredIfPossible(electionType == ElectionType.PREFERRED);
    Optional<ApiMessageAndVersion> record = builder.build();
    if (!record.isPresent()) {
        if (electionType == ElectionType.PREFERRED) {
            return new ApiError(Errors.PREFERRED_LEADER_NOT_AVAILABLE);
        } else {
            return new ApiError(Errors.ELIGIBLE_LEADERS_NOT_AVAILABLE);
        }
    }
    records.add(record.get());
    return ApiError.NONE;
}
Also used : PartitionRegistration(org.apache.kafka.metadata.PartitionRegistration) Uuid(org.apache.kafka.common.Uuid) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) ApiError(org.apache.kafka.common.requests.ApiError)

Example 82 with Uuid

use of org.apache.kafka.common.Uuid in project kafka by apache.

the class ReplicationControlManager method createTopic.

private ApiError createTopic(CreatableTopic topic, List<ApiMessageAndVersion> records, Map<String, CreatableTopicResult> successes) {
    Map<Integer, PartitionRegistration> newParts = new HashMap<>();
    if (!topic.assignments().isEmpty()) {
        if (topic.replicationFactor() != -1) {
            return new ApiError(INVALID_REQUEST, "A manual partition assignment was specified, but replication " + "factor was not set to -1.");
        }
        if (topic.numPartitions() != -1) {
            return new ApiError(INVALID_REQUEST, "A manual partition assignment was specified, but numPartitions " + "was not set to -1.");
        }
        OptionalInt replicationFactor = OptionalInt.empty();
        for (CreatableReplicaAssignment assignment : topic.assignments()) {
            if (newParts.containsKey(assignment.partitionIndex())) {
                return new ApiError(Errors.INVALID_REPLICA_ASSIGNMENT, "Found multiple manual partition assignments for partition " + assignment.partitionIndex());
            }
            validateManualPartitionAssignment(assignment.brokerIds(), replicationFactor);
            replicationFactor = OptionalInt.of(assignment.brokerIds().size());
            List<Integer> isr = assignment.brokerIds().stream().filter(clusterControl::unfenced).collect(Collectors.toList());
            if (isr.isEmpty()) {
                return new ApiError(Errors.INVALID_REPLICA_ASSIGNMENT, "All brokers specified in the manual partition assignment for " + "partition " + assignment.partitionIndex() + " are fenced.");
            }
            newParts.put(assignment.partitionIndex(), new PartitionRegistration(Replicas.toArray(assignment.brokerIds()), Replicas.toArray(isr), Replicas.NONE, Replicas.NONE, isr.get(0), 0, 0));
        }
        ApiError error = maybeCheckCreateTopicPolicy(() -> {
            Map<Integer, List<Integer>> assignments = new HashMap<>();
            newParts.entrySet().forEach(e -> assignments.put(e.getKey(), Replicas.toList(e.getValue().replicas)));
            Map<String, String> configs = new HashMap<>();
            topic.configs().forEach(config -> configs.put(config.name(), config.value()));
            return new CreateTopicPolicy.RequestMetadata(topic.name(), null, null, assignments, configs);
        });
        if (error.isFailure())
            return error;
    } else if (topic.replicationFactor() < -1 || topic.replicationFactor() == 0) {
        return new ApiError(Errors.INVALID_REPLICATION_FACTOR, "Replication factor must be larger than 0, or -1 to use the default value.");
    } else if (topic.numPartitions() < -1 || topic.numPartitions() == 0) {
        return new ApiError(Errors.INVALID_PARTITIONS, "Number of partitions was set to an invalid non-positive value.");
    } else {
        int numPartitions = topic.numPartitions() == -1 ? defaultNumPartitions : topic.numPartitions();
        short replicationFactor = topic.replicationFactor() == -1 ? defaultReplicationFactor : topic.replicationFactor();
        try {
            List<List<Integer>> replicas = clusterControl.placeReplicas(0, numPartitions, replicationFactor);
            for (int partitionId = 0; partitionId < replicas.size(); partitionId++) {
                int[] r = Replicas.toArray(replicas.get(partitionId));
                newParts.put(partitionId, new PartitionRegistration(r, r, Replicas.NONE, Replicas.NONE, r[0], 0, 0));
            }
        } catch (InvalidReplicationFactorException e) {
            return new ApiError(Errors.INVALID_REPLICATION_FACTOR, "Unable to replicate the partition " + replicationFactor + " time(s): " + e.getMessage());
        }
        ApiError error = maybeCheckCreateTopicPolicy(() -> {
            Map<String, String> configs = new HashMap<>();
            topic.configs().forEach(config -> configs.put(config.name(), config.value()));
            return new CreateTopicPolicy.RequestMetadata(topic.name(), numPartitions, replicationFactor, null, configs);
        });
        if (error.isFailure())
            return error;
    }
    Uuid topicId = Uuid.randomUuid();
    successes.put(topic.name(), new CreatableTopicResult().setName(topic.name()).setTopicId(topicId).setErrorCode((short) 0).setErrorMessage(null).setNumPartitions(newParts.size()).setReplicationFactor((short) newParts.get(0).replicas.length));
    records.add(new ApiMessageAndVersion(new TopicRecord().setName(topic.name()).setTopicId(topicId), TOPIC_RECORD.highestSupportedVersion()));
    for (Entry<Integer, PartitionRegistration> partEntry : newParts.entrySet()) {
        int partitionIndex = partEntry.getKey();
        PartitionRegistration info = partEntry.getValue();
        records.add(info.toRecord(topicId, partitionIndex));
    }
    return ApiError.NONE;
}
Also used : PartitionRegistration(org.apache.kafka.metadata.PartitionRegistration) RemoveTopicRecord(org.apache.kafka.common.metadata.RemoveTopicRecord) TopicRecord(org.apache.kafka.common.metadata.TopicRecord) TimelineHashMap(org.apache.kafka.timeline.TimelineHashMap) HashMap(java.util.HashMap) OptionalInt(java.util.OptionalInt) TimelineInteger(org.apache.kafka.timeline.TimelineInteger) Uuid(org.apache.kafka.common.Uuid) CreatableReplicaAssignment(org.apache.kafka.common.message.CreateTopicsRequestData.CreatableReplicaAssignment) InvalidReplicationFactorException(org.apache.kafka.common.errors.InvalidReplicationFactorException) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) CreatableTopicResult(org.apache.kafka.common.message.CreateTopicsResponseData.CreatableTopicResult) ArrayList(java.util.ArrayList) List(java.util.List) ApiError(org.apache.kafka.common.requests.ApiError)

Example 83 with Uuid

use of org.apache.kafka.common.Uuid in project kafka by apache.

the class ReplicationControlManager method createPartitions.

void createPartitions(CreatePartitionsTopic topic, List<ApiMessageAndVersion> records) {
    Uuid topicId = topicsByName.get(topic.name());
    if (topicId == null) {
        throw new UnknownTopicOrPartitionException();
    }
    TopicControlInfo topicInfo = topics.get(topicId);
    if (topicInfo == null) {
        throw new UnknownTopicOrPartitionException();
    }
    if (topic.count() == topicInfo.parts.size()) {
        throw new InvalidPartitionsException("Topic already has " + topicInfo.parts.size() + " partition(s).");
    } else if (topic.count() < topicInfo.parts.size()) {
        throw new InvalidPartitionsException("The topic " + topic.name() + " currently " + "has " + topicInfo.parts.size() + " partition(s); " + topic.count() + " would not be an increase.");
    }
    int additional = topic.count() - topicInfo.parts.size();
    if (topic.assignments() != null) {
        if (topic.assignments().size() != additional) {
            throw new InvalidReplicaAssignmentException("Attempted to add " + additional + " additional partition(s), but only " + topic.assignments().size() + " assignment(s) were specified.");
        }
    }
    Iterator<PartitionRegistration> iterator = topicInfo.parts.values().iterator();
    if (!iterator.hasNext()) {
        throw new UnknownServerException("Invalid state: topic " + topic.name() + " appears to have no partitions.");
    }
    PartitionRegistration partitionInfo = iterator.next();
    if (partitionInfo.replicas.length > Short.MAX_VALUE) {
        throw new UnknownServerException("Invalid replication factor " + partitionInfo.replicas.length + ": expected a number equal to less than " + Short.MAX_VALUE);
    }
    short replicationFactor = (short) partitionInfo.replicas.length;
    int startPartitionId = topicInfo.parts.size();
    List<List<Integer>> placements;
    List<List<Integer>> isrs;
    if (topic.assignments() != null) {
        placements = new ArrayList<>();
        isrs = new ArrayList<>();
        for (int i = 0; i < topic.assignments().size(); i++) {
            CreatePartitionsAssignment assignment = topic.assignments().get(i);
            validateManualPartitionAssignment(assignment.brokerIds(), OptionalInt.of(replicationFactor));
            placements.add(assignment.brokerIds());
            List<Integer> isr = assignment.brokerIds().stream().filter(clusterControl::unfenced).collect(Collectors.toList());
            if (isr.isEmpty()) {
                throw new InvalidReplicaAssignmentException("All brokers specified in the manual partition assignment for " + "partition " + (startPartitionId + i) + " are fenced.");
            }
            isrs.add(isr);
        }
    } else {
        placements = clusterControl.placeReplicas(startPartitionId, additional, replicationFactor);
        isrs = placements;
    }
    int partitionId = startPartitionId;
    for (int i = 0; i < placements.size(); i++) {
        List<Integer> placement = placements.get(i);
        List<Integer> isr = isrs.get(i);
        records.add(new ApiMessageAndVersion(new PartitionRecord().setPartitionId(partitionId).setTopicId(topicId).setReplicas(placement).setIsr(isr).setRemovingReplicas(Collections.emptyList()).setAddingReplicas(Collections.emptyList()).setLeader(isr.get(0)).setLeaderEpoch(0).setPartitionEpoch(0), PARTITION_RECORD.highestSupportedVersion()));
        partitionId++;
    }
}
Also used : PartitionRegistration(org.apache.kafka.metadata.PartitionRegistration) UnknownTopicOrPartitionException(org.apache.kafka.common.errors.UnknownTopicOrPartitionException) PartitionRecord(org.apache.kafka.common.metadata.PartitionRecord) InvalidPartitionsException(org.apache.kafka.common.errors.InvalidPartitionsException) UnknownServerException(org.apache.kafka.common.errors.UnknownServerException) TimelineInteger(org.apache.kafka.timeline.TimelineInteger) Uuid(org.apache.kafka.common.Uuid) CreatePartitionsAssignment(org.apache.kafka.common.message.CreatePartitionsRequestData.CreatePartitionsAssignment) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) ArrayList(java.util.ArrayList) List(java.util.List) InvalidReplicaAssignmentException(org.apache.kafka.common.errors.InvalidReplicaAssignmentException)

Example 84 with Uuid

use of org.apache.kafka.common.Uuid in project kafka by apache.

the class ReplicationControlManager method electLeaders.

ControllerResult<ElectLeadersResponseData> electLeaders(ElectLeadersRequestData request) {
    ElectionType electionType = electionType(request.electionType());
    List<ApiMessageAndVersion> records = new ArrayList<>();
    ElectLeadersResponseData response = new ElectLeadersResponseData();
    if (request.topicPartitions() == null) {
        // compatibility with the old controller.
        for (Entry<String, Uuid> topicEntry : topicsByName.entrySet()) {
            String topicName = topicEntry.getKey();
            ReplicaElectionResult topicResults = new ReplicaElectionResult().setTopic(topicName);
            response.replicaElectionResults().add(topicResults);
            TopicControlInfo topic = topics.get(topicEntry.getValue());
            if (topic != null) {
                for (int partitionId : topic.parts.keySet()) {
                    ApiError error = electLeader(topicName, partitionId, electionType, records);
                    // partitions which already have the desired leader.
                    if (error.error() != Errors.ELECTION_NOT_NEEDED) {
                        topicResults.partitionResult().add(new PartitionResult().setPartitionId(partitionId).setErrorCode(error.error().code()).setErrorMessage(error.message()));
                    }
                }
            }
        }
    } else {
        for (TopicPartitions topic : request.topicPartitions()) {
            ReplicaElectionResult topicResults = new ReplicaElectionResult().setTopic(topic.topic());
            response.replicaElectionResults().add(topicResults);
            for (int partitionId : topic.partitions()) {
                ApiError error = electLeader(topic.topic(), partitionId, electionType, records);
                topicResults.partitionResult().add(new PartitionResult().setPartitionId(partitionId).setErrorCode(error.error().code()).setErrorMessage(error.message()));
            }
        }
    }
    return ControllerResult.of(records, response);
}
Also used : ArrayList(java.util.ArrayList) ElectLeadersResponseData(org.apache.kafka.common.message.ElectLeadersResponseData) Uuid(org.apache.kafka.common.Uuid) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) ElectionType(org.apache.kafka.common.ElectionType) ReplicaElectionResult(org.apache.kafka.common.message.ElectLeadersResponseData.ReplicaElectionResult) ApiError(org.apache.kafka.common.requests.ApiError) PartitionResult(org.apache.kafka.common.message.ElectLeadersResponseData.PartitionResult) TopicPartitions(org.apache.kafka.common.message.ElectLeadersRequestData.TopicPartitions)

Example 85 with Uuid

use of org.apache.kafka.common.Uuid in project kafka by apache.

the class TopicsDelta method apply.

public TopicsImage apply() {
    Map<Uuid, TopicImage> newTopicsById = new HashMap<>(image.topicsById().size());
    Map<String, TopicImage> newTopicsByName = new HashMap<>(image.topicsByName().size());
    for (Entry<Uuid, TopicImage> entry : image.topicsById().entrySet()) {
        Uuid id = entry.getKey();
        TopicImage prevTopicImage = entry.getValue();
        TopicDelta delta = changedTopics.get(id);
        if (delta == null) {
            if (!deletedTopicIds.contains(id)) {
                newTopicsById.put(id, prevTopicImage);
                newTopicsByName.put(prevTopicImage.name(), prevTopicImage);
            }
        } else {
            TopicImage newTopicImage = delta.apply();
            newTopicsById.put(id, newTopicImage);
            newTopicsByName.put(delta.name(), newTopicImage);
        }
    }
    for (Entry<Uuid, TopicDelta> entry : changedTopics.entrySet()) {
        if (!newTopicsById.containsKey(entry.getKey())) {
            TopicImage newTopicImage = entry.getValue().apply();
            newTopicsById.put(newTopicImage.id(), newTopicImage);
            newTopicsByName.put(newTopicImage.name(), newTopicImage);
        }
    }
    return new TopicsImage(newTopicsById, newTopicsByName);
}
Also used : Uuid(org.apache.kafka.common.Uuid) HashMap(java.util.HashMap)

Aggregations

Uuid (org.apache.kafka.common.Uuid)95 Test (org.junit.jupiter.api.Test)55 HashMap (java.util.HashMap)42 TopicPartition (org.apache.kafka.common.TopicPartition)40 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)30 ArrayList (java.util.ArrayList)29 Map (java.util.Map)21 ApiMessageAndVersion (org.apache.kafka.server.common.ApiMessageAndVersion)21 LinkedHashMap (java.util.LinkedHashMap)18 List (java.util.List)15 FetchRequest (org.apache.kafka.common.requests.FetchRequest)14 TopicIdPartition (org.apache.kafka.common.TopicIdPartition)13 Errors (org.apache.kafka.common.protocol.Errors)12 FetchResponse (org.apache.kafka.common.requests.FetchResponse)12 Collections (java.util.Collections)11 ByteBuffer (java.nio.ByteBuffer)10 Node (org.apache.kafka.common.Node)10 CreateTopicsResponseData (org.apache.kafka.common.message.CreateTopicsResponseData)10 MetadataResponse (org.apache.kafka.common.requests.MetadataResponse)10 PartitionRegistration (org.apache.kafka.metadata.PartitionRegistration)10