Search in sources :

Example 1 with ApiMessageAndVersion

use of org.apache.kafka.server.common.ApiMessageAndVersion in project kafka by apache.

the class ClientQuotaControlManager method alterClientQuotaEntity.

private void alterClientQuotaEntity(ClientQuotaEntity entity, Map<String, Double> newQuotaConfigs, List<ApiMessageAndVersion> outputRecords, Map<ClientQuotaEntity, ApiError> outputResults) {
    // Check entity types and sanitize the names
    Map<String, String> validatedEntityMap = new HashMap<>(3);
    ApiError error = validateEntity(entity, validatedEntityMap);
    if (error.isFailure()) {
        outputResults.put(entity, error);
        return;
    }
    // Check the combination of entity types and get the config keys
    Map<String, ConfigDef.ConfigKey> configKeys = new HashMap<>(4);
    error = configKeysForEntityType(validatedEntityMap, configKeys);
    if (error.isFailure()) {
        outputResults.put(entity, error);
        return;
    }
    // Don't share objects between different records
    Supplier<List<EntityData>> recordEntitySupplier = () -> validatedEntityMap.entrySet().stream().map(mapEntry -> new EntityData().setEntityType(mapEntry.getKey()).setEntityName(mapEntry.getValue())).collect(Collectors.toList());
    List<ApiMessageAndVersion> newRecords = new ArrayList<>(newQuotaConfigs.size());
    Map<String, Double> currentQuotas = clientQuotaData.containsKey(entity) ? clientQuotaData.get(entity) : Collections.emptyMap();
    for (Map.Entry<String, Double> entry : newQuotaConfigs.entrySet()) {
        String key = entry.getKey();
        Double newValue = entry.getValue();
        if (newValue == null) {
            if (currentQuotas.containsKey(key)) {
                // Null value indicates removal
                newRecords.add(new ApiMessageAndVersion(new ClientQuotaRecord().setEntity(recordEntitySupplier.get()).setKey(key).setRemove(true), CLIENT_QUOTA_RECORD.highestSupportedVersion()));
            }
        } else {
            ApiError validationError = validateQuotaKeyValue(configKeys, key, newValue);
            if (validationError.isFailure()) {
                outputResults.put(entity, validationError);
                return;
            } else {
                final Double currentValue = currentQuotas.get(key);
                if (!Objects.equals(currentValue, newValue)) {
                    // Only record the new value if it has changed
                    newRecords.add(new ApiMessageAndVersion(new ClientQuotaRecord().setEntity(recordEntitySupplier.get()).setKey(key).setValue(newValue), CLIENT_QUOTA_RECORD.highestSupportedVersion()));
                }
            }
        }
    }
    outputRecords.addAll(newRecords);
    outputResults.put(entity, ApiError.NONE);
}
Also used : TimelineHashMap(org.apache.kafka.timeline.TimelineHashMap) HashMap(java.util.HashMap) Supplier(java.util.function.Supplier) ApiError(org.apache.kafka.common.requests.ApiError) ArrayList(java.util.ArrayList) InetAddress(java.net.InetAddress) ClientQuotaRecord(org.apache.kafka.common.metadata.ClientQuotaRecord) ClientQuotaEntity(org.apache.kafka.common.quota.ClientQuotaEntity) Map(java.util.Map) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) NoSuchElementException(java.util.NoSuchElementException) QuotaConfigs(org.apache.kafka.common.config.internals.QuotaConfigs) ConfigDef(org.apache.kafka.common.config.ConfigDef) ClientQuotaAlteration(org.apache.kafka.common.quota.ClientQuotaAlteration) Iterator(java.util.Iterator) EntityData(org.apache.kafka.common.metadata.ClientQuotaRecord.EntityData) Collection(java.util.Collection) UnknownHostException(java.net.UnknownHostException) Collectors(java.util.stream.Collectors) SnapshotRegistry(org.apache.kafka.timeline.SnapshotRegistry) Objects(java.util.Objects) List(java.util.List) CLIENT_QUOTA_RECORD(org.apache.kafka.common.metadata.MetadataRecordType.CLIENT_QUOTA_RECORD) Entry(java.util.Map.Entry) Errors(org.apache.kafka.common.protocol.Errors) InvalidRequestException(org.apache.kafka.common.errors.InvalidRequestException) Collections(java.util.Collections) TimelineHashMap(org.apache.kafka.timeline.TimelineHashMap) HashMap(java.util.HashMap) EntityData(org.apache.kafka.common.metadata.ClientQuotaRecord.EntityData) ArrayList(java.util.ArrayList) ClientQuotaRecord(org.apache.kafka.common.metadata.ClientQuotaRecord) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) ArrayList(java.util.ArrayList) List(java.util.List) ApiError(org.apache.kafka.common.requests.ApiError) TimelineHashMap(org.apache.kafka.timeline.TimelineHashMap) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with ApiMessageAndVersion

