Repository: helix
Updated Branches:
  refs/heads/master 5f142f2ec -> 0147f9466


[HELIX-676] Fix the issue that the controller keep updating idealstates when 
there is no real diff.

The causes of the problem are that:

1.A previous issue introduced into IntermediateStateCalcStage prevents 
ERROR/OFFLINE state replicas from being added to the intermediateState, given 
the controller thinks recovery rebalance is not necessary.
This makes the processed stateMapping in pipeline always different from the 
cached IdeaStates. And then causes endless updating.

2.Another separate change in persistAssignmentStage is also related to this 
issue. When updating the map/list, we used putAll. This call will keep all 
existing items but only modify the intersect. Our assumption previously is 
allow customized items. However, when we investigate this issue, it would be 
error-prone to allow these customized items in the map/list fields. Helix won't 
be able to tell if one item is added by the controller or users. So we decide 
to use clear and set instead. This ensure the map/list fields are always 
uptodate.


Project: http://git-wip-us.apache.org/repos/asf/helix/repo
Commit: http://git-wip-us.apache.org/repos/asf/helix/commit/9083950d
Tree: http://git-wip-us.apache.org/repos/asf/helix/tree/9083950d
Diff: http://git-wip-us.apache.org/repos/asf/helix/diff/9083950d

Branch: refs/heads/master
Commit: 9083950d9a0e5f5c377672fb5b21af13cdde0d9a
Parents: 5f142f2
Author: Jiajun Wang <jjw...@linkedin.com>
Authored: Mon Feb 12 11:45:18 2018 -0800
Committer: jiajunwang <ericwang1...@gmail.com>
Committed: Thu Mar 8 17:24:28 2018 -0800

----------------------------------------------------------------------
 .../controller/stages/IntermediateStateCalcStage.java | 14 +++++++++++---
 .../controller/stages/PersistAssignmentStage.java     |  2 ++
 2 files changed, 13 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/9083950d/helix-core/src/main/java/org/apache/helix/controller/stages/IntermediateStateCalcStage.java
----------------------------------------------------------------------
diff --git 
a/helix-core/src/main/java/org/apache/helix/controller/stages/IntermediateStateCalcStage.java
 
b/helix-core/src/main/java/org/apache/helix/controller/stages/IntermediateStateCalcStage.java
index 047cc9b..785ed7b 100644
--- 
a/helix-core/src/main/java/org/apache/helix/controller/stages/IntermediateStateCalcStage.java
+++ 
b/helix-core/src/main/java/org/apache/helix/controller/stages/IntermediateStateCalcStage.java
@@ -220,6 +220,10 @@ public class IntermediateStateCalcStage extends 
AbstractBaseStage {
       RebalanceType rebalanceType =
           getRebalanceType(cache, bestPossibleMap, preferenceList, 
stateModelDef, currentStateMap,
               idealState);
+
+      // TODO refine getRebalanceType to return more accurate rebalance types.
+      // So following logic doesn't need to check for more details.
+      boolean rebalanceNeeded = false;
       if (rebalanceType.equals(RebalanceType.RECOVERY_BALANCE)) {
         // Check if any error exist
         if (currentStateMap.values().contains(HelixDefinedState.ERROR.name())) 
{
@@ -228,10 +232,14 @@ public class IntermediateStateCalcStage extends 
AbstractBaseStage {
         // Check if recovery is needed for this partition
         if (!currentStateMap.equals(bestPossibleMap)) {
           partitionsNeedRecovery.add(partition);
-        }
-      } else if (rebalanceType.equals(RebalanceType.LOAD_BALANCE)){
+          rebalanceNeeded = true;
+        } // else, if currentState == bestPossibleState, no rebalance needed
+      } else if (rebalanceType.equals(RebalanceType.LOAD_BALANCE)) {
         partitionsNeedLoadbalance.add(partition);
-      } else {
+        rebalanceNeeded = true;
+      }
+
+      if (!rebalanceNeeded) {
         // no rebalance needed.
         Map<String, String> intermediateMap = new HashMap<>(bestPossibleMap);
         intermediatePartitionStateMap.setState(partition, intermediateMap);

http://git-wip-us.apache.org/repos/asf/helix/blob/9083950d/helix-core/src/main/java/org/apache/helix/controller/stages/PersistAssignmentStage.java
----------------------------------------------------------------------
diff --git 
a/helix-core/src/main/java/org/apache/helix/controller/stages/PersistAssignmentStage.java
 
b/helix-core/src/main/java/org/apache/helix/controller/stages/PersistAssignmentStage.java
index 047ded3..7281430 100644
--- 
a/helix-core/src/main/java/org/apache/helix/controller/stages/PersistAssignmentStage.java
+++ 
b/helix-core/src/main/java/org/apache/helix/controller/stages/PersistAssignmentStage.java
@@ -119,7 +119,9 @@ public class PersistAssignmentStage extends 
AbstractBaseStage {
               if (current != null) {
                 // Overwrite MapFields and ListFields items with the same key.
                 // Note that default merge will keep old values in the maps or 
lists unchanged, which is not desired.
+                current.getMapFields().clear();
                 
current.getMapFields().putAll(idealState.getRecord().getMapFields());
+                current.getListFields().clear();
                 
current.getListFields().putAll(idealState.getRecord().getListFields());
               }
               return current;

Reply via email to