You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by zz...@apache.org on 2014/08/21 23:03:58 UTC

[1/2] git commit: [HELIX-329] HelixAutoController isn't a very clear name, consider renaming

Repository: helix
Updated Branches:
  refs/heads/master 363c049e3 -> 3365bac22


[HELIX-329] HelixAutoController isn't a very clear name, consider renaming


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

Branch: refs/heads/master
Commit: 0746d07872cf3fb07ec2995adff7980e11e2a8b3
Parents: 325fe8b
Author: zzhang <zz...@apache.org>
Authored: Mon Aug 18 11:03:42 2014 -0700
Committer: zzhang <zz...@apache.org>
Committed: Mon Aug 18 11:03:42 2014 -0700

----------------------------------------------------------------------
 .../webapp/TestHelixAdminScenariosRest.java     |  22 +--
 .../java/org/apache/helix/HelixConnection.java  |   4 +-
 .../java/org/apache/helix/HelixManager.java     |   2 +-
 .../helix/controller/HelixControllerMain.java   |   6 +-
 .../apache/helix/manager/zk/ZKHelixManager.java |  18 +-
 .../helix/manager/zk/ZkHelixConnection.java     |   2 +-
 .../DistClusterControllerStateModel.java        | 135 ---------------
 .../DistClusterControllerStateModelFactory.java |  39 -----
 .../MultiClusterControllerStateModel.java       | 135 +++++++++++++++
 ...MultiClusterControllerStateModelFactory.java |  39 +++++
 .../helix/integration/TestAddClusterV2.java     |  14 +-
 .../TestAddNodeAfterControllerStart.java        |   8 +-
 .../integration/TestDistributedCMMain.java      | 168 -------------------
 .../integration/TestMultiClusterController.java | 135 ++++++++++++++-
 .../TestReelectedPipelineCorrectness.java       |   2 +-
 .../manager/TestConsecutiveZkSessionExpiry.java |  44 ++---
 .../TestHelixMultiClusterController.java        |  38 ++---
 .../manager/zk/MockMultiClusterController.java  |   6 +-
 .../manager/zk/TestZkHelixAutoController.java   | 119 -------------
 .../zk/TestZkHelixMultiClusterController.java   | 119 +++++++++++++
 .../TestClusterStatusMonitorLifecycle.java      |   2 +-
 .../TestDistControllerStateModel.java           | 120 -------------
 .../TestDistControllerStateModelFactory.java    |  34 ----
 .../TestMultiClusterControllerStateModel.java   | 120 +++++++++++++
 ...MultiClusterControllerStateModelFactory.java |  35 ++++
 25 files changed, 665 insertions(+), 701 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-admin-webapp/src/test/java/org/apache/helix/webapp/TestHelixAdminScenariosRest.java