use of org.apache.kafka.server.common.ApiMessageAndVersion in project kafka by apache.

the class ConfigurationControlManager method incrementalAlterConfigResource.

private void incrementalAlterConfigResource(ConfigResource configResource, Map<String, Entry<OpType, String>> keysToOps, Consumer<ConfigResource> existenceChecker, List<ApiMessageAndVersion> outputRecords, Map<ConfigResource, ApiError> outputResults) {
    List<ApiMessageAndVersion> newRecords = new ArrayList<>();
    for (Entry<String, Entry<OpType, String>> keysToOpsEntry : keysToOps.entrySet()) {
        String key = keysToOpsEntry.getKey();
        String currentValue = null;
        TimelineHashMap<String, String> currentConfigs = configData.get(configResource);
        if (currentConfigs != null) {
            currentValue = currentConfigs.get(key);
        }
        String newValue = currentValue;
        Entry<OpType, String> opTypeAndNewValue = keysToOpsEntry.getValue();
        OpType opType = opTypeAndNewValue.getKey();
        String opValue = opTypeAndNewValue.getValue();
        switch(opType) {
            case SET:
                newValue = opValue;
                break;
            case DELETE:
                newValue = null;
                break;
            case APPEND:
            case SUBTRACT:
                if (!isSplittable(configResource.type(), key)) {
                    outputResults.put(configResource, new ApiError(INVALID_CONFIG, "Can't " + opType + " to " + "key " + key + " because its type is not LIST."));
                    return;
                }
                List<String> newValueParts = getParts(newValue, key, configResource);
                if (opType == APPEND) {
                    if (!newValueParts.contains(opValue)) {
                        newValueParts.add(opValue);
                    }
                    newValue = String.join(",", newValueParts);
                } else if (newValueParts.remove(opValue)) {
                    newValue = String.join(",", newValueParts);
                }
                break;
        }
        if (!Objects.equals(currentValue, newValue)) {
            newRecords.add(new ApiMessageAndVersion(new ConfigRecord().setResourceType(configResource.type().id()).setResourceName(configResource.name()).setName(key).setValue(newValue), CONFIG_RECORD.highestSupportedVersion()));
        }
    }
    ApiError error = validateAlterConfig(configResource, newRecords, existenceChecker);
    if (error.isFailure()) {
        outputResults.put(configResource, error);
        return;
    }
    outputRecords.addAll(newRecords);
    outputResults.put(configResource, ApiError.NONE);
}
Also used : ConfigRecord(org.apache.kafka.common.metadata.ConfigRecord) Entry(java.util.Map.Entry) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) ArrayList(java.util.ArrayList) OpType(org.apache.kafka.clients.admin.AlterConfigOp.OpType) ApiError(org.apache.kafka.common.requests.ApiError)

Example 3 with ApiMessageAndVersion

use of org.apache.kafka.server.common.ApiMessageAndVersion in project kafka by apache.

the class ConfigurationControlManager method validateAlterConfig.

private ApiError validateAlterConfig(ConfigResource configResource, List<ApiMessageAndVersion> newRecords, Consumer<ConfigResource> existenceChecker) {
    Map<String, String> newConfigs = new HashMap<>();
    TimelineHashMap<String, String> existingConfigs = configData.get(configResource);
    if (existingConfigs != null)
        newConfigs.putAll(existingConfigs);
    for (ApiMessageAndVersion newRecord : newRecords) {
        ConfigRecord configRecord = (ConfigRecord) newRecord.message();
        if (configRecord.value() == null) {
            newConfigs.remove(configRecord.name());
        } else {
            newConfigs.put(configRecord.name(), configRecord.value());
        }
    }
    try {
        validator.validate(configResource, newConfigs);
        existenceChecker.accept(configResource);
        if (alterConfigPolicy.isPresent()) {
            alterConfigPolicy.get().validate(new RequestMetadata(configResource, newConfigs));
        }
    } catch (ConfigException e) {
        return new ApiError(INVALID_CONFIG, e.getMessage());
    } catch (Throwable e) {
        return ApiError.fromThrowable(e);
    }
    return ApiError.NONE;
}
Also used : ConfigRecord(org.apache.kafka.common.metadata.ConfigRecord) TimelineHashMap(org.apache.kafka.timeline.TimelineHashMap) HashMap(java.util.HashMap) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) ConfigException(org.apache.kafka.common.config.ConfigException) ApiError(org.apache.kafka.common.requests.ApiError) RequestMetadata(org.apache.kafka.server.policy.AlterConfigPolicy.RequestMetadata)

Example 4 with ApiMessageAndVersion

use of org.apache.kafka.server.common.ApiMessageAndVersion in project kafka by apache.

the class ReplicationControlManager method deleteTopic.

void deleteTopic(Uuid id, List<ApiMessageAndVersion> records) {
    TopicControlInfo topic = topics.get(id);
    if (topic == null) {
        throw new UnknownTopicIdException(UNKNOWN_TOPIC_ID.message());
    }
    records.add(new ApiMessageAndVersion(new RemoveTopicRecord().setTopicId(id), REMOVE_TOPIC_RECORD.highestSupportedVersion()));
}
Also used : ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) RemoveTopicRecord(org.apache.kafka.common.metadata.RemoveTopicRecord) UnknownTopicIdException(org.apache.kafka.common.errors.UnknownTopicIdException)

Example 5 with ApiMessageAndVersion

use of org.apache.kafka.server.common.ApiMessageAndVersion in project kafka by apache.

the class ReplicationControlManager method alterPartitionReassignment.

void alterPartitionReassignment(String topicName, ReassignablePartition target, List<ApiMessageAndVersion> records) {
    Uuid topicId = topicsByName.get(topicName);
    if (topicId == null) {
        throw new UnknownTopicOrPartitionException("Unable to find a topic " + "named " + topicName + ".");
    }
    TopicControlInfo topicInfo = topics.get(topicId);
    if (topicInfo == null) {
        throw new UnknownTopicOrPartitionException("Unable to find a topic " + "with ID " + topicId + ".");
    }
    TopicIdPartition tp = new TopicIdPartition(topicId, target.partitionIndex());
    PartitionRegistration part = topicInfo.parts.get(target.partitionIndex());
    if (part == null) {
        throw new UnknownTopicOrPartitionException("Unable to find partition " + topicName + ":" + target.partitionIndex() + ".");
    }
    Optional<ApiMessageAndVersion> record;
    if (target.replicas() == null) {
        record = cancelPartitionReassignment(topicName, tp, part);
    } else {
        record = changePartitionReassignment(tp, part, target);
    }
    record.ifPresent(records::add);
}
Also used : PartitionRegistration(org.apache.kafka.metadata.PartitionRegistration) Uuid(org.apache.kafka.common.Uuid) ApiMessageAndVersion(org.apache.kafka.server.common.ApiMessageAndVersion) UnknownTopicOrPartitionException(org.apache.kafka.common.errors.UnknownTopicOrPartitionException) TopicIdPartition(org.apache.kafka.controller.BrokersToIsrs.TopicIdPartition)

Aggregations

ApiMessageAndVersion (org.apache.kafka.server.common.ApiMessageAndVersion)84 ArrayList (java.util.ArrayList)38 Test (org.junit.jupiter.api.Test)35 Uuid (org.apache.kafka.common.Uuid)23 ApiError (org.apache.kafka.common.requests.ApiError)20 LogContext (org.apache.kafka.common.utils.LogContext)17 HashMap (java.util.HashMap)16 SnapshotRegistry (org.apache.kafka.timeline.SnapshotRegistry)15 List (java.util.List)12 Map (java.util.Map)12 PartitionChangeRecord (org.apache.kafka.common.metadata.PartitionChangeRecord)12 PartitionRegistration (org.apache.kafka.metadata.PartitionRegistration)11 TopicRecord (org.apache.kafka.common.metadata.TopicRecord)8 UnknownTopicOrPartitionException (org.apache.kafka.common.errors.UnknownTopicOrPartitionException)7 AlterIsrRequestData (org.apache.kafka.common.message.AlterIsrRequestData)7 Collections (java.util.Collections)6 Iterator (java.util.Iterator)6 Entry (java.util.Map.Entry)6 NoSuchElementException (java.util.NoSuchElementException)6 Optional (java.util.Optional)6