org.apache.kafka.common.requests.ApiVersionsResponse Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.kafka.common.requests;
import org.apache.kafka.common.feature.Features;
import org.apache.kafka.common.feature.FinalizedVersionRange;
import org.apache.kafka.common.feature.SupportedVersionRange;
import org.apache.kafka.common.message.ApiVersionsResponseData;
import org.apache.kafka.common.message.ApiVersionsResponseData.ApiVersionsResponseKey;
import org.apache.kafka.common.message.ApiVersionsResponseData.ApiVersionsResponseKeyCollection;
import org.apache.kafka.common.message.ApiVersionsResponseData.FinalizedFeatureKey;
import org.apache.kafka.common.message.ApiVersionsResponseData.FinalizedFeatureKeyCollection;
import org.apache.kafka.common.message.ApiVersionsResponseData.SupportedFeatureKey;
import org.apache.kafka.common.message.ApiVersionsResponseData.SupportedFeatureKeyCollection;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.protocol.ByteBufferAccessor;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.protocol.types.SchemaException;
import org.apache.kafka.common.protocol.types.Struct;
import org.apache.kafka.common.record.RecordBatch;
import java.nio.ByteBuffer;
import java.util.Map;
/**
* Possible error codes:
* - {@link Errors#UNSUPPORTED_VERSION}
* - {@link Errors#INVALID_REQUEST}
*/
public class ApiVersionsResponse extends AbstractResponse {
public static final long UNKNOWN_FINALIZED_FEATURES_EPOCH = -1L;
public static final ApiVersionsResponse DEFAULT_API_VERSIONS_RESPONSE =
createApiVersionsResponse(
DEFAULT_THROTTLE_TIME,
RecordBatch.CURRENT_MAGIC_VALUE,
Features.emptySupportedFeatures(),
Features.emptyFinalizedFeatures(),
UNKNOWN_FINALIZED_FEATURES_EPOCH);
public final ApiVersionsResponseData data;
public ApiVersionsResponse(ApiVersionsResponseData data) {
this.data = data;
}
public ApiVersionsResponse(Struct struct) {
this(new ApiVersionsResponseData(struct, (short) (ApiVersionsResponseData.SCHEMAS.length - 1)));
}
public ApiVersionsResponse(Struct struct, short version) {
this(new ApiVersionsResponseData(struct, version));
}
public ApiVersionsResponseData data() {
return data;
}
@Override
protected Struct toStruct(short version) {
return this.data.toStruct(version);
}
public ApiVersionsResponseKey apiVersion(short apiKey) {
return data.apiKeys().find(apiKey);
}
@Override
public Map errorCounts() {
return errorCounts(Errors.forCode(this.data.errorCode()));
}
@Override
public int throttleTimeMs() {
return this.data.throttleTimeMs();
}
@Override
public boolean shouldClientThrottle(short version) {
return version >= 2;
}
public static ApiVersionsResponse parse(ByteBuffer buffer, short version) {
// Fallback to version 0 for ApiVersions response. If a client sends an ApiVersionsRequest
// using a version higher than that supported by the broker, a version 0 response is sent
// to the client indicating UNSUPPORTED_VERSION. When the client receives the response, it
// falls back while parsing it into a Struct which means that the version received by this
// method is not necessary the real one. It may be version 0 as well.
int prev = buffer.position();
try {
return new ApiVersionsResponse(
new ApiVersionsResponseData(new ByteBufferAccessor(buffer), version));
} catch (RuntimeException e) {
buffer.position(prev);
if (version != 0)
return new ApiVersionsResponse(
new ApiVersionsResponseData(new ByteBufferAccessor(buffer), (short) 0));
else
throw e;
}
}
public static ApiVersionsResponse fromStruct(Struct struct, short version) {
// Fallback to version 0 for ApiVersions response. If a client sends an ApiVersionsRequest
// using a version higher than that supported by the broker, a version 0 response is sent
// to the client indicating UNSUPPORTED_VERSION. When the client receives the response, it
// falls back while parsing it into a Struct which means that the version received by this
// method is not necessary the real one. It may be version 0 as well.
try {
return new ApiVersionsResponse(struct, version);
} catch (SchemaException e) {
if (version != 0)
return new ApiVersionsResponse(struct, (short) 0);
else
throw e;
}
}
public static ApiVersionsResponse apiVersionsResponse(
int throttleTimeMs,
byte maxMagic,
Features latestSupportedFeatures) {
return apiVersionsResponse(
throttleTimeMs, maxMagic, latestSupportedFeatures, Features.emptyFinalizedFeatures(), UNKNOWN_FINALIZED_FEATURES_EPOCH);
}
public static ApiVersionsResponse apiVersionsResponse(
int throttleTimeMs,
byte maxMagic,
Features latestSupportedFeatures,
Features finalizedFeatures,
long finalizedFeaturesEpoch) {
if (maxMagic == RecordBatch.CURRENT_MAGIC_VALUE && throttleTimeMs == DEFAULT_THROTTLE_TIME) {
return new ApiVersionsResponse(createApiVersionsResponseData(
DEFAULT_API_VERSIONS_RESPONSE.throttleTimeMs(),
Errors.forCode(DEFAULT_API_VERSIONS_RESPONSE.data().errorCode()),
DEFAULT_API_VERSIONS_RESPONSE.data().apiKeys(),
latestSupportedFeatures,
finalizedFeatures,
finalizedFeaturesEpoch));
}
return createApiVersionsResponse(
throttleTimeMs, maxMagic, latestSupportedFeatures, finalizedFeatures, finalizedFeaturesEpoch);
}
public static ApiVersionsResponse createApiVersionsResponse(
final int throttleTimeMs,
final byte minMagic) {
return createApiVersionsResponse(
throttleTimeMs,
minMagic,
Features.emptySupportedFeatures(),
Features.emptyFinalizedFeatures(),
UNKNOWN_FINALIZED_FEATURES_EPOCH);
}
private static ApiVersionsResponse createApiVersionsResponse(
final int throttleTimeMs,
final byte minMagic,
final Features latestSupportedFeatures,
final Features finalizedFeatures,
final long finalizedFeaturesEpoch
) {
ApiVersionsResponseKeyCollection apiKeys = new ApiVersionsResponseKeyCollection();
for (ApiKeys apiKey : ApiKeys.enabledApis()) {
if (apiKey.minRequiredInterBrokerMagic <= minMagic) {
apiKeys.add(new ApiVersionsResponseKey()
.setApiKey(apiKey.id)
.setMinVersion(apiKey.oldestVersion())
.setMaxVersion(apiKey.latestVersion()));
}
}
return new ApiVersionsResponse(
createApiVersionsResponseData(
throttleTimeMs,
Errors.NONE,
apiKeys,
latestSupportedFeatures,
finalizedFeatures,
finalizedFeaturesEpoch));
}
public static ApiVersionsResponseData createApiVersionsResponseData(
final int throttleTimeMs,
final Errors error,
final ApiVersionsResponseKeyCollection apiKeys,
final Features latestSupportedFeatures,
final Features finalizedFeatures,
final long finalizedFeaturesEpoch
) {
final ApiVersionsResponseData data = new ApiVersionsResponseData();
data.setThrottleTimeMs(throttleTimeMs);
data.setErrorCode(error.code());
data.setApiKeys(apiKeys);
data.setSupportedFeatures(createSupportedFeatureKeys(latestSupportedFeatures));
data.setFinalizedFeatures(createFinalizedFeatureKeys(finalizedFeatures));
data.setFinalizedFeaturesEpoch(finalizedFeaturesEpoch);
return data;
}
private static SupportedFeatureKeyCollection createSupportedFeatureKeys(
Features latestSupportedFeatures) {
SupportedFeatureKeyCollection converted = new SupportedFeatureKeyCollection();
for (Map.Entry feature : latestSupportedFeatures.features().entrySet()) {
final SupportedFeatureKey key = new SupportedFeatureKey();
final SupportedVersionRange versionRange = feature.getValue();
key.setName(feature.getKey());
key.setMinVersion(versionRange.min());
key.setMaxVersion(versionRange.max());
converted.add(key);
}
return converted;
}
private static FinalizedFeatureKeyCollection createFinalizedFeatureKeys(
Features finalizedFeatures) {
FinalizedFeatureKeyCollection converted = new FinalizedFeatureKeyCollection();
for (Map.Entry feature : finalizedFeatures.features().entrySet()) {
final FinalizedFeatureKey key = new FinalizedFeatureKey();
final FinalizedVersionRange versionLevelRange = feature.getValue();
key.setName(feature.getKey());
key.setMinVersionLevel(versionLevelRange.min());
key.setMaxVersionLevel(versionLevelRange.max());
converted.add(key);
}
return converted;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy