From a32779bef8233686fafaa10a337dbd8235d48c05 Mon Sep 17 00:00:00 2001 From: xyuanlu Date: Mon, 18 Sep 2023 14:50:57 -0700 Subject: [PATCH 1/4] add APIs for evacuation --- .../java/org/apache/helix/HelixAdmin.java | 11 ++++++ .../apache/helix/manager/zk/ZKHelixAdmin.java | 35 +++++++++++++++++++ .../rebalancer/TestInstanceOperation.java | 13 ++++++- .../org/apache/helix/mock/MockHelixAdmin.java | 10 ++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/helix-core/src/main/java/org/apache/helix/HelixAdmin.java b/helix-core/src/main/java/org/apache/helix/HelixAdmin.java index 14863f57e7..03cbea5ec8 100644 --- a/helix-core/src/main/java/org/apache/helix/HelixAdmin.java +++ b/helix-core/src/main/java/org/apache/helix/HelixAdmin.java @@ -738,4 +738,15 @@ Map validateResourcesForWagedRebalance(String clusterName, */ Map validateInstancesForWagedRebalance(String clusterName, List instancesNames); + + /** + * Return if instance operation 'Evacuate' is finished. + * Only return true if there is no current state on the instance and that instance is still alive. + * @param clusterName + * @param instancesNames + * @return + */ + boolean isEvacuateFinished(String clusterName, String instancesNames); + + boolean isPrepopulateReady(String clusterName, String instancesNames); } diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java index 15b38fcbce..a3a2c34dd0 100644 --- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java +++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java @@ -47,6 +47,7 @@ import org.apache.helix.HelixDataAccessor; import org.apache.helix.HelixDefinedState; import org.apache.helix.HelixException; +import org.apache.helix.HelixProperty; import org.apache.helix.InstanceType; import org.apache.helix.PropertyKey; import org.apache.helix.PropertyPathBuilder; @@ -406,7 +407,41 @@ public ZNRecord update(ZNRecord currentData) { } } + @Override + public boolean isEvacuateFinished(String clusterName, String instanceName) { + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + PropertyKey.Builder keyBuilder = accessor.keyBuilder(); + + // check the instance is alive + LiveInstance liveInstance = accessor.getProperty(keyBuilder.liveInstance(instanceName)); + if (liveInstance == null) { + logger.warn("instance {} in cluster {} is not alive.", instanceName, clusterName); + return false; + } + + BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); + String sessionId = liveInstance.getEphemeralOwner(); + + String path = PropertyPathBuilder.instanceCurrentState(clusterName, instanceName, sessionId); + List currentStates = baseAccessor.getChildNames(path, 0); + if (currentStates == null) { + logger.warn("instance {} in cluster {} does not have live session.", instanceName, + clusterName); + return false; + } + return currentStates.isEmpty(); + } + + @Override + public boolean isPrepopulateReady(String clusterName, String instanceName) { + return this.getInstanceConfig(clusterName, instanceName) + .getInstanceOperation() + .equals(InstanceConstants.InstanceOperation.EVACUATE.name()); + } + + @Override public void enableResource(final String clusterName, final String resourceName, final boolean enabled) { logger.info("{} resource {} in cluster {}.", enabled ? "Enable" : "Disable", resourceName, diff --git a/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java b/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java index 3f459318b9..5813603b01 100644 --- a/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java +++ b/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java @@ -11,6 +11,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import org.apache.helix.ConfigAccessor; +import org.apache.helix.HelixAdmin; import org.apache.helix.HelixDataAccessor; import org.apache.helix.HelixRollbackException; import org.apache.helix.NotificationContext; @@ -22,6 +23,7 @@ import org.apache.helix.controller.rebalancer.waged.AssignmentMetadataStore; import org.apache.helix.integration.manager.ClusterControllerManager; import org.apache.helix.integration.manager.MockParticipantManager; +import org.apache.helix.manager.zk.ZKHelixAdmin; import org.apache.helix.manager.zk.ZKHelixDataAccessor; import org.apache.helix.manager.zk.ZkBucketDataAccessor; import org.apache.helix.model.BuiltInStateModelDefinitions; @@ -57,6 +59,8 @@ public class TestInstanceOperation extends ZkTestBase { private ZkHelixClusterVerifier _clusterVerifier; private ConfigAccessor _configAccessor; private long _stateModelDelay = 3L; + + private HelixAdmin _admin; protected AssignmentMetadataStore _assignmentMetadataStore; HelixDataAccessor _dataAccessor; @@ -91,6 +95,8 @@ public void beforeClass() throws Exception { createTestDBs(200); setUpWagedBaseline(); + + _admin = new ZKHelixAdmin(_gZkClient); } @Test @@ -119,6 +125,9 @@ public void testEvacuate() throws Exception { Assert.assertFalse(newPAssignedParticipants.contains(instanceToEvacuate)); Assert.assertTrue(newPAssignedParticipants.containsAll(currentActiveInstances)); } + + Assert.assertTrue(_admin.isEvacuateFinished(CLUSTER_NAME, instanceToEvacuate)); + Assert.assertTrue(_admin.isPrepopulateReady(CLUSTER_NAME, instanceToEvacuate)); } @Test(dependsOnMethods = "testEvacuate") @@ -215,6 +224,7 @@ public void testEvacuateAndCancelBeforeBootstrapFinish() throws Exception { TestHelper.verify( () -> ((_dataAccessor.getChildNames(_dataAccessor.keyBuilder().messages(participant))).isEmpty()), 30000); } + Assert.assertFalse(_admin.isEvacuateFinished(CLUSTER_NAME, instanceToEvacuate)); // sleep a bit so ST messages can start executing Thread.sleep(Math.abs(_stateModelDelay / 100)); @@ -261,6 +271,7 @@ public void testEvacuateAndCancelBeforeDropFinish() throws Exception { // message should be pending at the to evacuate participant TestHelper.verify( () -> ((_dataAccessor.getChildNames(_dataAccessor.keyBuilder().messages(instanceToEvacuate))).isEmpty()), 30000); + Assert.assertFalse(_admin.isEvacuateFinished(CLUSTER_NAME, instanceToEvacuate)); // cancel evacuation _gSetupTool.getClusterManagementTool() @@ -323,7 +334,7 @@ public void testMarkEvacuationAfterEMM() throws Exception { Assert.assertFalse(newPAssignedParticipants.contains(instanceToEvacuate)); Assert.assertTrue(newPAssignedParticipants.containsAll(currentActiveInstances)); } - + Assert.assertTrue(_admin.isPrepopulateReady(CLUSTER_NAME, instanceToEvacuate)); } @Test(dependsOnMethods = "testMarkEvacuationAfterEMM") diff --git a/helix-core/src/test/java/org/apache/helix/mock/MockHelixAdmin.java b/helix-core/src/test/java/org/apache/helix/mock/MockHelixAdmin.java index 81993475b8..56956d5cfa 100644 --- a/helix-core/src/test/java/org/apache/helix/mock/MockHelixAdmin.java +++ b/helix-core/src/test/java/org/apache/helix/mock/MockHelixAdmin.java @@ -550,4 +550,14 @@ public Map validateInstancesForWagedRebalance(String clusterNam List instancesNames) { return null; } + + @Override + public boolean isEvacuateFinished(String clusterName, String instancesNames) { + return false; + } + + @Override + public boolean isPrepopulateReady(String clusterName, String instancesNames) { + return false; + } } From cd805fbb4dbd5bfe2e8ed02ad4595841df147afc Mon Sep 17 00:00:00 2001 From: xyuanlu Date: Mon, 18 Sep 2023 17:19:01 -0700 Subject: [PATCH 2/4] address comment --- .../java/org/apache/helix/HelixAdmin.java | 2 +- .../rebalancer/DelayedAutoRebalancer.java | 5 +- .../apache/helix/manager/zk/ZKHelixAdmin.java | 740 ++++++++---------- .../rebalancer/TestInstanceOperation.java | 5 +- .../org/apache/helix/mock/MockHelixAdmin.java | 2 +- 5 files changed, 315 insertions(+), 439 deletions(-) diff --git a/helix-core/src/main/java/org/apache/helix/HelixAdmin.java b/helix-core/src/main/java/org/apache/helix/HelixAdmin.java index 03cbea5ec8..e3be8383c5 100644 --- a/helix-core/src/main/java/org/apache/helix/HelixAdmin.java +++ b/helix-core/src/main/java/org/apache/helix/HelixAdmin.java @@ -748,5 +748,5 @@ Map validateInstancesForWagedRebalance(String clusterName, */ boolean isEvacuateFinished(String clusterName, String instancesNames); - boolean isPrepopulateReady(String clusterName, String instancesNames); + boolean isReadyForPreparingJoiningCluster(String clusterName, String instancesNames); } diff --git a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/DelayedAutoRebalancer.java b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/DelayedAutoRebalancer.java index 56be045306..ff5824722d 100644 --- a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/DelayedAutoRebalancer.java +++ b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/DelayedAutoRebalancer.java @@ -33,7 +33,6 @@ import java.util.stream.Collectors; import org.apache.helix.HelixDefinedState; import org.apache.helix.api.config.StateTransitionThrottleConfig; -import org.apache.helix.constants.InstanceConstants; import org.apache.helix.controller.dataproviders.ResourceControllerDataProvider; import org.apache.helix.controller.rebalancer.constraint.MonitoredAbnormalResolver; import org.apache.helix.controller.rebalancer.util.DelayedRebalanceUtil; @@ -56,7 +55,7 @@ */ public class DelayedAutoRebalancer extends AbstractRebalancer { private static final Logger LOG = LoggerFactory.getLogger(DelayedAutoRebalancer.class); - private static final Set INSTANCE_OPERATION_TO_EXCLUDE = Set.of("EVACUATE", "SWAP_IN"); + public static final Set INSTANCE_OPERATION_TO_EXCLUDE_FROM_ASSIGNMENT = Set.of("EVACUATE", "SWAP_IN"); @Override public IdealState computeNewIdealState(String resourceName, @@ -205,7 +204,7 @@ private static List filterOutOnOperationInstances(Map nodes) { return nodes.stream() .filter( - instance -> !INSTANCE_OPERATION_TO_EXCLUDE.contains(instanceConfigMap.get(instance).getInstanceOperation())) + instance -> !INSTANCE_OPERATION_TO_EXCLUDE_FROM_ASSIGNMENT.contains(instanceConfigMap.get(instance).getInstanceOperation())) .collect(Collectors.toList()); } diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java index a3a2c34dd0..b0984766e0 100644 --- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java +++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java @@ -58,6 +58,7 @@ import org.apache.helix.api.status.ClusterManagementModeRequest; import org.apache.helix.api.topology.ClusterTopology; import org.apache.helix.constants.InstanceConstants; +import org.apache.helix.controller.rebalancer.DelayedAutoRebalancer; import org.apache.helix.controller.rebalancer.strategy.RebalanceStrategy; import org.apache.helix.controller.rebalancer.util.WagedValidationUtil; import org.apache.helix.controller.rebalancer.waged.WagedRebalancer; @@ -151,23 +152,21 @@ public ZKHelixAdmin(RealmAwareZkClient zkClient) { public ZKHelixAdmin(String zkAddress) { int timeOutInSec = Integer.parseInt(System.getProperty(CONNECTION_TIMEOUT, "30")); RealmAwareZkClient.RealmAwareZkClientConfig clientConfig = - new RealmAwareZkClient.RealmAwareZkClientConfig() - .setConnectInitTimeout(timeOutInSec * 1000L) + new RealmAwareZkClient.RealmAwareZkClientConfig().setConnectInitTimeout(timeOutInSec * 1000L) .setZkSerializer(new ZNRecordSerializer()); RealmAwareZkClient zkClient; if (Boolean.getBoolean(SystemPropertyKeys.MULTI_ZK_ENABLED) || zkAddress == null) { try { - zkClient = new FederatedZkClient( - new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder().build(), clientConfig); + zkClient = + new FederatedZkClient(new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder().build(), clientConfig); } catch (IllegalStateException | InvalidRoutingDataException e) { throw new HelixException("Not able to connect on multi-realm mode.", e); } } else { zkClient = SharedZkClientFactory.getInstance() - .buildZkClient(new HelixZkClient.ZkConnectionConfig(zkAddress), - clientConfig.createHelixZkClientConfig()); + .buildZkClient(new HelixZkClient.ZkConnectionConfig(zkAddress), clientConfig.createHelixZkClientConfig()); zkClient.waitUntilConnected(timeOutInSec, TimeUnit.SECONDS); } @@ -200,14 +199,12 @@ public void addInstance(String clusterName, InstanceConfig instanceConfig) { _zkClient.createPersistent(PropertyPathBuilder.instanceMessage(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceCurrentState(clusterName, nodeId), true); - _zkClient - .createPersistent(PropertyPathBuilder.instanceTaskCurrentState(clusterName, nodeId), true); + _zkClient.createPersistent(PropertyPathBuilder.instanceTaskCurrentState(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceCustomizedState(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceError(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceStatusUpdate(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceHistory(clusterName, nodeId), true); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.participantHistory(nodeId), new ParticipantHistory(nodeId)); } @@ -219,20 +216,17 @@ public void dropInstance(String clusterName, InstanceConfig instanceConfig) { String instanceConfigPath = PropertyPathBuilder.instanceConfig(clusterName, instanceName); if (!_zkClient.exists(instanceConfigPath)) { - throw new HelixException( - "Node " + instanceName + " does not exist in config for cluster " + clusterName); + throw new HelixException("Node " + instanceName + " does not exist in config for cluster " + clusterName); } String instancePath = PropertyPathBuilder.instance(clusterName, instanceName); if (!_zkClient.exists(instancePath)) { - throw new HelixException( - "Node " + instanceName + " does not exist in instances for cluster " + clusterName); + throw new HelixException("Node " + instanceName + " does not exist in instances for cluster " + clusterName); } String liveInstancePath = PropertyPathBuilder.liveInstance(clusterName, instanceName); if (_zkClient.exists(liveInstancePath)) { - throw new HelixException( - "Node " + instanceName + " is still alive for cluster " + clusterName + ", can't drop."); + throw new HelixException("Node " + instanceName + " is still alive for cluster " + clusterName + ", can't drop."); } // delete config path @@ -254,12 +248,10 @@ private void dropInstancePathRecursively(String instancePath, String instanceNam // Racing condition with controller's persisting node history, retryable. // We don't need to backoff here as this racing condition only happens once (controller // does not repeatedly write instance history) - logger.warn("Retrying dropping instance {} with exception {}", instanceName, - e.getCause().getMessage()); + logger.warn("Retrying dropping instance {} with exception {}", instanceName, e.getCause().getMessage()); retryCnt++; } else { - String errorMessage = - "Failed to drop instance: " + instanceName + ". Retry times: " + retryCnt; + String errorMessage = "Failed to drop instance: " + instanceName + ". Retry times: " + retryCnt; logger.error(errorMessage, e); throw new HelixException(errorMessage, e); } @@ -287,8 +279,8 @@ public void purgeOfflineInstances(String clusterName, long offlineDuration) { } }); if (failToPurgeInstances.size() > 0) { - LOG.error("ZKHelixAdmin::purgeOfflineInstances(): failed to drop the following instances: " - + failToPurgeInstances); + LOG.error( + "ZKHelixAdmin::purgeOfflineInstances(): failed to drop the following instances: " + failToPurgeInstances); } } @@ -306,56 +298,47 @@ public InstanceConfig getInstanceConfig(String clusterName, String instanceName) logger.info("Get instance config for instance {} from cluster {}.", instanceName, clusterName); String instanceConfigPath = PropertyPathBuilder.instanceConfig(clusterName, instanceName); if (!_zkClient.exists(instanceConfigPath)) { - throw new HelixException( - "instance" + instanceName + " does not exist in cluster " + clusterName); + throw new HelixException("instance" + instanceName + " does not exist in cluster " + clusterName); } - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.instanceConfig(instanceName)); } @Override - public boolean setInstanceConfig(String clusterName, String instanceName, - InstanceConfig newInstanceConfig) { - logger.info("Set instance config for instance {} to cluster {} with new InstanceConfig {}.", - instanceName, clusterName, - newInstanceConfig == null ? "NULL" : newInstanceConfig.toString()); + public boolean setInstanceConfig(String clusterName, String instanceName, InstanceConfig newInstanceConfig) { + logger.info("Set instance config for instance {} to cluster {} with new InstanceConfig {}.", instanceName, + clusterName, newInstanceConfig == null ? "NULL" : newInstanceConfig.toString()); String instanceConfigPath = PropertyPathBuilder.getPath(PropertyType.CONFIGS, clusterName, HelixConfigScope.ConfigScopeProperty.PARTICIPANT.toString(), instanceName); if (!_zkClient.exists(instanceConfigPath)) { - throw new HelixException( - "instance" + instanceName + " does not exist in cluster " + clusterName); + throw new HelixException("instance" + instanceName + " does not exist in cluster " + clusterName); } - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey instanceConfigPropertyKey = accessor.keyBuilder().instanceConfig(instanceName); InstanceConfig currentInstanceConfig = accessor.getProperty(instanceConfigPropertyKey); - if (!newInstanceConfig.getHostName().equals(currentInstanceConfig.getHostName()) - || !newInstanceConfig.getPort().equals(currentInstanceConfig.getPort())) { + if (!newInstanceConfig.getHostName().equals(currentInstanceConfig.getHostName()) || !newInstanceConfig.getPort() + .equals(currentInstanceConfig.getPort())) { throw new HelixException( - "Hostname and port cannot be changed, current hostname: " + currentInstanceConfig - .getHostName() + " and port: " + currentInstanceConfig.getPort() - + " is different from new hostname: " + newInstanceConfig.getHostName() - + "and new port: " + newInstanceConfig.getPort()); + "Hostname and port cannot be changed, current hostname: " + currentInstanceConfig.getHostName() + + " and port: " + currentInstanceConfig.getPort() + " is different from new hostname: " + + newInstanceConfig.getHostName() + "and new port: " + newInstanceConfig.getPort()); } return accessor.setProperty(instanceConfigPropertyKey, newInstanceConfig); } @Override - public void enableInstance(final String clusterName, final String instanceName, - final boolean enabled) { + public void enableInstance(final String clusterName, final String instanceName, final boolean enabled) { enableInstance(clusterName, instanceName, enabled, null, null); } @Override - public void enableInstance(final String clusterName, final String instanceName, - final boolean enabled, InstanceConstants.InstanceDisabledType disabledType, String reason) { - logger.info("{} instance {} in cluster {}.", enabled ? "Enable" : "Disable", instanceName, - clusterName); + public void enableInstance(final String clusterName, final String instanceName, final boolean enabled, + InstanceConstants.InstanceDisabledType disabledType, String reason) { + logger.info("{} instance {} in cluster {}.", enabled ? "Enable" : "Disable", instanceName, clusterName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor<>(_zkClient); // Eventually we will have all instances' enable/disable information in clusterConfig. Now we // update both instanceConfig and clusterConfig in transition period. @@ -388,7 +371,7 @@ public void setInstanceOperation(String clusterName, String instanceName, "Cluster " + clusterName + ", instance: " + instanceName + ", instance config does not exist"); } - boolean succeeded = baseAccessor.update(path, new DataUpdater() { + boolean succeeded = baseAccessor.update(path, new DataUpdater() { @Override public ZNRecord update(ZNRecord currentData) { if (currentData == null) { @@ -407,17 +390,34 @@ public ZNRecord update(ZNRecord currentData) { } } - @Override public boolean isEvacuateFinished(String clusterName, String instanceName) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + return !instanceHasCurrentSateOrMessage(clusterName, instanceName); + } + + @Override + public boolean isReadyForPreparingJoiningCluster(String clusterName, String instanceName) { + return !instanceHasCurrentSateOrMessage(clusterName, instanceName) + && DelayedAutoRebalancer.INSTANCE_OPERATION_TO_EXCLUDE_FROM_ASSIGNMENT.contains( + getInstanceConfig(clusterName, instanceName).getInstanceOperation()); + } + + /** + * Return true if Instance has any current state or pending message. Otherwise, return false if instance is offline, + * instance has no active session, or if instance is online but has no current state or pending message. + * @param clusterName + * @param instanceName + * @return + */ + private boolean instanceHasCurrentSateOrMessage(String clusterName, String instanceName) { + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); // check the instance is alive LiveInstance liveInstance = accessor.getProperty(keyBuilder.liveInstance(instanceName)); if (liveInstance == null) { - logger.warn("instance {} in cluster {} is not alive.", instanceName, clusterName); + logger.warn("Instance {} in cluster {} is not alive. The instance can be removed anyway.", instanceName, + clusterName); return false; } @@ -427,37 +427,34 @@ public boolean isEvacuateFinished(String clusterName, String instanceName) { String path = PropertyPathBuilder.instanceCurrentState(clusterName, instanceName, sessionId); List currentStates = baseAccessor.getChildNames(path, 0); if (currentStates == null) { - logger.warn("instance {} in cluster {} does not have live session.", instanceName, - clusterName); + logger.warn("Instance {} in cluster {} does not have live session. The instance can be removed anyway.", + instanceName, clusterName); return false; } - return currentStates.isEmpty(); - } - @Override - public boolean isPrepopulateReady(String clusterName, String instanceName) { - return this.getInstanceConfig(clusterName, instanceName) - .getInstanceOperation() - .equals(InstanceConstants.InstanceOperation.EVACUATE.name()); + List messages = accessor.getChildValues(keyBuilder.messages(instanceName), true); + if (messages != null) { + logger.warn("Instance {} in cluster {} has pending messages.", instanceName, clusterName); + return true; + } + + return !currentStates.isEmpty(); } - @Override - public void enableResource(final String clusterName, final String resourceName, - final boolean enabled) { - logger.info("{} resource {} in cluster {}.", enabled ? "Enable" : "Disable", resourceName, - clusterName); + @Override + public void enableResource(final String clusterName, final String resourceName, final boolean enabled) { + logger.info("{} resource {} in cluster {}.", enabled ? "Enable" : "Disable", resourceName, clusterName); String path = PropertyPathBuilder.idealState(clusterName, resourceName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); if (!baseAccessor.exists(path, 0)) { - throw new HelixException("Cluster " + clusterName + ", resource: " + resourceName - + ", ideal-state does not exist"); + throw new HelixException( + "Cluster " + clusterName + ", resource: " + resourceName + ", ideal-state does not exist"); } baseAccessor.update(path, new DataUpdater() { @Override public ZNRecord update(ZNRecord currentData) { if (currentData == null) { - throw new HelixException( - "Cluster: " + clusterName + ", resource: " + resourceName + ", ideal-state is null"); + throw new HelixException("Cluster: " + clusterName + ", resource: " + resourceName + ", ideal-state is null"); } IdealState idealState = new IdealState(currentData); idealState.enable(enabled); @@ -467,19 +464,18 @@ public ZNRecord update(ZNRecord currentData) { } @Override - public void enablePartition(final boolean enabled, final String clusterName, - final String instanceName, final String resourceName, final List partitionNames) { - logger.info("{} partitions {} for resource {} on instance {} in cluster {}.", - enabled ? "Enable" : "Disable", HelixUtil.serializeByComma(partitionNames), resourceName, - instanceName, clusterName); + public void enablePartition(final boolean enabled, final String clusterName, final String instanceName, + final String resourceName, final List partitionNames) { + logger.info("{} partitions {} for resource {} on instance {} in cluster {}.", enabled ? "Enable" : "Disable", + HelixUtil.serializeByComma(partitionNames), resourceName, instanceName, clusterName); String path = PropertyPathBuilder.instanceConfig(clusterName, instanceName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); // check instanceConfig exists if (!baseAccessor.exists(path, 0)) { - throw new HelixException("Cluster: " + clusterName + ", instance: " + instanceName - + ", instance config does not exist"); + throw new HelixException( + "Cluster: " + clusterName + ", instance: " + instanceName + ", instance config does not exist"); } // check resource exists @@ -497,8 +493,7 @@ public void enablePartition(final boolean enabled, final String clusterName, // throw new HelixException("Cluster: " + clusterName + ", resource: " + resourceName // + ", ideal state does not exist"); logger.warn( - "Disable partitions: " + partitionNames + " but Cluster: " + clusterName + ", resource: " - + resourceName + "Disable partitions: " + partitionNames + " but Cluster: " + clusterName + ", resource: " + resourceName + " does not exists. probably disable it during ERROR->DROPPED transtition"); } else { // check partitions exist. warn if not @@ -508,12 +503,11 @@ public void enablePartition(final boolean enabled, final String clusterName, && idealState.getPreferenceList(partitionName) == null) || ( idealState.getRebalanceMode() == RebalanceMode.USER_DEFINED && idealState.getPreferenceList(partitionName) == null) || ( - idealState.getRebalanceMode() == RebalanceMode.TASK - && idealState.getPreferenceList(partitionName) == null) || ( - idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED - && idealState.getInstanceStateMap(partitionName) == null)) { - logger.warn("Cluster: " + clusterName + ", resource: " + resourceName + ", partition: " - + partitionName + ", partition does not exist in ideal state"); + idealState.getRebalanceMode() == RebalanceMode.TASK && idealState.getPreferenceList(partitionName) == null) + || (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED + && idealState.getInstanceStateMap(partitionName) == null)) { + logger.warn("Cluster: " + clusterName + ", resource: " + resourceName + ", partition: " + partitionName + + ", partition does not exist in ideal state"); } } } @@ -524,8 +518,8 @@ public void enablePartition(final boolean enabled, final String clusterName, @Override public ZNRecord update(ZNRecord currentData) { if (currentData == null) { - throw new HelixException("Cluster: " + clusterName + ", instance: " + instanceName - + ", participant config is null"); + throw new HelixException( + "Cluster: " + clusterName + ", instance: " + instanceName + ", participant config is null"); } InstanceConfig instanceConfig = new InstanceConfig(currentData); @@ -553,8 +547,7 @@ public void enableCluster(String clusterName, boolean enabled) { public void enableCluster(String clusterName, boolean enabled, String reason) { logger.info("{} cluster {} for reason {}.", enabled ? "Enable" : "Disable", clusterName, reason == null ? "NULL" : reason); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); if (enabled) { @@ -578,11 +571,9 @@ public void enableMaintenanceMode(String clusterName, boolean enabled) { @Override public boolean isInMaintenanceMode(String clusterName) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); - return accessor.getBaseDataAccessor() - .exists(keyBuilder.maintenance().getPath(), AccessOption.PERSISTENT); + return accessor.getBaseDataAccessor().exists(keyBuilder.maintenance().getPath(), AccessOption.PERSISTENT); } @Override @@ -608,8 +599,7 @@ public void setClusterManagementMode(ClusterManagementModeRequest request) { @Override public ClusterManagementMode getClusterManagementMode(String clusterName) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); ClusterStatus status = accessor.getProperty(accessor.keyBuilder().clusterStatus()); return status == null ? null : new ClusterManagementMode(status.getManagementMode(), status.getManagementModeStatus()); @@ -617,8 +607,7 @@ public ClusterManagementMode getClusterManagementMode(String clusterName) { private void enableClusterPauseMode(String clusterName, boolean cancelPendingST, String reason) { String hostname = NetworkUtil.getLocalhostName(); - logger.info( - "Enable cluster pause mode for cluster: {}. CancelPendingST: {}. Reason: {}. From Host: {}", + logger.info("Enable cluster pause mode for cluster: {}. CancelPendingST: {}. Reason: {}. From Host: {}", clusterName, cancelPendingST, reason, hostname); BaseDataAccessor baseDataAccessor = new ZkBaseDataAccessor<>(_zkClient); @@ -631,8 +620,7 @@ private void enableClusterPauseMode(String clusterName, boolean cancelPendingST, // check whether cancellation is enabled ClusterConfig config = accessor.getProperty(accessor.keyBuilder().clusterConfig()); if (cancelPendingST && !config.isStateTransitionCancelEnabled()) { - throw new HelixConflictException( - "State transition cancellation not enabled in " + clusterName); + throw new HelixConflictException("State transition cancellation not enabled in " + clusterName); } PauseSignal pauseSignal = new PauseSignal(); @@ -651,8 +639,7 @@ private void enableClusterPauseMode(String clusterName, boolean cancelPendingST, private void disableClusterPauseMode(String clusterName) { logger.info("Disable cluster pause mode for cluster: {}", clusterName); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey pausePropertyKey = accessor.keyBuilder().pause(); PauseSignal pauseSignal = accessor.getProperty(pausePropertyKey); if (pauseSignal == null || !pauseSignal.isClusterPause()) { @@ -680,9 +667,8 @@ public void autoEnableMaintenanceMode(String clusterName, boolean enabled, Strin @Override public void manuallyEnableMaintenanceMode(String clusterName, boolean enabled, String reason, Map customFields) { - processMaintenanceMode(clusterName, enabled, reason, - MaintenanceSignal.AutoTriggerReason.NOT_APPLICABLE, customFields, - MaintenanceSignal.TriggeringEntity.USER); + processMaintenanceMode(clusterName, enabled, reason, MaintenanceSignal.AutoTriggerReason.NOT_APPLICABLE, + customFields, MaintenanceSignal.TriggeringEntity.USER); } /** @@ -694,16 +680,14 @@ public void manuallyEnableMaintenanceMode(String clusterName, boolean enabled, S * @param customFields * @param triggeringEntity */ - private void processMaintenanceMode(String clusterName, final boolean enabled, - final String reason, final MaintenanceSignal.AutoTriggerReason internalReason, - final Map customFields, + private void processMaintenanceMode(String clusterName, final boolean enabled, final String reason, + final MaintenanceSignal.AutoTriggerReason internalReason, final Map customFields, final MaintenanceSignal.TriggeringEntity triggeringEntity) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); logger.info("Cluster {} {} {} maintenance mode for reason {}.", clusterName, - triggeringEntity == MaintenanceSignal.TriggeringEntity.CONTROLLER ? "automatically" - : "manually", enabled ? "enters" : "exits", reason == null ? "NULL" : reason); + triggeringEntity == MaintenanceSignal.TriggeringEntity.CONTROLLER ? "automatically" : "manually", + enabled ? "enters" : "exits", reason == null ? "NULL" : reason); final long currentTime = System.currentTimeMillis(); if (!enabled) { // Exit maintenance mode @@ -742,20 +726,18 @@ private void processMaintenanceMode(String clusterName, final boolean enabled, // Record a MaintenanceSignal history if (!accessor.getBaseDataAccessor() - .update(keyBuilder.controllerLeaderHistory().getPath(), - (DataUpdater) oldRecord -> { - try { - if (oldRecord == null) { - oldRecord = new ZNRecord(PropertyType.HISTORY.toString()); - } - return new ControllerHistory(oldRecord) - .updateMaintenanceHistory(enabled, reason, currentTime, internalReason, - customFields, triggeringEntity); - } catch (IOException e) { - logger.error("Failed to update maintenance history! Exception: {}", e); - return oldRecord; - } - }, AccessOption.PERSISTENT)) { + .update(keyBuilder.controllerLeaderHistory().getPath(), (DataUpdater) oldRecord -> { + try { + if (oldRecord == null) { + oldRecord = new ZNRecord(PropertyType.HISTORY.toString()); + } + return new ControllerHistory(oldRecord).updateMaintenanceHistory(enabled, reason, currentTime, + internalReason, customFields, triggeringEntity); + } catch (IOException e) { + logger.error("Failed to update maintenance history! Exception: {}", e); + return oldRecord; + } + }, AccessOption.PERSISTENT)) { logger.error("Failed to write maintenance history to ZK!"); } } @@ -776,8 +758,8 @@ private enum ResetPartitionFailureReason { public String getMessage(String resourceName, List partitionNames, String instanceName, String errorStateEntity, String clusterName) { - return String.format("Can't reset state for %s.%s on %s, because " + message, resourceName, - partitionNames, instanceName, errorStateEntity, clusterName); + return String.format("Can't reset state for %s.%s on %s, because " + message, resourceName, partitionNames, + instanceName, errorStateEntity, clusterName); } } @@ -785,10 +767,9 @@ public String getMessage(String resourceName, List partitionNames, Strin public void resetPartition(String clusterName, String instanceName, String resourceName, List partitionNames) { logger.info("Reset partitions {} for resource {} on instance {} in cluster {}.", - partitionNames == null ? "NULL" : HelixUtil.serializeByComma(partitionNames), resourceName, - instanceName, clusterName); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + partitionNames == null ? "NULL" : HelixUtil.serializeByComma(partitionNames), resourceName, instanceName, + clusterName); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); // check the instance is alive @@ -798,37 +779,37 @@ public void resetPartition(String clusterName, String instanceName, String resou String instanceConfigPath = PropertyPathBuilder.instanceConfig(clusterName, instanceName); throw new HelixException(String.format( (_zkClient.exists(instanceConfigPath) ? ResetPartitionFailureReason.INSTANCE_NOT_ALIVE - : ResetPartitionFailureReason.INSTANCE_NON_EXISTENT) - .getMessage(resourceName, partitionNames, instanceName, instanceName, clusterName))); + : ResetPartitionFailureReason.INSTANCE_NON_EXISTENT).getMessage(resourceName, partitionNames, + instanceName, instanceName, clusterName))); } // check resource group exists IdealState idealState = accessor.getProperty(keyBuilder.idealStates(resourceName)); if (idealState == null) { - throw new HelixException(String.format(ResetPartitionFailureReason.RESOURCE_NON_EXISTENT - .getMessage(resourceName, partitionNames, instanceName, resourceName, clusterName))); + throw new HelixException(String.format( + ResetPartitionFailureReason.RESOURCE_NON_EXISTENT.getMessage(resourceName, partitionNames, instanceName, + resourceName, clusterName))); } // check partition exists in resource group Set resetPartitionNames = new HashSet(partitionNames); Set partitions = - (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED) ? idealState.getRecord() - .getMapFields().keySet() : idealState.getRecord().getListFields().keySet(); + (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED) ? idealState.getRecord().getMapFields().keySet() + : idealState.getRecord().getListFields().keySet(); if (!partitions.containsAll(resetPartitionNames)) { - throw new HelixException(String.format(ResetPartitionFailureReason.PARTITION_NON_EXISTENT - .getMessage(resourceName, partitionNames, instanceName, partitionNames.toString(), - clusterName))); + throw new HelixException(String.format( + ResetPartitionFailureReason.PARTITION_NON_EXISTENT.getMessage(resourceName, partitionNames, instanceName, + partitionNames.toString(), clusterName))); } // check partition is in ERROR state String sessionId = liveInstance.getEphemeralOwner(); - CurrentState curState = - accessor.getProperty(keyBuilder.currentState(instanceName, sessionId, resourceName)); + CurrentState curState = accessor.getProperty(keyBuilder.currentState(instanceName, sessionId, resourceName)); for (String partitionName : resetPartitionNames) { if (!curState.getState(partitionName).equals(HelixDefinedState.ERROR.toString())) { - throw new HelixException(String.format(ResetPartitionFailureReason.PARTITION_NOT_ERROR - .getMessage(resourceName, partitionNames, instanceName, partitionNames.toString(), - clusterName))); + throw new HelixException(String.format( + ResetPartitionFailureReason.PARTITION_NOT_ERROR.getMessage(resourceName, partitionNames, instanceName, + partitionNames.toString(), clusterName))); } } @@ -836,23 +817,23 @@ public void resetPartition(String clusterName, String instanceName, String resou String stateModelDef = idealState.getStateModelDefRef(); StateModelDefinition stateModel = accessor.getProperty(keyBuilder.stateModelDef(stateModelDef)); if (stateModel == null) { - throw new HelixException(String.format(ResetPartitionFailureReason.STATE_MODEL_NON_EXISTENT - .getMessage(resourceName, partitionNames, instanceName, stateModelDef, clusterName))); + throw new HelixException(String.format( + ResetPartitionFailureReason.STATE_MODEL_NON_EXISTENT.getMessage(resourceName, partitionNames, instanceName, + stateModelDef, clusterName))); } // check there is no pending messages for the partitions exist List messages = accessor.getChildValues(keyBuilder.messages(instanceName), true); for (Message message : messages) { - if (!MessageType.STATE_TRANSITION.name().equalsIgnoreCase(message.getMsgType()) || !sessionId - .equals(message.getTgtSessionId()) || !resourceName.equals(message.getResourceName()) + if (!MessageType.STATE_TRANSITION.name().equalsIgnoreCase(message.getMsgType()) || !sessionId.equals( + message.getTgtSessionId()) || !resourceName.equals(message.getResourceName()) || !resetPartitionNames.contains(message.getPartitionName())) { continue; } - throw new HelixException(String.format( - "Can't reset state for %s.%s on %s, because a pending message %s exists for resource %s", - resourceName, partitionNames, instanceName, message.toString(), - message.getResourceName())); + throw new HelixException( + String.format("Can't reset state for %s.%s on %s, because a pending message %s exists for resource %s", + resourceName, partitionNames, instanceName, message.toString(), message.getResourceName())); } String adminName = null; @@ -900,8 +881,7 @@ public void resetInstance(String clusterName, List instanceNames) { // TODO: not mp-safe logger.info("Reset instances {} in cluster {}.", instanceNames == null ? "NULL" : HelixUtil.serializeByComma(instanceNames), clusterName); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List extViews = accessor.getChildValues(keyBuilder.externalViews(), true); @@ -928,8 +908,7 @@ public void resetResource(String clusterName, List resourceNames) { // TODO: not mp-safe logger.info("Reset resources {} in cluster {}.", resourceNames == null ? "NULL" : HelixUtil.serializeByComma(resourceNames), clusterName); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List extViews = accessor.getChildValues(keyBuilder.externalViews(), true); @@ -956,8 +935,7 @@ public void resetResource(String clusterName, List resourceNames) { } for (String instanceName : resetPartitionNames.keySet()) { - resetPartition(clusterName, instanceName, extView.getResourceName(), - resetPartitionNames.get(instanceName)); + resetPartition(clusterName, instanceName, extView.getResourceName(), resetPartitionNames.get(instanceName)); } } } @@ -1058,16 +1036,14 @@ public List getInstancesInClusterWithTag(String clusterName, String tag) List instances = _zkClient.getChildren(memberInstancesPath); List result = new ArrayList(); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); for (String instanceName : instances) { InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceName)); if (config == null) { - throw new IllegalStateException(String - .format("Instance %s does not have a config, cluster might be in bad state", - instanceName)); + throw new IllegalStateException( + String.format("Instance %s does not have a config, cluster might be in bad state", instanceName)); } if (config.containsTag(tag)) { result.add(instanceName); @@ -1077,23 +1053,20 @@ public List getInstancesInClusterWithTag(String clusterName, String tag) } @Override - public void addResource(String clusterName, String resourceName, int partitions, - String stateModelRef) { - addResource(clusterName, resourceName, partitions, stateModelRef, - RebalanceMode.SEMI_AUTO.toString(), 0); + public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef) { + addResource(clusterName, resourceName, partitions, stateModelRef, RebalanceMode.SEMI_AUTO.toString(), 0); } @Override - public void addResource(String clusterName, String resourceName, int partitions, - String stateModelRef, String rebalancerMode) { + public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, + String rebalancerMode) { addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, 0); } @Override - public void addResource(String clusterName, String resourceName, int partitions, - String stateModelRef, String rebalancerMode, String rebalanceStrategy) { - addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, - rebalanceStrategy, 0, -1); + public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, + String rebalancerMode, String rebalanceStrategy) { + addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, rebalanceStrategy, 0, -1); } @Override @@ -1102,38 +1075,35 @@ public void addResource(String clusterName, String resourceName, IdealState idea String stateModelRef = idealstate.getStateModelDefRef(); String stateModelDefPath = PropertyPathBuilder.stateModelDef(clusterName, stateModelRef); if (!_zkClient.exists(stateModelDefPath)) { - throw new HelixException( - "State model " + stateModelRef + " not found in the cluster STATEMODELDEFS path"); + throw new HelixException("State model " + stateModelRef + " not found in the cluster STATEMODELDEFS path"); } String idealStatePath = PropertyPathBuilder.idealState(clusterName); String resourceIdealStatePath = idealStatePath + "/" + resourceName; if (_zkClient.exists(resourceIdealStatePath)) { - throw new HelixException("Skip the operation. Resource ideal state directory already exists:" - + resourceIdealStatePath); + throw new HelixException( + "Skip the operation. Resource ideal state directory already exists:" + resourceIdealStatePath); } ZKUtil.createChildren(_zkClient, idealStatePath, idealstate.getRecord()); } @Override - public void addResource(String clusterName, String resourceName, int partitions, - String stateModelRef, String rebalancerMode, int bucketSize) { - addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, bucketSize, - -1); + public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, + String rebalancerMode, int bucketSize) { + addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, bucketSize, -1); } @Override - public void addResource(String clusterName, String resourceName, int partitions, - String stateModelRef, String rebalancerMode, int bucketSize, int maxPartitionsPerInstance) { + public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, + String rebalancerMode, int bucketSize, int maxPartitionsPerInstance) { addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, RebalanceStrategy.DEFAULT_REBALANCE_STRATEGY, bucketSize, maxPartitionsPerInstance); } @Override - public void addResource(String clusterName, String resourceName, int partitions, - String stateModelRef, String rebalancerMode, String rebalanceStrategy, int bucketSize, - int maxPartitionsPerInstance) { + public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, + String rebalancerMode, String rebalanceStrategy, int bucketSize, int maxPartitionsPerInstance) { if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } @@ -1141,8 +1111,7 @@ public void addResource(String clusterName, String resourceName, int partitions, IdealState idealState = new IdealState(resourceName); idealState.setNumPartitions(partitions); idealState.setStateModelDefRef(stateModelRef); - RebalanceMode mode = - idealState.rebalanceModeFromString(rebalancerMode, RebalanceMode.SEMI_AUTO); + RebalanceMode mode = idealState.rebalanceModeFromString(rebalancerMode, RebalanceMode.SEMI_AUTO); idealState.setRebalanceMode(mode); idealState.setRebalanceStrategy(rebalanceStrategy); idealState.setReplicas("" + 0); @@ -1160,28 +1129,29 @@ public void addResource(String clusterName, String resourceName, int partitions, public List getClusters() { List zkToplevelPaths; - if (Boolean.getBoolean(SystemPropertyKeys.MULTI_ZK_ENABLED) - || _zkClient instanceof FederatedZkClient) { + if (Boolean.getBoolean(SystemPropertyKeys.MULTI_ZK_ENABLED) || _zkClient instanceof FederatedZkClient) { // If on multi-zk mode, we retrieve cluster information from Metadata Store Directory Service. Map> realmToShardingKeys; - String routingDataSourceEndpoint = - _zkClient.getRealmAwareZkConnectionConfig().getRoutingDataSourceEndpoint(); + String routingDataSourceEndpoint = _zkClient.getRealmAwareZkConnectionConfig().getRoutingDataSourceEndpoint(); if (routingDataSourceEndpoint == null || routingDataSourceEndpoint.isEmpty()) { // If endpoint is not given explicitly, use HTTP and the endpoint set in System Properties realmToShardingKeys = RoutingDataManager.getInstance().getRawRoutingData(); } else { - realmToShardingKeys = RoutingDataManager.getInstance().getRawRoutingData( - RoutingDataReaderType - .lookUp(_zkClient.getRealmAwareZkConnectionConfig().getRoutingDataSourceType()), - routingDataSourceEndpoint); + realmToShardingKeys = RoutingDataManager.getInstance() + .getRawRoutingData( + RoutingDataReaderType.lookUp(_zkClient.getRealmAwareZkConnectionConfig().getRoutingDataSourceType()), + routingDataSourceEndpoint); } if (realmToShardingKeys == null || realmToShardingKeys.isEmpty()) { return Collections.emptyList(); } // Preceding "/"s are removed: e.g.) "/CLUSTER-SHARDING-KEY" -> "CLUSTER-SHARDING-KEY" - zkToplevelPaths = realmToShardingKeys.values().stream().flatMap(List::stream) - .map(shardingKey -> shardingKey.substring(1)).collect(Collectors.toList()); + zkToplevelPaths = realmToShardingKeys.values() + .stream() + .flatMap(List::stream) + .map(shardingKey -> shardingKey.substring(1)) + .collect(Collectors.toList()); } else { // single-zk mode zkToplevelPaths = _zkClient.getChildren("/"); @@ -1205,8 +1175,7 @@ public List getResourcesInCluster(String clusterName) { public List getResourcesInClusterWithTag(String clusterName, String tag) { List resourcesWithTag = new ArrayList(); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); for (String resourceName : getResourcesInCluster(clusterName)) { @@ -1221,21 +1190,17 @@ public List getResourcesInClusterWithTag(String clusterName, String tag) @Override public IdealState getResourceIdealState(String clusterName, String resourceName) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.idealStates(resourceName)); } @Override - public void setResourceIdealState(String clusterName, String resourceName, - IdealState idealState) { - logger - .info("Set IdealState for resource {} in cluster {} with new IdealState {}.", resourceName, - clusterName, idealState == null ? "NULL" : idealState.toString()); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + public void setResourceIdealState(String clusterName, String resourceName, IdealState idealState) { + logger.info("Set IdealState for resource {} in cluster {} with new IdealState {}.", resourceName, clusterName, + idealState == null ? "NULL" : idealState.toString()); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.idealStates(resourceName), idealState); @@ -1250,8 +1215,7 @@ public void setResourceIdealState(String clusterName, String resourceName, @Override public void updateIdealState(String clusterName, String resourceName, IdealState idealState) { if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { - throw new HelixException( - "updateIdealState failed. Cluster: " + clusterName + " is NOT setup properly."); + throw new HelixException("updateIdealState failed. Cluster: " + clusterName + " is NOT setup properly."); } String zkPath = PropertyPathBuilder.idealState(clusterName, resourceName); if (!_zkClient.exists(zkPath)) { @@ -1277,33 +1241,28 @@ public void removeFromIdealState(String clusterName, String resourceName, IdealS @Override public ExternalView getResourceExternalView(String clusterName, String resourceName) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.externalView(resourceName)); } @Override - public CustomizedView getResourceCustomizedView(String clusterName, String resourceName, - String customizedStateType) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + public CustomizedView getResourceCustomizedView(String clusterName, String resourceName, String customizedStateType) { + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.customizedView(customizedStateType, resourceName)); } @Override - public void addStateModelDef(String clusterName, String stateModelDef, - StateModelDefinition stateModel) { + public void addStateModelDef(String clusterName, String stateModelDef, StateModelDefinition stateModel) { addStateModelDef(clusterName, stateModelDef, stateModel, false); } @Override - public void addStateModelDef(String clusterName, String stateModelDef, - StateModelDefinition stateModel, boolean recreateIfExists) { - logger - .info("Add StateModelDef {} in cluster {} with StateModel {}.", stateModelDef, clusterName, - stateModel == null ? "NULL" : stateModel.toString()); + public void addStateModelDef(String clusterName, String stateModelDef, StateModelDefinition stateModel, + boolean recreateIfExists) { + logger.info("Add StateModelDef {} in cluster {} with StateModel {}.", stateModelDef, clusterName, + stateModel == null ? "NULL" : stateModel.toString()); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } @@ -1311,8 +1270,7 @@ public void addStateModelDef(String clusterName, String stateModelDef, String stateModelPath = stateModelDefPath + "/" + stateModelDef; if (_zkClient.exists(stateModelPath)) { if (recreateIfExists) { - logger.info( - "Operation.State Model directory exists:" + stateModelPath + ", remove and recreate."); + logger.info("Operation.State Model directory exists:" + stateModelPath + ", remove and recreate."); _zkClient.deleteRecursively(stateModelPath); } else { logger.info("Skip the operation. State Model directory exists:" + stateModelPath); @@ -1320,8 +1278,7 @@ public void addStateModelDef(String clusterName, String stateModelDef, } } - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.stateModelDef(stateModelDef), stateModel); } @@ -1332,8 +1289,7 @@ public void dropResource(String clusterName, String resourceName) { if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("Cluster " + clusterName + " is not setup yet"); } - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.removeProperty(keyBuilder.idealStates(resourceName)); @@ -1342,8 +1298,7 @@ public void dropResource(String clusterName, String resourceName) { @Override public void addCloudConfig(String clusterName, CloudConfig cloudConfig) { - logger.info("Add CloudConfig to cluster {}, CloudConfig is {}.", clusterName, - cloudConfig.toString()); + logger.info("Add CloudConfig to cluster {}, CloudConfig is {}.", clusterName, cloudConfig.toString()); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); @@ -1352,8 +1307,7 @@ public void addCloudConfig(String clusterName, CloudConfig cloudConfig) { CloudConfig.Builder builder = new CloudConfig.Builder(cloudConfig); CloudConfig cloudConfigBuilder = builder.build(); - ZKHelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.cloudConfig(), cloudConfigBuilder); } @@ -1361,8 +1315,7 @@ public void addCloudConfig(String clusterName, CloudConfig cloudConfig) { @Override public void removeCloudConfig(String clusterName) { logger.info("Remove Cloud Config for cluster {}.", clusterName); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.removeProperty(keyBuilder.cloudConfig()); } @@ -1393,8 +1346,7 @@ public List getStateModelDefs(String clusterName) { @Override public StateModelDefinition getStateModelDef(String clusterName, String stateModelName) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.stateModelDef(stateModelName)); @@ -1403,14 +1355,12 @@ public StateModelDefinition getStateModelDef(String clusterName, String stateMod @Override public void dropCluster(String clusterName) { logger.info("Deleting cluster {}.", clusterName); - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); String root = "/" + clusterName; if (accessor.getChildNames(keyBuilder.liveInstances()).size() > 0) { - throw new HelixException( - "There are still live instances in the cluster, shut them down first."); + throw new HelixException("There are still live instances in the cluster, shut them down first."); } if (accessor.getProperty(keyBuilder.controllerLeader()) != null) { @@ -1446,13 +1396,12 @@ public void addClusterToGrandCluster(String clusterName, String grandCluster) { throw new HelixException("Grand cluster " + grandCluster + " has no instances"); } - ZKHelixDataAccessor accessor = - new ZKHelixDataAccessor(grandCluster, new ZkBaseDataAccessor<>(_zkClient)); + ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(grandCluster, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.idealStates(idealState.getResourceName()), idealState); - LOG.info("Cluster {} has been added to grand cluster {} with rebalance configuration {}.", - clusterName, grandCluster, idealState.getRecord().getSimpleFields().toString()); + LOG.info("Cluster {} has been added to grand cluster {} with rebalance configuration {}.", clusterName, + grandCluster, idealState.getRecord().getSimpleFields().toString()); } @Override @@ -1467,37 +1416,29 @@ public Map getConfig(HelixConfigScope scope, List keys) } @Override - public void addCustomizedStateConfig(String clusterName, - CustomizedStateConfig customizedStateConfig) { - logger.info( - "Add CustomizedStateConfig to cluster {}, CustomizedStateConfig is {}", - clusterName, customizedStateConfig.toString()); + public void addCustomizedStateConfig(String clusterName, CustomizedStateConfig customizedStateConfig) { + logger.info("Add CustomizedStateConfig to cluster {}, CustomizedStateConfig is {}", clusterName, + customizedStateConfig.toString()); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } - CustomizedStateConfig.Builder builder = - new CustomizedStateConfig.Builder(customizedStateConfig); + CustomizedStateConfig.Builder builder = new CustomizedStateConfig.Builder(customizedStateConfig); CustomizedStateConfig customizedStateConfigFromBuilder = builder.build(); - ZKHelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); - accessor.setProperty(keyBuilder.customizedStateConfig(), - customizedStateConfigFromBuilder); + accessor.setProperty(keyBuilder.customizedStateConfig(), customizedStateConfigFromBuilder); } @Override public void removeCustomizedStateConfig(String clusterName) { - logger.info( - "Remove CustomizedStateConfig from cluster {}.", clusterName); + logger.info("Remove CustomizedStateConfig from cluster {}.", clusterName); - ZKHelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.removeProperty(keyBuilder.customizedStateConfig()); - } @Override @@ -1507,47 +1448,38 @@ public void addTypeToCustomizedStateConfig(String clusterName, String type) { if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } - CustomizedStateConfig.Builder builder = - new CustomizedStateConfig.Builder(); + CustomizedStateConfig.Builder builder = new CustomizedStateConfig.Builder(); builder.addAggregationEnabledType(type); CustomizedStateConfig customizedStateConfigFromBuilder = builder.build(); - ZKHelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); - if(!accessor.updateProperty(keyBuilder.customizedStateConfig(), - customizedStateConfigFromBuilder)) { - throw new HelixException( - "Failed to add customized state config type " + type + " to cluster" + clusterName); + if (!accessor.updateProperty(keyBuilder.customizedStateConfig(), customizedStateConfigFromBuilder)) { + throw new HelixException("Failed to add customized state config type " + type + " to cluster" + clusterName); } } - @Override public void removeTypeFromCustomizedStateConfig(String clusterName, String type) { - logger.info("Remove type {} to CustomizedStateConfig of cluster {}", type, - clusterName); + logger.info("Remove type {} to CustomizedStateConfig of cluster {}", type, clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } - CustomizedStateConfig.Builder builder = new CustomizedStateConfig.Builder( - _configAccessor.getCustomizedStateConfig(clusterName)); + CustomizedStateConfig.Builder builder = + new CustomizedStateConfig.Builder(_configAccessor.getCustomizedStateConfig(clusterName)); if (!builder.getAggregationEnabledTypes().contains(type)) { - throw new HelixException("Type " + type - + " is missing from the CustomizedStateConfig of cluster " + clusterName); + throw new HelixException("Type " + type + " is missing from the CustomizedStateConfig of cluster " + clusterName); } builder.removeAggregationEnabledType(type); CustomizedStateConfig customizedStateConfigFromBuilder = builder.build(); - ZKHelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); - accessor.setProperty(keyBuilder.customizedStateConfig(), - customizedStateConfigFromBuilder); + accessor.setProperty(keyBuilder.customizedStateConfig(), customizedStateConfigFromBuilder); } @Override @@ -1588,8 +1520,7 @@ public ZNRecord update(ZNRecord currentData) { } @Override - public void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, - String group) { + public void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, String group) { List instanceNames = new LinkedList(); if (keyPrefix == null || keyPrefix.length() == 0) { keyPrefix = resourceName; @@ -1608,15 +1539,13 @@ public void rebalance(String clusterName, String resourceName, int replica, Stri } @Override - public void rebalance(String clusterName, String resourceName, int replica, - List instances) { + public void rebalance(String clusterName, String resourceName, int replica, List instances) { rebalance(clusterName, resourceName, replica, resourceName, instances, ""); } - void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, - List instanceNames, String groupId) { - logger.info("Rebalance resource {} with replica {} in cluster {}.", resourceName, replica, - clusterName); + void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, List instanceNames, + String groupId) { + logger.info("Rebalance resource {} with replica {} in cluster {}.", resourceName, replica, clusterName); // ensure we get the same idealState with the same set of instances Collections.sort(instanceNames); @@ -1673,9 +1602,9 @@ void rebalance(String clusterName, String resourceName, int replica, String keyP } if (idealState.getRebalanceMode() != RebalanceMode.FULL_AUTO && idealState.getRebalanceMode() != RebalanceMode.USER_DEFINED) { - ZNRecord newIdealState = DefaultIdealStateCalculator - .calculateIdealState(instanceNames, partitions, replica, keyPrefix, masterStateValue, - slaveStateValue); + ZNRecord newIdealState = + DefaultIdealStateCalculator.calculateIdealState(instanceNames, partitions, replica, keyPrefix, + masterStateValue, slaveStateValue); // for now keep mapField in SEMI_AUTO mode and remove listField in CUSTOMIZED mode if (idealState.getRebalanceMode() == RebalanceMode.SEMI_AUTO) { @@ -1697,20 +1626,17 @@ void rebalance(String clusterName, String resourceName, int replica, String keyP } @Override - public void addIdealState(String clusterName, String resourceName, String idealStateFile) - throws IOException { - logger.info("Add IdealState for resource {} to cluster {} by file name {}.", resourceName, - clusterName, idealStateFile); - ZNRecord idealStateRecord = - (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(idealStateFile))); + public void addIdealState(String clusterName, String resourceName, String idealStateFile) throws IOException { + logger.info("Add IdealState for resource {} to cluster {} by file name {}.", resourceName, clusterName, + idealStateFile); + ZNRecord idealStateRecord = (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(idealStateFile))); if (idealStateRecord.getId() == null || !idealStateRecord.getId().equals(resourceName)) { throw new IllegalArgumentException("ideal state must have same id as resource name"); } setResourceIdealState(clusterName, resourceName, new IdealState(idealStateRecord)); } - private static byte[] readFile(String filePath) - throws IOException { + private static byte[] readFile(String filePath) throws IOException { File file = new File(filePath); int size = (int) file.length(); @@ -1732,23 +1658,20 @@ private static byte[] readFile(String filePath) } @Override - public void addStateModelDef(String clusterName, String stateModelDefName, - String stateModelDefFile) + public void addStateModelDef(String clusterName, String stateModelDefName, String stateModelDefFile) throws IOException { - ZNRecord record = - (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(stateModelDefFile))); + ZNRecord record = (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(stateModelDefFile))); if (record == null || record.getId() == null || !record.getId().equals(stateModelDefName)) { - throw new IllegalArgumentException( - "state model definition must have same id as state model def name"); + throw new IllegalArgumentException("state model definition must have same id as state model def name"); } addStateModelDef(clusterName, stateModelDefName, new StateModelDefinition(record), false); } @Override - public void setConstraint(String clusterName, final ConstraintType constraintType, - final String constraintId, final ConstraintItem constraintItem) { - logger.info("Set constraint type {} with constraint id {} for cluster {}.", constraintType, - constraintId, clusterName); + public void setConstraint(String clusterName, final ConstraintType constraintType, final String constraintId, + final ConstraintItem constraintItem) { + logger.info("Set constraint type {} with constraint id {} for cluster {}.", constraintType, constraintId, + clusterName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName); @@ -1758,8 +1681,7 @@ public void setConstraint(String clusterName, final ConstraintType constraintTyp @Override public ZNRecord update(ZNRecord currentData) { ClusterConstraints constraints = - currentData == null ? new ClusterConstraints(constraintType) - : new ClusterConstraints(currentData); + currentData == null ? new ClusterConstraints(constraintType) : new ClusterConstraints(currentData); constraints.addConstraintItem(constraintId, constraintItem); return constraints.getRecord(); @@ -1768,10 +1690,9 @@ public ZNRecord update(ZNRecord currentData) { } @Override - public void removeConstraint(String clusterName, final ConstraintType constraintType, - final String constraintId) { - logger.info("Remove constraint type {} with constraint id {} for cluster {}.", constraintType, - constraintId, clusterName); + public void removeConstraint(String clusterName, final ConstraintType constraintType, final String constraintId) { + logger.info("Remove constraint type {} with constraint id {} for cluster {}.", constraintType, constraintId, + clusterName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName); @@ -1793,8 +1714,7 @@ public ZNRecord update(ZNRecord currentData) { @Override public ClusterConstraints getConstraints(String clusterName, ConstraintType constraintType) { - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName); return accessor.getProperty(keyBuilder.constraint(constraintType.toString())); @@ -1810,51 +1730,43 @@ public ClusterConstraints getConstraints(String clusterName, ConstraintType cons * @return */ @Override - public void rebalance(String clusterName, IdealState currentIdealState, - List instanceNames) { - logger.info("Rebalance resource {} in cluster {} with IdealState {}.", - currentIdealState.getResourceName(), clusterName, - currentIdealState == null ? "NULL" : currentIdealState.toString()); + public void rebalance(String clusterName, IdealState currentIdealState, List instanceNames) { + logger.info("Rebalance resource {} in cluster {} with IdealState {}.", currentIdealState.getResourceName(), + clusterName, currentIdealState == null ? "NULL" : currentIdealState.toString()); Set activeInstances = new HashSet(); for (String partition : currentIdealState.getPartitionSet()) { activeInstances.addAll(currentIdealState.getRecord().getListField(partition)); } instanceNames.removeAll(activeInstances); - Map previousIdealState = - RebalanceUtil.buildInternalIdealState(currentIdealState); + Map previousIdealState = RebalanceUtil.buildInternalIdealState(currentIdealState); Map balancedRecord = DefaultIdealStateCalculator.calculateNextIdealState(instanceNames, previousIdealState); - StateModelDefinition stateModDef = - this.getStateModelDef(clusterName, currentIdealState.getStateModelDefRef()); + StateModelDefinition stateModDef = this.getStateModelDef(clusterName, currentIdealState.getStateModelDefRef()); if (stateModDef == null) { - throw new HelixException( - "cannot find state model: " + currentIdealState.getStateModelDefRef()); + throw new HelixException("cannot find state model: " + currentIdealState.getStateModelDefRef()); } String[] states = RebalanceUtil.parseStates(clusterName, stateModDef); - ZNRecord newIdealStateRecord = DefaultIdealStateCalculator - .convertToZNRecord(balancedRecord, currentIdealState.getResourceName(), states[0], + ZNRecord newIdealStateRecord = + DefaultIdealStateCalculator.convertToZNRecord(balancedRecord, currentIdealState.getResourceName(), states[0], states[1]); Set partitionSet = new HashSet(); partitionSet.addAll(newIdealStateRecord.getMapFields().keySet()); partitionSet.addAll(newIdealStateRecord.getListFields().keySet()); - Map reversePartitionIndex = - (Map) balancedRecord.get("reversePartitionIndex"); + Map reversePartitionIndex = (Map) balancedRecord.get("reversePartitionIndex"); for (String partition : partitionSet) { if (reversePartitionIndex.containsKey(partition)) { String originPartitionName = reversePartitionIndex.get(partition); if (partition.equals(originPartitionName)) { continue; } - newIdealStateRecord.getMapFields() - .put(originPartitionName, newIdealStateRecord.getMapField(partition)); + newIdealStateRecord.getMapFields().put(originPartitionName, newIdealStateRecord.getMapField(partition)); newIdealStateRecord.getMapFields().remove(partition); - newIdealStateRecord.getListFields() - .put(originPartitionName, newIdealStateRecord.getListField(partition)); + newIdealStateRecord.getListFields().put(originPartitionName, newIdealStateRecord.getListField(partition)); newIdealStateRecord.getListFields().remove(partition); } } @@ -1866,18 +1778,15 @@ public void rebalance(String clusterName, IdealState currentIdealState, @Override public void addInstanceTag(String clusterName, String instanceName, String tag) { - logger - .info("Add instance tag {} for instance {} in cluster {}.", tag, instanceName, clusterName); + logger.info("Add instance tag {} for instance {} in cluster {}.", tag, instanceName, clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } if (!ZKUtil.isInstanceSetup(_zkClient, clusterName, instanceName, InstanceType.PARTICIPANT)) { - throw new HelixException( - "cluster " + clusterName + " instance " + instanceName + " is not setup yet"); + throw new HelixException("cluster " + clusterName + " instance " + instanceName + " is not setup yet"); } - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceName)); @@ -1887,18 +1796,15 @@ public void addInstanceTag(String clusterName, String instanceName, String tag) @Override public void removeInstanceTag(String clusterName, String instanceName, String tag) { - logger.info("Remove instance tag {} for instance {} in cluster {}.", tag, instanceName, - clusterName); + logger.info("Remove instance tag {} for instance {} in cluster {}.", tag, instanceName, clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } if (!ZKUtil.isInstanceSetup(_zkClient, clusterName, instanceName, InstanceType.PARTICIPANT)) { - throw new HelixException( - "cluster " + clusterName + " instance " + instanceName + " is not setup yet"); + throw new HelixException("cluster " + clusterName + " instance " + instanceName + " is not setup yet"); } - ZKHelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceName)); @@ -1908,18 +1814,15 @@ public void removeInstanceTag(String clusterName, String instanceName, String ta @Override public void setInstanceZoneId(String clusterName, String instanceName, String zoneId) { - logger.info("Set instance zoneId {} for instance {} in cluster {}.", zoneId, instanceName, - clusterName); + logger.info("Set instance zoneId {} for instance {} in cluster {}.", zoneId, instanceName, clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } if (!ZKUtil.isInstanceSetup(_zkClient, clusterName, instanceName, InstanceType.PARTICIPANT)) { - throw new HelixException( - "cluster " + clusterName + " instance " + instanceName + " is not setup yet"); + throw new HelixException("cluster " + clusterName + " instance " + instanceName + " is not setup yet"); } - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceName)); @@ -1929,8 +1832,7 @@ public void setInstanceZoneId(String clusterName, String instanceName, String zo @Override public void enableBatchMessageMode(String clusterName, boolean enabled) { - logger - .info("{} batch message mode for cluster {}.", enabled ? "Enable" : "Disable", clusterName); + logger.info("{} batch message mode for cluster {}.", enabled ? "Enable" : "Disable", clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } @@ -1943,35 +1845,34 @@ public void enableBatchMessageMode(String clusterName, boolean enabled) { @Override public void enableBatchMessageMode(String clusterName, String resourceName, boolean enabled) { - logger.info("{} batch message mode for resource {} in cluster {}.", - enabled ? "Enable" : "Disable", resourceName, clusterName); + logger.info("{} batch message mode for resource {} in cluster {}.", enabled ? "Enable" : "Disable", resourceName, + clusterName); // TODO: Change IdealState to ResourceConfig when configs are migrated to ResourceConfig IdealState idealState = getResourceIdealState(clusterName, resourceName); if (idealState == null) { - throw new HelixException("Cluster " + clusterName + ", resource: " + resourceName - + ", ideal-state does not exist"); + throw new HelixException( + "Cluster " + clusterName + ", resource: " + resourceName + ", ideal-state does not exist"); } idealState.setBatchMessageMode(enabled); setResourceIdealState(clusterName, resourceName, idealState); } - private void enableSingleInstance(final String clusterName, final String instanceName, - final boolean enabled, BaseDataAccessor baseAccessor, - InstanceConstants.InstanceDisabledType disabledType, String reason) { + private void enableSingleInstance(final String clusterName, final String instanceName, final boolean enabled, + BaseDataAccessor baseAccessor, InstanceConstants.InstanceDisabledType disabledType, String reason) { String path = PropertyPathBuilder.instanceConfig(clusterName, instanceName); if (!baseAccessor.exists(path, 0)) { - throw new HelixException("Cluster " + clusterName + ", instance: " + instanceName - + ", instance config does not exist"); + throw new HelixException( + "Cluster " + clusterName + ", instance: " + instanceName + ", instance config does not exist"); } baseAccessor.update(path, new DataUpdater() { @Override public ZNRecord update(ZNRecord currentData) { if (currentData == null) { - throw new HelixException("Cluster: " + clusterName + ", instance: " + instanceName - + ", participant config is null"); + throw new HelixException( + "Cluster: " + clusterName + ", instance: " + instanceName + ", participant config is null"); } InstanceConfig config = new InstanceConfig(currentData); @@ -1992,9 +1893,8 @@ public ZNRecord update(ZNRecord currentData) { } // TODO: Add history ZNode for all batched enabling/disabling histories with metadata. - private void enableBatchInstances(final String clusterName, final List instances, - final boolean enabled, BaseDataAccessor baseAccessor, - InstanceConstants.InstanceDisabledType disabledType, String reason) { + private void enableBatchInstances(final String clusterName, final List instances, final boolean enabled, + BaseDataAccessor baseAccessor, InstanceConstants.InstanceDisabledType disabledType, String reason) { // TODO: batch enable/disable is breaking backward compatibility on instance enable with older library // re-enable once batch enable/disable is ready @@ -2028,8 +1928,8 @@ public ZNRecord update(ZNRecord currentData) { // TODO: update the history ZNode String timeStamp = String.valueOf(System.currentTimeMillis()); disabledInstances.put(disabledInstance, timeStamp); - disabledInstancesWithInfo - .put(disabledInstance, assembleInstanceBatchedDisabledInfo(disabledType, reason, timeStamp)); + disabledInstancesWithInfo.put(disabledInstance, + assembleInstanceBatchedDisabledInfo(disabledType, reason, timeStamp)); } } clusterConfig.setDisabledInstances(disabledInstances); @@ -2040,14 +1940,12 @@ public ZNRecord update(ZNRecord currentData) { }, AccessOption.PERSISTENT); } - public static String assembleInstanceBatchedDisabledInfo( - InstanceConstants.InstanceDisabledType disabledType, String reason, String timeStamp) { + public static String assembleInstanceBatchedDisabledInfo(InstanceConstants.InstanceDisabledType disabledType, + String reason, String timeStamp) { Map disableInfo = new TreeMap<>(); - disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_ENABLED_DISABLE_TIMESTAMP.toString(), - timeStamp); + disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_ENABLED_DISABLE_TIMESTAMP.toString(), timeStamp); if (disabledType != null) { - disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_DISABLED_TYPE.toString(), - disabledType.toString()); + disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_DISABLED_TYPE.toString(), disabledType.toString()); } if (reason != null) { disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_DISABLED_REASON.toString(), reason); @@ -2094,8 +1992,7 @@ public void finalize() { } @Override - public boolean addResourceWithWeight(String clusterName, IdealState idealState, - ResourceConfig resourceConfig) { + public boolean addResourceWithWeight(String clusterName, IdealState idealState, ResourceConfig resourceConfig) { // Null checks if (clusterName == null || clusterName.isEmpty()) { throw new HelixException("Cluster name is null or empty!"); @@ -2116,16 +2013,14 @@ public boolean addResourceWithWeight(String clusterName, IdealState idealState, // Order in which a resource should be added: // 1. Validate the weights in ResourceConfig against ClusterConfig // Check that all capacity keys in ClusterConfig are set up in every partition in ResourceConfig field - if (!validateWeightForResourceConfig(_configAccessor.getClusterConfig(clusterName), - resourceConfig, idealState)) { - throw new HelixException(String - .format("Could not add resource %s with weight! Failed to validate the ResourceConfig!", + if (!validateWeightForResourceConfig(_configAccessor.getClusterConfig(clusterName), resourceConfig, idealState)) { + throw new HelixException( + String.format("Could not add resource %s with weight! Failed to validate the ResourceConfig!", idealState.getResourceName())); } // 2. Add the resourceConfig to ZK - _configAccessor - .setResourceConfig(clusterName, resourceConfig.getResourceName(), resourceConfig); + _configAccessor.setResourceConfig(clusterName, resourceConfig.getResourceName(), resourceConfig); // 3. Add the idealState to ZK setResourceIdealState(clusterName, idealState.getResourceName(), idealState); @@ -2147,8 +2042,7 @@ public boolean enableWagedRebalance(String clusterName, List resourceNam throw new HelixException("Resource name list is invalid!"); } - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List enabledIdealStates = new ArrayList<>(); List enabledIdealStateKeys = new ArrayList<>(); @@ -2164,12 +2058,11 @@ public boolean enableWagedRebalance(String clusterName, List resourceNam enabledResourceNames.add(idealState.getResourceName()); } } - List resourcesNotFound = - resourceNames.stream().filter(resourceName -> !enabledResourceNames.contains(resourceName)) - .collect(Collectors.toList()); + List resourcesNotFound = resourceNames.stream() + .filter(resourceName -> !enabledResourceNames.contains(resourceName)) + .collect(Collectors.toList()); if (!resourcesNotFound.isEmpty()) { - throw new HelixException( - String.format("Some resources do not have IdealStates: %s", resourcesNotFound)); + throw new HelixException(String.format("Some resources do not have IdealStates: %s", resourcesNotFound)); } boolean[] success = accessor.setChildren(enabledIdealStateKeys, enabledIdealStates); for (boolean s : success) { @@ -2181,8 +2074,7 @@ public boolean enableWagedRebalance(String clusterName, List resourceNam } @Override - public Map validateResourcesForWagedRebalance(String clusterName, - List resourceNames) { + public Map validateResourcesForWagedRebalance(String clusterName, List resourceNames) { // Null checks if (clusterName == null || clusterName.isEmpty()) { throw new HelixException("Cluster name is invalid!"); @@ -2192,14 +2084,12 @@ public Map validateResourcesForWagedRebalance(String clusterNam } // Ensure that all instances are valid - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List instances = accessor.getChildNames(keyBuilder.instanceConfigs()); if (validateInstancesForWagedRebalance(clusterName, instances).containsValue(false)) { - throw new HelixException(String - .format("Instance capacities haven't been configured properly for cluster %s", - clusterName)); + throw new HelixException( + String.format("Instance capacities haven't been configured properly for cluster %s", clusterName)); } Map result = new HashMap<>(); @@ -2211,15 +2101,13 @@ public Map validateResourcesForWagedRebalance(String clusterNam continue; } ResourceConfig resourceConfig = _configAccessor.getResourceConfig(clusterName, resourceName); - result.put(resourceName, - validateWeightForResourceConfig(clusterConfig, resourceConfig, idealState)); + result.put(resourceName, validateWeightForResourceConfig(clusterConfig, resourceConfig, idealState)); } return result; } @Override - public Map validateInstancesForWagedRebalance(String clusterName, - List instanceNames) { + public Map validateInstancesForWagedRebalance(String clusterName, List instanceNames) { // Null checks if (clusterName == null || clusterName.isEmpty()) { throw new HelixException("Cluster name is invalid!"); @@ -2250,19 +2138,17 @@ public Map validateInstancesForWagedRebalance(String clusterNam * @param idealState * @return true if ResourceConfig has all the required fields. False otherwise. */ - private boolean validateWeightForResourceConfig(ClusterConfig clusterConfig, - ResourceConfig resourceConfig, IdealState idealState) { + private boolean validateWeightForResourceConfig(ClusterConfig clusterConfig, ResourceConfig resourceConfig, + IdealState idealState) { if (resourceConfig == null) { if (clusterConfig.getDefaultPartitionWeightMap().isEmpty()) { - logger.error( - "ResourceConfig for {} is null, and there are no default weights set in ClusterConfig!", + logger.error("ResourceConfig for {} is null, and there are no default weights set in ClusterConfig!", idealState.getResourceName()); return false; } // If ResourceConfig is null AND the default partition weight map is defined, and the map has all the required keys, we consider this valid since the default weights will be used // Need to check the map contains all the required keys - if (clusterConfig.getDefaultPartitionWeightMap().keySet() - .containsAll(clusterConfig.getInstanceCapacityKeys())) { + if (clusterConfig.getDefaultPartitionWeightMap().keySet().containsAll(clusterConfig.getInstanceCapacityKeys())) { // Contains all the required keys, so consider it valid since it will use the default weights return true; } @@ -2277,8 +2163,7 @@ private boolean validateWeightForResourceConfig(ClusterConfig clusterConfig, try { capacityMap = resourceConfig.getPartitionCapacityMap(); } catch (IOException ex) { - logger.error("Invalid partition capacity configuration of resource: {}", - idealState.getResourceName(), ex); + logger.error("Invalid partition capacity configuration of resource: {}", idealState.getResourceName(), ex); return false; } @@ -2292,16 +2177,15 @@ private boolean validateWeightForResourceConfig(ClusterConfig clusterConfig, // So check using numPartitions instead // This check allows us to fail early on instead of having to loop through all partitions if (capacityMapSet.size() != idealState.getNumPartitions() && !hasDefaultCapacity) { - logger.error( - "ResourceConfig for {} does not have all partitions defined in PartitionCapacityMap!", + logger.error("ResourceConfig for {} does not have all partitions defined in PartitionCapacityMap!", idealState.getResourceName()); return false; } // Loop through all partitions and validate - capacityMap.keySet().forEach(partitionName -> WagedValidationUtil - .validateAndGetPartitionCapacity(partitionName, resourceConfig, capacityMap, - clusterConfig)); + capacityMap.keySet() + .forEach(partitionName -> WagedValidationUtil.validateAndGetPartitionCapacity(partitionName, resourceConfig, + capacityMap, clusterConfig)); return true; } @@ -2312,23 +2196,20 @@ public Builder() { public ZKHelixAdmin build() { validate(); return new ZKHelixAdmin( - createZkClient(_realmMode, _realmAwareZkConnectionConfig, _realmAwareZkClientConfig, - _zkAddress), false); + createZkClient(_realmMode, _realmAwareZkConnectionConfig, _realmAwareZkClientConfig, _zkAddress), false); } } private Set findTimeoutOfflineInstances(String clusterName, long offlineDuration) { // in case there is no customized timeout value, use the one defined in cluster config if (offlineDuration == ClusterConfig.OFFLINE_DURATION_FOR_PURGE_NOT_SET) { - offlineDuration = - _configAccessor.getClusterConfig(clusterName).getOfflineDurationForPurge(); + offlineDuration = _configAccessor.getClusterConfig(clusterName).getOfflineDurationForPurge(); if (offlineDuration == ClusterConfig.OFFLINE_DURATION_FOR_PURGE_NOT_SET) { return Collections.emptySet(); } } - HelixDataAccessor accessor = - new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List instanceConfigNames = accessor.getChildNames(keyBuilder.instanceConfigs()); List instancePathNames = accessor.getChildNames(keyBuilder.instances()); @@ -2338,8 +2219,7 @@ private Set findTimeoutOfflineInstances(String clusterName, long offline liveNodes.forEach(offlineInstanceNames::remove); long finalOfflineDuration = offlineDuration; offlineInstanceNames.removeIf(instanceName -> { - ParticipantHistory participantHistory = - accessor.getProperty(keyBuilder.participantHistory(instanceName)); + ParticipantHistory participantHistory = accessor.getProperty(keyBuilder.participantHistory(instanceName)); if (participantHistory == null && instanceConfigNames.contains(instanceName)) { // this is likely caused by a new instance joining and should not be purged return true; @@ -2347,10 +2227,8 @@ private Set findTimeoutOfflineInstances(String clusterName, long offline // If participant history is null without config, a race condition happened and should be // cleaned up. // Otherwise, if the participant has not been offline for more than the duration, no clean up - return (participantHistory != null && ( - participantHistory.getLastOfflineTime() == ParticipantHistory.ONLINE - || System.currentTimeMillis() - participantHistory.getLastOfflineTime() - < finalOfflineDuration)); + return (participantHistory != null && (participantHistory.getLastOfflineTime() == ParticipantHistory.ONLINE + || System.currentTimeMillis() - participantHistory.getLastOfflineTime() < finalOfflineDuration)); }); return offlineInstanceNames; diff --git a/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java b/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java index 5813603b01..63ce710686 100644 --- a/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java +++ b/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java @@ -16,7 +16,6 @@ import org.apache.helix.HelixRollbackException; import org.apache.helix.NotificationContext; import org.apache.helix.TestHelper; -import org.apache.helix.api.status.ClusterManagementMode; import org.apache.helix.common.ZkTestBase; import org.apache.helix.constants.InstanceConstants; import org.apache.helix.controller.rebalancer.strategy.CrushEdRebalanceStrategy; @@ -127,7 +126,7 @@ public void testEvacuate() throws Exception { } Assert.assertTrue(_admin.isEvacuateFinished(CLUSTER_NAME, instanceToEvacuate)); - Assert.assertTrue(_admin.isPrepopulateReady(CLUSTER_NAME, instanceToEvacuate)); + Assert.assertTrue(_admin.isReadyForPreparingJoiningCluster(CLUSTER_NAME, instanceToEvacuate)); } @Test(dependsOnMethods = "testEvacuate") @@ -334,7 +333,7 @@ public void testMarkEvacuationAfterEMM() throws Exception { Assert.assertFalse(newPAssignedParticipants.contains(instanceToEvacuate)); Assert.assertTrue(newPAssignedParticipants.containsAll(currentActiveInstances)); } - Assert.assertTrue(_admin.isPrepopulateReady(CLUSTER_NAME, instanceToEvacuate)); + Assert.assertTrue(_admin.isReadyForPreparingJoiningCluster(CLUSTER_NAME, instanceToEvacuate)); } @Test(dependsOnMethods = "testMarkEvacuationAfterEMM") diff --git a/helix-core/src/test/java/org/apache/helix/mock/MockHelixAdmin.java b/helix-core/src/test/java/org/apache/helix/mock/MockHelixAdmin.java index 56956d5cfa..512a7b4db7 100644 --- a/helix-core/src/test/java/org/apache/helix/mock/MockHelixAdmin.java +++ b/helix-core/src/test/java/org/apache/helix/mock/MockHelixAdmin.java @@ -557,7 +557,7 @@ public boolean isEvacuateFinished(String clusterName, String instancesNames) { } @Override - public boolean isPrepopulateReady(String clusterName, String instancesNames) { + public boolean isReadyForPreparingJoiningCluster(String clusterName, String instancesNames) { return false; } } From ba1786a6412e14a82830139503ef2be4ee0e637d Mon Sep 17 00:00:00 2001 From: xyuanlu Date: Mon, 18 Sep 2023 17:34:01 -0700 Subject: [PATCH 3/4] revert accidental format --- .../java/org/apache/helix/HelixAdmin.java | 10 +- .../apache/helix/manager/zk/ZKHelixAdmin.java | 691 +++++++++++------- .../rebalancer/TestInstanceOperation.java | 2 +- 3 files changed, 424 insertions(+), 279 deletions(-) diff --git a/helix-core/src/main/java/org/apache/helix/HelixAdmin.java b/helix-core/src/main/java/org/apache/helix/HelixAdmin.java index e3be8383c5..085a987b1e 100644 --- a/helix-core/src/main/java/org/apache/helix/HelixAdmin.java +++ b/helix-core/src/main/java/org/apache/helix/HelixAdmin.java @@ -741,12 +741,18 @@ Map validateInstancesForWagedRebalance(String clusterName, /** * Return if instance operation 'Evacuate' is finished. - * Only return true if there is no current state on the instance and that instance is still alive. * @param clusterName * @param instancesNames - * @return + * @return Return true if there is no current state nor pending message on the instance. */ boolean isEvacuateFinished(String clusterName, String instancesNames); + /** + * Return if instance is ready for preparing joining cluster. The instance should have no current state, + * no pending message and tagged with operation that exclude the instance from Helix assignment. + * @param clusterName + * @param instancesNames + * @return true if the instance is ready for preparing joining cluster. + */ boolean isReadyForPreparingJoiningCluster(String clusterName, String instancesNames); } diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java index b0984766e0..ff1e9ab1b5 100644 --- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java +++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java @@ -152,21 +152,23 @@ public ZKHelixAdmin(RealmAwareZkClient zkClient) { public ZKHelixAdmin(String zkAddress) { int timeOutInSec = Integer.parseInt(System.getProperty(CONNECTION_TIMEOUT, "30")); RealmAwareZkClient.RealmAwareZkClientConfig clientConfig = - new RealmAwareZkClient.RealmAwareZkClientConfig().setConnectInitTimeout(timeOutInSec * 1000L) + new RealmAwareZkClient.RealmAwareZkClientConfig() + .setConnectInitTimeout(timeOutInSec * 1000L) .setZkSerializer(new ZNRecordSerializer()); RealmAwareZkClient zkClient; if (Boolean.getBoolean(SystemPropertyKeys.MULTI_ZK_ENABLED) || zkAddress == null) { try { - zkClient = - new FederatedZkClient(new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder().build(), clientConfig); + zkClient = new FederatedZkClient( + new RealmAwareZkClient.RealmAwareZkConnectionConfig.Builder().build(), clientConfig); } catch (IllegalStateException | InvalidRoutingDataException e) { throw new HelixException("Not able to connect on multi-realm mode.", e); } } else { zkClient = SharedZkClientFactory.getInstance() - .buildZkClient(new HelixZkClient.ZkConnectionConfig(zkAddress), clientConfig.createHelixZkClientConfig()); + .buildZkClient(new HelixZkClient.ZkConnectionConfig(zkAddress), + clientConfig.createHelixZkClientConfig()); zkClient.waitUntilConnected(timeOutInSec, TimeUnit.SECONDS); } @@ -199,12 +201,14 @@ public void addInstance(String clusterName, InstanceConfig instanceConfig) { _zkClient.createPersistent(PropertyPathBuilder.instanceMessage(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceCurrentState(clusterName, nodeId), true); - _zkClient.createPersistent(PropertyPathBuilder.instanceTaskCurrentState(clusterName, nodeId), true); + _zkClient + .createPersistent(PropertyPathBuilder.instanceTaskCurrentState(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceCustomizedState(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceError(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceStatusUpdate(clusterName, nodeId), true); _zkClient.createPersistent(PropertyPathBuilder.instanceHistory(clusterName, nodeId), true); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.participantHistory(nodeId), new ParticipantHistory(nodeId)); } @@ -216,17 +220,20 @@ public void dropInstance(String clusterName, InstanceConfig instanceConfig) { String instanceConfigPath = PropertyPathBuilder.instanceConfig(clusterName, instanceName); if (!_zkClient.exists(instanceConfigPath)) { - throw new HelixException("Node " + instanceName + " does not exist in config for cluster " + clusterName); + throw new HelixException( + "Node " + instanceName + " does not exist in config for cluster " + clusterName); } String instancePath = PropertyPathBuilder.instance(clusterName, instanceName); if (!_zkClient.exists(instancePath)) { - throw new HelixException("Node " + instanceName + " does not exist in instances for cluster " + clusterName); + throw new HelixException( + "Node " + instanceName + " does not exist in instances for cluster " + clusterName); } String liveInstancePath = PropertyPathBuilder.liveInstance(clusterName, instanceName); if (_zkClient.exists(liveInstancePath)) { - throw new HelixException("Node " + instanceName + " is still alive for cluster " + clusterName + ", can't drop."); + throw new HelixException( + "Node " + instanceName + " is still alive for cluster " + clusterName + ", can't drop."); } // delete config path @@ -248,10 +255,12 @@ private void dropInstancePathRecursively(String instancePath, String instanceNam // Racing condition with controller's persisting node history, retryable. // We don't need to backoff here as this racing condition only happens once (controller // does not repeatedly write instance history) - logger.warn("Retrying dropping instance {} with exception {}", instanceName, e.getCause().getMessage()); + logger.warn("Retrying dropping instance {} with exception {}", instanceName, + e.getCause().getMessage()); retryCnt++; } else { - String errorMessage = "Failed to drop instance: " + instanceName + ". Retry times: " + retryCnt; + String errorMessage = + "Failed to drop instance: " + instanceName + ". Retry times: " + retryCnt; logger.error(errorMessage, e); throw new HelixException(errorMessage, e); } @@ -279,8 +288,8 @@ public void purgeOfflineInstances(String clusterName, long offlineDuration) { } }); if (failToPurgeInstances.size() > 0) { - LOG.error( - "ZKHelixAdmin::purgeOfflineInstances(): failed to drop the following instances: " + failToPurgeInstances); + LOG.error("ZKHelixAdmin::purgeOfflineInstances(): failed to drop the following instances: " + + failToPurgeInstances); } } @@ -298,47 +307,56 @@ public InstanceConfig getInstanceConfig(String clusterName, String instanceName) logger.info("Get instance config for instance {} from cluster {}.", instanceName, clusterName); String instanceConfigPath = PropertyPathBuilder.instanceConfig(clusterName, instanceName); if (!_zkClient.exists(instanceConfigPath)) { - throw new HelixException("instance" + instanceName + " does not exist in cluster " + clusterName); + throw new HelixException( + "instance" + instanceName + " does not exist in cluster " + clusterName); } - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.instanceConfig(instanceName)); } @Override - public boolean setInstanceConfig(String clusterName, String instanceName, InstanceConfig newInstanceConfig) { - logger.info("Set instance config for instance {} to cluster {} with new InstanceConfig {}.", instanceName, - clusterName, newInstanceConfig == null ? "NULL" : newInstanceConfig.toString()); + public boolean setInstanceConfig(String clusterName, String instanceName, + InstanceConfig newInstanceConfig) { + logger.info("Set instance config for instance {} to cluster {} with new InstanceConfig {}.", + instanceName, clusterName, + newInstanceConfig == null ? "NULL" : newInstanceConfig.toString()); String instanceConfigPath = PropertyPathBuilder.getPath(PropertyType.CONFIGS, clusterName, HelixConfigScope.ConfigScopeProperty.PARTICIPANT.toString(), instanceName); if (!_zkClient.exists(instanceConfigPath)) { - throw new HelixException("instance" + instanceName + " does not exist in cluster " + clusterName); + throw new HelixException( + "instance" + instanceName + " does not exist in cluster " + clusterName); } - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey instanceConfigPropertyKey = accessor.keyBuilder().instanceConfig(instanceName); InstanceConfig currentInstanceConfig = accessor.getProperty(instanceConfigPropertyKey); - if (!newInstanceConfig.getHostName().equals(currentInstanceConfig.getHostName()) || !newInstanceConfig.getPort() - .equals(currentInstanceConfig.getPort())) { + if (!newInstanceConfig.getHostName().equals(currentInstanceConfig.getHostName()) + || !newInstanceConfig.getPort().equals(currentInstanceConfig.getPort())) { throw new HelixException( - "Hostname and port cannot be changed, current hostname: " + currentInstanceConfig.getHostName() - + " and port: " + currentInstanceConfig.getPort() + " is different from new hostname: " - + newInstanceConfig.getHostName() + "and new port: " + newInstanceConfig.getPort()); + "Hostname and port cannot be changed, current hostname: " + currentInstanceConfig + .getHostName() + " and port: " + currentInstanceConfig.getPort() + + " is different from new hostname: " + newInstanceConfig.getHostName() + + "and new port: " + newInstanceConfig.getPort()); } return accessor.setProperty(instanceConfigPropertyKey, newInstanceConfig); } @Override - public void enableInstance(final String clusterName, final String instanceName, final boolean enabled) { + public void enableInstance(final String clusterName, final String instanceName, + final boolean enabled) { enableInstance(clusterName, instanceName, enabled, null, null); } @Override - public void enableInstance(final String clusterName, final String instanceName, final boolean enabled, - InstanceConstants.InstanceDisabledType disabledType, String reason) { - logger.info("{} instance {} in cluster {}.", enabled ? "Enable" : "Disable", instanceName, clusterName); + public void enableInstance(final String clusterName, final String instanceName, + final boolean enabled, InstanceConstants.InstanceDisabledType disabledType, String reason) { + logger.info("{} instance {} in cluster {}.", enabled ? "Enable" : "Disable", instanceName, + clusterName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor<>(_zkClient); // Eventually we will have all instances' enable/disable information in clusterConfig. Now we // update both instanceConfig and clusterConfig in transition period. @@ -371,7 +389,7 @@ public void setInstanceOperation(String clusterName, String instanceName, "Cluster " + clusterName + ", instance: " + instanceName + ", instance config does not exist"); } - boolean succeeded = baseAccessor.update(path, new DataUpdater() { + boolean succeeded = baseAccessor.update(path, new DataUpdater() { @Override public ZNRecord update(ZNRecord currentData) { if (currentData == null) { @@ -432,8 +450,9 @@ private boolean instanceHasCurrentSateOrMessage(String clusterName, String insta return false; } + // see if instance has pending message. List messages = accessor.getChildValues(keyBuilder.messages(instanceName), true); - if (messages != null) { + if (messages != null && !messages.isEmpty()) { logger.warn("Instance {} in cluster {} has pending messages.", instanceName, clusterName); return true; } @@ -447,14 +466,15 @@ public void enableResource(final String clusterName, final String resourceName, String path = PropertyPathBuilder.idealState(clusterName, resourceName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); if (!baseAccessor.exists(path, 0)) { - throw new HelixException( - "Cluster " + clusterName + ", resource: " + resourceName + ", ideal-state does not exist"); + throw new HelixException("Cluster " + clusterName + ", resource: " + resourceName + + ", ideal-state does not exist"); } baseAccessor.update(path, new DataUpdater() { @Override public ZNRecord update(ZNRecord currentData) { if (currentData == null) { - throw new HelixException("Cluster: " + clusterName + ", resource: " + resourceName + ", ideal-state is null"); + throw new HelixException( + "Cluster: " + clusterName + ", resource: " + resourceName + ", ideal-state is null"); } IdealState idealState = new IdealState(currentData); idealState.enable(enabled); @@ -464,18 +484,19 @@ public ZNRecord update(ZNRecord currentData) { } @Override - public void enablePartition(final boolean enabled, final String clusterName, final String instanceName, - final String resourceName, final List partitionNames) { - logger.info("{} partitions {} for resource {} on instance {} in cluster {}.", enabled ? "Enable" : "Disable", - HelixUtil.serializeByComma(partitionNames), resourceName, instanceName, clusterName); + public void enablePartition(final boolean enabled, final String clusterName, + final String instanceName, final String resourceName, final List partitionNames) { + logger.info("{} partitions {} for resource {} on instance {} in cluster {}.", + enabled ? "Enable" : "Disable", HelixUtil.serializeByComma(partitionNames), resourceName, + instanceName, clusterName); String path = PropertyPathBuilder.instanceConfig(clusterName, instanceName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); // check instanceConfig exists if (!baseAccessor.exists(path, 0)) { - throw new HelixException( - "Cluster: " + clusterName + ", instance: " + instanceName + ", instance config does not exist"); + throw new HelixException("Cluster: " + clusterName + ", instance: " + instanceName + + ", instance config does not exist"); } // check resource exists @@ -493,7 +514,8 @@ public void enablePartition(final boolean enabled, final String clusterName, fin // throw new HelixException("Cluster: " + clusterName + ", resource: " + resourceName // + ", ideal state does not exist"); logger.warn( - "Disable partitions: " + partitionNames + " but Cluster: " + clusterName + ", resource: " + resourceName + "Disable partitions: " + partitionNames + " but Cluster: " + clusterName + ", resource: " + + resourceName + " does not exists. probably disable it during ERROR->DROPPED transtition"); } else { // check partitions exist. warn if not @@ -503,11 +525,12 @@ public void enablePartition(final boolean enabled, final String clusterName, fin && idealState.getPreferenceList(partitionName) == null) || ( idealState.getRebalanceMode() == RebalanceMode.USER_DEFINED && idealState.getPreferenceList(partitionName) == null) || ( - idealState.getRebalanceMode() == RebalanceMode.TASK && idealState.getPreferenceList(partitionName) == null) - || (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED - && idealState.getInstanceStateMap(partitionName) == null)) { - logger.warn("Cluster: " + clusterName + ", resource: " + resourceName + ", partition: " + partitionName - + ", partition does not exist in ideal state"); + idealState.getRebalanceMode() == RebalanceMode.TASK + && idealState.getPreferenceList(partitionName) == null) || ( + idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED + && idealState.getInstanceStateMap(partitionName) == null)) { + logger.warn("Cluster: " + clusterName + ", resource: " + resourceName + ", partition: " + + partitionName + ", partition does not exist in ideal state"); } } } @@ -518,8 +541,8 @@ public void enablePartition(final boolean enabled, final String clusterName, fin @Override public ZNRecord update(ZNRecord currentData) { if (currentData == null) { - throw new HelixException( - "Cluster: " + clusterName + ", instance: " + instanceName + ", participant config is null"); + throw new HelixException("Cluster: " + clusterName + ", instance: " + instanceName + + ", participant config is null"); } InstanceConfig instanceConfig = new InstanceConfig(currentData); @@ -547,7 +570,8 @@ public void enableCluster(String clusterName, boolean enabled) { public void enableCluster(String clusterName, boolean enabled, String reason) { logger.info("{} cluster {} for reason {}.", enabled ? "Enable" : "Disable", clusterName, reason == null ? "NULL" : reason); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); if (enabled) { @@ -571,9 +595,11 @@ public void enableMaintenanceMode(String clusterName, boolean enabled) { @Override public boolean isInMaintenanceMode(String clusterName) { - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); - return accessor.getBaseDataAccessor().exists(keyBuilder.maintenance().getPath(), AccessOption.PERSISTENT); + return accessor.getBaseDataAccessor() + .exists(keyBuilder.maintenance().getPath(), AccessOption.PERSISTENT); } @Override @@ -599,7 +625,8 @@ public void setClusterManagementMode(ClusterManagementModeRequest request) { @Override public ClusterManagementMode getClusterManagementMode(String clusterName) { - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); ClusterStatus status = accessor.getProperty(accessor.keyBuilder().clusterStatus()); return status == null ? null : new ClusterManagementMode(status.getManagementMode(), status.getManagementModeStatus()); @@ -607,7 +634,8 @@ public ClusterManagementMode getClusterManagementMode(String clusterName) { private void enableClusterPauseMode(String clusterName, boolean cancelPendingST, String reason) { String hostname = NetworkUtil.getLocalhostName(); - logger.info("Enable cluster pause mode for cluster: {}. CancelPendingST: {}. Reason: {}. From Host: {}", + logger.info( + "Enable cluster pause mode for cluster: {}. CancelPendingST: {}. Reason: {}. From Host: {}", clusterName, cancelPendingST, reason, hostname); BaseDataAccessor baseDataAccessor = new ZkBaseDataAccessor<>(_zkClient); @@ -620,7 +648,8 @@ private void enableClusterPauseMode(String clusterName, boolean cancelPendingST, // check whether cancellation is enabled ClusterConfig config = accessor.getProperty(accessor.keyBuilder().clusterConfig()); if (cancelPendingST && !config.isStateTransitionCancelEnabled()) { - throw new HelixConflictException("State transition cancellation not enabled in " + clusterName); + throw new HelixConflictException( + "State transition cancellation not enabled in " + clusterName); } PauseSignal pauseSignal = new PauseSignal(); @@ -639,7 +668,8 @@ private void enableClusterPauseMode(String clusterName, boolean cancelPendingST, private void disableClusterPauseMode(String clusterName) { logger.info("Disable cluster pause mode for cluster: {}", clusterName); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey pausePropertyKey = accessor.keyBuilder().pause(); PauseSignal pauseSignal = accessor.getProperty(pausePropertyKey); if (pauseSignal == null || !pauseSignal.isClusterPause()) { @@ -667,8 +697,9 @@ public void autoEnableMaintenanceMode(String clusterName, boolean enabled, Strin @Override public void manuallyEnableMaintenanceMode(String clusterName, boolean enabled, String reason, Map customFields) { - processMaintenanceMode(clusterName, enabled, reason, MaintenanceSignal.AutoTriggerReason.NOT_APPLICABLE, - customFields, MaintenanceSignal.TriggeringEntity.USER); + processMaintenanceMode(clusterName, enabled, reason, + MaintenanceSignal.AutoTriggerReason.NOT_APPLICABLE, customFields, + MaintenanceSignal.TriggeringEntity.USER); } /** @@ -680,14 +711,16 @@ public void manuallyEnableMaintenanceMode(String clusterName, boolean enabled, S * @param customFields * @param triggeringEntity */ - private void processMaintenanceMode(String clusterName, final boolean enabled, final String reason, - final MaintenanceSignal.AutoTriggerReason internalReason, final Map customFields, + private void processMaintenanceMode(String clusterName, final boolean enabled, + final String reason, final MaintenanceSignal.AutoTriggerReason internalReason, + final Map customFields, final MaintenanceSignal.TriggeringEntity triggeringEntity) { - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); logger.info("Cluster {} {} {} maintenance mode for reason {}.", clusterName, - triggeringEntity == MaintenanceSignal.TriggeringEntity.CONTROLLER ? "automatically" : "manually", - enabled ? "enters" : "exits", reason == null ? "NULL" : reason); + triggeringEntity == MaintenanceSignal.TriggeringEntity.CONTROLLER ? "automatically" + : "manually", enabled ? "enters" : "exits", reason == null ? "NULL" : reason); final long currentTime = System.currentTimeMillis(); if (!enabled) { // Exit maintenance mode @@ -726,18 +759,20 @@ private void processMaintenanceMode(String clusterName, final boolean enabled, f // Record a MaintenanceSignal history if (!accessor.getBaseDataAccessor() - .update(keyBuilder.controllerLeaderHistory().getPath(), (DataUpdater) oldRecord -> { - try { - if (oldRecord == null) { - oldRecord = new ZNRecord(PropertyType.HISTORY.toString()); - } - return new ControllerHistory(oldRecord).updateMaintenanceHistory(enabled, reason, currentTime, - internalReason, customFields, triggeringEntity); - } catch (IOException e) { - logger.error("Failed to update maintenance history! Exception: {}", e); - return oldRecord; - } - }, AccessOption.PERSISTENT)) { + .update(keyBuilder.controllerLeaderHistory().getPath(), + (DataUpdater) oldRecord -> { + try { + if (oldRecord == null) { + oldRecord = new ZNRecord(PropertyType.HISTORY.toString()); + } + return new ControllerHistory(oldRecord) + .updateMaintenanceHistory(enabled, reason, currentTime, internalReason, + customFields, triggeringEntity); + } catch (IOException e) { + logger.error("Failed to update maintenance history! Exception: {}", e); + return oldRecord; + } + }, AccessOption.PERSISTENT)) { logger.error("Failed to write maintenance history to ZK!"); } } @@ -758,8 +793,8 @@ private enum ResetPartitionFailureReason { public String getMessage(String resourceName, List partitionNames, String instanceName, String errorStateEntity, String clusterName) { - return String.format("Can't reset state for %s.%s on %s, because " + message, resourceName, partitionNames, - instanceName, errorStateEntity, clusterName); + return String.format("Can't reset state for %s.%s on %s, because " + message, resourceName, + partitionNames, instanceName, errorStateEntity, clusterName); } } @@ -767,9 +802,10 @@ public String getMessage(String resourceName, List partitionNames, Strin public void resetPartition(String clusterName, String instanceName, String resourceName, List partitionNames) { logger.info("Reset partitions {} for resource {} on instance {} in cluster {}.", - partitionNames == null ? "NULL" : HelixUtil.serializeByComma(partitionNames), resourceName, instanceName, - clusterName); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + partitionNames == null ? "NULL" : HelixUtil.serializeByComma(partitionNames), resourceName, + instanceName, clusterName); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); // check the instance is alive @@ -779,37 +815,37 @@ public void resetPartition(String clusterName, String instanceName, String resou String instanceConfigPath = PropertyPathBuilder.instanceConfig(clusterName, instanceName); throw new HelixException(String.format( (_zkClient.exists(instanceConfigPath) ? ResetPartitionFailureReason.INSTANCE_NOT_ALIVE - : ResetPartitionFailureReason.INSTANCE_NON_EXISTENT).getMessage(resourceName, partitionNames, - instanceName, instanceName, clusterName))); + : ResetPartitionFailureReason.INSTANCE_NON_EXISTENT) + .getMessage(resourceName, partitionNames, instanceName, instanceName, clusterName))); } // check resource group exists IdealState idealState = accessor.getProperty(keyBuilder.idealStates(resourceName)); if (idealState == null) { - throw new HelixException(String.format( - ResetPartitionFailureReason.RESOURCE_NON_EXISTENT.getMessage(resourceName, partitionNames, instanceName, - resourceName, clusterName))); + throw new HelixException(String.format(ResetPartitionFailureReason.RESOURCE_NON_EXISTENT + .getMessage(resourceName, partitionNames, instanceName, resourceName, clusterName))); } // check partition exists in resource group Set resetPartitionNames = new HashSet(partitionNames); Set partitions = - (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED) ? idealState.getRecord().getMapFields().keySet() - : idealState.getRecord().getListFields().keySet(); + (idealState.getRebalanceMode() == RebalanceMode.CUSTOMIZED) ? idealState.getRecord() + .getMapFields().keySet() : idealState.getRecord().getListFields().keySet(); if (!partitions.containsAll(resetPartitionNames)) { - throw new HelixException(String.format( - ResetPartitionFailureReason.PARTITION_NON_EXISTENT.getMessage(resourceName, partitionNames, instanceName, - partitionNames.toString(), clusterName))); + throw new HelixException(String.format(ResetPartitionFailureReason.PARTITION_NON_EXISTENT + .getMessage(resourceName, partitionNames, instanceName, partitionNames.toString(), + clusterName))); } // check partition is in ERROR state String sessionId = liveInstance.getEphemeralOwner(); - CurrentState curState = accessor.getProperty(keyBuilder.currentState(instanceName, sessionId, resourceName)); + CurrentState curState = + accessor.getProperty(keyBuilder.currentState(instanceName, sessionId, resourceName)); for (String partitionName : resetPartitionNames) { if (!curState.getState(partitionName).equals(HelixDefinedState.ERROR.toString())) { - throw new HelixException(String.format( - ResetPartitionFailureReason.PARTITION_NOT_ERROR.getMessage(resourceName, partitionNames, instanceName, - partitionNames.toString(), clusterName))); + throw new HelixException(String.format(ResetPartitionFailureReason.PARTITION_NOT_ERROR + .getMessage(resourceName, partitionNames, instanceName, partitionNames.toString(), + clusterName))); } } @@ -817,23 +853,23 @@ public void resetPartition(String clusterName, String instanceName, String resou String stateModelDef = idealState.getStateModelDefRef(); StateModelDefinition stateModel = accessor.getProperty(keyBuilder.stateModelDef(stateModelDef)); if (stateModel == null) { - throw new HelixException(String.format( - ResetPartitionFailureReason.STATE_MODEL_NON_EXISTENT.getMessage(resourceName, partitionNames, instanceName, - stateModelDef, clusterName))); + throw new HelixException(String.format(ResetPartitionFailureReason.STATE_MODEL_NON_EXISTENT + .getMessage(resourceName, partitionNames, instanceName, stateModelDef, clusterName))); } // check there is no pending messages for the partitions exist List messages = accessor.getChildValues(keyBuilder.messages(instanceName), true); for (Message message : messages) { - if (!MessageType.STATE_TRANSITION.name().equalsIgnoreCase(message.getMsgType()) || !sessionId.equals( - message.getTgtSessionId()) || !resourceName.equals(message.getResourceName()) + if (!MessageType.STATE_TRANSITION.name().equalsIgnoreCase(message.getMsgType()) || !sessionId + .equals(message.getTgtSessionId()) || !resourceName.equals(message.getResourceName()) || !resetPartitionNames.contains(message.getPartitionName())) { continue; } - throw new HelixException( - String.format("Can't reset state for %s.%s on %s, because a pending message %s exists for resource %s", - resourceName, partitionNames, instanceName, message.toString(), message.getResourceName())); + throw new HelixException(String.format( + "Can't reset state for %s.%s on %s, because a pending message %s exists for resource %s", + resourceName, partitionNames, instanceName, message.toString(), + message.getResourceName())); } String adminName = null; @@ -881,7 +917,8 @@ public void resetInstance(String clusterName, List instanceNames) { // TODO: not mp-safe logger.info("Reset instances {} in cluster {}.", instanceNames == null ? "NULL" : HelixUtil.serializeByComma(instanceNames), clusterName); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List extViews = accessor.getChildValues(keyBuilder.externalViews(), true); @@ -908,7 +945,8 @@ public void resetResource(String clusterName, List resourceNames) { // TODO: not mp-safe logger.info("Reset resources {} in cluster {}.", resourceNames == null ? "NULL" : HelixUtil.serializeByComma(resourceNames), clusterName); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List extViews = accessor.getChildValues(keyBuilder.externalViews(), true); @@ -935,7 +973,8 @@ public void resetResource(String clusterName, List resourceNames) { } for (String instanceName : resetPartitionNames.keySet()) { - resetPartition(clusterName, instanceName, extView.getResourceName(), resetPartitionNames.get(instanceName)); + resetPartition(clusterName, instanceName, extView.getResourceName(), + resetPartitionNames.get(instanceName)); } } } @@ -1036,14 +1075,16 @@ public List getInstancesInClusterWithTag(String clusterName, String tag) List instances = _zkClient.getChildren(memberInstancesPath); List result = new ArrayList(); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); for (String instanceName : instances) { InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceName)); if (config == null) { - throw new IllegalStateException( - String.format("Instance %s does not have a config, cluster might be in bad state", instanceName)); + throw new IllegalStateException(String + .format("Instance %s does not have a config, cluster might be in bad state", + instanceName)); } if (config.containsTag(tag)) { result.add(instanceName); @@ -1053,20 +1094,23 @@ public List getInstancesInClusterWithTag(String clusterName, String tag) } @Override - public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef) { - addResource(clusterName, resourceName, partitions, stateModelRef, RebalanceMode.SEMI_AUTO.toString(), 0); + public void addResource(String clusterName, String resourceName, int partitions, + String stateModelRef) { + addResource(clusterName, resourceName, partitions, stateModelRef, + RebalanceMode.SEMI_AUTO.toString(), 0); } @Override - public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, - String rebalancerMode) { + public void addResource(String clusterName, String resourceName, int partitions, + String stateModelRef, String rebalancerMode) { addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, 0); } @Override - public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, - String rebalancerMode, String rebalanceStrategy) { - addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, rebalanceStrategy, 0, -1); + public void addResource(String clusterName, String resourceName, int partitions, + String stateModelRef, String rebalancerMode, String rebalanceStrategy) { + addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, + rebalanceStrategy, 0, -1); } @Override @@ -1075,35 +1119,38 @@ public void addResource(String clusterName, String resourceName, IdealState idea String stateModelRef = idealstate.getStateModelDefRef(); String stateModelDefPath = PropertyPathBuilder.stateModelDef(clusterName, stateModelRef); if (!_zkClient.exists(stateModelDefPath)) { - throw new HelixException("State model " + stateModelRef + " not found in the cluster STATEMODELDEFS path"); + throw new HelixException( + "State model " + stateModelRef + " not found in the cluster STATEMODELDEFS path"); } String idealStatePath = PropertyPathBuilder.idealState(clusterName); String resourceIdealStatePath = idealStatePath + "/" + resourceName; if (_zkClient.exists(resourceIdealStatePath)) { - throw new HelixException( - "Skip the operation. Resource ideal state directory already exists:" + resourceIdealStatePath); + throw new HelixException("Skip the operation. Resource ideal state directory already exists:" + + resourceIdealStatePath); } ZKUtil.createChildren(_zkClient, idealStatePath, idealstate.getRecord()); } @Override - public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, - String rebalancerMode, int bucketSize) { - addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, bucketSize, -1); + public void addResource(String clusterName, String resourceName, int partitions, + String stateModelRef, String rebalancerMode, int bucketSize) { + addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, bucketSize, + -1); } @Override - public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, - String rebalancerMode, int bucketSize, int maxPartitionsPerInstance) { + public void addResource(String clusterName, String resourceName, int partitions, + String stateModelRef, String rebalancerMode, int bucketSize, int maxPartitionsPerInstance) { addResource(clusterName, resourceName, partitions, stateModelRef, rebalancerMode, RebalanceStrategy.DEFAULT_REBALANCE_STRATEGY, bucketSize, maxPartitionsPerInstance); } @Override - public void addResource(String clusterName, String resourceName, int partitions, String stateModelRef, - String rebalancerMode, String rebalanceStrategy, int bucketSize, int maxPartitionsPerInstance) { + public void addResource(String clusterName, String resourceName, int partitions, + String stateModelRef, String rebalancerMode, String rebalanceStrategy, int bucketSize, + int maxPartitionsPerInstance) { if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } @@ -1111,7 +1158,8 @@ public void addResource(String clusterName, String resourceName, int partitions, IdealState idealState = new IdealState(resourceName); idealState.setNumPartitions(partitions); idealState.setStateModelDefRef(stateModelRef); - RebalanceMode mode = idealState.rebalanceModeFromString(rebalancerMode, RebalanceMode.SEMI_AUTO); + RebalanceMode mode = + idealState.rebalanceModeFromString(rebalancerMode, RebalanceMode.SEMI_AUTO); idealState.setRebalanceMode(mode); idealState.setRebalanceStrategy(rebalanceStrategy); idealState.setReplicas("" + 0); @@ -1129,29 +1177,28 @@ public void addResource(String clusterName, String resourceName, int partitions, public List getClusters() { List zkToplevelPaths; - if (Boolean.getBoolean(SystemPropertyKeys.MULTI_ZK_ENABLED) || _zkClient instanceof FederatedZkClient) { + if (Boolean.getBoolean(SystemPropertyKeys.MULTI_ZK_ENABLED) + || _zkClient instanceof FederatedZkClient) { // If on multi-zk mode, we retrieve cluster information from Metadata Store Directory Service. Map> realmToShardingKeys; - String routingDataSourceEndpoint = _zkClient.getRealmAwareZkConnectionConfig().getRoutingDataSourceEndpoint(); + String routingDataSourceEndpoint = + _zkClient.getRealmAwareZkConnectionConfig().getRoutingDataSourceEndpoint(); if (routingDataSourceEndpoint == null || routingDataSourceEndpoint.isEmpty()) { // If endpoint is not given explicitly, use HTTP and the endpoint set in System Properties realmToShardingKeys = RoutingDataManager.getInstance().getRawRoutingData(); } else { - realmToShardingKeys = RoutingDataManager.getInstance() - .getRawRoutingData( - RoutingDataReaderType.lookUp(_zkClient.getRealmAwareZkConnectionConfig().getRoutingDataSourceType()), - routingDataSourceEndpoint); + realmToShardingKeys = RoutingDataManager.getInstance().getRawRoutingData( + RoutingDataReaderType + .lookUp(_zkClient.getRealmAwareZkConnectionConfig().getRoutingDataSourceType()), + routingDataSourceEndpoint); } if (realmToShardingKeys == null || realmToShardingKeys.isEmpty()) { return Collections.emptyList(); } // Preceding "/"s are removed: e.g.) "/CLUSTER-SHARDING-KEY" -> "CLUSTER-SHARDING-KEY" - zkToplevelPaths = realmToShardingKeys.values() - .stream() - .flatMap(List::stream) - .map(shardingKey -> shardingKey.substring(1)) - .collect(Collectors.toList()); + zkToplevelPaths = realmToShardingKeys.values().stream().flatMap(List::stream) + .map(shardingKey -> shardingKey.substring(1)).collect(Collectors.toList()); } else { // single-zk mode zkToplevelPaths = _zkClient.getChildren("/"); @@ -1175,7 +1222,8 @@ public List getResourcesInCluster(String clusterName) { public List getResourcesInClusterWithTag(String clusterName, String tag) { List resourcesWithTag = new ArrayList(); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); for (String resourceName : getResourcesInCluster(clusterName)) { @@ -1190,17 +1238,21 @@ public List getResourcesInClusterWithTag(String clusterName, String tag) @Override public IdealState getResourceIdealState(String clusterName, String resourceName) { - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.idealStates(resourceName)); } @Override - public void setResourceIdealState(String clusterName, String resourceName, IdealState idealState) { - logger.info("Set IdealState for resource {} in cluster {} with new IdealState {}.", resourceName, clusterName, - idealState == null ? "NULL" : idealState.toString()); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + public void setResourceIdealState(String clusterName, String resourceName, + IdealState idealState) { + logger + .info("Set IdealState for resource {} in cluster {} with new IdealState {}.", resourceName, + clusterName, idealState == null ? "NULL" : idealState.toString()); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.idealStates(resourceName), idealState); @@ -1215,7 +1267,8 @@ public void setResourceIdealState(String clusterName, String resourceName, Ideal @Override public void updateIdealState(String clusterName, String resourceName, IdealState idealState) { if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { - throw new HelixException("updateIdealState failed. Cluster: " + clusterName + " is NOT setup properly."); + throw new HelixException( + "updateIdealState failed. Cluster: " + clusterName + " is NOT setup properly."); } String zkPath = PropertyPathBuilder.idealState(clusterName, resourceName); if (!_zkClient.exists(zkPath)) { @@ -1241,28 +1294,33 @@ public void removeFromIdealState(String clusterName, String resourceName, IdealS @Override public ExternalView getResourceExternalView(String clusterName, String resourceName) { - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.externalView(resourceName)); } @Override - public CustomizedView getResourceCustomizedView(String clusterName, String resourceName, String customizedStateType) { - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + public CustomizedView getResourceCustomizedView(String clusterName, String resourceName, + String customizedStateType) { + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.customizedView(customizedStateType, resourceName)); } @Override - public void addStateModelDef(String clusterName, String stateModelDef, StateModelDefinition stateModel) { + public void addStateModelDef(String clusterName, String stateModelDef, + StateModelDefinition stateModel) { addStateModelDef(clusterName, stateModelDef, stateModel, false); } @Override - public void addStateModelDef(String clusterName, String stateModelDef, StateModelDefinition stateModel, - boolean recreateIfExists) { - logger.info("Add StateModelDef {} in cluster {} with StateModel {}.", stateModelDef, clusterName, - stateModel == null ? "NULL" : stateModel.toString()); + public void addStateModelDef(String clusterName, String stateModelDef, + StateModelDefinition stateModel, boolean recreateIfExists) { + logger + .info("Add StateModelDef {} in cluster {} with StateModel {}.", stateModelDef, clusterName, + stateModel == null ? "NULL" : stateModel.toString()); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } @@ -1270,7 +1328,8 @@ public void addStateModelDef(String clusterName, String stateModelDef, StateMode String stateModelPath = stateModelDefPath + "/" + stateModelDef; if (_zkClient.exists(stateModelPath)) { if (recreateIfExists) { - logger.info("Operation.State Model directory exists:" + stateModelPath + ", remove and recreate."); + logger.info( + "Operation.State Model directory exists:" + stateModelPath + ", remove and recreate."); _zkClient.deleteRecursively(stateModelPath); } else { logger.info("Skip the operation. State Model directory exists:" + stateModelPath); @@ -1278,7 +1337,8 @@ public void addStateModelDef(String clusterName, String stateModelDef, StateMode } } - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.stateModelDef(stateModelDef), stateModel); } @@ -1289,7 +1349,8 @@ public void dropResource(String clusterName, String resourceName) { if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("Cluster " + clusterName + " is not setup yet"); } - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.removeProperty(keyBuilder.idealStates(resourceName)); @@ -1298,7 +1359,8 @@ public void dropResource(String clusterName, String resourceName) { @Override public void addCloudConfig(String clusterName, CloudConfig cloudConfig) { - logger.info("Add CloudConfig to cluster {}, CloudConfig is {}.", clusterName, cloudConfig.toString()); + logger.info("Add CloudConfig to cluster {}, CloudConfig is {}.", clusterName, + cloudConfig.toString()); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); @@ -1307,7 +1369,8 @@ public void addCloudConfig(String clusterName, CloudConfig cloudConfig) { CloudConfig.Builder builder = new CloudConfig.Builder(cloudConfig); CloudConfig cloudConfigBuilder = builder.build(); - ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.cloudConfig(), cloudConfigBuilder); } @@ -1315,7 +1378,8 @@ public void addCloudConfig(String clusterName, CloudConfig cloudConfig) { @Override public void removeCloudConfig(String clusterName) { logger.info("Remove Cloud Config for cluster {}.", clusterName); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.removeProperty(keyBuilder.cloudConfig()); } @@ -1346,7 +1410,8 @@ public List getStateModelDefs(String clusterName) { @Override public StateModelDefinition getStateModelDef(String clusterName, String stateModelName) { - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); return accessor.getProperty(keyBuilder.stateModelDef(stateModelName)); @@ -1355,12 +1420,14 @@ public StateModelDefinition getStateModelDef(String clusterName, String stateMod @Override public void dropCluster(String clusterName) { logger.info("Deleting cluster {}.", clusterName); - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); String root = "/" + clusterName; if (accessor.getChildNames(keyBuilder.liveInstances()).size() > 0) { - throw new HelixException("There are still live instances in the cluster, shut them down first."); + throw new HelixException( + "There are still live instances in the cluster, shut them down first."); } if (accessor.getProperty(keyBuilder.controllerLeader()) != null) { @@ -1396,12 +1463,13 @@ public void addClusterToGrandCluster(String clusterName, String grandCluster) { throw new HelixException("Grand cluster " + grandCluster + " has no instances"); } - ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(grandCluster, new ZkBaseDataAccessor<>(_zkClient)); + ZKHelixDataAccessor accessor = + new ZKHelixDataAccessor(grandCluster, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.idealStates(idealState.getResourceName()), idealState); - LOG.info("Cluster {} has been added to grand cluster {} with rebalance configuration {}.", clusterName, - grandCluster, idealState.getRecord().getSimpleFields().toString()); + LOG.info("Cluster {} has been added to grand cluster {} with rebalance configuration {}.", + clusterName, grandCluster, idealState.getRecord().getSimpleFields().toString()); } @Override @@ -1416,29 +1484,37 @@ public Map getConfig(HelixConfigScope scope, List keys) } @Override - public void addCustomizedStateConfig(String clusterName, CustomizedStateConfig customizedStateConfig) { - logger.info("Add CustomizedStateConfig to cluster {}, CustomizedStateConfig is {}", clusterName, - customizedStateConfig.toString()); + public void addCustomizedStateConfig(String clusterName, + CustomizedStateConfig customizedStateConfig) { + logger.info( + "Add CustomizedStateConfig to cluster {}, CustomizedStateConfig is {}", + clusterName, customizedStateConfig.toString()); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } - CustomizedStateConfig.Builder builder = new CustomizedStateConfig.Builder(customizedStateConfig); + CustomizedStateConfig.Builder builder = + new CustomizedStateConfig.Builder(customizedStateConfig); CustomizedStateConfig customizedStateConfigFromBuilder = builder.build(); - ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); - accessor.setProperty(keyBuilder.customizedStateConfig(), customizedStateConfigFromBuilder); + accessor.setProperty(keyBuilder.customizedStateConfig(), + customizedStateConfigFromBuilder); } @Override public void removeCustomizedStateConfig(String clusterName) { - logger.info("Remove CustomizedStateConfig from cluster {}.", clusterName); + logger.info( + "Remove CustomizedStateConfig from cluster {}.", clusterName); - ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); accessor.removeProperty(keyBuilder.customizedStateConfig()); + } @Override @@ -1448,38 +1524,47 @@ public void addTypeToCustomizedStateConfig(String clusterName, String type) { if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } - CustomizedStateConfig.Builder builder = new CustomizedStateConfig.Builder(); + CustomizedStateConfig.Builder builder = + new CustomizedStateConfig.Builder(); builder.addAggregationEnabledType(type); CustomizedStateConfig customizedStateConfigFromBuilder = builder.build(); - ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); - if (!accessor.updateProperty(keyBuilder.customizedStateConfig(), customizedStateConfigFromBuilder)) { - throw new HelixException("Failed to add customized state config type " + type + " to cluster" + clusterName); + if(!accessor.updateProperty(keyBuilder.customizedStateConfig(), + customizedStateConfigFromBuilder)) { + throw new HelixException( + "Failed to add customized state config type " + type + " to cluster" + clusterName); } } + @Override public void removeTypeFromCustomizedStateConfig(String clusterName, String type) { - logger.info("Remove type {} to CustomizedStateConfig of cluster {}", type, clusterName); + logger.info("Remove type {} to CustomizedStateConfig of cluster {}", type, + clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } - CustomizedStateConfig.Builder builder = - new CustomizedStateConfig.Builder(_configAccessor.getCustomizedStateConfig(clusterName)); + CustomizedStateConfig.Builder builder = new CustomizedStateConfig.Builder( + _configAccessor.getCustomizedStateConfig(clusterName)); if (!builder.getAggregationEnabledTypes().contains(type)) { - throw new HelixException("Type " + type + " is missing from the CustomizedStateConfig of cluster " + clusterName); + throw new HelixException("Type " + type + + " is missing from the CustomizedStateConfig of cluster " + clusterName); } builder.removeAggregationEnabledType(type); CustomizedStateConfig customizedStateConfigFromBuilder = builder.build(); - ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); - accessor.setProperty(keyBuilder.customizedStateConfig(), customizedStateConfigFromBuilder); + accessor.setProperty(keyBuilder.customizedStateConfig(), + customizedStateConfigFromBuilder); } @Override @@ -1520,7 +1605,8 @@ public ZNRecord update(ZNRecord currentData) { } @Override - public void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, String group) { + public void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, + String group) { List instanceNames = new LinkedList(); if (keyPrefix == null || keyPrefix.length() == 0) { keyPrefix = resourceName; @@ -1539,13 +1625,15 @@ public void rebalance(String clusterName, String resourceName, int replica, Stri } @Override - public void rebalance(String clusterName, String resourceName, int replica, List instances) { + public void rebalance(String clusterName, String resourceName, int replica, + List instances) { rebalance(clusterName, resourceName, replica, resourceName, instances, ""); } - void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, List instanceNames, - String groupId) { - logger.info("Rebalance resource {} with replica {} in cluster {}.", resourceName, replica, clusterName); + void rebalance(String clusterName, String resourceName, int replica, String keyPrefix, + List instanceNames, String groupId) { + logger.info("Rebalance resource {} with replica {} in cluster {}.", resourceName, replica, + clusterName); // ensure we get the same idealState with the same set of instances Collections.sort(instanceNames); @@ -1602,9 +1690,9 @@ void rebalance(String clusterName, String resourceName, int replica, String keyP } if (idealState.getRebalanceMode() != RebalanceMode.FULL_AUTO && idealState.getRebalanceMode() != RebalanceMode.USER_DEFINED) { - ZNRecord newIdealState = - DefaultIdealStateCalculator.calculateIdealState(instanceNames, partitions, replica, keyPrefix, - masterStateValue, slaveStateValue); + ZNRecord newIdealState = DefaultIdealStateCalculator + .calculateIdealState(instanceNames, partitions, replica, keyPrefix, masterStateValue, + slaveStateValue); // for now keep mapField in SEMI_AUTO mode and remove listField in CUSTOMIZED mode if (idealState.getRebalanceMode() == RebalanceMode.SEMI_AUTO) { @@ -1626,17 +1714,20 @@ void rebalance(String clusterName, String resourceName, int replica, String keyP } @Override - public void addIdealState(String clusterName, String resourceName, String idealStateFile) throws IOException { - logger.info("Add IdealState for resource {} to cluster {} by file name {}.", resourceName, clusterName, - idealStateFile); - ZNRecord idealStateRecord = (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(idealStateFile))); + public void addIdealState(String clusterName, String resourceName, String idealStateFile) + throws IOException { + logger.info("Add IdealState for resource {} to cluster {} by file name {}.", resourceName, + clusterName, idealStateFile); + ZNRecord idealStateRecord = + (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(idealStateFile))); if (idealStateRecord.getId() == null || !idealStateRecord.getId().equals(resourceName)) { throw new IllegalArgumentException("ideal state must have same id as resource name"); } setResourceIdealState(clusterName, resourceName, new IdealState(idealStateRecord)); } - private static byte[] readFile(String filePath) throws IOException { + private static byte[] readFile(String filePath) + throws IOException { File file = new File(filePath); int size = (int) file.length(); @@ -1658,20 +1749,23 @@ private static byte[] readFile(String filePath) throws IOException { } @Override - public void addStateModelDef(String clusterName, String stateModelDefName, String stateModelDefFile) + public void addStateModelDef(String clusterName, String stateModelDefName, + String stateModelDefFile) throws IOException { - ZNRecord record = (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(stateModelDefFile))); + ZNRecord record = + (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(stateModelDefFile))); if (record == null || record.getId() == null || !record.getId().equals(stateModelDefName)) { - throw new IllegalArgumentException("state model definition must have same id as state model def name"); + throw new IllegalArgumentException( + "state model definition must have same id as state model def name"); } addStateModelDef(clusterName, stateModelDefName, new StateModelDefinition(record), false); } @Override - public void setConstraint(String clusterName, final ConstraintType constraintType, final String constraintId, - final ConstraintItem constraintItem) { - logger.info("Set constraint type {} with constraint id {} for cluster {}.", constraintType, constraintId, - clusterName); + public void setConstraint(String clusterName, final ConstraintType constraintType, + final String constraintId, final ConstraintItem constraintItem) { + logger.info("Set constraint type {} with constraint id {} for cluster {}.", constraintType, + constraintId, clusterName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName); @@ -1681,7 +1775,8 @@ public void setConstraint(String clusterName, final ConstraintType constraintTyp @Override public ZNRecord update(ZNRecord currentData) { ClusterConstraints constraints = - currentData == null ? new ClusterConstraints(constraintType) : new ClusterConstraints(currentData); + currentData == null ? new ClusterConstraints(constraintType) + : new ClusterConstraints(currentData); constraints.addConstraintItem(constraintId, constraintItem); return constraints.getRecord(); @@ -1690,9 +1785,10 @@ public ZNRecord update(ZNRecord currentData) { } @Override - public void removeConstraint(String clusterName, final ConstraintType constraintType, final String constraintId) { - logger.info("Remove constraint type {} with constraint id {} for cluster {}.", constraintType, constraintId, - clusterName); + public void removeConstraint(String clusterName, final ConstraintType constraintType, + final String constraintId) { + logger.info("Remove constraint type {} with constraint id {} for cluster {}.", constraintType, + constraintId, clusterName); BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName); @@ -1714,7 +1810,8 @@ public ZNRecord update(ZNRecord currentData) { @Override public ClusterConstraints getConstraints(String clusterName, ConstraintType constraintType) { - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName); return accessor.getProperty(keyBuilder.constraint(constraintType.toString())); @@ -1730,43 +1827,51 @@ public ClusterConstraints getConstraints(String clusterName, ConstraintType cons * @return */ @Override - public void rebalance(String clusterName, IdealState currentIdealState, List instanceNames) { - logger.info("Rebalance resource {} in cluster {} with IdealState {}.", currentIdealState.getResourceName(), - clusterName, currentIdealState == null ? "NULL" : currentIdealState.toString()); + public void rebalance(String clusterName, IdealState currentIdealState, + List instanceNames) { + logger.info("Rebalance resource {} in cluster {} with IdealState {}.", + currentIdealState.getResourceName(), clusterName, + currentIdealState == null ? "NULL" : currentIdealState.toString()); Set activeInstances = new HashSet(); for (String partition : currentIdealState.getPartitionSet()) { activeInstances.addAll(currentIdealState.getRecord().getListField(partition)); } instanceNames.removeAll(activeInstances); - Map previousIdealState = RebalanceUtil.buildInternalIdealState(currentIdealState); + Map previousIdealState = + RebalanceUtil.buildInternalIdealState(currentIdealState); Map balancedRecord = DefaultIdealStateCalculator.calculateNextIdealState(instanceNames, previousIdealState); - StateModelDefinition stateModDef = this.getStateModelDef(clusterName, currentIdealState.getStateModelDefRef()); + StateModelDefinition stateModDef = + this.getStateModelDef(clusterName, currentIdealState.getStateModelDefRef()); if (stateModDef == null) { - throw new HelixException("cannot find state model: " + currentIdealState.getStateModelDefRef()); + throw new HelixException( + "cannot find state model: " + currentIdealState.getStateModelDefRef()); } String[] states = RebalanceUtil.parseStates(clusterName, stateModDef); - ZNRecord newIdealStateRecord = - DefaultIdealStateCalculator.convertToZNRecord(balancedRecord, currentIdealState.getResourceName(), states[0], + ZNRecord newIdealStateRecord = DefaultIdealStateCalculator + .convertToZNRecord(balancedRecord, currentIdealState.getResourceName(), states[0], states[1]); Set partitionSet = new HashSet(); partitionSet.addAll(newIdealStateRecord.getMapFields().keySet()); partitionSet.addAll(newIdealStateRecord.getListFields().keySet()); - Map reversePartitionIndex = (Map) balancedRecord.get("reversePartitionIndex"); + Map reversePartitionIndex = + (Map) balancedRecord.get("reversePartitionIndex"); for (String partition : partitionSet) { if (reversePartitionIndex.containsKey(partition)) { String originPartitionName = reversePartitionIndex.get(partition); if (partition.equals(originPartitionName)) { continue; } - newIdealStateRecord.getMapFields().put(originPartitionName, newIdealStateRecord.getMapField(partition)); + newIdealStateRecord.getMapFields() + .put(originPartitionName, newIdealStateRecord.getMapField(partition)); newIdealStateRecord.getMapFields().remove(partition); - newIdealStateRecord.getListFields().put(originPartitionName, newIdealStateRecord.getListField(partition)); + newIdealStateRecord.getListFields() + .put(originPartitionName, newIdealStateRecord.getListField(partition)); newIdealStateRecord.getListFields().remove(partition); } } @@ -1778,15 +1883,18 @@ public void rebalance(String clusterName, IdealState currentIdealState, List(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceName)); @@ -1796,15 +1904,18 @@ public void addInstanceTag(String clusterName, String instanceName, String tag) @Override public void removeInstanceTag(String clusterName, String instanceName, String tag) { - logger.info("Remove instance tag {} for instance {} in cluster {}.", tag, instanceName, clusterName); + logger.info("Remove instance tag {} for instance {} in cluster {}.", tag, instanceName, + clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } if (!ZKUtil.isInstanceSetup(_zkClient, clusterName, instanceName, InstanceType.PARTICIPANT)) { - throw new HelixException("cluster " + clusterName + " instance " + instanceName + " is not setup yet"); + throw new HelixException( + "cluster " + clusterName + " instance " + instanceName + " is not setup yet"); } - ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + ZKHelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceName)); @@ -1814,15 +1925,18 @@ public void removeInstanceTag(String clusterName, String instanceName, String ta @Override public void setInstanceZoneId(String clusterName, String instanceName, String zoneId) { - logger.info("Set instance zoneId {} for instance {} in cluster {}.", zoneId, instanceName, clusterName); + logger.info("Set instance zoneId {} for instance {} in cluster {}.", zoneId, instanceName, + clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } if (!ZKUtil.isInstanceSetup(_zkClient, clusterName, instanceName, InstanceType.PARTICIPANT)) { - throw new HelixException("cluster " + clusterName + " instance " + instanceName + " is not setup yet"); + throw new HelixException( + "cluster " + clusterName + " instance " + instanceName + " is not setup yet"); } - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceName)); @@ -1832,7 +1946,8 @@ public void setInstanceZoneId(String clusterName, String instanceName, String zo @Override public void enableBatchMessageMode(String clusterName, boolean enabled) { - logger.info("{} batch message mode for cluster {}.", enabled ? "Enable" : "Disable", clusterName); + logger + .info("{} batch message mode for cluster {}.", enabled ? "Enable" : "Disable", clusterName); if (!ZKUtil.isClusterSetup(clusterName, _zkClient)) { throw new HelixException("cluster " + clusterName + " is not setup yet"); } @@ -1845,34 +1960,35 @@ public void enableBatchMessageMode(String clusterName, boolean enabled) { @Override public void enableBatchMessageMode(String clusterName, String resourceName, boolean enabled) { - logger.info("{} batch message mode for resource {} in cluster {}.", enabled ? "Enable" : "Disable", resourceName, - clusterName); + logger.info("{} batch message mode for resource {} in cluster {}.", + enabled ? "Enable" : "Disable", resourceName, clusterName); // TODO: Change IdealState to ResourceConfig when configs are migrated to ResourceConfig IdealState idealState = getResourceIdealState(clusterName, resourceName); if (idealState == null) { - throw new HelixException( - "Cluster " + clusterName + ", resource: " + resourceName + ", ideal-state does not exist"); + throw new HelixException("Cluster " + clusterName + ", resource: " + resourceName + + ", ideal-state does not exist"); } idealState.setBatchMessageMode(enabled); setResourceIdealState(clusterName, resourceName, idealState); } - private void enableSingleInstance(final String clusterName, final String instanceName, final boolean enabled, - BaseDataAccessor baseAccessor, InstanceConstants.InstanceDisabledType disabledType, String reason) { + private void enableSingleInstance(final String clusterName, final String instanceName, + final boolean enabled, BaseDataAccessor baseAccessor, + InstanceConstants.InstanceDisabledType disabledType, String reason) { String path = PropertyPathBuilder.instanceConfig(clusterName, instanceName); if (!baseAccessor.exists(path, 0)) { - throw new HelixException( - "Cluster " + clusterName + ", instance: " + instanceName + ", instance config does not exist"); + throw new HelixException("Cluster " + clusterName + ", instance: " + instanceName + + ", instance config does not exist"); } baseAccessor.update(path, new DataUpdater() { @Override public ZNRecord update(ZNRecord currentData) { if (currentData == null) { - throw new HelixException( - "Cluster: " + clusterName + ", instance: " + instanceName + ", participant config is null"); + throw new HelixException("Cluster: " + clusterName + ", instance: " + instanceName + + ", participant config is null"); } InstanceConfig config = new InstanceConfig(currentData); @@ -1893,8 +2009,9 @@ public ZNRecord update(ZNRecord currentData) { } // TODO: Add history ZNode for all batched enabling/disabling histories with metadata. - private void enableBatchInstances(final String clusterName, final List instances, final boolean enabled, - BaseDataAccessor baseAccessor, InstanceConstants.InstanceDisabledType disabledType, String reason) { + private void enableBatchInstances(final String clusterName, final List instances, + final boolean enabled, BaseDataAccessor baseAccessor, + InstanceConstants.InstanceDisabledType disabledType, String reason) { // TODO: batch enable/disable is breaking backward compatibility on instance enable with older library // re-enable once batch enable/disable is ready @@ -1928,8 +2045,8 @@ public ZNRecord update(ZNRecord currentData) { // TODO: update the history ZNode String timeStamp = String.valueOf(System.currentTimeMillis()); disabledInstances.put(disabledInstance, timeStamp); - disabledInstancesWithInfo.put(disabledInstance, - assembleInstanceBatchedDisabledInfo(disabledType, reason, timeStamp)); + disabledInstancesWithInfo + .put(disabledInstance, assembleInstanceBatchedDisabledInfo(disabledType, reason, timeStamp)); } } clusterConfig.setDisabledInstances(disabledInstances); @@ -1940,12 +2057,14 @@ public ZNRecord update(ZNRecord currentData) { }, AccessOption.PERSISTENT); } - public static String assembleInstanceBatchedDisabledInfo(InstanceConstants.InstanceDisabledType disabledType, - String reason, String timeStamp) { + public static String assembleInstanceBatchedDisabledInfo( + InstanceConstants.InstanceDisabledType disabledType, String reason, String timeStamp) { Map disableInfo = new TreeMap<>(); - disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_ENABLED_DISABLE_TIMESTAMP.toString(), timeStamp); + disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_ENABLED_DISABLE_TIMESTAMP.toString(), + timeStamp); if (disabledType != null) { - disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_DISABLED_TYPE.toString(), disabledType.toString()); + disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_DISABLED_TYPE.toString(), + disabledType.toString()); } if (reason != null) { disableInfo.put(ClusterConfig.ClusterConfigProperty.HELIX_DISABLED_REASON.toString(), reason); @@ -1992,7 +2111,8 @@ public void finalize() { } @Override - public boolean addResourceWithWeight(String clusterName, IdealState idealState, ResourceConfig resourceConfig) { + public boolean addResourceWithWeight(String clusterName, IdealState idealState, + ResourceConfig resourceConfig) { // Null checks if (clusterName == null || clusterName.isEmpty()) { throw new HelixException("Cluster name is null or empty!"); @@ -2013,14 +2133,16 @@ public boolean addResourceWithWeight(String clusterName, IdealState idealState, // Order in which a resource should be added: // 1. Validate the weights in ResourceConfig against ClusterConfig // Check that all capacity keys in ClusterConfig are set up in every partition in ResourceConfig field - if (!validateWeightForResourceConfig(_configAccessor.getClusterConfig(clusterName), resourceConfig, idealState)) { - throw new HelixException( - String.format("Could not add resource %s with weight! Failed to validate the ResourceConfig!", + if (!validateWeightForResourceConfig(_configAccessor.getClusterConfig(clusterName), + resourceConfig, idealState)) { + throw new HelixException(String + .format("Could not add resource %s with weight! Failed to validate the ResourceConfig!", idealState.getResourceName())); } // 2. Add the resourceConfig to ZK - _configAccessor.setResourceConfig(clusterName, resourceConfig.getResourceName(), resourceConfig); + _configAccessor + .setResourceConfig(clusterName, resourceConfig.getResourceName(), resourceConfig); // 3. Add the idealState to ZK setResourceIdealState(clusterName, idealState.getResourceName(), idealState); @@ -2042,7 +2164,8 @@ public boolean enableWagedRebalance(String clusterName, List resourceNam throw new HelixException("Resource name list is invalid!"); } - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List enabledIdealStates = new ArrayList<>(); List enabledIdealStateKeys = new ArrayList<>(); @@ -2058,11 +2181,12 @@ public boolean enableWagedRebalance(String clusterName, List resourceNam enabledResourceNames.add(idealState.getResourceName()); } } - List resourcesNotFound = resourceNames.stream() - .filter(resourceName -> !enabledResourceNames.contains(resourceName)) - .collect(Collectors.toList()); + List resourcesNotFound = + resourceNames.stream().filter(resourceName -> !enabledResourceNames.contains(resourceName)) + .collect(Collectors.toList()); if (!resourcesNotFound.isEmpty()) { - throw new HelixException(String.format("Some resources do not have IdealStates: %s", resourcesNotFound)); + throw new HelixException( + String.format("Some resources do not have IdealStates: %s", resourcesNotFound)); } boolean[] success = accessor.setChildren(enabledIdealStateKeys, enabledIdealStates); for (boolean s : success) { @@ -2074,7 +2198,8 @@ public boolean enableWagedRebalance(String clusterName, List resourceNam } @Override - public Map validateResourcesForWagedRebalance(String clusterName, List resourceNames) { + public Map validateResourcesForWagedRebalance(String clusterName, + List resourceNames) { // Null checks if (clusterName == null || clusterName.isEmpty()) { throw new HelixException("Cluster name is invalid!"); @@ -2084,12 +2209,14 @@ public Map validateResourcesForWagedRebalance(String clusterNam } // Ensure that all instances are valid - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<>(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List instances = accessor.getChildNames(keyBuilder.instanceConfigs()); if (validateInstancesForWagedRebalance(clusterName, instances).containsValue(false)) { - throw new HelixException( - String.format("Instance capacities haven't been configured properly for cluster %s", clusterName)); + throw new HelixException(String + .format("Instance capacities haven't been configured properly for cluster %s", + clusterName)); } Map result = new HashMap<>(); @@ -2101,13 +2228,15 @@ public Map validateResourcesForWagedRebalance(String clusterNam continue; } ResourceConfig resourceConfig = _configAccessor.getResourceConfig(clusterName, resourceName); - result.put(resourceName, validateWeightForResourceConfig(clusterConfig, resourceConfig, idealState)); + result.put(resourceName, + validateWeightForResourceConfig(clusterConfig, resourceConfig, idealState)); } return result; } @Override - public Map validateInstancesForWagedRebalance(String clusterName, List instanceNames) { + public Map validateInstancesForWagedRebalance(String clusterName, + List instanceNames) { // Null checks if (clusterName == null || clusterName.isEmpty()) { throw new HelixException("Cluster name is invalid!"); @@ -2138,17 +2267,19 @@ public Map validateInstancesForWagedRebalance(String clusterNam * @param idealState * @return true if ResourceConfig has all the required fields. False otherwise. */ - private boolean validateWeightForResourceConfig(ClusterConfig clusterConfig, ResourceConfig resourceConfig, - IdealState idealState) { + private boolean validateWeightForResourceConfig(ClusterConfig clusterConfig, + ResourceConfig resourceConfig, IdealState idealState) { if (resourceConfig == null) { if (clusterConfig.getDefaultPartitionWeightMap().isEmpty()) { - logger.error("ResourceConfig for {} is null, and there are no default weights set in ClusterConfig!", + logger.error( + "ResourceConfig for {} is null, and there are no default weights set in ClusterConfig!", idealState.getResourceName()); return false; } // If ResourceConfig is null AND the default partition weight map is defined, and the map has all the required keys, we consider this valid since the default weights will be used // Need to check the map contains all the required keys - if (clusterConfig.getDefaultPartitionWeightMap().keySet().containsAll(clusterConfig.getInstanceCapacityKeys())) { + if (clusterConfig.getDefaultPartitionWeightMap().keySet() + .containsAll(clusterConfig.getInstanceCapacityKeys())) { // Contains all the required keys, so consider it valid since it will use the default weights return true; } @@ -2163,7 +2294,8 @@ private boolean validateWeightForResourceConfig(ClusterConfig clusterConfig, Res try { capacityMap = resourceConfig.getPartitionCapacityMap(); } catch (IOException ex) { - logger.error("Invalid partition capacity configuration of resource: {}", idealState.getResourceName(), ex); + logger.error("Invalid partition capacity configuration of resource: {}", + idealState.getResourceName(), ex); return false; } @@ -2177,15 +2309,16 @@ private boolean validateWeightForResourceConfig(ClusterConfig clusterConfig, Res // So check using numPartitions instead // This check allows us to fail early on instead of having to loop through all partitions if (capacityMapSet.size() != idealState.getNumPartitions() && !hasDefaultCapacity) { - logger.error("ResourceConfig for {} does not have all partitions defined in PartitionCapacityMap!", + logger.error( + "ResourceConfig for {} does not have all partitions defined in PartitionCapacityMap!", idealState.getResourceName()); return false; } // Loop through all partitions and validate - capacityMap.keySet() - .forEach(partitionName -> WagedValidationUtil.validateAndGetPartitionCapacity(partitionName, resourceConfig, - capacityMap, clusterConfig)); + capacityMap.keySet().forEach(partitionName -> WagedValidationUtil + .validateAndGetPartitionCapacity(partitionName, resourceConfig, capacityMap, + clusterConfig)); return true; } @@ -2196,20 +2329,23 @@ public Builder() { public ZKHelixAdmin build() { validate(); return new ZKHelixAdmin( - createZkClient(_realmMode, _realmAwareZkConnectionConfig, _realmAwareZkClientConfig, _zkAddress), false); + createZkClient(_realmMode, _realmAwareZkConnectionConfig, _realmAwareZkClientConfig, + _zkAddress), false); } } private Set findTimeoutOfflineInstances(String clusterName, long offlineDuration) { // in case there is no customized timeout value, use the one defined in cluster config if (offlineDuration == ClusterConfig.OFFLINE_DURATION_FOR_PURGE_NOT_SET) { - offlineDuration = _configAccessor.getClusterConfig(clusterName).getOfflineDurationForPurge(); + offlineDuration = + _configAccessor.getClusterConfig(clusterName).getOfflineDurationForPurge(); if (offlineDuration == ClusterConfig.OFFLINE_DURATION_FOR_PURGE_NOT_SET) { return Collections.emptySet(); } } - HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); + HelixDataAccessor accessor = + new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient)); PropertyKey.Builder keyBuilder = accessor.keyBuilder(); List instanceConfigNames = accessor.getChildNames(keyBuilder.instanceConfigs()); List instancePathNames = accessor.getChildNames(keyBuilder.instances()); @@ -2219,7 +2355,8 @@ private Set findTimeoutOfflineInstances(String clusterName, long offline liveNodes.forEach(offlineInstanceNames::remove); long finalOfflineDuration = offlineDuration; offlineInstanceNames.removeIf(instanceName -> { - ParticipantHistory participantHistory = accessor.getProperty(keyBuilder.participantHistory(instanceName)); + ParticipantHistory participantHistory = + accessor.getProperty(keyBuilder.participantHistory(instanceName)); if (participantHistory == null && instanceConfigNames.contains(instanceName)) { // this is likely caused by a new instance joining and should not be purged return true; @@ -2227,8 +2364,10 @@ private Set findTimeoutOfflineInstances(String clusterName, long offline // If participant history is null without config, a race condition happened and should be // cleaned up. // Otherwise, if the participant has not been offline for more than the duration, no clean up - return (participantHistory != null && (participantHistory.getLastOfflineTime() == ParticipantHistory.ONLINE - || System.currentTimeMillis() - participantHistory.getLastOfflineTime() < finalOfflineDuration)); + return (participantHistory != null && ( + participantHistory.getLastOfflineTime() == ParticipantHistory.ONLINE + || System.currentTimeMillis() - participantHistory.getLastOfflineTime() + < finalOfflineDuration)); }); return offlineInstanceNames; diff --git a/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java b/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java index 63ce710686..6c51d58bbc 100644 --- a/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java +++ b/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java @@ -111,7 +111,6 @@ public void testEvacuate() throws Exception { _gSetupTool.getClusterManagementTool() .setInstanceOperation(CLUSTER_NAME, instanceToEvacuate, InstanceConstants.InstanceOperation.EVACUATE); - System.out.println("123"); Assert.assertTrue(_clusterVerifier.verifyByPolling()); // New ev should contain all instances but the evacuated one @@ -224,6 +223,7 @@ public void testEvacuateAndCancelBeforeBootstrapFinish() throws Exception { () -> ((_dataAccessor.getChildNames(_dataAccessor.keyBuilder().messages(participant))).isEmpty()), 30000); } Assert.assertFalse(_admin.isEvacuateFinished(CLUSTER_NAME, instanceToEvacuate)); + Assert.assertFalse(_admin.isReadyForPreparingJoiningCluster(CLUSTER_NAME, instanceToEvacuate)); // sleep a bit so ST messages can start executing Thread.sleep(Math.abs(_stateModelDelay / 100)); From 6bbeb726957115c504a2aff97cfe66a586d2e9bf Mon Sep 17 00:00:00 2001 From: xyuanlu Date: Mon, 18 Sep 2023 22:02:25 -0700 Subject: [PATCH 4/4] address comments --- .../org/apache/helix/manager/zk/ZKHelixAdmin.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java index ff1e9ab1b5..44afee5e1b 100644 --- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java +++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java @@ -410,7 +410,8 @@ public ZNRecord update(ZNRecord currentData) { @Override public boolean isEvacuateFinished(String clusterName, String instanceName) { - return !instanceHasCurrentSateOrMessage(clusterName, instanceName); + return !instanceHasCurrentSateOrMessage(clusterName, instanceName) && (getInstanceConfig(clusterName, + instanceName).getInstanceOperation().equals(InstanceConstants.InstanceOperation.EVACUATE.name())); } @Override @@ -440,6 +441,15 @@ private boolean instanceHasCurrentSateOrMessage(String clusterName, String insta } BaseDataAccessor baseAccessor = new ZkBaseDataAccessor(_zkClient); + // count number of sessions under CurrentState folder. If it is carrying over from prv session, + // then there are > 1 session ZNodes. + List sessions = baseAccessor.getChildNames(PropertyPathBuilder.instanceCurrentState(clusterName, instanceName), 0); + if (sessions.size() > 1) { + logger.warn("Instance {} in cluster {} is carrying over from prev session.", instanceName, + clusterName); + return true; + } + String sessionId = liveInstance.getEphemeralOwner(); String path = PropertyPathBuilder.instanceCurrentState(clusterName, instanceName, sessionId);