use of org.apache.kafka.common.message.AlterIsrResponseData in project kafka by apache.
the class ReplicationControlManager method alterIsr.
ControllerResult<AlterIsrResponseData> alterIsr(AlterIsrRequestData request) {
clusterControl.checkBrokerEpoch(request.brokerId(), request.brokerEpoch());
AlterIsrResponseData response = new AlterIsrResponseData();
List<ApiMessageAndVersion> records = new ArrayList<>();
for (AlterIsrRequestData.TopicData topicData : request.topics()) {
AlterIsrResponseData.TopicData responseTopicData = new AlterIsrResponseData.TopicData().setName(topicData.name());
response.topics().add(responseTopicData);
Uuid topicId = topicsByName.get(topicData.name());
if (topicId == null || !topics.containsKey(topicId)) {
for (AlterIsrRequestData.PartitionData partitionData : topicData.partitions()) {
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionData.partitionIndex()).setErrorCode(UNKNOWN_TOPIC_OR_PARTITION.code()));
}
log.info("Rejecting alterIsr request for unknown topic ID {}.", topicId);
continue;
}
TopicControlInfo topic = topics.get(topicId);
for (AlterIsrRequestData.PartitionData partitionData : topicData.partitions()) {
int partitionId = partitionData.partitionIndex();
PartitionRegistration partition = topic.parts.get(partitionId);
if (partition == null) {
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionId).setErrorCode(UNKNOWN_TOPIC_OR_PARTITION.code()));
log.info("Rejecting alterIsr request for unknown partition {}-{}.", topic.name, partitionId);
continue;
}
if (partitionData.leaderEpoch() != partition.leaderEpoch) {
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionId).setErrorCode(FENCED_LEADER_EPOCH.code()));
log.debug("Rejecting alterIsr request from node {} for {}-{} because " + "the current leader epoch is {}, not {}.", request.brokerId(), topic.name, partitionId, partition.leaderEpoch, partitionData.leaderEpoch());
continue;
}
if (request.brokerId() != partition.leader) {
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionId).setErrorCode(INVALID_REQUEST.code()));
log.info("Rejecting alterIsr request from node {} for {}-{} because " + "the current leader is {}.", request.brokerId(), topic.name, partitionId, partition.leader);
continue;
}
if (partitionData.currentIsrVersion() != partition.partitionEpoch) {
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionId).setErrorCode(INVALID_UPDATE_VERSION.code()));
log.info("Rejecting alterIsr request from node {} for {}-{} because " + "the current partition epoch is {}, not {}.", request.brokerId(), topic.name, partitionId, partition.partitionEpoch, partitionData.currentIsrVersion());
continue;
}
int[] newIsr = Replicas.toArray(partitionData.newIsr());
if (!Replicas.validateIsr(partition.replicas, newIsr)) {
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionId).setErrorCode(INVALID_REQUEST.code()));
log.error("Rejecting alterIsr request from node {} for {}-{} because " + "it specified an invalid ISR {}.", request.brokerId(), topic.name, partitionId, partitionData.newIsr());
continue;
}
if (!Replicas.contains(newIsr, partition.leader)) {
// An alterIsr request can't ask for the current leader to be removed.
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionId).setErrorCode(INVALID_REQUEST.code()));
log.error("Rejecting alterIsr request from node {} for {}-{} because " + "it specified an invalid ISR {} that doesn't include itself.", request.brokerId(), topic.name, partitionId, partitionData.newIsr());
continue;
}
// At this point, we have decided to perform the ISR change. We use
// PartitionChangeBuilder to find out what its effect will be.
PartitionChangeBuilder builder = new PartitionChangeBuilder(partition, topic.id, partitionId, r -> clusterControl.unfenced(r), () -> configurationControl.uncleanLeaderElectionEnabledForTopic(topicData.name()));
builder.setTargetIsr(partitionData.newIsr());
Optional<ApiMessageAndVersion> record = builder.build();
Errors result = Errors.NONE;
if (record.isPresent()) {
records.add(record.get());
PartitionChangeRecord change = (PartitionChangeRecord) record.get().message();
partition = partition.merge(change);
if (log.isDebugEnabled()) {
log.debug("Node {} has altered ISR for {}-{} to {}.", request.brokerId(), topic.name, partitionId, change.isr());
}
if (change.leader() != request.brokerId() && change.leader() != NO_LEADER_CHANGE) {
// Normally, an alterIsr request, which is made by the partition
// leader itself, is not allowed to modify the partition leader.
// However, if there is an ongoing partition reassignment and the
// ISR change completes it, then the leader may change as part of
// the changes made during reassignment cleanup.
//
// In this case, we report back FENCED_LEADER_EPOCH to the leader
// which made the alterIsr request. This lets it know that it must
// fetch new metadata before trying again. This return code is
// unusual because we both return an error and generate a new
// metadata record. We usually only do one or the other.
log.info("AlterIsr request from node {} for {}-{} completed " + "the ongoing partition reassignment and triggered a " + "leadership change. Reutrning FENCED_LEADER_EPOCH.", request.brokerId(), topic.name, partitionId);
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionId).setErrorCode(FENCED_LEADER_EPOCH.code()));
continue;
} else if (change.removingReplicas() != null || change.addingReplicas() != null) {
log.info("AlterIsr request from node {} for {}-{} completed " + "the ongoing partition reassignment.", request.brokerId(), topic.name, partitionId);
}
}
responseTopicData.partitions().add(new AlterIsrResponseData.PartitionData().setPartitionIndex(partitionId).setErrorCode(result.code()).setLeaderId(partition.leader).setLeaderEpoch(partition.leaderEpoch).setCurrentIsrVersion(partition.partitionEpoch).setIsr(Replicas.toList(partition.isr)));
}
}
return ControllerResult.of(records, response);
}
use of org.apache.kafka.common.message.AlterIsrResponseData in project kafka by apache.
the class ReplicationControlManagerTest method testReassignPartitions.
@Test
public void testReassignPartitions() throws Exception {
ReplicationControlTestContext ctx = new ReplicationControlTestContext();
ReplicationControlManager replication = ctx.replicationControl;
ctx.registerBrokers(0, 1, 2, 3);
ctx.unfenceBrokers(0, 1, 2, 3);
Uuid fooId = ctx.createTestTopic("foo", new int[][] { new int[] { 1, 2, 3 }, new int[] { 3, 2, 1 } }).topicId();
ctx.createTestTopic("bar", new int[][] { new int[] { 1, 2, 3 } }).topicId();
assertEquals(NONE_REASSIGNING, replication.listPartitionReassignments(null));
ControllerResult<AlterPartitionReassignmentsResponseData> alterResult = replication.alterPartitionReassignments(new AlterPartitionReassignmentsRequestData().setTopics(asList(new ReassignableTopic().setName("foo").setPartitions(asList(new ReassignablePartition().setPartitionIndex(0).setReplicas(asList(3, 2, 1)), new ReassignablePartition().setPartitionIndex(1).setReplicas(asList(0, 2, 1)), new ReassignablePartition().setPartitionIndex(2).setReplicas(asList(0, 2, 1)))), new ReassignableTopic().setName("bar"))));
assertEquals(new AlterPartitionReassignmentsResponseData().setErrorMessage(null).setResponses(asList(new ReassignableTopicResponse().setName("foo").setPartitions(asList(new ReassignablePartitionResponse().setPartitionIndex(0).setErrorMessage(null), new ReassignablePartitionResponse().setPartitionIndex(1).setErrorMessage(null), new ReassignablePartitionResponse().setPartitionIndex(2).setErrorCode(UNKNOWN_TOPIC_OR_PARTITION.code()).setErrorMessage("Unable to find partition foo:2."))), new ReassignableTopicResponse().setName("bar"))), alterResult.response());
ctx.replay(alterResult.records());
ListPartitionReassignmentsResponseData currentReassigning = new ListPartitionReassignmentsResponseData().setErrorMessage(null).setTopics(asList(new OngoingTopicReassignment().setName("foo").setPartitions(asList(new OngoingPartitionReassignment().setPartitionIndex(1).setRemovingReplicas(asList(3)).setAddingReplicas(asList(0)).setReplicas(asList(0, 2, 1, 3))))));
assertEquals(currentReassigning, replication.listPartitionReassignments(null));
assertEquals(NONE_REASSIGNING, replication.listPartitionReassignments(asList(new ListPartitionReassignmentsTopics().setName("bar").setPartitionIndexes(asList(0, 1, 2)))));
assertEquals(currentReassigning, replication.listPartitionReassignments(asList(new ListPartitionReassignmentsTopics().setName("foo").setPartitionIndexes(asList(0, 1, 2)))));
ControllerResult<AlterPartitionReassignmentsResponseData> cancelResult = replication.alterPartitionReassignments(new AlterPartitionReassignmentsRequestData().setTopics(asList(new ReassignableTopic().setName("foo").setPartitions(asList(new ReassignablePartition().setPartitionIndex(0).setReplicas(null), new ReassignablePartition().setPartitionIndex(1).setReplicas(null), new ReassignablePartition().setPartitionIndex(2).setReplicas(null))), new ReassignableTopic().setName("bar").setPartitions(asList(new ReassignablePartition().setPartitionIndex(0).setReplicas(null))))));
assertEquals(ControllerResult.atomicOf(Collections.singletonList(new ApiMessageAndVersion(new PartitionChangeRecord().setTopicId(fooId).setPartitionId(1).setReplicas(asList(2, 1, 3)).setLeader(3).setRemovingReplicas(Collections.emptyList()).setAddingReplicas(Collections.emptyList()), (short) 0)), new AlterPartitionReassignmentsResponseData().setErrorMessage(null).setResponses(asList(new ReassignableTopicResponse().setName("foo").setPartitions(asList(new ReassignablePartitionResponse().setPartitionIndex(0).setErrorCode(NO_REASSIGNMENT_IN_PROGRESS.code()).setErrorMessage(null), new ReassignablePartitionResponse().setPartitionIndex(1).setErrorCode(NONE.code()).setErrorMessage(null), new ReassignablePartitionResponse().setPartitionIndex(2).setErrorCode(UNKNOWN_TOPIC_OR_PARTITION.code()).setErrorMessage("Unable to find partition foo:2."))), new ReassignableTopicResponse().setName("bar").setPartitions(asList(new ReassignablePartitionResponse().setPartitionIndex(0).setErrorCode(NO_REASSIGNMENT_IN_PROGRESS.code()).setErrorMessage(null)))))), cancelResult);
log.info("running final alterIsr...");
ControllerResult<AlterIsrResponseData> alterIsrResult = replication.alterIsr(new AlterIsrRequestData().setBrokerId(3).setBrokerEpoch(103).setTopics(asList(new TopicData().setName("foo").setPartitions(asList(new PartitionData().setPartitionIndex(1).setCurrentIsrVersion(1).setLeaderEpoch(0).setNewIsr(asList(3, 0, 2, 1)))))));
assertEquals(new AlterIsrResponseData().setTopics(asList(new AlterIsrResponseData.TopicData().setName("foo").setPartitions(asList(new AlterIsrResponseData.PartitionData().setPartitionIndex(1).setErrorCode(FENCED_LEADER_EPOCH.code()))))), alterIsrResult.response());
ctx.replay(alterIsrResult.records());
assertEquals(NONE_REASSIGNING, replication.listPartitionReassignments(null));
}
use of org.apache.kafka.common.message.AlterIsrResponseData in project kafka by apache.
the class ReplicationControlManagerTest method assertAlterIsrResponse.
private AlterIsrResponseData.PartitionData assertAlterIsrResponse(ControllerResult<AlterIsrResponseData> alterIsrResult, TopicPartition topicPartition, Errors expectedError) {
AlterIsrResponseData response = alterIsrResult.response();
assertEquals(1, response.topics().size());
AlterIsrResponseData.TopicData topicData = response.topics().get(0);
assertEquals(topicPartition.topic(), topicData.name());
assertEquals(1, topicData.partitions().size());
AlterIsrResponseData.PartitionData partitionData = topicData.partitions().get(0);
assertEquals(topicPartition.partition(), partitionData.partitionIndex());
assertEquals(expectedError, Errors.forCode(partitionData.errorCode()));
return partitionData;
}
use of org.apache.kafka.common.message.AlterIsrResponseData in project kafka by apache.
the class ReplicationControlManagerTest method sendAlterIsr.
private ControllerResult<AlterIsrResponseData> sendAlterIsr(ReplicationControlManager replicationControl, int brokerId, long brokerEpoch, String topic, AlterIsrRequestData.PartitionData partitionData) throws Exception {
AlterIsrRequestData request = new AlterIsrRequestData().setBrokerId(brokerId).setBrokerEpoch(brokerEpoch);
AlterIsrRequestData.TopicData topicData = new AlterIsrRequestData.TopicData().setName(topic);
request.topics().add(topicData);
topicData.partitions().add(partitionData);
ControllerResult<AlterIsrResponseData> result = replicationControl.alterIsr(request);
RecordTestUtils.replayAll(replicationControl, result.records());
return result;
}
use of org.apache.kafka.common.message.AlterIsrResponseData in project kafka by apache.
the class ReplicationControlManagerTest method testShrinkAndExpandIsr.
@Test
public void testShrinkAndExpandIsr() throws Exception {
ReplicationControlTestContext ctx = new ReplicationControlTestContext();
ReplicationControlManager replicationControl = ctx.replicationControl;
ctx.registerBrokers(0, 1, 2);
ctx.unfenceBrokers(0, 1, 2);
CreatableTopicResult createTopicResult = ctx.createTestTopic("foo", new int[][] { new int[] { 0, 1, 2 } });
TopicIdPartition topicIdPartition = new TopicIdPartition(createTopicResult.topicId(), 0);
TopicPartition topicPartition = new TopicPartition("foo", 0);
assertEquals(OptionalInt.of(0), ctx.currentLeader(topicIdPartition));
long brokerEpoch = ctx.currentBrokerEpoch(0);
PartitionData shrinkIsrRequest = newAlterIsrPartition(replicationControl, topicIdPartition, asList(0, 1));
ControllerResult<AlterIsrResponseData> shrinkIsrResult = sendAlterIsr(replicationControl, 0, brokerEpoch, "foo", shrinkIsrRequest);
AlterIsrResponseData.PartitionData shrinkIsrResponse = assertAlterIsrResponse(shrinkIsrResult, topicPartition, NONE);
assertConsistentAlterIsrResponse(replicationControl, topicIdPartition, shrinkIsrResponse);
PartitionData expandIsrRequest = newAlterIsrPartition(replicationControl, topicIdPartition, asList(0, 1, 2));
ControllerResult<AlterIsrResponseData> expandIsrResult = sendAlterIsr(replicationControl, 0, brokerEpoch, "foo", expandIsrRequest);
AlterIsrResponseData.PartitionData expandIsrResponse = assertAlterIsrResponse(expandIsrResult, topicPartition, NONE);
assertConsistentAlterIsrResponse(replicationControl, topicIdPartition, expandIsrResponse);
}
Aggregations