You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by dd...@apache.org on 2011/12/09 23:31:57 UTC

svn commit: r1212669 - in /incubator/ambari/trunk: ./ client/src/main/java/org/apache/ambari/common/state/ controller/src/main/java/org/apache/ambari/resource/statemachine/ controller/src/test/java/org/apache/ambari/controller/ controller/src/test/java...

Author: ddas
Date: Fri Dec  9 22:31:56 2011
New Revision: 1212669

URL: http://svn.apache.org/viewvc?rev=1212669&view=rev
Log:
AMBARI-150. Simplifies states in controller state machine.

Added:
    incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/NoOpDispatcher.java
    incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImplServiceCreation.java
    incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestRoleImpl.java
    incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestServiceImpl.java
Modified:
    incubator/ambari/trunk/CHANGES.txt
    incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachine.java
    incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachineFactory.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterStateFSM.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java
    incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/controller/TestHeartbeat.java
    incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImpl.java

Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Fri Dec  9 22:31:56 2011
@@ -2,6 +2,8 @@ Ambari Change log
 
 Release 0.1.0 - unreleased
 
+  AMBARI-150. Simplifies states in controller state machine (thejas via ddas)
+
   AMBARI-149. Filter the meta ambari category out of the flattened stacks.
   (omalley)
 
@@ -10,7 +12,7 @@ Release 0.1.0 - unreleased
   AMBARI-147. Create a stack flattener and introduce Guice. (omalley)
 
   AMBARI-145. FSMs are created for only those components that have 
-  active roles (Thejas M Nair via ddas)
+  active roles (thejas via ddas)
 
   AMBARI-146. Fix test case failures in agent's FileUtil. (omalley)
 

Modified: incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachine.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachine.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachine.java (original)
+++ incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachine.java Fri Dec  9 22:31:56 2011
@@ -23,4 +23,5 @@ public interface StateMachine
   public STATE getCurrentState();
   public STATE doTransition(EVENTTYPE eventType, EVENT event)
         throws InvalidStateTransitonException;
+  public void setCurrentState(STATE state);
 }

Modified: incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachineFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachineFactory.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachineFactory.java (original)
+++ incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/state/StateMachineFactory.java Fri Dec  9 22:31:56 2011
@@ -439,5 +439,10 @@ final public class StateMachineFactory
           (operand, currentState, eventType, event);
       return currentState;
     }
