diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java index 61936bb..2ee02ac 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java @@ -229,8 +229,9 @@ RMAppState.ACCEPTED, RMAppState.FINISHED, RMAppState.FAILED, RMAppState.KILLED, RMAppState.FINAL_SAVING), RMAppEventType.RECOVER, new RMAppRecoveredTransition()) - .addTransition(RMAppState.NEW, RMAppState.KILLED, RMAppEventType.KILL, - new AppKilledTransition()) + .addTransition(RMAppState.NEW, RMAppState.FINAL_SAVING, RMAppEventType.KILL, + new FinalSavingTransition( + new AppKilledTransition(), RMAppState.KILLED)) .addTransition(RMAppState.NEW, RMAppState.FINAL_SAVING, RMAppEventType.APP_REJECTED, new FinalSavingTransition(new AppRejectedTransition(), @@ -326,7 +327,7 @@ // ignorable transitions .addTransition(RMAppState.FINAL_SAVING, RMAppState.FINAL_SAVING, EnumSet.of(RMAppEventType.NODE_UPDATE, RMAppEventType.KILL, - RMAppEventType.APP_NEW_SAVED)) + RMAppEventType.APP_NEW_SAVED, RMAppEventType.START)) // Transitions from FINISHING state .addTransition(RMAppState.FINISHING, RMAppState.FINISHED, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java index 920bd4f..4693d8b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java @@ -684,16 +684,30 @@ public void testAppNewKill() throws IOException { UserGroupInformation fooUser = UserGroupInformation.createUserForTesting( "fooTestAppNewKill", new String[] {"foo_group"}); - RMApp application = createNewTestApp(null); - // NEW => KILLED event RMAppEventType.KILL + ApplicationId applicationId = MockApps.newAppID(appId++); + String user = MockApps.newUserName(); + RMApp application = new RMAppImpl(applicationId, rmContext, conf, null, + user, null, new ApplicationSubmissionContextPBImpl(), null, null, + System.currentTimeMillis(), "YARN", null, null) { + @Override + protected void onInvalidStateTransition(RMAppEventType rmAppEventType, + RMAppState state) { + Assert.assertTrue("RMAppImpl: can't handle " + rmAppEventType + + " at state " + state, false); + } + }; + // NEW => FINAL_SAVING event RMAppEventType.KILL RMAppEvent event = new RMAppKillByClientEvent( application.getApplicationId(), "Application killed by user.", fooUser, Server.getRemoteIp()); application.handle(event); rmDispatcher.await(); + assertAppState(RMAppState.FINAL_SAVING, application); + + // FINAL_SAVING ==> KILLED event RMAppEventType.APP_UPDATE_SAVED sendAppUpdateSavedEvent(application); assertKilled(application); - assertAppFinalStateNotSaved(application); + verifyApplicationFinished(RMAppState.KILLED); verifyAppRemovedSchedulerEvent(RMAppState.KILLED); verifyRMAppFieldsForFinalTransitions(application); @@ -1156,8 +1170,9 @@ public void testAppStartAfterKilled() throws IOException { LOG.info("--- START: testAppStartAfterKilled ---"); ApplicationId applicationId = MockApps.newAppID(appId++); + String user = MockApps.newUserName(); RMApp application = new RMAppImpl(applicationId, rmContext, conf, null, - null, null, new ApplicationSubmissionContextPBImpl(), null, null, + user, null, new ApplicationSubmissionContextPBImpl(), null, null, System.currentTimeMillis(), "YARN", null, null) { @Override protected void onInvalidStateTransition(RMAppEventType rmAppEventType, @@ -1175,6 +1190,8 @@ protected void onInvalidStateTransition(RMAppEventType rmAppEventType, fooUser, Server.getRemoteIp()); application.handle(event); rmDispatcher.await(); + assertAppState(RMAppState.FINAL_SAVING, application); + sendAppUpdateSavedEvent(application); assertKilled(application); // KILLED => KILLED event RMAppEventType.START @@ -1186,6 +1203,41 @@ protected void onInvalidStateTransition(RMAppEventType rmAppEventType, assertAppState(RMAppState.KILLED, application); } + @Test (timeout = 30000) + public void testAppStartAtFinalSaving() throws IOException { + LOG.info("--- START: testAppStartAtFinalSaving ---"); + + ApplicationId applicationId = MockApps.newAppID(appId++); + String user = MockApps.newUserName(); + RMApp application = new RMAppImpl(applicationId, rmContext, conf, null, + user, null, new ApplicationSubmissionContextPBImpl(), null, null, + System.currentTimeMillis(), "YARN", null, null) { + @Override + protected void onInvalidStateTransition(RMAppEventType rmAppEventType, + RMAppState state) { + Assert.assertTrue("RMAppImpl: can't handle " + rmAppEventType + + " at state " + state, false); + } + }; + + // NEW => FINAL_SAVING event RMAppEventType.KILL + UserGroupInformation fooUser = UserGroupInformation.createUserForTesting( + "testAppStartAtFinalSaving", new String[] {"foo_group"}); + RMAppEvent event = new RMAppKillByClientEvent( + applicationId, "Application killed by user.", + fooUser, Server.getRemoteIp()); + application.handle(event); + rmDispatcher.await(); + assertAppState(RMAppState.FINAL_SAVING, application); + + // FINAL_SAVING => FINAL_SAVING event RMAppEventType.START + event = new RMAppFailedAttemptEvent(application.getApplicationId(), + RMAppEventType.START, "", false); + application.handle(event); + rmDispatcher.await(); + assertAppState(RMAppState.FINAL_SAVING, application); + } + @Test(timeout = 30000) public void testAppsRecoveringStates() throws Exception { RMState state = new RMState();