You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by hu...@apache.org on 2019/05/22 23:41:37 UTC

[helix] 12/14: Add Util check instance is already in stable state

This is an automated email from the ASF dual-hosted git repository.

hulee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/helix.git

commit ae2e3cb4d40f15cd89ba9b99831d0feb1b64bdd8
Author: Junkai Xue <jx...@linkedin.com>
AuthorDate: Fri Mar 15 16:35:01 2019 -0700

    Add Util check instance is already in stable state
    
    We have two choice of checking instance in stable state:
    1. Compare IdealState with ExternalView
    2. Compare IdealState with CurrentState.
    
    Finally choose IS vs EV is because:
    1. We have simple cache in REST, read current state will still cause multiple reads from different hosts for current state. But EV can shared by each host.
    2. EV is the decision maker for router, which is kinda source of truth of real production environment. So EV is the final choice.
    
    RB=1598176
    BUG=HELIX-1676
    G=helix-reviewers
    A=jjwang
    
    Signed-off-by: Hunter Lee <hu...@linkedin.com>
---
 .../apache/helix/util/InstanceValidationUtil.java  | 41 +++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/helix-core/src/main/java/org/apache/helix/util/InstanceValidationUtil.java b/helix-core/src/main/java/org/apache/helix/util/InstanceValidationUtil.java
index 81266c2..351c50d 100644
--- a/helix-core/src/main/java/org/apache/helix/util/InstanceValidationUtil.java
+++ b/helix-core/src/main/java/org/apache/helix/util/InstanceValidationUtil.java
@@ -19,6 +19,7 @@ package org.apache.helix.util;
  * under the License.
  */
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import org.apache.helix.AccessOption;
@@ -29,6 +30,8 @@ import org.apache.helix.HelixException;
 import org.apache.helix.PropertyKey;
 import org.apache.helix.model.ClusterConfig;
 import org.apache.helix.model.CurrentState;
+import org.apache.helix.model.ExternalView;
+import org.apache.helix.model.IdealState;
 import org.apache.helix.model.InstanceConfig;
 import org.apache.helix.model.LiveInstance;
 import org.apache.helix.model.RESTConfig;
@@ -48,7 +51,7 @@ public class InstanceValidationUtil {
     instanceHealthStatus,
     partitionHealthStatus
   }
-  
+
   private InstanceValidationUtil() {
   }
 
@@ -246,4 +249,40 @@ public class InstanceValidationUtil {
       Map<String, Map<String, String>> partitionHealthMap) {
     return true;
   }
+
+  /**
+   * Check instance is already in the stable state. Here stable means all the ideal state mapping
+   * matches external view (view of current state).
+   *
+   * It requires persist assignment on!
+   *
+   * @param dataAccessor
+   * @param instanceName
+   * @return
+   */
+  public static boolean isInstanceStable(HelixDataAccessor dataAccessor, String instanceName) {
+    PropertyKey.Builder keyBuilder = dataAccessor.keyBuilder();
+    ClusterConfig clusterConfig = dataAccessor.getProperty(keyBuilder.clusterConfig());
+    if (!clusterConfig.isPersistIntermediateAssignment()) {
+      throw new HelixException("isInstanceStable needs persist assignment on!");
+    }
+
+    List<String> idealStateNames = dataAccessor.getChildNames(keyBuilder.idealStates());
+    for (String idealStateName : idealStateNames) {
+      IdealState idealState = dataAccessor.getProperty(keyBuilder.idealStates(idealStateName));
+      ExternalView externalView = dataAccessor.getProperty(keyBuilder.externalView(idealStateName));
+      for (String partition : idealState.getPartitionSet()) {
+        Map<String, String> isPartitionMap = idealState.getInstanceStateMap(partition);
+        Map<String, String> evPartitionMap = externalView.getStateMap(partition);
+        if (isPartitionMap.containsKey(instanceName) && (!evPartitionMap.containsKey(instanceName)
+            || !evPartitionMap.get(instanceName).equals(isPartitionMap.get(instanceName)))) {
+          // only checks the state from IS matches EV. Return false when
+          // 1. This partition not has current state on this instance
+          // 2. The state does not match the state on ideal state
+          return false;
+        }
+      }
+    }
+    return true;
+  }
 }