+
+    @Override
+    public void setCurrentState(STATE state) {
+      currentState = state;
+    }
   }
 }

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java Fri Dec  9 22:31:56 2011
@@ -42,14 +42,10 @@ import org.apache.commons.logging.LogFac
 public class ClusterImpl implements ClusterFSM, EventHandler<ClusterEvent> {
 
   /* The state machine for the cluster looks like:
-   * INACTIVE --START--> STARTING --START_SUCCESS from all services--> ACTIVE
+   * INACTIVE or FAIL --START--> STARTING --START_SUCCESS from all services--> ACTIVE
    *                                --START_FAILURE from any service--> FAIL
-   * ACTIVE --STOP--> STOPPING --STOP_SUCCESS from all services--> INACTIVE
-   *                             --STOP_FAILURE from any service--> UNCLEAN_STOP
-   * FAIL --STOP--> STOPPING --STOP_SUCCESS--> STOPPED
-   *                           --STOP_FAILURE--> UNCLEAN_STOP
-   * INACTIVE --RELEASE_NODES--> ATTIC
-   * ATTIC --ADD_NODES--> INACTIVE
+   * ACTIVE or FAIL --STOP--> STOPPING --STOP_SUCCESS from all services--> INACTIVE
+   *                             --STOP_FAILURE from any service--> FAIL
    */
 
   private static final StateMachineFactory
@@ -59,6 +55,9 @@ public class ClusterImpl implements Clus
   
   .addTransition(ClusterStateFSM.INACTIVE, ClusterStateFSM.STARTING, 
       ClusterEventType.START, new StartClusterTransition())
+
+  .addTransition(ClusterStateFSM.FAIL, ClusterStateFSM.STARTING, 
+      ClusterEventType.START, new StartClusterTransition())
       
   .addTransition(ClusterStateFSM.STARTING, EnumSet.of(ClusterStateFSM.ACTIVE, 
       ClusterStateFSM.STARTING), ClusterEventType.START_SUCCESS, 
@@ -70,31 +69,19 @@ public class ClusterImpl implements Clus
   .addTransition(ClusterStateFSM.ACTIVE, ClusterStateFSM.STOPPING, 
       ClusterEventType.STOP, new StopClusterTransition())
       
+  .addTransition(ClusterStateFSM.FAIL, ClusterStateFSM.STOPPING, 
+      ClusterEventType.STOP, new StopClusterTransition())
+      
   .addTransition(ClusterStateFSM.STOPPING, EnumSet.of(ClusterStateFSM.INACTIVE,
       ClusterStateFSM.STOPPING), ClusterEventType.STOP_SUCCESS,
       new ServiceStoppedTransition())
       
-  .addTransition(ClusterStateFSM.STOPPING, ClusterStateFSM.UNCLEAN_STOP, 
+  .addTransition(ClusterStateFSM.STOPPING, ClusterStateFSM.FAIL, 
       ClusterEventType.STOP_FAILURE)
       
-  .addTransition(ClusterStateFSM.FAIL, ClusterStateFSM.STOPPING, 
-      ClusterEventType.STOP)
-      
-  .addTransition(ClusterStateFSM.STOPPING, ClusterStateFSM.INACTIVE, 
-      ClusterEventType.STOP_SUCCESS)
-      
   .addTransition(ClusterStateFSM.INACTIVE, ClusterStateFSM.INACTIVE, 
       ClusterEventType.STOP_SUCCESS)
       
-  .addTransition(ClusterStateFSM.STOPPING, ClusterStateFSM.UNCLEAN_STOP, 
-      ClusterEventType.STOP_FAILURE)
-      
-  .addTransition(ClusterStateFSM.INACTIVE, ClusterStateFSM.ATTIC, 
-      ClusterEventType.RELEASE_NODES)
-      
-  .addTransition(ClusterStateFSM.ATTIC, ClusterStateFSM.INACTIVE, 
-      ClusterEventType.ADD_NODES)
-      
   .installTopology();
   
   private List<ServiceFSM> services;
@@ -116,7 +103,11 @@ public class ClusterImpl implements Clus
     for (String service :
       cluster.getClusterDefinition(revision).getEnabledServices()) {
       if(hasActiveRoles(cluster, service)){
-        ServiceImpl serviceImpl = new ServiceImpl(cluster, this, service);
+        ServiceImpl serviceImpl = new ServiceImpl(
+            cluster.getComponentDefinition(service).getActiveRoles(), 
+            this, 
+            service);
+        
         serviceImpls.add(serviceImpl);
       }
     }

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterStateFSM.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterStateFSM.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterStateFSM.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterStateFSM.java Fri Dec  9 22:31:56 2011
@@ -18,5 +18,5 @@
 package org.apache.ambari.resource.statemachine;
 
 public enum ClusterStateFSM {
-  INACTIVE, STARTING, ACTIVE, FAIL, ATTIC, STOPPING, UNCLEAN_STOP
+  INACTIVE, STARTING, ACTIVE, FAIL, STOPPING, 
 }
\ No newline at end of file

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java Fri Dec  9 22:31:56 2011
@@ -24,30 +24,29 @@ import org.apache.ambari.event.EventHand
 
 public class RoleImpl implements RoleFSM, EventHandler<RoleEvent> {
 
-  private RoleState myState;
-  private String roleName;
-  private ServiceFSM service;
+  private final String roleName;
+  private final ServiceFSM service;
   
   /* The state machine for the role looks like:
-   * INACTIVE --S_START--> STARTING --S_START_SUCCESS--> ACTIVE
+   * (INACTIVE or FAIL) --S_START--> STARTING --S_START_SUCCESS--> ACTIVE
    *                                --S_START_FAILURE--> FAIL
-   * ACTIVE --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
-   *                             --S_STOP_FAILURE--> UNCLEAN_STOP
-   * FAIL --S_STOP--> STOPPING --S_STOP_SUCCESS--> STOPPED
-   *                           --S_STOP_FAILURE--> UNCLEAN_STOP
+   * (ACTIVE or FAIL) --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
+   *                             --S_STOP_FAILURE--> FAIL
    */
   
   private static final StateMachineFactory 
   <RoleImpl, RoleState, RoleEventType, RoleEvent> stateMachineFactory 
          = new StateMachineFactory<RoleImpl, RoleState, RoleEventType, 
          RoleEvent>(RoleState.INACTIVE)
-         
+
+         //START event transitions
          .addTransition(RoleState.INACTIVE, RoleState.STARTING, 
              RoleEventType.START)
              
-         .addTransition(RoleState.STOPPED, RoleState.STARTING, 
+         .addTransition(RoleState.FAIL, RoleState.STARTING, 
              RoleEventType.START)
              
+          //START_SUCCESS event transitions   
          .addTransition(RoleState.STARTING, 
              RoleState.ACTIVE,
              RoleEventType.START_SUCCESS, new SuccessfulStartTransition())
@@ -59,33 +58,25 @@ public class RoleImpl implements RoleFSM
              RoleEventType.START_SUCCESS)
              
          .addTransition(RoleState.STARTING, 
-             RoleState.STARTING,
-             RoleEventType.START_FAILURE)
-             
-         .addTransition(RoleState.FAIL, RoleState.FAIL, 
+             RoleState.FAIL,
              RoleEventType.START_FAILURE)
-             
+
+          //STOP event transitions   
          .addTransition(RoleState.ACTIVE, RoleState.STOPPING, 
              RoleEventType.STOP)
-             
+
+         .addTransition(RoleState.FAIL, RoleState.STOPPING, 
+             RoleEventType.STOP)
+
+          //STOP_SUCCESS event transitions   
          .addTransition(RoleState.STOPPING, RoleState.INACTIVE,
              RoleEventType.STOP_SUCCESS, new RoleStopTransition())
-             
-         .addTransition(RoleState.STOPPING, RoleState.UNCLEAN_STOP,
-             RoleEventType.STOP_FAILURE)
-             
-         .addTransition(RoleState.FAIL, RoleState.STOPPING, RoleEventType.STOP)
-         
-         .addTransition(RoleState.STOPPING, RoleState.STOPPED, 
-             RoleEventType.STOP_SUCCESS)
-             
-         .addTransition(RoleState.STOPPED, RoleState.STOPPED,
+
+         .addTransition(RoleState.INACTIVE, RoleState.INACTIVE,
              RoleEventType.STOP_SUCCESS)
              
-         .addTransition(RoleState.STOPPING, RoleState.UNCLEAN_STOP, 
-             RoleEventType.STOP_FAILURE)
-             
-         .addTransition(RoleState.UNCLEAN_STOP, RoleState.UNCLEAN_STOP,
+          //STOP_FAILURE event transitions                
+         .addTransition(RoleState.STOPPING, RoleState.FAIL,
              RoleEventType.STOP_FAILURE)
              
          .installTopology();
@@ -96,11 +87,10 @@ public class RoleImpl implements RoleFSM
   public RoleImpl(ServiceFSM service, String roleName) {
     this.roleName = roleName;
     this.service = service;
-    this.myState = RoleState.INACTIVE;
     stateMachine = stateMachineFactory.make(this);
   }
   
-  public StateMachine getStateMachine() {
+  StateMachine<RoleState, RoleEventType, RoleEvent> getStateMachine() {
     return stateMachine;
   }
   
@@ -133,11 +123,24 @@ public class RoleImpl implements RoleFSM
       //if one instance of the role starts up fine, we consider the service
       //as ready for the 'safe-mode' kinds of checks
       StateMachineInvoker.getAMBARIEventHandler().handle(
-          new ServiceEvent(ServiceEventType.ROLE_STARTED, service, 
+          new ServiceEvent(ServiceEventType.ROLE_START_SUCCESS, service, 
               operand));
     }
   }
   
+  static class FailedStartTransition implements 
+  SingleArcTransition<RoleImpl, RoleEvent>  {
+
+    @Override
+    public void transition(RoleImpl operand, RoleEvent event) {
+      ServiceFSM service = operand.getAssociatedService();
+      //if one instance of the role starts up fine, we consider the service
+      //as ready for the 'safe-mode' kinds of checks
+      StateMachineInvoker.getAMBARIEventHandler().handle(
+          new ServiceEvent(ServiceEventType.ROLE_START_SUCCESS, service, 
+              operand));
+    }
+  }
   
   static class RoleStopTransition implements
   SingleArcTransition<RoleImpl, RoleEvent> {
@@ -146,7 +149,7 @@ public class RoleImpl implements RoleFSM
     public void transition(RoleImpl operand, RoleEvent event) {
       ServiceFSM service = operand.getAssociatedService();
       StateMachineInvoker.getAMBARIEventHandler().handle(
-          new ServiceEvent(ServiceEventType.ROLE_STOPPED, service,
+          new ServiceEvent(ServiceEventType.ROLE_STOP_SUCCESS, service,
               operand));
     }
   }
@@ -166,7 +169,7 @@ public class RoleImpl implements RoleFSM
   @Override
   public boolean shouldStop() {
     return getRoleState() == RoleState.STOPPING 
-        || getRoleState() == RoleState.STOPPED;
+        || getRoleState() == RoleState.INACTIVE;
   }
 
   @Override
@@ -174,4 +177,5 @@ public class RoleImpl implements RoleFSM
     return getRoleState() == RoleState.STARTING 
         || getRoleState() == RoleState.ACTIVE;
   }
+
 }

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java Fri Dec  9 22:31:56 2011
@@ -18,5 +18,5 @@
 package org.apache.ambari.resource.statemachine;
 
 public enum RoleState {
-  INACTIVE, STARTING, ACTIVE, FAIL, STOPPING, UNCLEAN_STOP, STOPPED
+  INACTIVE, STARTING, ACTIVE, FAIL, STOPPING, 
 }
\ No newline at end of file

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java Fri Dec  9 22:31:56 2011
@@ -32,26 +32,21 @@ public enum ServiceEventType {
   STOP,
 
   //Producer: Service
-  START_SUCCESS,
-  
-  //Producer: Service
-  START_FAILURE,
-  
-  //Producer: Service
   AVAILABLE_CHECK_SUCCESS,
   
   //Producer: Service
   AVAILABLE_CHECK_FAILURE,
-  
-  //Producer: Service
-  STOP_SUCCESS,
-  
-  //Producer: Service
-  STOP_FAILURE,
-  
+
   //Producer: Role
-  ROLE_STARTED,
-  
+  ROLE_START_SUCCESS,
+
+  //Producer: Role
+  ROLE_START_FAILURE,
+
+  //Producer: Role
+  ROLE_STOP_SUCCESS,
+
   //Producer: Role
-  ROLE_STOPPED
+  ROLE_STOP_FAILURE
+  
 }

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java Fri Dec  9 22:31:56 2011
@@ -27,26 +27,21 @@ import org.apache.ambari.common.state.Mu
 import org.apache.ambari.common.state.SingleArcTransition;
 import org.apache.ambari.common.state.StateMachine;
 import org.apache.ambari.common.state.StateMachineFactory;
-import org.apache.ambari.components.ComponentPlugin;
-import org.apache.ambari.controller.Cluster;
 import org.apache.ambari.event.EventHandler;
 
 public class ServiceImpl implements ServiceFSM, EventHandler<ServiceEvent> {
 
-  private ClusterFSM clusterFsm;
-  private ComponentPlugin plugin;
+  private final ClusterFSM clusterFsm;
   
   /* The state machine for the service looks like:
-   * INACTIVE --S_START--> PRESTART
+   * INACTIVE or FAIL --S_START--> PRESTART
    * PRESTART --S_PRESTART_FAILURE--> FAIL
    * PRESTART --S_PRESTART_SUCCESS--> STARTING --S_START_SUCCESS--> STARTED
    *                                           --S_START_FAILURE--> FAIL
-   * STARTED --S_AVAILABLE--> ACTIVE  (check for things like safemode here)
-   * STARTED --S_UNAVAILABLE--> FAIL
-   * ACTIVE --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
-   *                             --S_STOP_FAILURE--> UNCLEAN_STOP
-   * FAIL --S_STOP--> STOPPING --S_STOP_SUCCESS--> STOPPED
-   *                           --S_STOP_FAILURE--> UNCLEAN_STOP
+   * STARTED --S_AVAILABLE_CHECK_SUCCESS--> ACTIVE  (check for things like safemode here)
+   * STARTED --S_AVAILABLE_CHECK_FAILURE--> FAIL
+   * ACTIVE or FAIL --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
+   *                             --S_STOP_FAILURE--> FAIL
    */
   
   private static final StateMachineFactory 
@@ -55,10 +50,10 @@ public class ServiceImpl implements Serv
          = new StateMachineFactory<ServiceImpl, ServiceState, ServiceEventType,
          ServiceEvent>(ServiceState.INACTIVE)
          
-         .addTransition(ServiceState.INACTIVE, ServiceState.PRESTART, 
+          .addTransition(ServiceState.INACTIVE, ServiceState.PRESTART, 
              ServiceEventType.START)
              
-         .addTransition(ServiceState.STOPPED, ServiceState.PRESTART, 
+         .addTransition(ServiceState.FAIL, ServiceState.PRESTART, 
              ServiceEventType.START)
              
          .addTransition(ServiceState.PRESTART, ServiceState.FAIL, 
@@ -66,14 +61,14 @@ public class ServiceImpl implements Serv
              
          .addTransition(ServiceState.PRESTART, ServiceState.STARTING, 
              ServiceEventType.PRESTART_SUCCESS, new StartServiceTransition())    
-             
+          
          .addTransition(ServiceState.STARTING, 
              EnumSet.of(ServiceState.STARTED, ServiceState.STARTING), 
-             ServiceEventType.ROLE_STARTED,
+             ServiceEventType.ROLE_START_SUCCESS,
              new RoleStartedTransition())
              
          .addTransition(ServiceState.STARTING, ServiceState.FAIL, 
-             ServiceEventType.START_FAILURE)
+             ServiceEventType.ROLE_START_FAILURE)
              
          .addTransition(ServiceState.STARTED, 
              ServiceState.ACTIVE,
@@ -86,30 +81,24 @@ public class ServiceImpl implements Serv
              new UnavailableTransition())
                       
          .addTransition(ServiceState.ACTIVE, ServiceState.ACTIVE, 
-             ServiceEventType.ROLE_STARTED)
+             ServiceEventType.ROLE_START_SUCCESS)
              
          .addTransition(ServiceState.ACTIVE, ServiceState.STOPPING, 
              ServiceEventType.STOP, new StopServiceTransition())
              
          .addTransition(ServiceState.STOPPING, 
              EnumSet.of(ServiceState.INACTIVE, ServiceState.STOPPING),
-             ServiceEventType.STOP_SUCCESS, 
+             ServiceEventType.ROLE_STOP_SUCCESS, 
              new RoleStoppedTransition())
              
-         .addTransition(ServiceState.STOPPING, ServiceState.UNCLEAN_STOP, 
-             ServiceEventType.STOP_FAILURE)
+         .addTransition(ServiceState.STOPPING, ServiceState.FAIL, 
+             ServiceEventType.ROLE_STOP_FAILURE)
              
          .addTransition(ServiceState.FAIL, ServiceState.STOPPING, 
-             ServiceEventType.STOP)
-             
-         .addTransition(ServiceState.STOPPING, ServiceState.STOPPED, 
-             ServiceEventType.STOP_SUCCESS)
-             
-         .addTransition(ServiceState.STOPPED, ServiceState.STOPPED, 
-             ServiceEventType.STOP_SUCCESS)
+             ServiceEventType.STOP, new StopServiceTransition())
              
-         .addTransition(ServiceState.STOPPING, ServiceState.UNCLEAN_STOP,
-             ServiceEventType.STOP_FAILURE)
+         .addTransition(ServiceState.INACTIVE, ServiceState.INACTIVE, 
+             ServiceEventType.ROLE_STOP_SUCCESS)
              
          .installTopology();
   
@@ -118,22 +107,24 @@ public class ServiceImpl implements Serv
   private final List<RoleFSM> serviceRoles = new ArrayList<RoleFSM>();
   private Iterator<RoleFSM> iterator;
   private final String serviceName;
-  
-  public ServiceImpl(Cluster cluster, ClusterFSM clusterFsm, String serviceName)
+
+  public ServiceImpl(String[] roles, ClusterFSM clusterFsm, String serviceName)
       throws IOException {
     this.clusterFsm = clusterFsm;
     this.serviceName = serviceName;
-    //load plugin and get the roles and create them
-    this.plugin = cluster.getComponentDefinition(serviceName);
-    String[] roles = this.plugin.getActiveRoles();
+    setRoles(roles);
+    stateMachine = stateMachineFactory.make(this);
+  }
+    
+  private void setRoles(String[] roles) {
+    serviceRoles.clear();
+    //get the roles for this service
     for (String role : roles) {
       RoleImpl roleImpl = new RoleImpl(this, role);
       serviceRoles.add(roleImpl);
-    }
-    
-    stateMachine = stateMachineFactory.make(this);
+    }    
   }
-    
+
   public StateMachine getStateMachine() {
     return stateMachine;
   }
@@ -157,10 +148,6 @@ public class ServiceImpl implements Serv
   public String getServiceName() {
     return serviceName;
   }
-  
-  public void addRoles(List<RoleFSM> roles) {
-    this.serviceRoles.addAll(roles);
-  }
     
   private RoleFSM getFirstRole() {
     //this call should reset the iterator
@@ -304,4 +291,5 @@ public class ServiceImpl implements Serv
   public List<RoleFSM> getRoles() {
     return serviceRoles;
   }
+
 }

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java Fri Dec  9 22:31:56 2011
@@ -18,5 +18,5 @@
 package org.apache.ambari.resource.statemachine;
 
 public enum ServiceState {
-  INACTIVE, PRESTART, STARTING, STARTED, ACTIVE, FAIL, STOPPING, UNCLEAN_STOP, STOPPED
+  INACTIVE, PRESTART, STARTING, STARTED, ACTIVE, FAIL, STOPPING,
 }
\ No newline at end of file

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java Fri Dec  9 22:31:56 2011
@@ -47,7 +47,14 @@ public class StateMachineInvoker {
   private static Dispatcher dispatcher;
   
   private static Log LOG = LogFactory.getLog(StateMachineInvoker.class);
+  public Dispatcher getAMBARIDispatcher() {
+    return dispatcher;
+  }
   
+  public static void setAMBARIDispatcher(Dispatcher dispatcher1) {
+    dispatcher = dispatcher1;
+  }  
+
   public static EventHandler getAMBARIEventHandler() {
     return dispatcher.getEventHandler();
   }
@@ -115,4 +122,7 @@ public class StateMachineInvoker {
       long clusterDefinitionRev) {
     return clusters.get(clusterId).getClusterState();
   }
+  
+  
+  
 }

Modified: incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/controller/TestHeartbeat.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/controller/TestHeartbeat.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/controller/TestHeartbeat.java (original)
+++ incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/controller/TestHeartbeat.java Fri Dec  9 22:31:56 2011
@@ -17,6 +17,11 @@
  */
 package org.apache.ambari.controller;
 
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -49,12 +54,6 @@ import org.apache.ambari.resource.statem
 import org.apache.ambari.resource.statemachine.ServiceFSM;
 import org.apache.ambari.resource.statemachine.ServiceState;
 import org.apache.ambari.resource.statemachine.StateMachineInvoker;
-
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -206,7 +205,7 @@ public class TestHeartbeat {
     ServiceFSM serviceImpl = clusterImpl.getServices().get(0);
     ((TestServiceImpl)serviceImpl).setServiceState(ServiceState.STARTED);
     c.put("cluster1", clusterImpl);
-    checkSpecialAction(ServiceState.STARTED, ServiceEventType.ROLE_STARTED, 
+    checkSpecialAction(ServiceState.STARTED, ServiceEventType.ROLE_START_SUCCESS, 
         SpecialServiceIDs.SERVICE_AVAILABILITY_CHECK_ID);
   }
   

Added: incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/NoOpDispatcher.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/NoOpDispatcher.java?rev=1212669&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/NoOpDispatcher.java (added)
+++ incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/NoOpDispatcher.java Fri Dec  9 22:31:56 2011
@@ -0,0 +1,36 @@
+package org.apache.ambari.resource.statemachine;
+
+import org.apache.ambari.event.Dispatcher;
+import org.apache.ambari.event.Event;
+import org.apache.ambari.event.EventHandler;
+
+/**
+ * To test objects with state in isolation, set this no-op Dispatcher
+ */
+class NoOPDispatcher implements Dispatcher{
+  class NoOPEventHandler implements EventHandler<Event>{
+
+    @Override
+    public void handle(Event event) {
+     //no-op
+    }
+    
+  }
+  EventHandler<?> ehandler = new NoOPEventHandler();
+  
+  @Override
+  public EventHandler<?> getEventHandler() {
+    return ehandler;
+  }
+
+  @Override
+  public void register(Class<? extends Enum> eventType, EventHandler handler) {
+    //no-op
+  }
+
+  @Override
+  public void start() {
+    //no-op
+  }
+  
+}
\ No newline at end of file

Modified: incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImpl.java?rev=1212669&r1=1212668&r2=1212669&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImpl.java (original)
+++ incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImpl.java Fri Dec  9 22:31:56 2011
@@ -6,80 +6,104 @@ import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertEquals;
 
 import java.io.IOException;
-import java.util.Arrays;
+import java.util.ArrayList;
 
 import org.apache.ambari.common.rest.entities.ClusterDefinition;
-import org.apache.ambari.components.ComponentPlugin;
+import org.apache.ambari.common.rest.entities.ClusterState;
 import org.apache.ambari.controller.Cluster;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+/**
+ *Test ClusterImpl state transitions
+ */
 public class TestClusterImpl {
+  
 
+  ClusterImpl clusterImpl;
+  ClusterEventType [] startEvents = {
+      ClusterEventType.START, 
+      ClusterEventType.START_SUCCESS,
+  };
+  
+  ClusterStateFSM [] startStates = {
+      ClusterStateFSM.STARTING,
+      ClusterStateFSM.ACTIVE
+  };
+  
+  
+  @BeforeMethod
+  public void setup() throws IOException{
+    StateMachineInvoker.setAMBARIDispatcher(new NoOPDispatcher());
+   
+    ClusterDefinition clusterDef = mock(ClusterDefinition.class);
+    when(clusterDef.getEnabledServices()).thenReturn(new ArrayList<String>());
+    Cluster cluster = mock(Cluster.class);
+    when(cluster.getClusterDefinition(anyInt())).thenReturn(clusterDef);
+    ClusterState clusterState= new ClusterState();
+    clusterImpl = new ClusterImpl(cluster, 1, clusterState);
+  }
+  
   /**
-   * Create cluster with two components, both having active roles.
-   * There should be two component objects in the ClusterImpl created
-   * @throws IOException
+   * Test INACTIVE to ACTIVE transition 
+   * @throws Exception
    */
   @Test
-  public void testClusterImplWithTwoActiveComponents() throws IOException {
-
-    //set component plugin that returns one active role
-    ComponentPlugin pluginWActiveRole = mock(ComponentPlugin.class);
-    String[] servicesWithActive = {"abc"};
-    when(pluginWActiveRole.getActiveRoles()).thenReturn(servicesWithActive);
-
-    ClusterImpl clusterImpl = buildClusterImplWithComponents(pluginWActiveRole, pluginWActiveRole);
-    assertEquals(clusterImpl.getServices().size(), 2, "number of components with active service");     
+  public void testInactiveToActive() throws Exception{
+    verifyTransitions(ClusterStateFSM.INACTIVE, startEvents, startStates);
+  }
 
+ 
+  /**
+   * Test FAIL to ACTIVE transition
+   * @throws Exception
+   */
+  @Test
+  public void testFailToActive() throws Exception{
+    verifyTransitions(ClusterStateFSM.FAIL, startEvents, startStates);
   }
   
+  ClusterEventType [] stopEvents = {
+      ClusterEventType.STOP, 
+      ClusterEventType.STOP_SUCCESS,
+  };
+  
+  ClusterStateFSM [] stopStates = {
+      ClusterStateFSM.STOPPING,
+      ClusterStateFSM.INACTIVE
+  };
+  
+  
   /**
-   * Create cluster with two components, only one of which has active role(s)
-   * There should be only one component object in the ClusterImpl created
-   * @throws IOException
+   * Test ACTIVE to INACTIVE transition
+   * @throws Exception
    */
   @Test
-  public void testClusterImplWithOneActiveComponents() throws IOException {
-
-    //set component plugin that returns one active role
-    ComponentPlugin pluginWActiveRole = mock(ComponentPlugin.class);
-    String[] servicesWithActive = {"abc"};
-    when(pluginWActiveRole.getActiveRoles()).thenReturn(servicesWithActive);
-
-    //set component plugin that returns NO active roles
-    ComponentPlugin pluginWOActiveRole = mock(ComponentPlugin.class);
-    String[] servicesNoActive = {};
-    when(pluginWOActiveRole.getActiveRoles()).thenReturn(servicesNoActive);
-    
-    ClusterImpl clusterImpl = buildClusterImplWithComponents(pluginWActiveRole, pluginWOActiveRole);
-    assertEquals(clusterImpl.getServices().size(), 1, "number of components with active service");     
-    
+  public void testActivetoInactive() throws Exception{
+    verifyTransitions(ClusterStateFSM.ACTIVE, stopEvents, stopStates);
   }
   
   
-
   /**
-   * Create a mocked ClusterImpl that has two components, using the ComponentPlugins args 
-   * @param componentPlugin1 - the ComponentPlugin for first component
-   * @param componentPlugin2 - the ComponentPlugin for second component
-   * @return the ClusterImpl 
-   * @throws IOException
+   * Test FAIL to INACTIVE transition
+   * @throws Exception
    */
-  private ClusterImpl buildClusterImplWithComponents(
-      ComponentPlugin componentPlugin1, ComponentPlugin componentPlugin2)
-          throws IOException {
-    //set list of components
-    ClusterDefinition cdef = mock(ClusterDefinition.class);
-    when(cdef.getEnabledServices()).thenReturn(Arrays.asList("comp1","comp2"));
-
-    Cluster cluster = mock(Cluster.class);
-    when(cluster.getClusterDefinition(anyInt())).thenReturn(cdef);
-
-    when(cluster.getComponentDefinition("comp1")).thenReturn(componentPlugin1);
-    when(cluster.getComponentDefinition("comp2")).thenReturn(componentPlugin2);
-
-    ClusterImpl clusterImpl = new ClusterImpl(cluster, 1, null);
-    return clusterImpl;
+  @Test
+  public void testFailtoInactive() throws Exception{
+    verifyTransitions(ClusterStateFSM.FAIL, stopEvents, stopStates);
   }
-
+  
+  private void verifyTransitions(ClusterStateFSM startState, ClusterEventType[] ClusterEvents,
+      ClusterStateFSM[] ClusterStateFSMs) {
+    
+    clusterImpl.getStateMachine().setCurrentState(startState);
+    for(int i=0; i < ClusterEvents.length; i++){
+      ClusterEventType rEvent = ClusterEvents[i];
+      clusterImpl.handle(new ClusterEvent(rEvent, clusterImpl));
+      ClusterStateFSM expectedRState = ClusterStateFSMs[i];
+      assertEquals(clusterImpl.getStateMachine().getCurrentState(), expectedRState);
+    }
+    
+  }
+  
 }

Added: incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImplServiceCreation.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImplServiceCreation.java?rev=1212669&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImplServiceCreation.java (added)
+++ incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestClusterImplServiceCreation.java Fri Dec  9 22:31:56 2011
@@ -0,0 +1,85 @@
+package org.apache.ambari.resource.statemachine;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.ambari.common.rest.entities.ClusterDefinition;
+import org.apache.ambari.components.ComponentPlugin;
+import org.apache.ambari.controller.Cluster;
+import org.testng.annotations.Test;
+
+public class TestClusterImpl {
+
+  /**
+   * Create cluster with two components, both having active roles.
+   * There should be two component objects in the ClusterImpl created
+   * @throws IOException
+   */
+  @Test
+  public void testClusterImplWithTwoActiveComponents() throws IOException {
+
+    //set component plugin that returns one active role
+    ComponentPlugin pluginWActiveRole = mock(ComponentPlugin.class);
+    String[] servicesWithActive = {"abc"};
+    when(pluginWActiveRole.getActiveRoles()).thenReturn(servicesWithActive);
+
+    ClusterImpl clusterImpl = buildClusterImplWithComponents(pluginWActiveRole, pluginWActiveRole);
+    assertEquals(clusterImpl.getServices().size(), 2, "number of components with active service");     
+
+  }
+  
+  /**
+   * Create cluster with two components, only one of which has active role(s)
+   * There should be only one component object in the ClusterImpl created
+   * @throws IOException
+   */
+  @Test
+  public void testClusterImplWithOneActiveComponents() throws IOException {
+
+    //set component plugin that returns one active role
+    ComponentPlugin pluginWActiveRole = mock(ComponentPlugin.class);
+    String[] servicesWithActive = {"abc"};
+    when(pluginWActiveRole.getActiveRoles()).thenReturn(servicesWithActive);
+
+    //set component plugin that returns NO active roles
+    ComponentPlugin pluginWOActiveRole = mock(ComponentPlugin.class);
+    String[] servicesNoActive = {};
+    when(pluginWOActiveRole.getActiveRoles()).thenReturn(servicesNoActive);
+    
+    ClusterImpl clusterImpl = buildClusterImplWithComponents(pluginWActiveRole, pluginWOActiveRole);
+    assertEquals(clusterImpl.getServices().size(), 1, "number of components with active service");     
+    
+  }
+  
+  
+
+  /**
+   * Create a mocked ClusterImpl that has two components, using the ComponentPlugins args 
+   * @param componentPlugin1 - the ComponentPlugin for first component
+   * @param componentPlugin2 - the ComponentPlugin for second component
+   * @return the ClusterImpl 
+   * @throws IOException
+   */
+  private ClusterImpl buildClusterImplWithComponents(
+      ComponentPlugin componentPlugin1, ComponentPlugin componentPlugin2)
+          throws IOException {
+    //set list of components
+    ClusterDefinition cdef = mock(ClusterDefinition.class);
+    when(cdef.getEnabledServices()).thenReturn(Arrays.asList("comp1","comp2"));
+
+    Cluster cluster = mock(Cluster.class);
+    when(cluster.getClusterDefinition(anyInt())).thenReturn(cdef);
+
+    when(cluster.getComponentDefinition("comp1")).thenReturn(componentPlugin1);
+    when(cluster.getComponentDefinition("comp2")).thenReturn(componentPlugin2);
+
+    ClusterImpl clusterImpl = new ClusterImpl(cluster, 1, null);
+    return clusterImpl;
+  }
+
+}

Added: incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestRoleImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestRoleImpl.java?rev=1212669&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestRoleImpl.java (added)
+++ incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestRoleImpl.java Fri Dec  9 22:31:56 2011
@@ -0,0 +1,149 @@
+package org.apache.ambari.resource.statemachine;
+
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.apache.ambari.common.state.InvalidStateTransitonException;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+
+public class TestRoleImpl {
+  RoleImpl role;
+  
+
+  @BeforeMethod
+  public void setup(){
+    StateMachineInvoker.setAMBARIDispatcher(new NoOPDispatcher());
+    ServiceFSM service = mock(ServiceFSM.class);  
+    role = new RoleImpl(service, "role1");
+   
+  }
+ 
+  @Test
+  public void testStateTransitionsInactiveToActive() throws IOException {     
+    //from inactive to active
+    verifyTransitions(RoleState.INACTIVE, getEventsForActivate(), getStatesToActive());
+  }
+
+  @Test
+  public void testStateTransitionsFailToActive() throws IOException {
+    //from fail to active
+    verifyTransitions(RoleState.FAIL, getEventsForActivate(), getStatesToActive());
+  }
+  
+  @Test
+  public void testStateTransitionsActiveToActive() throws IOException {
+    //start event on active state throws exception
+      verifyTransitionException(RoleState.ACTIVE, getEventsForActivate(), getStatesToActive());
+  }  
+  
+  RoleEventType[] getEventsForActivate(){
+    //events that would move role to activated
+    RoleEventType[] roleEvents = {RoleEventType.START, RoleEventType.START_SUCCESS};
+    return roleEvents;
+  }
+  
+  RoleState[] getStatesToActive(){
+    //states to active state
+    RoleState[] roleStates = {RoleState.STARTING, RoleState.ACTIVE};
+    return roleStates;
+  }
+
+  @Test
+  public void testStateTransitionFailToInactive(){
+    //from fail to inactive
+    verifyTransitions(RoleState.FAIL, getEventsForInActivate(), getStatesToInActive());
+  }
+  
+  @Test
+  public void testStateTransitionActiveToInactive(){
+    //from active to inactive
+    verifyTransitions(RoleState.ACTIVE, getEventsForInActivate(), getStatesToInActive());
+  }
+  
+  @Test
+  public void testStateTransitionInactiveToInactive(){
+    //inactive to inactive throw exception
+    verifyTransitionException(RoleState.INACTIVE, getEventsForInActivate(), getStatesToInActive());
+  } 
+  
+  
+  RoleEventType[] getEventsForInActivate(){
+    //events that would move role to activated
+    RoleEventType[] roleEvents = {RoleEventType.STOP, RoleEventType.STOP_SUCCESS};
+    return roleEvents;
+  }
+  
+  RoleState[] getStatesToInActive(){
+    //states to active state
+    RoleState[] roleStates = {RoleState.STOPPING, RoleState.INACTIVE};
+    return roleStates;
+  }
+  
+  @Test
+  public void testStateTransitionInactiveToFail(){
+    RoleEventType[] startFailEvents = {RoleEventType.START, RoleEventType.START_FAILURE};
+    RoleState[] roleStates = {RoleState.STARTING, RoleState.FAIL};
+    //inactive to inactive throw exception
+    verifyTransitions(RoleState.INACTIVE, startFailEvents, roleStates);
+  } 
+
+  @Test
+  public void testStateTransitionActiveToFail(){
+    RoleEventType[] startFailEvents = {RoleEventType.STOP, RoleEventType.STOP_FAILURE};
+    RoleState[] roleStates = {RoleState.STOPPING, RoleState.FAIL};
+    //inactive to inactive throw exception
+    verifyTransitions(RoleState.ACTIVE, startFailEvents, roleStates);
+  }
+  
+  private void verifyTransitionException(RoleState startState, RoleEventType[] roleEvents,
+      RoleState[] roleStates){
+    boolean foundException = false;
+    try{
+      verifyTransitions(startState, roleEvents, roleStates);
+    }catch(InvalidStateTransitonException e){
+      foundException = true;
+    }
+    assertTrue(foundException, "exception expected");
+  }
+  
+  private void verifyTransitions(RoleState startState, RoleEventType[] roleEvents,
+      RoleState[] roleStates) {
+    role.getStateMachine().setCurrentState(startState);
+    for(int i=0; i < roleEvents.length; i++){
+      RoleEventType rEvent = roleEvents[i];
+      role.handle(new RoleEvent(rEvent, role));
+      RoleState expectedRState = roleStates[i];
+      assertEquals(role.getRoleState(), expectedRState);
+    }
+    
+  }
+
+
+
+  
+
+  
+
+//  static class RoleImplTestModule extends AbstractModule{
+//
+//    @Override
+//    protected void configure() {
+//      bind(RoleFSM.class).to(RoleImpl.class);
+//      bind(ServiceFSM.class).to(ServiceImpl.class);
+//      bind(ClusterFSM.class).to(ClusterImpl.class);
+//
+//      install(new FactoryModuleBuilder()
+//      .implement(Cluster.class,Cluster.class)
+//      .build(ClusterFactory.class));
+//
+//    }
+//
+//  }
+
+}

Added: incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestServiceImpl.java?rev=1212669&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestServiceImpl.java (added)
+++ incubator/ambari/trunk/controller/src/test/java/org/apache/ambari/resource/statemachine/TestServiceImpl.java Fri Dec  9 22:31:56 2011
@@ -0,0 +1,271 @@
+package org.apache.ambari.resource.statemachine;
+
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ */
+public class TestServiceImpl {
+  
+
+  ServiceImpl service;
+  ServiceEventType [] startEvents = {
+      ServiceEventType.START, 
+      ServiceEventType.PRESTART_SUCCESS,
+      ServiceEventType.ROLE_START_SUCCESS,
+      ServiceEventType.AVAILABLE_CHECK_SUCCESS
+  };
+  
+  ServiceState [] startStates = {
+      ServiceState.PRESTART,
+      ServiceState.STARTING,
+      ServiceState.STARTED,
+      ServiceState.ACTIVE
+  };
+  
+  
+  @BeforeMethod
+  public void setup() throws IOException{
+    StateMachineInvoker.setAMBARIDispatcher(new NoOPDispatcher());
+    String roles[] = {"role1"};
+    ClusterImpl clusterImpl = mock(ClusterImpl.class);
+    service = new ServiceImpl(roles, clusterImpl, "service1");  
+  }
+  
+  /**
+   * Test INACTIVE to ACTIVE transition with one role
+   * @throws Exception
+   */
+  @Test
+  public void testInactiveToActiveOneRole() throws Exception{
+    verifyTransitions(ServiceState.INACTIVE, startEvents, startStates);
+  }
+
+  /**
+   * Test INACTIVE to ACTIVE transition with two roles
+   * @throws Exception
+   */
+  @Test
+  public void testInactiveToActiveTwoRole() throws Exception{
+    String roles[] = {"role1", "role2"};
+    setRoles(roles);
+    ServiceEventType [] events = {
+        ServiceEventType.START, 
+        ServiceEventType.PRESTART_SUCCESS,
+        ServiceEventType.ROLE_START_SUCCESS, //1st role
+        ServiceEventType.ROLE_START_SUCCESS, //2nd role
+        ServiceEventType.AVAILABLE_CHECK_SUCCESS
+    };
+    ServiceState [] states = {
+        ServiceState.PRESTART,
+        ServiceState.STARTING,
+        ServiceState.STARTING,
+        ServiceState.STARTED,
+        ServiceState.ACTIVE
+    };
+    
+    verifyTransitions(ServiceState.INACTIVE, events, states);
+  }
+  
+  /**
+   * Test FAIL to ACTIVE transition with one roles
+   * @throws Exception
+   */
+  @Test
+  public void testFailToActiveOneRole() throws Exception{
+    verifyTransitions(ServiceState.FAIL, startEvents, startStates);
+  }
+  
+  /**
+   * Test start failure scenario 
+   * @throws Exception
+   */
+  @Test
+  public void testInactiveToFail1() throws Exception{
+
+    ServiceEventType[] events = truncateServiceEventArray(startEvents, 2,
+        ServiceEventType.PRESTART_FAILURE);
+
+    ServiceState[] states = getFailedStartSequence(2);
+    verifyTransitions(ServiceState.INACTIVE, events, states);
+    
+  }
+  
+
+  private ServiceState[] getFailedStartSequence(int i) {
+    return truncateServiceStateArray(startStates, i, ServiceState.FAIL);
+  }
+
+  /**
+   * Test start failure scenario 
+   * @throws Exception
+   */
+  @Test
+  public void testInactiveToFail2() throws Exception{
+
+    ServiceEventType[] events = truncateServiceEventArray(startEvents, 3,
+        ServiceEventType.ROLE_START_FAILURE);
+    ServiceState[] states = getFailedStartSequence(3);
+
+    verifyTransitions(ServiceState.INACTIVE, events, states);
+    
+  }
+  
+  
+  /**
+   * Test start failure scenario 
+   * @throws Exception
+   */
+  @Test
+  public void testInactiveToFail3() throws Exception{
+
+    ServiceEventType[] events = truncateServiceEventArray(startEvents, 4,
+        ServiceEventType.AVAILABLE_CHECK_FAILURE);
+    ServiceState[] states = getFailedStartSequence(4);
+
+    verifyTransitions(ServiceState.INACTIVE, events, states);
+    
+  }
+  
+  
+  /**
+   * truncate startevents with lenght n and replace with state at position n-1 
+   * with newState
+   * @param startEvents
+   * @param n
+   * @param newState
+   * @return
+   */
+  private ServiceEventType[] truncateServiceEventArray(
+      ServiceEventType[] startEvents, int n, ServiceEventType newState) {
+    return truncateArrayAndReplaceLastState(startEvents, n, newState, ServiceEventType.class);
+  }
+
+  private ServiceState[] truncateServiceStateArray(
+      ServiceState[] startEvents2, int n, ServiceState prestartFailure) {
+    return truncateArrayAndReplaceLastState(startStates, n, prestartFailure, ServiceState.class);
+  }
+
+  ServiceEventType [] stopEvents = {
+      ServiceEventType.STOP, 
+      ServiceEventType.ROLE_STOP_SUCCESS,
+  };
+  
+  ServiceState [] stopStates = {
+      ServiceState.STOPPING,
+      ServiceState.INACTIVE
+  };
+   
+
+  
+  /**
+   * Test active to inactive transition with one role
+   * @throws Exception
+   */
+  @Test
+  public void testActiveToInactiveOneRole() throws Exception{
+    verifyTransitions(ServiceState.ACTIVE, stopEvents, stopStates);
+  }
+  
+  /**
+   * Test fail to inactive transition with one role
+   * @throws Exception
+   */
+  @Test
+  public void testFailToInactiveOneRole() throws Exception{
+    verifyTransitions(ServiceState.FAIL, stopEvents, stopStates);
+  }
+  
+  /**
+   * Test failure in stop role
+   * @throws Exception
+   */
+  @Test
+  public void testActiveStopFailure() throws Exception{
+    ServiceEventType [] stopEvents = {
+        ServiceEventType.STOP, 
+        ServiceEventType.ROLE_STOP_FAILURE,
+    };
+    
+    ServiceState [] stopStates = {
+        ServiceState.STOPPING,
+        ServiceState.FAIL
+    };
+    verifyTransitions(ServiceState.ACTIVE, stopEvents, stopStates);
+  }
+  
+  
+  /**
+   * Test active to inactive transition with two roles
+   * @throws Exception
+   */
+  @Test
+  public void testActiveToInactiveTwoRoles() throws Exception{
+    String roles[] = {"role1", "role2"};
+    ServiceEventType [] stopEvents = {
+        ServiceEventType.STOP, 
+        ServiceEventType.ROLE_STOP_SUCCESS,//1st role
+        ServiceEventType.ROLE_STOP_SUCCESS,//2nd role
+    };
+    
+    ServiceState [] stopStates = {
+        ServiceState.STOPPING,
+        ServiceState.STOPPING,
+        ServiceState.INACTIVE
+    };
+    
+    setRoles(roles);
+    verifyTransitions(ServiceState.ACTIVE, stopEvents, stopStates);
+  }
+  
+  
+  /**
+   * truncate inpArr array with length n and replace state at position n-1
+   * with newState
+   * @param inpArr
+   * @param n
+   * @param newState
+   * @param tclass
+   * @return
+   */
+  private<T>  T[] truncateArrayAndReplaceLastState(
+      T[] inpArr,
+      int n, T newState, Class<?> tclass) {
+    T[] newEnumArr =  Arrays.copyOf(inpArr, n);
+    newEnumArr[n-1] = newState;
+    return newEnumArr;
+  }
+  
+  /**
+   * Call ServiceImpl.setRoles private function using reflection
+   * @param roles
+   * @throws Exception
+   */
+  private void setRoles(String[] roles) throws Exception {
+    Method method = ServiceImpl.class.getDeclaredMethod("setRoles", new Class[]{String[].class});
+    method.setAccessible(true);
+    method.invoke(service, new Object[]{roles});
+
+  }
+
+  private void verifyTransitions(ServiceState startState, ServiceEventType[] serviceEvents,
+      ServiceState[] serviceStates) {
+    service.getStateMachine().setCurrentState(startState);
+    for(int i=0; i < serviceEvents.length; i++){
+      ServiceEventType rEvent = serviceEvents[i];
+      service.handle(new ServiceEvent(rEvent, service));
+      ServiceState expectedRState = serviceStates[i];
+      assertEquals(service.getServiceState(), expectedRState);
+    }
+    
+  }
+  
+}