diff --git a/common/src/main/java/org/astraea/common/admin/AdminImpl.java b/common/src/main/java/org/astraea/common/admin/AdminImpl.java index 2d0c01eba5..38b13322ff 100644 --- a/common/src/main/java/org/astraea/common/admin/AdminImpl.java +++ b/common/src/main/java/org/astraea/common/admin/AdminImpl.java @@ -684,7 +684,7 @@ private CompletionStage> replicas(Set topics) { Replica.builder() .topic(topicName) .partition(partitionId) - .internal(internal) + .isInternal(internal) .isAdding(isAdding) .isRemoving(isRemoving) .broker( diff --git a/common/src/main/java/org/astraea/common/admin/ClusterInfoBuilder.java b/common/src/main/java/org/astraea/common/admin/ClusterInfoBuilder.java index 2661d46071..c259f1c9d3 100644 --- a/common/src/main/java/org/astraea/common/admin/ClusterInfoBuilder.java +++ b/common/src/main/java/org/astraea/common/admin/ClusterInfoBuilder.java @@ -216,7 +216,7 @@ public ClusterInfoBuilder addTopic( .isAdding(false) .isRemoving(false) .lag(0) - .internal(false) + .isInternal(false) .isLeader(index == 0) .isSync(true) .isFuture(false) diff --git a/common/src/main/java/org/astraea/common/admin/Replica.java b/common/src/main/java/org/astraea/common/admin/Replica.java index 84a82b3c13..9f95af2ad2 100644 --- a/common/src/main/java/org/astraea/common/admin/Replica.java +++ b/common/src/main/java/org/astraea/common/admin/Replica.java @@ -16,13 +16,49 @@ */ package org.astraea.common.admin; -public interface Replica { +import java.util.Objects; - static ReplicaBuilder builder() { - return new ReplicaBuilder(); +/** + * @param topic topic name + * @param partition partition id + * @param broker information of the node hosts this replica + * @param isLeader true if this replica is a leader replica + * @param isSync true if this replica is synced + * @param isOffline true if this replica is offline + * @param isAdding true if this replica is adding and syncing data + * @param isRemoving true if this replica will be deleted in the future. + * @param isFuture true if this log is created by AlterReplicaLogDirsRequest and will replace the + * current log of the replica at some time in the future. + * @param isPreferredLeader true if the replica is the preferred leader + * @param lag (LEO - high watermark) if it is the current log, * (LEO) if it is the future log, (-1) + * if the host of replica is offline + * @param size The size of all log segments in this replica in bytes. It returns -1 if the host of + * replica is offline + * @param path that indicates the data folder path which stored this replica on a specific Kafka + * node. It returns null if the host of replica is offline + * @param isInternal true if this replica belongs to internal topic + */ +public record Replica( + String topic, + int partition, + Broker broker, + boolean isLeader, + boolean isSync, + boolean isOffline, + boolean isAdding, + boolean isRemoving, + boolean isFuture, + boolean isPreferredLeader, + long lag, + long size, + String path, + boolean isInternal) { + + public static Builder builder() { + return new Builder(); } - static ReplicaBuilder builder(Replica replica) { + public static Builder builder(Replica replica) { return Replica.builder().replica(replica); } @@ -31,7 +67,7 @@ static ReplicaBuilder builder(Replica replica) { * * @return TopicPartitionReplica */ - default TopicPartitionReplica topicPartitionReplica() { + public TopicPartitionReplica topicPartitionReplica() { return TopicPartitionReplica.of(topic(), partition(), broker().id()); } @@ -40,105 +76,202 @@ default TopicPartitionReplica topicPartitionReplica() { * * @return TopicPartition */ - default TopicPartition topicPartition() { + public TopicPartition topicPartition() { return TopicPartition.of(topic(), partition()); } - /** - * @return topic name - */ - String topic(); - - /** - * @return partition id - */ - int partition(); - - /** - * @return information of the node hosts this replica - */ - Broker broker(); - - /** - * @return true if this replica is a leader replica - */ - boolean isLeader(); - /** * @return true if this replica is a follower replica */ - default boolean isFollower() { + public boolean isFollower() { return !isLeader(); } - /** - * @return true if this replica is synced - */ - boolean isSync(); - - /** - * @return true if this replica is offline - */ - boolean isOffline(); - /** * @return true if this replica is online */ - default boolean isOnline() { + public boolean isOnline() { return !isOffline(); } - /** - * @return true if this replica is adding and syncing data - */ - boolean isAdding(); - - /** - * @return true if this replica will be deleted in the future. - */ - boolean isRemoving(); - - /** - * Whether this replica has been created by a AlterReplicaLogDirsRequest but not yet replaced the - * current replica on the broker. - * - * @return true if this log is created by AlterReplicaLogDirsRequest and will replace the current - * log of the replica at some time in the future. - */ - boolean isFuture(); - /** * @return true if this is current log of replica. */ - default boolean isCurrent() { + public boolean isCurrent() { return !isFuture(); } - /** - * @return true if the replica is the preferred leader - */ - boolean isPreferredLeader(); + public static class Builder { - /** - * @return (LEO - high watermark) if it is the current log, * (LEO) if it is the future log, * - * (-1) if the host of replica is offline - */ - long lag(); + private String topic; + private int partition; + private Broker broker; + private long lag; + private long size; - /** - * @return The size of all log segments in this replica in bytes. It returns -1 if the host of - * replica is offline - */ - long size(); + private boolean isAdding; - /** - * @return that indicates the data folder path which stored this replica on a specific Kafka node. - * It returns null if the host of replica is offline - */ - String path(); + private boolean isRemoving; + private boolean isInternal; + private boolean isLeader; + private boolean isSync; + private boolean isFuture; + private boolean isOffline; + private boolean isPreferredLeader; + private String path; - /** - * @return true if this replica belongs to internal topic - */ - boolean internal(); + private Builder() {} + + public Builder replica(Replica replica) { + this.topic = replica.topic(); + this.partition = replica.partition(); + this.broker = replica.broker(); + this.lag = replica.lag(); + this.size = replica.size(); + this.isAdding = replica.isAdding; + this.isRemoving = replica.isRemoving; + this.isInternal = replica.isInternal; + this.isLeader = replica.isLeader(); + this.isSync = replica.isSync(); + this.isFuture = replica.isFuture(); + this.isOffline = replica.isOffline(); + this.isPreferredLeader = replica.isPreferredLeader(); + this.path = replica.path(); + return this; + } + + public Builder topic(String topic) { + this.topic = topic; + return this; + } + + public Builder partition(int partition) { + this.partition = partition; + return this; + } + + public Builder broker(Broker broker) { + this.broker = broker; + return this; + } + + public Builder lag(long lag) { + this.lag = lag; + return this; + } + + public Builder size(long size) { + this.size = size; + return this; + } + + public Builder isAdding(boolean isAdding) { + this.isAdding = isAdding; + return this; + } + + public Builder isRemoving(boolean isRemoving) { + this.isRemoving = isRemoving; + return this; + } + + public Builder isInternal(boolean isInternal) { + this.isInternal = isInternal; + return this; + } + + public Builder isLeader(boolean leader) { + this.isLeader = leader; + return this; + } + + public Builder isSync(boolean isSync) { + this.isSync = isSync; + return this; + } + + public Builder isFuture(boolean isFuture) { + this.isFuture = isFuture; + return this; + } + + public Builder isOffline(boolean offline) { + this.isOffline = offline; + return this; + } + + public Builder isPreferredLeader(boolean isPreferredLeader) { + this.isPreferredLeader = isPreferredLeader; + return this; + } + + public Builder path(String path) { + this.path = path; + return this; + } + + /** + * a helper used to set all flags for a replica leader. + * + * @return a replica leader + */ + public Replica buildLeader() { + return new Replica( + Objects.requireNonNull(topic), + partition, + Objects.requireNonNull(broker), + true, + true, + false, + false, + false, + false, + true, + 0, + size, + Objects.requireNonNull(path), + isInternal); + } + + /** + * a helper used to set all flags for a in-sync replica follower. + * + * @return a replica leader + */ + public Replica buildInSyncFollower() { + return new Replica( + Objects.requireNonNull(topic), + partition, + Objects.requireNonNull(broker), + false, + true, + false, + false, + false, + false, + false, + 0, + size, + Objects.requireNonNull(path), + isInternal); + } + + public Replica build() { + return new Replica( + Objects.requireNonNull(topic), + partition, + Objects.requireNonNull(broker), + isLeader, + isSync, + isOffline, + isAdding, + isRemoving, + isFuture, + isPreferredLeader, + lag, + size, + path, + isInternal); + } + } } diff --git a/common/src/main/java/org/astraea/common/admin/ReplicaBuilder.java b/common/src/main/java/org/astraea/common/admin/ReplicaBuilder.java deleted file mode 100644 index b7e1929643..0000000000 --- a/common/src/main/java/org/astraea/common/admin/ReplicaBuilder.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * 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.astraea.common.admin; - -import java.util.Objects; - -public class ReplicaBuilder { - - private String topic; - private int partition; - private Broker broker; - private long lag; - private long size; - - private boolean isAdding; - - private boolean isRemoving; - private boolean internal; - private boolean isLeader; - private boolean isSync; - private boolean isFuture; - private boolean isOffline; - private boolean isPreferredLeader; - private String path; - - ReplicaBuilder replica(Replica replica) { - this.topic = replica.topic(); - this.partition = replica.partition(); - this.broker = replica.broker(); - this.lag = replica.lag(); - this.size = replica.size(); - this.isLeader = replica.isLeader(); - this.isSync = replica.isSync(); - this.isFuture = replica.isFuture(); - this.isOffline = replica.isOffline(); - this.isPreferredLeader = replica.isPreferredLeader(); - this.path = replica.path(); - - return this; - } - - public ReplicaBuilder topic(String topic) { - this.topic = topic; - return this; - } - - public ReplicaBuilder partition(int partition) { - this.partition = partition; - return this; - } - - public ReplicaBuilder broker(Broker broker) { - this.broker = broker; - return this; - } - - public ReplicaBuilder lag(long lag) { - this.lag = lag; - return this; - } - - public ReplicaBuilder size(long size) { - this.size = size; - return this; - } - - public ReplicaBuilder isAdding(boolean isAdding) { - this.isAdding = isAdding; - return this; - } - - public ReplicaBuilder isRemoving(boolean isRemoving) { - this.isRemoving = isRemoving; - return this; - } - - public ReplicaBuilder internal(boolean internal) { - this.internal = internal; - return this; - } - - public ReplicaBuilder isLeader(boolean leader) { - this.isLeader = leader; - return this; - } - - public ReplicaBuilder isSync(boolean isSync) { - this.isSync = isSync; - return this; - } - - public ReplicaBuilder isFuture(boolean isFuture) { - this.isFuture = isFuture; - return this; - } - - public ReplicaBuilder isOffline(boolean offline) { - this.isOffline = offline; - return this; - } - - public ReplicaBuilder isPreferredLeader(boolean isPreferredLeader) { - this.isPreferredLeader = isPreferredLeader; - return this; - } - - public ReplicaBuilder path(String path) { - this.path = path; - return this; - } - - /** - * a helper used to set all flags for a replica leader. - * - * @return a replica leader - */ - public Replica buildLeader() { - Objects.requireNonNull(path); - return new ReplicaImpl( - this.isLeader(true) - .isPreferredLeader(true) - .isSync(true) - .isFuture(false) - .isOffline(false) - .isRemoving(false) - .isAdding(false) - .lag(0)); - } - - /** - * a helper used to set all flags for a in-sync replica follower. - * - * @return a replica leader - */ - public Replica buildInSyncFollower() { - Objects.requireNonNull(path); - return new ReplicaImpl( - this.isLeader(false) - .isPreferredLeader(false) - .isSync(true) - .isFuture(false) - .isOffline(false) - .isRemoving(false) - .isAdding(false) - .lag(0)); - } - - public Replica build() { - return new ReplicaImpl(this); - } - - private static class ReplicaImpl implements Replica { - private final String topic; - private final int partition; - private final Broker broker; - private final long lag; - private final long size; - - private final boolean internal; - private final boolean isLeader; - - private final boolean isAdding; - - private final boolean isRemoving; - private final boolean isSync; - private final boolean isFuture; - private final boolean isOffline; - private final boolean isPreferredLeader; - private final String path; - - private ReplicaImpl(ReplicaBuilder builder) { - this.topic = Objects.requireNonNull(builder.topic); - this.partition = builder.partition; - this.broker = Objects.requireNonNull(builder.broker); - this.isAdding = builder.isAdding; - this.isRemoving = builder.isRemoving; - this.lag = builder.lag; - this.size = builder.size; - this.internal = builder.internal; - this.isLeader = builder.isLeader; - this.isSync = builder.isSync; - this.isFuture = builder.isFuture; - this.isOffline = builder.isOffline; - this.isPreferredLeader = builder.isPreferredLeader; - this.path = builder.path; - } - - @Override - public boolean isFuture() { - return isFuture; - } - - @Override - public boolean isPreferredLeader() { - return isPreferredLeader; - } - - @Override - public long lag() { - return lag; - } - - @Override - public long size() { - return size; - } - - @Override - public String path() { - return path; - } - - @Override - public boolean internal() { - return internal; - } - - @Override - public String topic() { - return topic; - } - - @Override - public int partition() { - return partition; - } - - @Override - public Broker broker() { - return broker; - } - - @Override - public boolean isLeader() { - return isLeader; - } - - @Override - public boolean isSync() { - return isSync; - } - - @Override - public boolean isOffline() { - return isOffline; - } - - @Override - public boolean isAdding() { - return isAdding; - } - - @Override - public boolean isRemoving() { - return isRemoving; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ReplicaImpl replica = (ReplicaImpl) o; - return partition == replica.partition - && lag == replica.lag - && size == replica.size - && internal == replica.internal - && isLeader == replica.isLeader - && isAdding == replica.isAdding - && isRemoving == replica.isRemoving - && isSync == replica.isSync - && isFuture == replica.isFuture - && isOffline == replica.isOffline - && isPreferredLeader == replica.isPreferredLeader - && topic.equals(replica.topic) - && broker.id() == replica.broker.id() - && broker.host().equals(replica.broker.host()) - && broker.port() == replica.broker.port() - && Objects.equals(path, replica.path); - } - - @Override - public String toString() { - return "Replica{" - + "topic='" - + topic() - + '\'' - + ", partition=" - + partition() - + ", broker=" - + broker() - + ", path='" - + path() - + '\'' - + ", " - + (isOffline() ? "offline" : isLeader() ? "leader" : "follower") - + '}'; - } - - @Override - public int hashCode() { - return Objects.hash( - topic, - partition, - broker, - lag, - size, - internal, - isLeader, - isAdding, - isRemoving, - isSync, - isFuture, - isOffline, - isPreferredLeader, - path); - } - } -} diff --git a/common/src/test/java/org/astraea/common/admin/AdminTest.java b/common/src/test/java/org/astraea/common/admin/AdminTest.java index a0675e8184..efab4420c6 100644 --- a/common/src/test/java/org/astraea/common/admin/AdminTest.java +++ b/common/src/test/java/org/astraea/common/admin/AdminTest.java @@ -201,7 +201,7 @@ void testClusterInfo() { var replicas = admin.clusterInfo(Set.of(t.name())).toCompletableFuture().join().replicas(); Assertions.assertNotEquals(0, replicas.size()); - replicas.forEach(r -> Assertions.assertEquals(t.internal(), r.internal())); + replicas.forEach(r -> Assertions.assertEquals(t.internal(), r.isInternal())); replicas.forEach(r -> Assertions.assertFalse(r.isAdding())); replicas.forEach(r -> Assertions.assertFalse(r.isRemoving())); }); diff --git a/gui/src/main/java/org/astraea/gui/tab/topic/ReplicaNode.java b/gui/src/main/java/org/astraea/gui/tab/topic/ReplicaNode.java index 8d0e1905a5..ff0026948b 100644 --- a/gui/src/main/java/org/astraea/gui/tab/topic/ReplicaNode.java +++ b/gui/src/main/java/org/astraea/gui/tab/topic/ReplicaNode.java @@ -63,7 +63,7 @@ static List> allResult(ClusterInfo clusterInfo) { var result = new LinkedHashMap(); result.put(TOPIC_NAME_KEY, replica.topic()); result.put(PARTITION_KEY, replica.partition()); - result.put("internal", replica.internal()); + result.put("internal", replica.isInternal()); result.put("broker", replica.broker().id()); if (replica.path() != null) result.put(PATH_KEY, replica.path()); result.put("isLeader", replica.isLeader());