----------------------------------------------------------------------
diff --git a/helix-admin-webapp/src/test/java/org/apache/helix/webapp/TestHelixAdminScenariosRest.java b/helix-admin-webapp/src/test/java/org/apache/helix/webapp/TestHelixAdminScenariosRest.java
index 5aa26d2..bb8b983 100644
--- a/helix-admin-webapp/src/test/java/org/apache/helix/webapp/TestHelixAdminScenariosRest.java
+++ b/helix-admin-webapp/src/test/java/org/apache/helix/webapp/TestHelixAdminScenariosRest.java
@@ -332,7 +332,7 @@ public class TestHelixAdminScenariosRest extends AdminTestBase {
 
     Map<String, MockParticipant> participants =
         new HashMap<String, MockParticipant>();
-    Map<String, MockMultiClusterController> distControllers =
+    Map<String, MockMultiClusterController> multiClusterControllers =
         new HashMap<String, MockMultiClusterController>();
 
     // setup cluster
@@ -356,10 +356,10 @@ public class TestHelixAdminScenariosRest extends AdminTestBase {
     // start controller nodes
     for (int i = 0; i < 2; i++) {
       String controllerName = "controller_900" + i;
-      MockMultiClusterController distController =
+      MockMultiClusterController multiClusterController =
           new MockMultiClusterController(_zkaddr, controllerClusterName, controllerName);
-      distController.syncStart();
-      distControllers.put(controllerName, distController);
+      multiClusterController.syncStart();
+      multiClusterControllers.put(controllerName, multiClusterController);
     }
 
     String clusterUrl = getClusterUrl(clusterName);
@@ -398,7 +398,7 @@ public class TestHelixAdminScenariosRest extends AdminTestBase {
     Assert.assertFalse(_zkclient.exists("/" + clusterName));
 
     // clean up
-    for (MockMultiClusterController controller : distControllers.values()) {
+    for (MockMultiClusterController controller : multiClusterControllers.values()) {
       controller.syncStop();
     }
 
@@ -747,7 +747,7 @@ public class TestHelixAdminScenariosRest extends AdminTestBase {
 
     Map<String, MockParticipant> participants =
         new HashMap<String, MockParticipant>();
-    Map<String, MockMultiClusterController> distControllers =
+    Map<String, MockMultiClusterController> multiClusterControllers =
         new HashMap<String, MockMultiClusterController>();
 
     // setup cluster
@@ -771,10 +771,10 @@ public class TestHelixAdminScenariosRest extends AdminTestBase {
     // start controller nodes
     for (int i = 0; i < 2; i++) {
       String controllerName = "controller_900" + i;
-      MockMultiClusterController distController =
+      MockMultiClusterController multiClusterController =
           new MockMultiClusterController(_zkaddr, controllerClusterName, controllerName);
-      distController.syncStart();
-      distControllers.put(controllerName, distController);
+      multiClusterController.syncStart();
+      multiClusterControllers.put(controllerName, multiClusterController);
     }
     Thread.sleep(100);
 
@@ -794,7 +794,7 @@ public class TestHelixAdminScenariosRest extends AdminTestBase {
     deleteUrl(clusterUrl, true);
 
     // verify leader node
-    HelixDataAccessor accessor = distControllers.get("controller_9001").getHelixDataAccessor();
+    HelixDataAccessor accessor = multiClusterControllers.get("controller_9001").getHelixDataAccessor();
     LiveInstance controllerLeader = accessor.getProperty(accessor.keyBuilder().controllerLeader());
     Assert.assertTrue(controllerLeader.getInstanceName().startsWith("controller_900"));
 
@@ -821,7 +821,7 @@ public class TestHelixAdminScenariosRest extends AdminTestBase {
     Thread.sleep(1000);
 
     // clean up
-    for (MockMultiClusterController controller : distControllers.values()) {
+    for (MockMultiClusterController controller : multiClusterControllers.values()) {
       controller.syncStop();
     }
     for (MockParticipant participant : participants.values()) {

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/HelixConnection.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/HelixConnection.java b/helix-core/src/main/java/org/apache/helix/HelixConnection.java
index 4b7487b..5e13ee8 100644
--- a/helix-core/src/main/java/org/apache/helix/HelixConnection.java
+++ b/helix-core/src/main/java/org/apache/helix/HelixConnection.java
@@ -77,12 +77,12 @@ public interface HelixConnection {
   HelixController createController(ClusterId clusterId, ControllerId controllerId);
 
   /**
-   * create an autonomous helix-controller
+   * create a multi-cluster controller
    * @param clusterId
    * @param controllerId
    * @return
    */
-  HelixMultiClusterController createAutoController(ClusterId clusterId, ControllerId controllerId);
+  HelixMultiClusterController createMultiClusterController(ClusterId clusterId, ControllerId controllerId);
 
   /**
    * create a cluster-accessor

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/HelixManager.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/HelixManager.java b/helix-core/src/main/java/org/apache/helix/HelixManager.java
index 9e2bd14..4e2af9f 100644
--- a/helix-core/src/main/java/org/apache/helix/HelixManager.java
+++ b/helix-core/src/main/java/org/apache/helix/HelixManager.java
@@ -135,7 +135,7 @@ public interface HelixManager {
 
   /**
    * Add listener for controller change
-   * Used in distributed cluster controller
+   * Used in multi-cluster controller
    */
   void addControllerListener(ControllerChangeListener listener);
 

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java b/helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java
index ca540c5..2f5686c 100644
--- a/helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java
+++ b/helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java
@@ -49,7 +49,7 @@ import org.apache.helix.HelixManagerFactory;
 import org.apache.helix.InstanceType;
 import org.apache.helix.api.id.StateModelDefId;
 import org.apache.helix.manager.zk.HelixManagerShutdownHook;
-import org.apache.helix.participant.DistClusterControllerStateModelFactory;
+import org.apache.helix.participant.MultiClusterControllerStateModelFactory;
 import org.apache.helix.participant.StateMachineEngine;
 import org.apache.log4j.Logger;
 
@@ -162,8 +162,8 @@ public class HelixControllerMain {
             HelixManagerFactory.getZKHelixManager(clusterName, controllerName,
                 InstanceType.CONTROLLER_PARTICIPANT, zkConnectString);
 
-        DistClusterControllerStateModelFactory stateModelFactory =
-            new DistClusterControllerStateModelFactory(zkConnectString);
+        MultiClusterControllerStateModelFactory stateModelFactory =
+            new MultiClusterControllerStateModelFactory(zkConnectString);
 
         StateMachineEngine stateMach = manager.getStateMachineEngine();
         stateMach.registerStateModelFactory(StateModelDefId.LeaderStandby, stateModelFactory);

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java
index 12a3fe6..c3e044a 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixManager.java
@@ -105,7 +105,7 @@ public class ZKHelixManager implements HelixManager {
       break;
     }
     case CONTROLLER_PARTICIPANT: {
-      _role = conn.createAutoController(clusterId, ControllerId.from(instanceName));
+      _role = conn.createMultiClusterController(clusterId, ControllerId.from(instanceName));
       break;
     }
     case ADMINISTRATOR: {
@@ -277,8 +277,8 @@ public class ZKHelixManager implements HelixManager {
       break;
     }
     case CONTROLLER_PARTICIPANT: {
-      HelixMultiClusterController autoController = (HelixMultiClusterController) _role;
-      engine = autoController.getStateMachineEngine();
+      HelixMultiClusterController multiClusterController = (HelixMultiClusterController) _role;
+      engine = multiClusterController.getStateMachineEngine();
       break;
     }
     default:
@@ -298,8 +298,8 @@ public class ZKHelixManager implements HelixManager {
       break;
     }
     case CONTROLLER_PARTICIPANT: {
-      HelixMultiClusterController autoController = (HelixMultiClusterController) _role;
-      isLeader = autoController.isLeader();
+      HelixMultiClusterController multiClusterController = (HelixMultiClusterController) _role;
+      isLeader = multiClusterController.isLeader();
       break;
     }
     default:
@@ -341,8 +341,8 @@ public class ZKHelixManager implements HelixManager {
       break;
     }
     case CONTROLLER_PARTICIPANT: {
-      HelixMultiClusterController autoController = (HelixMultiClusterController) _role;
-      autoController.addPreConnectCallback(callback);
+      HelixMultiClusterController multiClusterController = (HelixMultiClusterController) _role;
+      multiClusterController.addPreConnectCallback(callback);
       break;
     }
     default:
@@ -360,8 +360,8 @@ public class ZKHelixManager implements HelixManager {
       break;
     }
     case CONTROLLER_PARTICIPANT: {
-      HelixMultiClusterController autoController = (HelixMultiClusterController) _role;
-      autoController.setLiveInstanceInfoProvider(liveInstanceInfoProvider);
+      HelixMultiClusterController multiClusterController = (HelixMultiClusterController) _role;
+      multiClusterController.setLiveInstanceInfoProvider(liveInstanceInfoProvider);
       break;
     }
     default:

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java b/helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java
index 0a9dc94..32191ec 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java
@@ -210,7 +210,7 @@ public class ZkHelixConnection implements HelixConnection, IZkStateListener {
   }
 
   @Override
-  public HelixMultiClusterController createAutoController(ClusterId clusterId, ControllerId controllerId) {
+  public HelixMultiClusterController createMultiClusterController(ClusterId clusterId, ControllerId controllerId) {
     return new ZkHelixMultiClusterController(this, clusterId, controllerId);
   }
 

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/participant/DistClusterControllerStateModel.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/participant/DistClusterControllerStateModel.java b/helix-core/src/main/java/org/apache/helix/participant/DistClusterControllerStateModel.java
deleted file mode 100644
index 4579810..0000000
--- a/helix-core/src/main/java/org/apache/helix/participant/DistClusterControllerStateModel.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.apache.helix.participant;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.helix.HelixManager;
-import org.apache.helix.HelixManagerFactory;
-import org.apache.helix.InstanceType;
-import org.apache.helix.NotificationContext;
-import org.apache.helix.api.TransitionHandler;
-import org.apache.helix.model.Message;
-import org.apache.helix.participant.statemachine.StateModelInfo;
-import org.apache.helix.participant.statemachine.StateModelParser;
-import org.apache.helix.participant.statemachine.StateTransitionError;
-import org.apache.helix.participant.statemachine.Transition;
-import org.apache.log4j.Logger;
-
-@StateModelInfo(initialState = "OFFLINE", states = {
-    "LEADER", "STANDBY"
-})
-public class DistClusterControllerStateModel extends TransitionHandler {
-  private static Logger logger = Logger.getLogger(DistClusterControllerStateModel.class);
-  private HelixManager _controller = null;
-  private final String _zkAddr;
-
-  public DistClusterControllerStateModel(String zkAddr) {
-    StateModelParser parser = new StateModelParser();
-    _currentState = parser.getInitialState(DistClusterControllerStateModel.class);
-    _zkAddr = zkAddr;
-  }
-
-  @Transition(to = "STANDBY", from = "OFFLINE")
-  public void onBecomeStandbyFromOffline(Message message, NotificationContext context) {
-    logger.info("Becoming standby from offline");
-  }
-
-  @Transition(to = "LEADER", from = "STANDBY")
-  public void onBecomeLeaderFromStandby(Message message, NotificationContext context)
-      throws Exception {
-    String clusterName = message.getPartitionId().stringify();
-    String controllerName = message.getTgtName();
-
-    logger.info(controllerName + " becomes leader from standby for " + clusterName);
-    // System.out.println(controllerName + " becomes leader from standby for " + clusterName);
-
-    if (_controller == null) {
-      _controller =
-          HelixManagerFactory.getZKHelixManager(clusterName, controllerName,
-              InstanceType.CONTROLLER, _zkAddr);
-      _controller.connect();
-      _controller.startTimerTasks();
-    } else {
-      logger.error("controller already exists:" + _controller.getInstanceName() + " for "
-          + clusterName);
-    }
-
-  }
-
-  @Transition(to = "STANDBY", from = "LEADER")
-  public void onBecomeStandbyFromLeader(Message message, NotificationContext context) {
-    String clusterName = message.getPartitionId().stringify();
-    String controllerName = message.getTgtName();
-
-    logger.info(controllerName + " becoming standby from leader for " + clusterName);
-
-    if (_controller != null) {
-      _controller.disconnect();
-      _controller = null;
-    } else {
-      logger.error("No controller exists for " + clusterName);
-    }
-  }
-
-  @Transition(to = "OFFLINE", from = "STANDBY")
-  public void onBecomeOfflineFromStandby(Message message, NotificationContext context) {
-    String clusterName = message.getPartitionId().stringify();
-    String controllerName = message.getTgtName();
-
-    logger.info(controllerName + " becoming offline from standby for cluster:" + clusterName);
-
-  }
-
-  @Transition(to = "DROPPED", from = "OFFLINE")
-  public void onBecomeDroppedFromOffline(Message message, NotificationContext context) {
-    logger.info("Becoming dropped from offline");
-  }
-
-  @Transition(to = "OFFLINE", from = "DROPPED")
-  public void onBecomeOfflineFromDropped(Message message, NotificationContext context) {
-    logger.info("Becoming offline from dropped");
-  }
-
-  @Override
-  public void rollbackOnError(Message message, NotificationContext context,
-      StateTransitionError error) {
-    String clusterName = message.getPartitionId().stringify();
-    String controllerName = message.getTgtName();
-
-    logger.error(controllerName + " rollbacks on error for " + clusterName);
-
-    if (_controller != null) {
-      _controller.disconnect();
-      _controller = null;
-    }
-
-  }
-
-  @Override
-  public void reset() {
-    if (_controller != null) {
-      // System.out.println("disconnect " + _controller.getInstanceName()
-      // + "(" + _controller.getInstanceType()
-      // + ") from " + _controller.getClusterName());
-      _controller.disconnect();
-      _controller = null;
-    }
-
-  }
-}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/participant/DistClusterControllerStateModelFactory.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/participant/DistClusterControllerStateModelFactory.java b/helix-core/src/main/java/org/apache/helix/participant/DistClusterControllerStateModelFactory.java
deleted file mode 100644
index 5f21e90..0000000
--- a/helix-core/src/main/java/org/apache/helix/participant/DistClusterControllerStateModelFactory.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.apache.helix.participant;
-
-import org.apache.helix.api.StateTransitionHandlerFactory;
-import org.apache.helix.api.id.PartitionId;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-public class DistClusterControllerStateModelFactory extends
-    StateTransitionHandlerFactory<DistClusterControllerStateModel> {
-  private final String _zkAddr;
-
-  public DistClusterControllerStateModelFactory(String zkAddr) {
-    _zkAddr = zkAddr;
-  }
-
-  @Override
-  public DistClusterControllerStateModel createStateTransitionHandler(PartitionId partition) {
-    return new DistClusterControllerStateModel(_zkAddr);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerStateModel.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerStateModel.java b/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerStateModel.java
new file mode 100644
index 0000000..c482c0f
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerStateModel.java
@@ -0,0 +1,135 @@
+package org.apache.helix.participant;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.helix.HelixManager;
+import org.apache.helix.HelixManagerFactory;
+import org.apache.helix.InstanceType;
+import org.apache.helix.NotificationContext;
+import org.apache.helix.api.TransitionHandler;
+import org.apache.helix.model.Message;
+import org.apache.helix.participant.statemachine.StateModelInfo;
+import org.apache.helix.participant.statemachine.StateModelParser;
+import org.apache.helix.participant.statemachine.StateTransitionError;
+import org.apache.helix.participant.statemachine.Transition;
+import org.apache.log4j.Logger;
+
+@StateModelInfo(initialState = "OFFLINE", states = {
+    "LEADER", "STANDBY"
+})
+public class MultiClusterControllerStateModel extends TransitionHandler {
+  private static Logger logger = Logger.getLogger(MultiClusterControllerStateModel.class);
+  private HelixManager _controller = null;
+  private final String _zkAddr;
+
+  public MultiClusterControllerStateModel(String zkAddr) {
+    StateModelParser parser = new StateModelParser();
+    _currentState = parser.getInitialState(MultiClusterControllerStateModel.class);
+    _zkAddr = zkAddr;
+  }
+
+  @Transition(to = "STANDBY", from = "OFFLINE")
+  public void onBecomeStandbyFromOffline(Message message, NotificationContext context) {
+    logger.info("Becoming standby from offline");
+  }
+
+  @Transition(to = "LEADER", from = "STANDBY")
+  public void onBecomeLeaderFromStandby(Message message, NotificationContext context)
+      throws Exception {
+    String clusterName = message.getPartitionId().stringify();
+    String controllerName = message.getTgtName();
+
+    logger.info(controllerName + " becomes leader from standby for " + clusterName);
+    // System.out.println(controllerName + " becomes leader from standby for " + clusterName);
+
+    if (_controller == null) {
+      _controller =
+          HelixManagerFactory.getZKHelixManager(clusterName, controllerName,
+              InstanceType.CONTROLLER, _zkAddr);
+      _controller.connect();
+      _controller.startTimerTasks();
+    } else {
+      logger.error("controller already exists:" + _controller.getInstanceName() + " for "
+          + clusterName);
+    }
+
+  }
+
+  @Transition(to = "STANDBY", from = "LEADER")
+  public void onBecomeStandbyFromLeader(Message message, NotificationContext context) {
+    String clusterName = message.getPartitionId().stringify();
+    String controllerName = message.getTgtName();
+
+    logger.info(controllerName + " becoming standby from leader for " + clusterName);
+
+    if (_controller != null) {
+      _controller.disconnect();
+      _controller = null;
+    } else {
+      logger.error("No controller exists for " + clusterName);
+    }
+  }
+
+  @Transition(to = "OFFLINE", from = "STANDBY")
+  public void onBecomeOfflineFromStandby(Message message, NotificationContext context) {
+    String clusterName = message.getPartitionId().stringify();
+    String controllerName = message.getTgtName();
+
+    logger.info(controllerName + " becoming offline from standby for cluster:" + clusterName);
+
+  }
+
+  @Transition(to = "DROPPED", from = "OFFLINE")
+  public void onBecomeDroppedFromOffline(Message message, NotificationContext context) {
+    logger.info("Becoming dropped from offline");
+  }
+
+  @Transition(to = "OFFLINE", from = "DROPPED")
+  public void onBecomeOfflineFromDropped(Message message, NotificationContext context) {
+    logger.info("Becoming offline from dropped");
+  }
+
+  @Override
+  public void rollbackOnError(Message message, NotificationContext context,
+      StateTransitionError error) {
+    String clusterName = message.getPartitionId().stringify();
+    String controllerName = message.getTgtName();
+
+    logger.error(controllerName + " rollbacks on error for " + clusterName);
+
+    if (_controller != null) {
+      _controller.disconnect();
+      _controller = null;
+    }
+
+  }
+
+  @Override
+  public void reset() {
+    if (_controller != null) {
+      // System.out.println("disconnect " + _controller.getInstanceName()
+      // + "(" + _controller.getInstanceType()
+      // + ") from " + _controller.getClusterName());
+      _controller.disconnect();
+      _controller = null;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerStateModelFactory.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerStateModelFactory.java b/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerStateModelFactory.java
new file mode 100644
index 0000000..5dc39e7
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerStateModelFactory.java
@@ -0,0 +1,39 @@
+package org.apache.helix.participant;
+
+import org.apache.helix.api.StateTransitionHandlerFactory;
+import org.apache.helix.api.id.PartitionId;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+public class MultiClusterControllerStateModelFactory extends
+    StateTransitionHandlerFactory<MultiClusterControllerStateModel> {
+  private final String _zkAddr;
+
+  public MultiClusterControllerStateModelFactory(String zkAddr) {
+    _zkAddr = zkAddr;
+  }
+
+  @Override
+  public MultiClusterControllerStateModel createStateTransitionHandler(PartitionId partition) {
+    return new MultiClusterControllerStateModel(_zkAddr);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/integration/TestAddClusterV2.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/TestAddClusterV2.java b/helix-core/src/test/java/org/apache/helix/integration/TestAddClusterV2.java
index 5d7df59..c64d43e 100644
--- a/helix-core/src/test/java/org/apache/helix/integration/TestAddClusterV2.java
+++ b/helix-core/src/test/java/org/apache/helix/integration/TestAddClusterV2.java
@@ -50,7 +50,7 @@ public class TestAddClusterV2 extends ZkTestBase {
   protected static final String TEST_DB = "TestDB";
 
   MockParticipant[] _participants = new MockParticipant[NODE_NR];
-  MockMultiClusterController[] _distControllers = new MockMultiClusterController[NODE_NR];
+  MockMultiClusterController[] _multiClusterControllers = new MockMultiClusterController[NODE_NR];
 
   @BeforeClass
   public void beforeClass() throws Exception {
@@ -94,12 +94,12 @@ public class TestAddClusterV2 extends ZkTestBase {
       _participants[i].syncStart();
     }
 
-    // start distributed cluster controllers
+    // start multi-cluster controllers
     for (int i = 0; i < NODE_NR; i++) {
       String controllerName = "controller_" + i;
-      _distControllers[i] =
+      _multiClusterControllers[i] =
           new MockMultiClusterController(_zkaddr, CONTROLLER_CLUSTER, controllerName);
-      _distControllers[i].syncStart();
+      _multiClusterControllers[i].syncStart();
     }
 
     verifyClusters();
@@ -135,8 +135,8 @@ public class TestAddClusterV2 extends ZkTestBase {
     String leader = getCurrentLeader(CONTROLLER_CLUSTER);
     int leaderIdx = -1;
     for (int i = 0; i < NODE_NR; i++) {
-      if (!_distControllers[i].getInstanceName().equals(leader)) {
-        _distControllers[i].syncStop();
+      if (!_multiClusterControllers[i].getInstanceName().equals(leader)) {
+        _multiClusterControllers[i].syncStop();
         verifyClusters();
       } else {
         leaderIdx = i;
@@ -144,7 +144,7 @@ public class TestAddClusterV2 extends ZkTestBase {
     }
     Assert.assertNotSame(leaderIdx, -1);
 
-    _distControllers[leaderIdx].syncStop();
+    _multiClusterControllers[leaderIdx].syncStop();
 
     for (int i = 0; i < NODE_NR; i++) {
       _participants[i].syncStop();

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/integration/TestAddNodeAfterControllerStart.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/TestAddNodeAfterControllerStart.java b/helix-core/src/test/java/org/apache/helix/integration/TestAddNodeAfterControllerStart.java
index 97acc1c..a7b405e 100644
--- a/helix-core/src/test/java/org/apache/helix/integration/TestAddNodeAfterControllerStart.java
+++ b/helix-core/src/test/java/org/apache/helix/integration/TestAddNodeAfterControllerStart.java
@@ -96,7 +96,7 @@ public class TestAddNodeAfterControllerStart extends ZkTestBase {
   }
 
   @Test
-  public void testDistributed() throws Exception {
+  public void testMultiCluster() throws Exception {
     String testName = TestUtil.getTestName();
     String clusterName = testName;
     System.out.println("START " + clusterName + " at " + new Date(System.currentTimeMillis()));
@@ -106,9 +106,9 @@ public class TestAddNodeAfterControllerStart extends ZkTestBase {
     TestHelper.setupCluster(grandClusterName, _zkaddr, 0, "controller", null, 0, 0, 1, 0, null,
         true);
 
-    MockMultiClusterController distController =
+    MockMultiClusterController multiClusterController =
         new MockMultiClusterController(_zkaddr, grandClusterName, "controller_0");
-    distController.syncStart();
+    multiClusterController.syncStart();
 
     // setup cluster
     _setupTool.addCluster(clusterName, true);
@@ -165,7 +165,7 @@ public class TestAddNodeAfterControllerStart extends ZkTestBase {
     Assert.assertEquals(numberOfListeners, 2); // 1 of participant, and 1 of controller
 
     // clean up
-    distController.syncStop();
+    multiClusterController.syncStop();
     for (int i = 0; i < nodeNr; i++) {
       participants[i].syncStop();
     }

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/integration/TestDistributedCMMain.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/TestDistributedCMMain.java b/helix-core/src/test/java/org/apache/helix/integration/TestDistributedCMMain.java
deleted file mode 100644
index cf32d73..0000000
--- a/helix-core/src/test/java/org/apache/helix/integration/TestDistributedCMMain.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package org.apache.helix.integration;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import java.util.Date;
-
-import org.apache.helix.PropertyKey.Builder;
-import org.apache.helix.TestHelper;
-import org.apache.helix.manager.zk.MockParticipant;
-import org.apache.helix.manager.zk.MockMultiClusterController;
-import org.apache.helix.manager.zk.ZKHelixDataAccessor;
-import org.apache.helix.model.LiveInstance;
-import org.apache.helix.testutil.ZkTestBase;
-import org.apache.helix.tools.ClusterStateVerifier;
-import org.apache.helix.tools.ClusterStateVerifier.BestPossAndExtViewZkVerifier;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-public class TestDistributedCMMain extends ZkTestBase {
-
-  @Test
-  public void testDistributedCMMain() throws Exception {
-    String className = TestHelper.getTestClassName();
-    String methodName = TestHelper.getTestMethodName();
-    String clusterNamePrefix = className + "_" + methodName;
-    final int n = 5;
-    final int clusterNb = 10;
-
-    System.out
-        .println("START " + clusterNamePrefix + " at " + new Date(System.currentTimeMillis()));
-
-    // setup 10 clusters
-    for (int i = 0; i < clusterNb; i++) {
-      String clusterName = clusterNamePrefix + "0_" + i;
-      String participantName = "localhost" + i;
-      String resourceName = "TestDB" + i;
-      TestHelper.setupCluster(clusterName, _zkaddr, 12918, // participant port
-          participantName, // participant name prefix
-          resourceName, // resource name prefix
-          1, // resources
-          8, // partitions per resource
-          n, // number of nodes
-          3, // replicas
-          "MasterSlave", true); // do rebalance
-    }
-
-    // setup controller cluster
-    final String controllerClusterName = "CONTROLLER_" + clusterNamePrefix;
-    TestHelper.setupCluster("CONTROLLER_" + clusterNamePrefix, _zkaddr, 0, // controller
-                                                                           // port
-        "controller", // participant name prefix
-        clusterNamePrefix, // resource name prefix
-        1, // resources
-        clusterNb, // partitions per resource
-        n, // number of nodes
-        3, // replicas
-        "LeaderStandby", true); // do rebalance
-
-    // start distributed cluster controllers
-    MockMultiClusterController[] controllers = new MockMultiClusterController[n + n];
-    for (int i = 0; i < n; i++) {
-      controllers[i] =
-          new MockMultiClusterController(_zkaddr, controllerClusterName, "controller_" + i);
-      controllers[i].syncStart();
-    }
-
-    boolean result =
-        ClusterStateVerifier.verifyByZkCallback(
-            new ClusterStateVerifier.BestPossAndExtViewZkVerifier(_zkaddr, controllerClusterName),
-            30000);
-    Assert.assertTrue(result, "Controller cluster NOT in ideal state");
-
-    // start first cluster
-    MockParticipant[] participants = new MockParticipant[n];
-    final String firstClusterName = clusterNamePrefix + "0_0";
-    for (int i = 0; i < n; i++) {
-      String instanceName = "localhost0_" + (12918 + i);
-      participants[i] = new MockParticipant(_zkaddr, firstClusterName, instanceName);
-      participants[i].syncStart();
-    }
-
-    result =
-        ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(_zkaddr,
-            firstClusterName));
-    Assert.assertTrue(result, "first cluster NOT in ideal state");
-
-    // add more controllers to controller cluster
-    for (int i = 0; i < n; i++) {
-      String controller = "controller_" + (n + i);
-      _setupTool.addInstanceToCluster(controllerClusterName, controller);
-    }
-    _setupTool.rebalanceStorageCluster(controllerClusterName, clusterNamePrefix + "0", 6);
-    for (int i = n; i < 2 * n; i++) {
-      controllers[i] =
-          new MockMultiClusterController(_zkaddr, controllerClusterName, "controller_" + i);
-      controllers[i].syncStart();
-    }
-
-    // verify controller cluster
-    result =
-        ClusterStateVerifier
-            .verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(_zkaddr,
-                controllerClusterName));
-    Assert.assertTrue(result, "Controller cluster NOT in ideal state");
-
-    // verify first cluster
-    result =
-        ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(_zkaddr,
-            firstClusterName));
-    Assert.assertTrue(result, "first cluster NOT in ideal state");
-
-    // stop controller_0-5
-    ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(controllerClusterName, _baseAccessor);
-    Builder keyBuilder = accessor.keyBuilder();
-    for (int i = 0; i < n; i++) {
-      LiveInstance leader = accessor.getProperty(keyBuilder.controllerLeader());
-      String leaderName = leader.getId();
-      int j = Integer.parseInt(leaderName.substring(leaderName.lastIndexOf('_') + 1));
-      controllers[j].syncStop();
-
-      result =
-          ClusterStateVerifier
-              .verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(_zkaddr,
-                  controllerClusterName));
-      Assert.assertTrue(result, "Controller cluster NOT in ideal state");
-
-      result =
-          ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(_zkaddr,
-              firstClusterName));
-      Assert.assertTrue(result, "first cluster NOT in ideal state");
-    }
-
-    // clean up
-    // wait for all zk callbacks done
-    System.out.println("Cleaning up...");
-    for (int i = 0; i < 5; i++) {
-      result =
-          ClusterStateVerifier
-              .verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(_zkaddr,
-                  controllerClusterName));
-      controllers[i].syncStop();
-    }
-
-    for (int i = 0; i < 5; i++) {
-      participants[i].syncStop();
-    }
-
-    System.out.println("END " + clusterNamePrefix + " at " + new Date(System.currentTimeMillis()));
-
-  }
-}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/integration/TestMultiClusterController.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/TestMultiClusterController.java b/helix-core/src/test/java/org/apache/helix/integration/TestMultiClusterController.java
index 8945843..d197a15 100644
--- a/helix-core/src/test/java/org/apache/helix/integration/TestMultiClusterController.java
+++ b/helix-core/src/test/java/org/apache/helix/integration/TestMultiClusterController.java
@@ -36,7 +36,7 @@ import org.testng.annotations.Test;
 public class TestMultiClusterController extends ZkTestBase {
 
   @Test
-  public void test() throws Exception {
+  public void testBasic() throws Exception {
     String className = TestHelper.getTestClassName();
     String methodName = TestHelper.getTestMethodName();
     String clusterNamePrefix = className + "_" + methodName;
@@ -73,7 +73,7 @@ public class TestMultiClusterController extends ZkTestBase {
         3, // replicas
         "LeaderStandby", true); // do rebalance
 
-    // start distributed cluster controllers
+    // start multi-cluster controllers
     MockMultiClusterController[] controllers = new MockMultiClusterController[n];
     for (int i = 0; i < n; i++) {
       controllers[i] =
@@ -141,4 +141,135 @@ public class TestMultiClusterController extends ZkTestBase {
     System.out.println("END " + clusterNamePrefix + " at " + new Date(System.currentTimeMillis()));
 
   }
+
+  @Test
+  public void testAddAndStop() throws Exception {
+    String className = TestHelper.getTestClassName();
+    String methodName = TestHelper.getTestMethodName();
+    String clusterNamePrefix = className + "_" + methodName;
+    final int n = 5;
+    final int clusterNb = 10;
+
+    System.out
+        .println("START " + clusterNamePrefix + " at " + new Date(System.currentTimeMillis()));
+
+    // setup 10 clusters
+    for (int i = 0; i < clusterNb; i++) {
+      String clusterName = clusterNamePrefix + "0_" + i;
+      String participantName = "localhost" + i;
+      String resourceName = "TestDB" + i;
+      TestHelper.setupCluster(clusterName, _zkaddr, 12918, // participant port
+          participantName, // participant name prefix
+          resourceName, // resource name prefix
+          1, // resources
+          8, // partitions per resource
+          n, // number of nodes
+          3, // replicas
+          "MasterSlave", true); // do rebalance
+    }
+
+    // setup controller cluster
+    final String controllerClusterName = "CONTROLLER_" + clusterNamePrefix;
+    TestHelper.setupCluster("CONTROLLER_" + clusterNamePrefix, _zkaddr, 0, // controller
+                                                                           // port
+        "controller", // participant name prefix
+        clusterNamePrefix, // resource name prefix
+        1, // resources
+        clusterNb, // partitions per resource
+        n, // number of nodes
+        3, // replicas
+        "LeaderStandby", true); // do rebalance
+
+    // start multi-cluster cluster controllers
+    MockMultiClusterController[] controllers = new MockMultiClusterController[n + n];
+    for (int i = 0; i < n; i++) {
+      controllers[i] =
+          new MockMultiClusterController(_zkaddr, controllerClusterName, "controller_" + i);
+      controllers[i].syncStart();
+    }
+
+    boolean result =
+        ClusterStateVerifier.verifyByZkCallback(
+            new ClusterStateVerifier.BestPossAndExtViewZkVerifier(_zkaddr, controllerClusterName),
+            30000);
+    Assert.assertTrue(result, "Controller cluster NOT in ideal state");
+
+    // start first cluster
+    MockParticipant[] participants = new MockParticipant[n];
+    final String firstClusterName = clusterNamePrefix + "0_0";
+    for (int i = 0; i < n; i++) {
+      String instanceName = "localhost0_" + (12918 + i);
+      participants[i] = new MockParticipant(_zkaddr, firstClusterName, instanceName);
+      participants[i].syncStart();
+    }
+
+    result =
+        ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(_zkaddr,
+            firstClusterName));
+    Assert.assertTrue(result, "first cluster NOT in ideal state");
+
+    // add more controllers to controller cluster
+    for (int i = 0; i < n; i++) {
+      String controller = "controller_" + (n + i);
+      _setupTool.addInstanceToCluster(controllerClusterName, controller);
+    }
+    _setupTool.rebalanceStorageCluster(controllerClusterName, clusterNamePrefix + "0", 6);
+    for (int i = n; i < 2 * n; i++) {
+      controllers[i] =
+          new MockMultiClusterController(_zkaddr, controllerClusterName, "controller_" + i);
+      controllers[i].syncStart();
+    }
+
+    // verify controller cluster
+    result =
+        ClusterStateVerifier
+            .verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(_zkaddr,
+                controllerClusterName));
+    Assert.assertTrue(result, "Controller cluster NOT in ideal state");
+
+    // verify first cluster
+    result =
+        ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(_zkaddr,
+            firstClusterName));
+    Assert.assertTrue(result, "first cluster NOT in ideal state");
+
+    // stop controller_0-5
+    ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(controllerClusterName, _baseAccessor);
+    Builder keyBuilder = accessor.keyBuilder();
+    for (int i = 0; i < n; i++) {
+      LiveInstance leader = accessor.getProperty(keyBuilder.controllerLeader());
+      String leaderName = leader.getId();
+      int j = Integer.parseInt(leaderName.substring(leaderName.lastIndexOf('_') + 1));
+      controllers[j].syncStop();
+
+      result =
+          ClusterStateVerifier
+              .verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(_zkaddr,
+                  controllerClusterName));
+      Assert.assertTrue(result, "Controller cluster NOT in ideal state");
+
+      result =
+          ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(_zkaddr,
+              firstClusterName));
+      Assert.assertTrue(result, "first cluster NOT in ideal state");
+    }
+
+    // clean up
+    // wait for all zk callbacks done
+    System.out.println("Cleaning up...");
+    for (int i = 0; i < 5; i++) {
+      result =
+          ClusterStateVerifier
+              .verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(_zkaddr,
+                  controllerClusterName));
+      controllers[i].syncStop();
+    }
+
+    for (int i = 0; i < 5; i++) {
+      participants[i].syncStop();
+    }
+
+    System.out.println("END " + clusterNamePrefix + " at " + new Date(System.currentTimeMillis()));
+
+  }
 }

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/integration/TestReelectedPipelineCorrectness.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/TestReelectedPipelineCorrectness.java b/helix-core/src/test/java/org/apache/helix/integration/TestReelectedPipelineCorrectness.java
index e522008..ba01ae7 100644
--- a/helix-core/src/test/java/org/apache/helix/integration/TestReelectedPipelineCorrectness.java
+++ b/helix-core/src/test/java/org/apache/helix/integration/TestReelectedPipelineCorrectness.java
@@ -66,7 +66,7 @@ public class TestReelectedPipelineCorrectness extends ZkTestBase {
         NUM_REPLICAS, // replicas
         "MasterSlave", RebalanceMode.FULL_AUTO, true); // do rebalance
 
-    // configure distributed controllers
+    // configure multi-cluster controllers
     String controllerCluster = clusterName + "_controllers";
     _setupTool.addCluster(controllerCluster, true);
     for (int i = 0; i < NUM_CONTROLLERS; i++) {

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/integration/manager/TestConsecutiveZkSessionExpiry.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/manager/TestConsecutiveZkSessionExpiry.java b/helix-core/src/test/java/org/apache/helix/integration/manager/TestConsecutiveZkSessionExpiry.java
index 1b55af5..4052052 100644
--- a/helix-core/src/test/java/org/apache/helix/integration/manager/TestConsecutiveZkSessionExpiry.java
+++ b/helix-core/src/test/java/org/apache/helix/integration/manager/TestConsecutiveZkSessionExpiry.java
@@ -162,7 +162,7 @@ public class TestConsecutiveZkSessionExpiry extends ZkTestBase {
   }
 
   @Test
-  public void testDistributedController() throws Exception {
+  public void testMultiClusterController() throws Exception {
     // Logger.getRootLogger().setLevel(Level.INFO);
     String className = TestHelper.getTestClassName();
     String methodName = TestHelper.getTestMethodName();
@@ -180,20 +180,20 @@ public class TestConsecutiveZkSessionExpiry extends ZkTestBase {
         2, // replicas
         "MasterSlave", true); // do rebalance
 
-    MockMultiClusterController[] distributedControllers = new MockMultiClusterController[n];
+    MockMultiClusterController[] multiClusterControllers = new MockMultiClusterController[n];
     CountDownLatch startCountdown = new CountDownLatch(1);
     CountDownLatch endCountdown = new CountDownLatch(1);
 
     for (int i = 0; i < n; i++) {
       String contrllerName = "localhost_" + (12918 + i);
-      distributedControllers[i] = new MockMultiClusterController(_zkaddr, clusterName, contrllerName);
-      distributedControllers[i].getStateMachineEngine().registerStateModelFactory(StateModelDefId.MasterSlave,
+      multiClusterControllers[i] = new MockMultiClusterController(_zkaddr, clusterName, contrllerName);
+      multiClusterControllers[i].getStateMachineEngine().registerStateModelFactory(StateModelDefId.MasterSlave,
           new MockMSModelFactory());
       if (i == 0) {
-        distributedControllers[i].addPreConnectCallback(new PreConnectTestCallback(contrllerName,
+        multiClusterControllers[i].addPreConnectCallback(new PreConnectTestCallback(contrllerName,
             startCountdown, endCountdown));
       }
-      distributedControllers[i].connect();
+      multiClusterControllers[i].connect();
     }
 
     boolean result =
@@ -201,23 +201,23 @@ public class TestConsecutiveZkSessionExpiry extends ZkTestBase {
             clusterName));
     Assert.assertTrue(result);
 
-    // expire the session of distributedController
-    LOG.info("1st Expiring distributedController session...");
-    String oldSessionId = distributedControllers[0].getSessionId();
+    // expire the session of multiClusterController
+    LOG.info("1st Expiring multiClusterController session...");
+    String oldSessionId = multiClusterControllers[0].getSessionId();
 
-    ZkTestHelper.asyncExpireSession(distributedControllers[0].getZkClient());
-    String newSessionId = distributedControllers[0].getSessionId();
-    LOG.info("Expried distributedController session. oldSessionId: " + oldSessionId
+    ZkTestHelper.asyncExpireSession(multiClusterControllers[0].getZkClient());
+    String newSessionId = multiClusterControllers[0].getSessionId();
+    LOG.info("Expried multiClusterController session. oldSessionId: " + oldSessionId
         + ", newSessionId: " + newSessionId);
 
     // expire zk session again during HelixManager#handleNewSession()
     startCountdown.await();
-    LOG.info("2nd Expiring distributedController session...");
-    oldSessionId = distributedControllers[0].getSessionId();
+    LOG.info("2nd Expiring multiClusterController session...");
+    oldSessionId = multiClusterControllers[0].getSessionId();
 
-    ZkTestHelper.asyncExpireSession(distributedControllers[0].getZkClient());
-    newSessionId = distributedControllers[0].getSessionId();
-    LOG.info("Expried distributedController session. oldSessionId: " + oldSessionId
+    ZkTestHelper.asyncExpireSession(multiClusterControllers[0].getZkClient());
+    newSessionId = multiClusterControllers[0].getSessionId();
+    LOG.info("Expried multiClusterController session. oldSessionId: " + oldSessionId
         + ", newSessionId: " + newSessionId);
 
     endCountdown.countDown();
@@ -239,18 +239,18 @@ public class TestConsecutiveZkSessionExpiry extends ZkTestBase {
     Assert.assertEquals(leader.getId(), "localhost_12919");
 
     // check localhost_12918 has 2 handlers: message and leader-election
-    TestHelper.printHandlers(distributedControllers[0], distributedControllers[0].getHandlers());
-    List<ZkCallbackHandler> handlers = distributedControllers[0].getHandlers();
+    TestHelper.printHandlers(multiClusterControllers[0], multiClusterControllers[0].getHandlers());
+    List<ZkCallbackHandler> handlers = multiClusterControllers[0].getHandlers();
     Assert
         .assertEquals(
             handlers.size(),
             2,
-            "Distributed controller should have 2 handler (message and leader election) after lose leadership, but was "
+            "MultiCluster controller should have 2 handler (message and leader election) after lose leadership, but was "
                 + handlers.size());
 
     // clean up
-    distributedControllers[0].disconnect();
-    distributedControllers[1].disconnect();
+    multiClusterControllers[0].disconnect();
+    multiClusterControllers[1].disconnect();
     Assert.assertNull(HelixTestUtil.pollForProperty(LiveInstance.class, accessor,
         keyBuilder.liveInstance("localhost_12918"), false));
     Assert.assertNull(HelixTestUtil.pollForProperty(LiveInstance.class, accessor,

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/integration/manager/TestHelixMultiClusterController.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/integration/manager/TestHelixMultiClusterController.java b/helix-core/src/test/java/org/apache/helix/integration/manager/TestHelixMultiClusterController.java
index 51e7e19..9b41caf 100644
--- a/helix-core/src/test/java/org/apache/helix/integration/manager/TestHelixMultiClusterController.java
+++ b/helix-core/src/test/java/org/apache/helix/integration/manager/TestHelixMultiClusterController.java
@@ -63,15 +63,15 @@ public class TestHelixMultiClusterController extends ZkTestBase {
         2, // replicas
         "MasterSlave", true); // do rebalance
 
-    HelixManager[] distributedControllers = new HelixManager[n];
+    HelixManager[] multiClusterControllers = new HelixManager[n];
     for (int i = 0; i < n; i++) {
       int port = 12918 + i;
-      distributedControllers[i] =
+      multiClusterControllers[i] =
           new ZKHelixManager(clusterName, "localhost_" + port, InstanceType.CONTROLLER_PARTICIPANT,
               _zkaddr);
-      distributedControllers[i].getStateMachineEngine().registerStateModelFactory(StateModelDefId.MasterSlave,
+      multiClusterControllers[i].getStateMachineEngine().registerStateModelFactory(StateModelDefId.MasterSlave,
           new MockMSModelFactory());
-      distributedControllers[i].connect();
+      multiClusterControllers[i].connect();
     }
 
     boolean result =
@@ -79,8 +79,8 @@ public class TestHelixMultiClusterController extends ZkTestBase {
             clusterName));
     Assert.assertTrue(result);
 
-    // disconnect first distributed-controller, and verify second takes leadership
-    distributedControllers[0].disconnect();
+    // disconnect first multi-cluster-controller, and verify second takes leadership
+    multiClusterControllers[0].disconnect();
 
     // verify leader changes to localhost_12919
     Thread.sleep(100);
@@ -98,11 +98,11 @@ public class TestHelixMultiClusterController extends ZkTestBase {
     Assert.assertEquals(leader.getId(), "localhost_12919");
 
     // clean up
-    distributedControllers[1].disconnect();
+    multiClusterControllers[1].disconnect();
     Assert.assertNull(accessor.getProperty(keyBuilder.liveInstance("localhost_12919")));
     Assert.assertNull(accessor.getProperty(keyBuilder.controllerLeader()));
 
-    System.out.println("START " + clusterName + " at " + new Date(System.currentTimeMillis()));
+    System.out.println("END " + clusterName + " at " + new Date(System.currentTimeMillis()));
   }
 
   /**
@@ -114,13 +114,13 @@ public class TestHelixMultiClusterController extends ZkTestBase {
   void expireController(MockMultiClusterController expireController,
       MockMultiClusterController newController) throws Exception {
     String clusterName = expireController.getClusterName();
-    LOG.info("Expiring distributedController: " + expireController.getInstanceName()
+    LOG.info("Expiring multiClusterController: " + expireController.getInstanceName()
         + ", session: " + expireController.getSessionId() + " ...");
     String oldSessionId = expireController.getSessionId();
 
     ZkTestHelper.expireSession(expireController.getZkClient());
     String newSessionId = expireController.getSessionId();
-    LOG.debug("Expried distributedController: " + expireController.getInstanceName()
+    LOG.debug("Expried multiClusterController: " + expireController.getInstanceName()
         + ", oldSessionId: " + oldSessionId + ", newSessionId: " + newSessionId);
 
     boolean result =
@@ -143,7 +143,7 @@ public class TestHelixMultiClusterController extends ZkTestBase {
 
     List<ZkCallbackHandler> handlers = expireController.getHandlers();
     Assert.assertEquals(handlers.size(), 2,
-        "Distributed controller should have 2 handler (message and leader-election) after lose leadership, but was "
+        "MultiCluster controller should have 2 handler (message and leader-election) after lose leadership, but was "
             + handlers.size());
   }
 
@@ -166,15 +166,15 @@ public class TestHelixMultiClusterController extends ZkTestBase {
         2, // replicas
         "MasterSlave", true); // do rebalance
 
-    MockMultiClusterController[] distributedControllers = new MockMultiClusterController[n];
+    MockMultiClusterController[] multiClusterControllers = new MockMultiClusterController[n];
 
     for (int i = 0; i < n; i++) {
       String contrllerName = "localhost_" + (12918 + i);
-      distributedControllers[i] =
+      multiClusterControllers[i] =
           new MockMultiClusterController(_zkaddr, clusterName, contrllerName);
-      distributedControllers[i].getStateMachineEngine().registerStateModelFactory(StateModelDefId.MasterSlave,
+      multiClusterControllers[i].getStateMachineEngine().registerStateModelFactory(StateModelDefId.MasterSlave,
           new MockMSModelFactory());
-      distributedControllers[i].connect();
+      multiClusterControllers[i].connect();
     }
 
     boolean result =
@@ -183,18 +183,18 @@ public class TestHelixMultiClusterController extends ZkTestBase {
     Assert.assertTrue(result);
 
     // expire localhost_12918
-    expireController(distributedControllers[0], distributedControllers[1]);
+    expireController(multiClusterControllers[0], multiClusterControllers[1]);
 
     // expire localhost_12919
-    expireController(distributedControllers[1], distributedControllers[0]);
+    expireController(multiClusterControllers[1], multiClusterControllers[0]);
 
     // clean up
     ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, _baseAccessor);
     PropertyKey.Builder keyBuilder = accessor.keyBuilder();
 
     for (int i = 0; i < n; i++) {
-      distributedControllers[i].disconnect();
-      Assert.assertNull(accessor.getProperty(keyBuilder.liveInstance(distributedControllers[i]
+      multiClusterControllers[i].disconnect();
+      Assert.assertNull(accessor.getProperty(keyBuilder.liveInstance(multiClusterControllers[i]
           .getInstanceName())));
     }
     Assert.assertNull(accessor.getProperty(keyBuilder.controllerLeader()));

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java b/helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java
index f68444c..63c3e84 100644
--- a/helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java
+++ b/helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java
@@ -25,7 +25,7 @@ import java.util.concurrent.CountDownLatch;
 
 import org.apache.helix.InstanceType;
 import org.apache.helix.api.id.StateModelDefId;
-import org.apache.helix.participant.DistClusterControllerStateModelFactory;
+import org.apache.helix.participant.MultiClusterControllerStateModelFactory;
 import org.apache.helix.participant.StateMachineEngine;
 import org.apache.log4j.Logger;
 
@@ -63,8 +63,8 @@ public class MockMultiClusterController extends ZKHelixManager implements Runnab
   public void run() {
     try {
       StateMachineEngine stateMach = getStateMachineEngine();
-      DistClusterControllerStateModelFactory lsModelFactory =
-          new DistClusterControllerStateModelFactory(_zkAddress);
+      MultiClusterControllerStateModelFactory lsModelFactory =
+          new MultiClusterControllerStateModelFactory(_zkAddress);
       stateMach.registerStateModelFactory(StateModelDefId.LeaderStandby, lsModelFactory);
 
       connect();

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/manager/zk/TestZkHelixAutoController.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/manager/zk/TestZkHelixAutoController.java b/helix-core/src/test/java/org/apache/helix/manager/zk/TestZkHelixAutoController.java
deleted file mode 100644
index a34dc66..0000000
--- a/helix-core/src/test/java/org/apache/helix/manager/zk/TestZkHelixAutoController.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.apache.helix.manager.zk;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import java.util.Date;
-
-import org.apache.helix.HelixMultiClusterController;
-import org.apache.helix.HelixConnection;
-import org.apache.helix.HelixDataAccessor;
-import org.apache.helix.PropertyKey;
-import org.apache.helix.TestHelper;
-import org.apache.helix.api.id.ClusterId;
-import org.apache.helix.api.id.ControllerId;
-import org.apache.helix.model.LiveInstance;
-import org.apache.helix.testutil.ZkTestBase;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-public class TestZkHelixAutoController extends ZkTestBase {
-  @Test
-  public void testOnConnectedAndDisconnecting() throws Exception {
-    // Logger.getRootLogger().setLevel(Level.INFO);
-    String className = TestHelper.getTestClassName();
-    String methodName = TestHelper.getTestMethodName();
-    String clusterName = className + "_" + methodName;
-    int n = 2;
-
-    System.out.println("START " + clusterName + " at " + new Date(System.currentTimeMillis()));
-
-    TestHelper.setupCluster(clusterName, _zkaddr, 12918, // participant port
-        "localhost", // participant name prefix
-        "TestDB", // resource name prefix
-        1, // resources
-        32, // partitions per resource
-        n, // number of nodes
-        2, // replicas
-        "MasterSlave", true); // do rebalance
-
-    // create connection
-    HelixConnection connection = new ZkHelixConnection(_zkaddr);
-    connection.connect();
-
-    // start auto-controller
-    ClusterId clusterId = ClusterId.from(clusterName);
-    final HelixMultiClusterController[] controllers = new HelixMultiClusterController[n];
-    for (int i = 0; i < n; i++) {
-      int port = 12918 + i;
-      ControllerId controllerId = ControllerId.from("localhost_" + port);
-      controllers[i] = connection.createAutoController(clusterId, controllerId);
-      controllers[i].start();
-    }
-
-    // check live-instance znode for localhost_12918/12919 exists
-    final HelixDataAccessor accessor =
-        new ZKHelixDataAccessor(clusterName, _baseAccessor);
-    final PropertyKey.Builder keyBuilder = accessor.keyBuilder();
-
-    for (int i = 0; i < n; i++) {
-      String instanceName = controllers[i].getControllerId().stringify();
-      Assert.assertNotNull(accessor.getProperty(keyBuilder.liveInstance(instanceName)));
-    }
-
-    // check leader znode exists
-    LiveInstance leader = accessor.getProperty(keyBuilder.controllerLeader());
-    Assert.assertNotNull(leader);
-    Assert.assertEquals(leader.getInstanceName(), controllers[0].getControllerId().stringify());
-
-    // stop controller localhost_12918
-    controllers[0].stop();
-
-    // check live-instance znode for localhost_12918 is gone
-    String instanceName = controllers[0].getControllerId().stringify();
-    Assert.assertNull(accessor.getProperty(keyBuilder.liveInstance(instanceName)));
-
-    // check localhost_12919 becomes the new leader
-    boolean success = TestHelper.verify(new TestHelper.Verifier() {
-
-      @Override
-      public boolean verify() throws Exception {
-        LiveInstance leader = accessor.getProperty(keyBuilder.controllerLeader());
-        if (leader == null) {
-          return false;
-        }
-        return leader.getInstanceName().equals(controllers[1].getControllerId().stringify());
-
-      }
-    }, 3 * 1000);
-    Assert.assertTrue(success, "fail to re-elect new leader");
-
-    // clean up
-    connection.disconnect();
-
-    // check live-instance znode for localhost_12919 is gone
-    instanceName = controllers[1].getControllerId().stringify();
-    Assert.assertNull(accessor.getProperty(keyBuilder.liveInstance(instanceName)));
-
-    // check leader znode is gone
-    Assert.assertNull(accessor.getProperty(keyBuilder.controllerLeader()));
-
-    System.out.println("END " + clusterName + " at " + new Date(System.currentTimeMillis()));
-  }
-}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/manager/zk/TestZkHelixMultiClusterController.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/manager/zk/TestZkHelixMultiClusterController.java b/helix-core/src/test/java/org/apache/helix/manager/zk/TestZkHelixMultiClusterController.java
new file mode 100644
index 0000000..7e1a0b9
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/manager/zk/TestZkHelixMultiClusterController.java
@@ -0,0 +1,119 @@
+package org.apache.helix.manager.zk;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Date;
+
+import org.apache.helix.HelixMultiClusterController;
+import org.apache.helix.HelixConnection;
+import org.apache.helix.HelixDataAccessor;
+import org.apache.helix.PropertyKey;
+import org.apache.helix.TestHelper;
+import org.apache.helix.api.id.ClusterId;
+import org.apache.helix.api.id.ControllerId;
+import org.apache.helix.model.LiveInstance;
+import org.apache.helix.testutil.ZkTestBase;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class TestZkHelixMultiClusterController extends ZkTestBase {
+  @Test
+  public void testOnConnectedAndDisconnecting() throws Exception {
+    // Logger.getRootLogger().setLevel(Level.INFO);
+    String className = TestHelper.getTestClassName();
+    String methodName = TestHelper.getTestMethodName();
+    String clusterName = className + "_" + methodName;
+    int n = 2;
+
+    System.out.println("START " + clusterName + " at " + new Date(System.currentTimeMillis()));
+
+    TestHelper.setupCluster(clusterName, _zkaddr, 12918, // participant port
+        "localhost", // participant name prefix
+        "TestDB", // resource name prefix
+        1, // resources
+        32, // partitions per resource
+        n, // number of nodes
+        2, // replicas
+        "MasterSlave", true); // do rebalance
+
+    // create connection
+    HelixConnection connection = new ZkHelixConnection(_zkaddr);
+    connection.connect();
+
+    // start multi-cluster-controller
+    ClusterId clusterId = ClusterId.from(clusterName);
+    final HelixMultiClusterController[] controllers = new HelixMultiClusterController[n];
+    for (int i = 0; i < n; i++) {
+      int port = 12918 + i;
+      ControllerId controllerId = ControllerId.from("localhost_" + port);
+      controllers[i] = connection.createMultiClusterController(clusterId, controllerId);
+      controllers[i].start();
+    }
+
+    // check live-instance znode for localhost_12918/12919 exists
+    final HelixDataAccessor accessor =
+        new ZKHelixDataAccessor(clusterName, _baseAccessor);
+    final PropertyKey.Builder keyBuilder = accessor.keyBuilder();
+
+    for (int i = 0; i < n; i++) {
+      String instanceName = controllers[i].getControllerId().stringify();
+      Assert.assertNotNull(accessor.getProperty(keyBuilder.liveInstance(instanceName)));
+    }
+
+    // check leader znode exists
+    LiveInstance leader = accessor.getProperty(keyBuilder.controllerLeader());
+    Assert.assertNotNull(leader);
+    Assert.assertEquals(leader.getInstanceName(), controllers[0].getControllerId().stringify());
+
+    // stop controller localhost_12918
+    controllers[0].stop();
+
+    // check live-instance znode for localhost_12918 is gone
+    String instanceName = controllers[0].getControllerId().stringify();
+    Assert.assertNull(accessor.getProperty(keyBuilder.liveInstance(instanceName)));
+
+    // check localhost_12919 becomes the new leader
+    boolean success = TestHelper.verify(new TestHelper.Verifier() {
+
+      @Override
+      public boolean verify() throws Exception {
+        LiveInstance leader = accessor.getProperty(keyBuilder.controllerLeader());
+        if (leader == null) {
+          return false;
+        }
+        return leader.getInstanceName().equals(controllers[1].getControllerId().stringify());
+
+      }
+    }, 3 * 1000);
+    Assert.assertTrue(success, "fail to re-elect new leader");
+
+    // clean up
+    connection.disconnect();
+
+    // check live-instance znode for localhost_12919 is gone
+    instanceName = controllers[1].getControllerId().stringify();
+    Assert.assertNull(accessor.getProperty(keyBuilder.liveInstance(instanceName)));
+
+    // check leader znode is gone
+    Assert.assertNull(accessor.getProperty(keyBuilder.controllerLeader()));
+
+    System.out.println("END " + clusterName + " at " + new Date(System.currentTimeMillis()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/monitoring/TestClusterStatusMonitorLifecycle.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/monitoring/TestClusterStatusMonitorLifecycle.java b/helix-core/src/test/java/org/apache/helix/monitoring/TestClusterStatusMonitorLifecycle.java
index 2b8d5e5..1ade42c 100644
--- a/helix-core/src/test/java/org/apache/helix/monitoring/TestClusterStatusMonitorLifecycle.java
+++ b/helix-core/src/test/java/org/apache/helix/monitoring/TestClusterStatusMonitorLifecycle.java
@@ -90,7 +90,7 @@ public class TestClusterStatusMonitorLifecycle extends ZkTestBase {
         3, // replicas
         "LeaderStandby", true); // do rebalance
 
-    // start distributed cluster controllers
+    // start multi-cluster controllers
     _controllers = new MockMultiClusterController[n + n];
     for (int i = 0; i < n; i++) {
       _controllers[i] =

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModel.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModel.java b/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModel.java
deleted file mode 100644
index 116cd72..0000000
--- a/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModel.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.apache.helix.participant;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.helix.NotificationContext;
-import org.apache.helix.TestHelper;
-import org.apache.helix.api.id.MessageId;
-import org.apache.helix.api.id.PartitionId;
-import org.apache.helix.model.Message;
-import org.apache.helix.model.Message.MessageType;
-import org.apache.helix.participant.DistClusterControllerStateModel;
-import org.apache.helix.testutil.ZkTestBase;
-import org.apache.log4j.Logger;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-public class TestDistControllerStateModel extends ZkTestBase {
-  private static Logger LOG = Logger.getLogger(TestDistControllerStateModel.class);
-
-  final String clusterName = "TestDistControllerStateModel";
-  DistClusterControllerStateModel stateModel = null;
-
-  @BeforeMethod()
-  public void beforeMethod() {
-    stateModel = new DistClusterControllerStateModel(_zkaddr);
-    if (_zkclient.exists("/" + clusterName)) {
-      _zkclient.deleteRecursive("/" + clusterName);
-    }
-    TestHelper.setupEmptyCluster(_zkclient, clusterName);
-  }
-
-  @Test()
-  public void testOnBecomeStandbyFromOffline() {
-    stateModel.onBecomeStandbyFromOffline(null, null);
-  }
-
-  @Test()
-  public void testOnBecomeLeaderFromStandby() {
-    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
-    message.setPartitionId(PartitionId.from(clusterName));
-    message.setTgtName("controller_0");
-    try {
-      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
-    } catch (Exception e) {
-      LOG.error("Exception becoming leader from standby", e);
-    }
-    stateModel.onBecomeStandbyFromLeader(message, new NotificationContext(null));
-  }
-
-  @Test()
-  public void testOnBecomeStandbyFromLeader() {
-    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
-    message.setPartitionId(PartitionId.from(clusterName));
-    message.setTgtName("controller_0");
-    stateModel.onBecomeStandbyFromLeader(message, new NotificationContext(null));
-  }
-
-  @Test()
-  public void testOnBecomeOfflineFromStandby() {
-    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
-    message.setPartitionId(PartitionId.from(clusterName));
-    message.setTgtName("controller_0");
-
-    stateModel.onBecomeOfflineFromStandby(message, null);
-  }
-
-  @Test()
-  public void testOnBecomeDroppedFromOffline() {
-    stateModel.onBecomeDroppedFromOffline(null, null);
-  }
-
-  @Test()
-  public void testOnBecomeOfflineFromDropped() {
-    stateModel.onBecomeOfflineFromDropped(null, null);
-  }
-
-  @Test()
-  public void testRollbackOnError() {
-    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
-    message.setPartitionId(PartitionId.from(clusterName));
-    message.setTgtName("controller_0");
-    try {
-      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
-    } catch (Exception e) {
-      LOG.error("Exception becoming leader from standby", e);
-    }
-    stateModel.rollbackOnError(message, new NotificationContext(null), null);
-  }
-
-  @Test()
-  public void testReset() {
-    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
-    message.setPartitionId(PartitionId.from(clusterName));
-    message.setTgtName("controller_0");
-    try {
-      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
-    } catch (Exception e) {
-      LOG.error("Exception becoming leader from standby", e);
-    }
-    stateModel.reset();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModelFactory.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModelFactory.java b/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModelFactory.java
deleted file mode 100644
index 7055500..0000000
--- a/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModelFactory.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.apache.helix.participant;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.helix.api.id.PartitionId;
-import org.testng.annotations.Test;
-
-public class TestDistControllerStateModelFactory {
-
-  @Test()
-  public void testDistControllerStateModelFactory() {
-    DistClusterControllerStateModelFactory factory =
-        new DistClusterControllerStateModelFactory("localhost:2181");
-    DistClusterControllerStateModel stateModel = factory.createStateTransitionHandler(PartitionId.from("key"));
-    stateModel.onBecomeStandbyFromOffline(null, null);
-  }
-}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModel.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModel.java b/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModel.java
new file mode 100644
index 0000000..c991976
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModel.java
@@ -0,0 +1,120 @@
+package org.apache.helix.participant;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.helix.NotificationContext;
+import org.apache.helix.TestHelper;
+import org.apache.helix.api.id.MessageId;
+import org.apache.helix.api.id.PartitionId;
+import org.apache.helix.model.Message;
+import org.apache.helix.model.Message.MessageType;
+import org.apache.helix.participant.MultiClusterControllerStateModel;
+import org.apache.helix.testutil.ZkTestBase;
+import org.apache.log4j.Logger;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class TestMultiClusterControllerStateModel extends ZkTestBase {
+  private static Logger LOG = Logger.getLogger(TestMultiClusterControllerStateModel.class);
+
+  final String clusterName = "TestMultiClusterControllerStateModel";
+  MultiClusterControllerStateModel stateModel = null;
+
+  @BeforeMethod()
+  public void beforeMethod() {
+    stateModel = new MultiClusterControllerStateModel(_zkaddr);
+    if (_zkclient.exists("/" + clusterName)) {
+      _zkclient.deleteRecursive("/" + clusterName);
+    }
+    TestHelper.setupEmptyCluster(_zkclient, clusterName);
+  }
+
+  @Test()
+  public void testOnBecomeStandbyFromOffline() {
+    stateModel.onBecomeStandbyFromOffline(null, null);
+  }
+
+  @Test()
+  public void testOnBecomeLeaderFromStandby() {
+    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
+    message.setPartitionId(PartitionId.from(clusterName));
+    message.setTgtName("controller_0");
+    try {
+      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
+    } catch (Exception e) {
+      LOG.error("Exception becoming leader from standby", e);
+    }
+    stateModel.onBecomeStandbyFromLeader(message, new NotificationContext(null));
+  }
+
+  @Test()
+  public void testOnBecomeStandbyFromLeader() {
+    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
+    message.setPartitionId(PartitionId.from(clusterName));
+    message.setTgtName("controller_0");
+    stateModel.onBecomeStandbyFromLeader(message, new NotificationContext(null));
+  }
+
+  @Test()
+  public void testOnBecomeOfflineFromStandby() {
+    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
+    message.setPartitionId(PartitionId.from(clusterName));
+    message.setTgtName("controller_0");
+
+    stateModel.onBecomeOfflineFromStandby(message, null);
+  }
+
+  @Test()
+  public void testOnBecomeDroppedFromOffline() {
+    stateModel.onBecomeDroppedFromOffline(null, null);
+  }
+
+  @Test()
+  public void testOnBecomeOfflineFromDropped() {
+    stateModel.onBecomeOfflineFromDropped(null, null);
+  }
+
+  @Test()
+  public void testRollbackOnError() {
+    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
+    message.setPartitionId(PartitionId.from(clusterName));
+    message.setTgtName("controller_0");
+    try {
+      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
+    } catch (Exception e) {
+      LOG.error("Exception becoming leader from standby", e);
+    }
+    stateModel.rollbackOnError(message, new NotificationContext(null), null);
+  }
+
+  @Test()
+  public void testReset() {
+    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
+    message.setPartitionId(PartitionId.from(clusterName));
+    message.setTgtName("controller_0");
+    try {
+      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
+    } catch (Exception e) {
+      LOG.error("Exception becoming leader from standby", e);
+    }
+    stateModel.reset();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/0746d078/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModelFactory.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModelFactory.java b/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModelFactory.java
new file mode 100644
index 0000000..43eded0
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModelFactory.java
@@ -0,0 +1,35 @@
+package org.apache.helix.participant;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.helix.api.id.PartitionId;
+import org.testng.annotations.Test;
+
+public class TestMultiClusterControllerStateModelFactory {
+
+  @Test()
+  public void test() {
+    MultiClusterControllerStateModelFactory factory =
+        new MultiClusterControllerStateModelFactory("localhost:2181");
+    MultiClusterControllerStateModel stateModel =
+        factory.createStateTransitionHandler(PartitionId.from("key"));
+    stateModel.onBecomeStandbyFromOffline(null, null);
+  }
+}


[2/2] git commit: [HELIX-329] HelixAutoController isn't a very clear name, consider renaming, rb=24807

Posted by zz...@apache.org.
[HELIX-329] HelixAutoController isn't a very clear name, consider renaming, rb=24807


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

Branch: refs/heads/master
Commit: 3365bac22c3d7f39efcac9b4e74d50515f6ead9f
Parents: 0746d07 363c049
Author: zzhang <zz...@apache.org>
Authored: Thu Aug 21 14:03:43 2014 -0700
Committer: zzhang <zz...@apache.org>
Committed: Thu Aug 21 14:03:43 2014 -0700

----------------------------------------------------------------------
 helix-core/helix-core-0.7.1-SNAPSHOT.ivy        |   3 +-
 .../main/java/org/apache/helix/api/Cluster.java |  16 +-
 .../helix/api/accessor/ClusterAccessor.java     |   3 +-
 .../controller/GenericHelixController.java      |  54 ++-
 .../helix/controller/HelixControllerMain.java   |   9 +-
 .../controller/stages/ClusterDataCache.java     |  24 +-
 .../manager/zk/ControllerManagerHelper.java     |   5 +
 .../helix/manager/zk/ZkCallbackHandler.java     |   4 +
 .../helix/manager/zk/ZkHelixConnection.java     |   9 +-
 .../helix/manager/zk/ZkHelixController.java     |   6 +
 .../org/apache/helix/model/InstanceConfig.java  |   2 +-
 .../MultiClusterControllerStateModel.java       | 135 ------
 ...MultiClusterControllerStateModelFactory.java |  39 --
 ...MultiClusterControllerTransitionHandler.java | 135 ++++++
 ...usterControllerTransitionHandlerFactory.java |  38 ++
 .../java/org/apache/helix/task/JobContext.java  |  11 +
 .../java/org/apache/helix/task/JobQueue.java    |  99 ++++
 .../java/org/apache/helix/task/TaskConfig.java  |  37 +-
 .../java/org/apache/helix/task/TaskDriver.java  | 173 ++++++-
 .../org/apache/helix/task/TaskRebalancer.java   |  78 ++-
 .../org/apache/helix/task/TaskStateModel.java   |   6 +
 .../java/org/apache/helix/task/TaskUtil.java    |  37 +-
 .../java/org/apache/helix/task/Workflow.java    |  28 +-
 .../org/apache/helix/task/WorkflowConfig.java   |  50 +-
 .../org/apache/helix/task/WorkflowContext.java  |   8 +-
 .../integration/TestZkCallbackHandlerLeak.java  |  35 +-
 .../manager/TestZkCallbackHandlerLeak.java      | 474 -------------------
 .../integration/task/TestTaskRebalancer.java    |  59 ++-
 .../apache/helix/integration/task/TestUtil.java |   6 +-
 .../manager/zk/MockMultiClusterController.java  |   6 +-
 .../TestMultiClusterControllerStateModel.java   |   6 +-
 ...MultiClusterControllerStateModelFactory.java |   6 +-
 .../helix/provisioning/yarn/AppLauncher.java    |   6 +-
 .../yarn/AppStatusReportGenerator.java          |  14 +-
 .../provisioning/yarn/YarnProvisioner.java      |   6 +-
 pom.xml                                         |  15 +-
 36 files changed, 868 insertions(+), 774 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/3365bac2/helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java
----------------------------------------------------------------------
diff --cc helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java
index 2f5686c,b652f35..50f5ca0
--- a/helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java
+++ b/helix-core/src/main/java/org/apache/helix/controller/HelixControllerMain.java
@@@ -49,7 -49,8 +49,8 @@@ import org.apache.helix.HelixManagerFac
  import org.apache.helix.InstanceType;
  import org.apache.helix.api.id.StateModelDefId;
  import org.apache.helix.manager.zk.HelixManagerShutdownHook;
- import org.apache.helix.participant.MultiClusterControllerStateModelFactory;
++import org.apache.helix.participant.MultiClusterControllerTransitionHandlerFactory;
+ import org.apache.helix.model.HelixConfigScope.ConfigScopeProperty;
 -import org.apache.helix.participant.DistClusterControllerStateModelFactory;
  import org.apache.helix.participant.StateMachineEngine;
  import org.apache.log4j.Logger;
  
@@@ -162,8 -165,8 +165,8 @@@ public class HelixControllerMain 
              HelixManagerFactory.getZKHelixManager(clusterName, controllerName,
                  InstanceType.CONTROLLER_PARTICIPANT, zkConnectString);
  
-         MultiClusterControllerStateModelFactory stateModelFactory =
-             new MultiClusterControllerStateModelFactory(zkConnectString);
 -        DistClusterControllerStateModelFactory stateModelFactory =
 -            new DistClusterControllerStateModelFactory(zkConnectString);
++        MultiClusterControllerTransitionHandlerFactory stateModelFactory =
++            new MultiClusterControllerTransitionHandlerFactory(zkConnectString);
  
          StateMachineEngine stateMach = manager.getStateMachineEngine();
          stateMach.registerStateModelFactory(StateModelDefId.LeaderStandby, stateModelFactory);

http://git-wip-us.apache.org/repos/asf/helix/blob/3365bac2/helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java
----------------------------------------------------------------------
diff --cc helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java
index 32191ec,38332c5..222f15c
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZkHelixConnection.java
@@@ -210,7 -210,8 +210,8 @@@ public class ZkHelixConnection implemen
    }
  
    @Override
-   public HelixMultiClusterController createMultiClusterController(ClusterId clusterId, ControllerId controllerId) {
 -  public HelixMultiClusterController createAutoController(ClusterId clusterId,
++  public HelixMultiClusterController createMultiClusterController(ClusterId clusterId,
+       ControllerId controllerId) {
      return new ZkHelixMultiClusterController(this, clusterId, controllerId);
    }
  

http://git-wip-us.apache.org/repos/asf/helix/blob/3365bac2/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerTransitionHandler.java
----------------------------------------------------------------------
diff --cc helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerTransitionHandler.java
index 0000000,0000000..46f3c0f
new file mode 100644
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerTransitionHandler.java
@@@ -1,0 -1,0 +1,135 @@@
++package org.apache.helix.participant;
++
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++
++import org.apache.helix.HelixManager;
++import org.apache.helix.HelixManagerFactory;
++import org.apache.helix.InstanceType;
++import org.apache.helix.NotificationContext;
++import org.apache.helix.api.TransitionHandler;
++import org.apache.helix.model.Message;
++import org.apache.helix.participant.statemachine.StateModelInfo;
++import org.apache.helix.participant.statemachine.StateModelParser;
++import org.apache.helix.participant.statemachine.StateTransitionError;
++import org.apache.helix.participant.statemachine.Transition;
++import org.apache.log4j.Logger;
++
++@StateModelInfo(initialState = "OFFLINE", states = {
++    "LEADER", "STANDBY"
++})
++public class MultiClusterControllerTransitionHandler extends TransitionHandler {
++  private static Logger logger = Logger.getLogger(MultiClusterControllerTransitionHandler.class);
++  private HelixManager _controller = null;
++  private final String _zkAddr;
++
++  public MultiClusterControllerTransitionHandler(String zkAddr) {
++    StateModelParser parser = new StateModelParser();
++    _currentState = parser.getInitialState(MultiClusterControllerTransitionHandler.class);
++    _zkAddr = zkAddr;
++  }
++
++  @Transition(to = "STANDBY", from = "OFFLINE")
++  public void onBecomeStandbyFromOffline(Message message, NotificationContext context) {
++    logger.info("Becoming standby from offline");
++  }
++
++  @Transition(to = "LEADER", from = "STANDBY")
++  public void onBecomeLeaderFromStandby(Message message, NotificationContext context)
++      throws Exception {
++    String clusterName = message.getPartitionId().stringify();
++    String controllerName = message.getTgtName();
++
++    logger.info(controllerName + " becomes leader from standby for " + clusterName);
++    // System.out.println(controllerName + " becomes leader from standby for " + clusterName);
++
++    if (_controller == null) {
++      _controller =
++          HelixManagerFactory.getZKHelixManager(clusterName, controllerName,
++              InstanceType.CONTROLLER, _zkAddr);
++      _controller.connect();
++      _controller.startTimerTasks();
++    } else {
++      logger.error("controller already exists:" + _controller.getInstanceName() + " for "
++          + clusterName);
++    }
++
++  }
++
++  @Transition(to = "STANDBY", from = "LEADER")
++  public void onBecomeStandbyFromLeader(Message message, NotificationContext context) {
++    String clusterName = message.getPartitionId().stringify();
++    String controllerName = message.getTgtName();
++
++    logger.info(controllerName + " becoming standby from leader for " + clusterName);
++
++    if (_controller != null) {
++      _controller.disconnect();
++      _controller = null;
++    } else {
++      logger.error("No controller exists for " + clusterName);
++    }
++  }
++
++  @Transition(to = "OFFLINE", from = "STANDBY")
++  public void onBecomeOfflineFromStandby(Message message, NotificationContext context) {
++    String clusterName = message.getPartitionId().stringify();
++    String controllerName = message.getTgtName();
++
++    logger.info(controllerName + " becoming offline from standby for cluster:" + clusterName);
++
++  }
++
++  @Transition(to = "DROPPED", from = "OFFLINE")
++  public void onBecomeDroppedFromOffline(Message message, NotificationContext context) {
++    logger.info("Becoming dropped from offline");
++  }
++
++  @Transition(to = "OFFLINE", from = "DROPPED")
++  public void onBecomeOfflineFromDropped(Message message, NotificationContext context) {
++    logger.info("Becoming offline from dropped");
++  }
++
++  @Override
++  public void rollbackOnError(Message message, NotificationContext context,
++      StateTransitionError error) {
++    String clusterName = message.getPartitionId().stringify();
++    String controllerName = message.getTgtName();
++
++    logger.error(controllerName + " rollbacks on error for " + clusterName);
++
++    if (_controller != null) {
++      _controller.disconnect();
++      _controller = null;
++    }
++
++  }
++
++  @Override
++  public void reset() {
++    if (_controller != null) {
++      // System.out.println("disconnect " + _controller.getInstanceName()
++      // + "(" + _controller.getInstanceType()
++      // + ") from " + _controller.getClusterName());
++      _controller.disconnect();
++      _controller = null;
++    }
++
++  }
++}

http://git-wip-us.apache.org/repos/asf/helix/blob/3365bac2/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerTransitionHandlerFactory.java
----------------------------------------------------------------------
diff --cc helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerTransitionHandlerFactory.java
index 0000000,0000000..f368c7a
new file mode 100644
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/participant/MultiClusterControllerTransitionHandlerFactory.java
@@@ -1,0 -1,0 +1,38 @@@
++package org.apache.helix.participant;
++
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++
++import org.apache.helix.api.StateTransitionHandlerFactory;
++import org.apache.helix.api.id.PartitionId;
++
++public class MultiClusterControllerTransitionHandlerFactory extends
++    StateTransitionHandlerFactory<MultiClusterControllerTransitionHandler> {
++  private final String _zkAddr;
++
++  public MultiClusterControllerTransitionHandlerFactory(String zkAddr) {
++    _zkAddr = zkAddr;
++  }
++
++  @Override
++  public MultiClusterControllerTransitionHandler createStateTransitionHandler(PartitionId partition) {
++    return new MultiClusterControllerTransitionHandler(_zkAddr);
++  }
++
++}

http://git-wip-us.apache.org/repos/asf/helix/blob/3365bac2/helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java
----------------------------------------------------------------------
diff --cc helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java
index 63c3e84,f68444c..79e64d0
--- a/helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java
+++ b/helix-core/src/test/java/org/apache/helix/manager/zk/MockMultiClusterController.java
@@@ -25,7 -25,7 +25,7 @@@ import java.util.concurrent.CountDownLa
  
  import org.apache.helix.InstanceType;
  import org.apache.helix.api.id.StateModelDefId;
- import org.apache.helix.participant.MultiClusterControllerStateModelFactory;
 -import org.apache.helix.participant.DistClusterControllerStateModelFactory;
++import org.apache.helix.participant.MultiClusterControllerTransitionHandlerFactory;
  import org.apache.helix.participant.StateMachineEngine;
  import org.apache.log4j.Logger;
  
@@@ -63,8 -63,8 +63,8 @@@ public class MockMultiClusterControlle
    public void run() {
      try {
        StateMachineEngine stateMach = getStateMachineEngine();
-       MultiClusterControllerStateModelFactory lsModelFactory =
-           new MultiClusterControllerStateModelFactory(_zkAddress);
 -      DistClusterControllerStateModelFactory lsModelFactory =
 -          new DistClusterControllerStateModelFactory(_zkAddress);
++      MultiClusterControllerTransitionHandlerFactory lsModelFactory =
++          new MultiClusterControllerTransitionHandlerFactory(_zkAddress);
        stateMach.registerStateModelFactory(StateModelDefId.LeaderStandby, lsModelFactory);
  
        connect();

http://git-wip-us.apache.org/repos/asf/helix/blob/3365bac2/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModel.java
----------------------------------------------------------------------
diff --cc helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModel.java
index c991976,0000000..6714ed8
mode 100644,000000..100644
--- a/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModel.java
+++ b/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModel.java
@@@ -1,120 -1,0 +1,120 @@@
 +package org.apache.helix.participant;
 +
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +
 +import org.apache.helix.NotificationContext;
 +import org.apache.helix.TestHelper;
 +import org.apache.helix.api.id.MessageId;
 +import org.apache.helix.api.id.PartitionId;
 +import org.apache.helix.model.Message;
 +import org.apache.helix.model.Message.MessageType;
- import org.apache.helix.participant.MultiClusterControllerStateModel;
++import org.apache.helix.participant.MultiClusterControllerTransitionHandler;
 +import org.apache.helix.testutil.ZkTestBase;
 +import org.apache.log4j.Logger;
 +import org.testng.annotations.BeforeMethod;
 +import org.testng.annotations.Test;
 +
 +public class TestMultiClusterControllerStateModel extends ZkTestBase {
 +  private static Logger LOG = Logger.getLogger(TestMultiClusterControllerStateModel.class);
 +
 +  final String clusterName = "TestMultiClusterControllerStateModel";
-   MultiClusterControllerStateModel stateModel = null;
++  MultiClusterControllerTransitionHandler stateModel = null;
 +
 +  @BeforeMethod()
 +  public void beforeMethod() {
-     stateModel = new MultiClusterControllerStateModel(_zkaddr);
++    stateModel = new MultiClusterControllerTransitionHandler(_zkaddr);
 +    if (_zkclient.exists("/" + clusterName)) {
 +      _zkclient.deleteRecursive("/" + clusterName);
 +    }
 +    TestHelper.setupEmptyCluster(_zkclient, clusterName);
 +  }
 +
 +  @Test()
 +  public void testOnBecomeStandbyFromOffline() {
 +    stateModel.onBecomeStandbyFromOffline(null, null);
 +  }
 +
 +  @Test()
 +  public void testOnBecomeLeaderFromStandby() {
 +    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
 +    message.setPartitionId(PartitionId.from(clusterName));
 +    message.setTgtName("controller_0");
 +    try {
 +      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
 +    } catch (Exception e) {
 +      LOG.error("Exception becoming leader from standby", e);
 +    }
 +    stateModel.onBecomeStandbyFromLeader(message, new NotificationContext(null));
 +  }
 +
 +  @Test()
 +  public void testOnBecomeStandbyFromLeader() {
 +    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
 +    message.setPartitionId(PartitionId.from(clusterName));
 +    message.setTgtName("controller_0");
 +    stateModel.onBecomeStandbyFromLeader(message, new NotificationContext(null));
 +  }
 +
 +  @Test()
 +  public void testOnBecomeOfflineFromStandby() {
 +    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
 +    message.setPartitionId(PartitionId.from(clusterName));
 +    message.setTgtName("controller_0");
 +
 +    stateModel.onBecomeOfflineFromStandby(message, null);
 +  }
 +
 +  @Test()
 +  public void testOnBecomeDroppedFromOffline() {
 +    stateModel.onBecomeDroppedFromOffline(null, null);
 +  }
 +
 +  @Test()
 +  public void testOnBecomeOfflineFromDropped() {
 +    stateModel.onBecomeOfflineFromDropped(null, null);
 +  }
 +
 +  @Test()
 +  public void testRollbackOnError() {
 +    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
 +    message.setPartitionId(PartitionId.from(clusterName));
 +    message.setTgtName("controller_0");
 +    try {
 +      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
 +    } catch (Exception e) {
 +      LOG.error("Exception becoming leader from standby", e);
 +    }
 +    stateModel.rollbackOnError(message, new NotificationContext(null), null);
 +  }
 +
 +  @Test()
 +  public void testReset() {
 +    Message message = new Message(MessageType.STATE_TRANSITION, MessageId.from("0"));
 +    message.setPartitionId(PartitionId.from(clusterName));
 +    message.setTgtName("controller_0");
 +    try {
 +      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
 +    } catch (Exception e) {
 +      LOG.error("Exception becoming leader from standby", e);
 +    }
 +    stateModel.reset();
 +  }
 +
 +}

http://git-wip-us.apache.org/repos/asf/helix/blob/3365bac2/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModelFactory.java
----------------------------------------------------------------------
diff --cc helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModelFactory.java
index 43eded0,0000000..922a60d
mode 100644,000000..100644
--- a/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModelFactory.java
+++ b/helix-core/src/test/java/org/apache/helix/participant/TestMultiClusterControllerStateModelFactory.java
@@@ -1,35 -1,0 +1,35 @@@
 +package org.apache.helix.participant;
 +
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +
 +import org.apache.helix.api.id.PartitionId;
 +import org.testng.annotations.Test;
 +
 +public class TestMultiClusterControllerStateModelFactory {
 +
 +  @Test()
 +  public void test() {
-     MultiClusterControllerStateModelFactory factory =
-         new MultiClusterControllerStateModelFactory("localhost:2181");
-     MultiClusterControllerStateModel stateModel =
++    MultiClusterControllerTransitionHandlerFactory factory =
++        new MultiClusterControllerTransitionHandlerFactory("localhost:2181");
++    MultiClusterControllerTransitionHandler stateModel =
 +        factory.createStateTransitionHandler(PartitionId.from("key"));
 +    stateModel.onBecomeStandbyFromOffline(null, null);
 +  }
 +}