diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/application/ApplicationImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/application/ApplicationImpl.java index edf6359..2ceb713 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/application/ApplicationImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/application/ApplicationImpl.java @@ -131,6 +131,9 @@ public ApplicationState getApplicationState() { .addTransition(ApplicationState.NEW, ApplicationState.NEW, ApplicationEventType.INIT_CONTAINER, new InitContainerTransition()) + .addTransition(ApplicationState.NEW, ApplicationState.FINISHED, + ApplicationEventType.APPLICATION_LOG_HANDLING_FINISHED, + new AppShutDownTransition()) // Transitions from INITING state .addTransition(ApplicationState.INITING, ApplicationState.INITING, @@ -153,6 +156,9 @@ public ApplicationState getApplicationState() { .addTransition(ApplicationState.INITING, ApplicationState.RUNNING, ApplicationEventType.APPLICATION_INITED, new AppInitDoneTransition()) + .addTransition(ApplicationState.INITING, ApplicationState.FINISHED, + ApplicationEventType.APPLICATION_LOG_HANDLING_FINISHED, + new AppShutDownTransition()) // Transitions from RUNNING state .addTransition(ApplicationState.RUNNING, @@ -169,6 +175,9 @@ public ApplicationState getApplicationState() { ApplicationState.APPLICATION_RESOURCES_CLEANINGUP), ApplicationEventType.FINISH_APPLICATION, new AppFinishTriggeredTransition()) + .addTransition(ApplicationState.RUNNING, ApplicationState.FINISHED, + ApplicationEventType.APPLICATION_LOG_HANDLING_FINISHED, + new AppShutDownTransition()) // Transitions from FINISHING_CONTAINERS_WAIT state. .addTransition( @@ -177,6 +186,10 @@ public ApplicationState getApplicationState() { ApplicationState.APPLICATION_RESOURCES_CLEANINGUP), ApplicationEventType.APPLICATION_CONTAINER_FINISHED, new AppFinishTransition()) + .addTransition(ApplicationState.FINISHING_CONTAINERS_WAIT, + ApplicationState.FINISHED, + ApplicationEventType.APPLICATION_LOG_HANDLING_FINISHED, + new AppShutDownTransition()) // Transitions from APPLICATION_RESOURCES_CLEANINGUP state .addTransition(ApplicationState.APPLICATION_RESOURCES_CLEANINGUP, @@ -186,6 +199,10 @@ public ApplicationState getApplicationState() { ApplicationState.FINISHED, ApplicationEventType.APPLICATION_RESOURCES_CLEANEDUP, new AppCompletelyDoneTransition()) + .addTransition(ApplicationState.APPLICATION_RESOURCES_CLEANINGUP, + ApplicationState.FINISHED, + ApplicationEventType.APPLICATION_LOG_HANDLING_FINISHED, + new AppShutDownTransition()) // Transitions from FINISHED state .addTransition(ApplicationState.FINISHED, @@ -408,6 +425,16 @@ public void transition(ApplicationImpl app, ApplicationEvent event) { } } + static class AppShutDownTransition implements + SingleArcTransition { + + @Override + public void transition(ApplicationImpl app, ApplicationEvent event) { + LOG.info("Application " + app.getAppId() + + " is shutted down since NodeManager has been killed."); + } + } + @Override public void handle(ApplicationEvent event) { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/application/TestApplication.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/application/TestApplication.java index 429ad45..15773b1 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/application/TestApplication.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/application/TestApplication.java @@ -413,6 +413,78 @@ public void testAppFinishedOnIniting() { } } + @Test + public void testAppShutedDown() { + WrappedApplication wa = null; + try { + //Test transition from NEW TO FINISHED + wa = new WrappedApplication(5, 314159265358979L, "yak", 3); + assertEquals(ApplicationState.NEW, wa.app.getApplicationState()); + wa.appLogsAggregatedFinished(); + assertEquals(ApplicationState.FINISHED, wa.app.getApplicationState()); + + //Test transition from INITING TO FINISHED + wa = new WrappedApplication(5, 314159265358979L, "yak", 3); + wa.initApplication(); + wa.initContainer(-1); + assertEquals(ApplicationState.INITING, wa.app.getApplicationState()); + wa.appLogsAggregatedFinished(); + assertEquals(ApplicationState.FINISHED, wa.app.getApplicationState()); + + //Test transition from RUNNING TO FINISHED + wa = new WrappedApplication(5, 314159265358979L, "yak", 3); + wa.initApplication(); + wa.initContainer(-1); + assertEquals(ApplicationState.INITING, wa.app.getApplicationState()); + wa.applicationInited(); + assertEquals(ApplicationState.RUNNING, wa.app.getApplicationState()); + wa.appLogsAggregatedFinished(); + assertEquals(ApplicationState.FINISHED, wa.app.getApplicationState()); + + //Test transition from FINISHING_CONTAINERS_WAIT TO FINISHED + wa = new WrappedApplication(4, 314159265358979L, "yak", 3); + wa.initApplication(); + wa.initContainer(-1); + assertEquals(ApplicationState.INITING, wa.app.getApplicationState()); + wa.applicationInited(); + assertEquals(ApplicationState.RUNNING, wa.app.getApplicationState()); + wa.containerFinished(0); + wa.appFinished(); + assertEquals(ApplicationState.FINISHING_CONTAINERS_WAIT, + wa.app.getApplicationState()); + wa.appLogsAggregatedFinished(); + assertEquals(ApplicationState.FINISHED, wa.app.getApplicationState()); + + //Test transition from APPLICATION_RESOURCES_CLEANINGUP TO FINISHED + wa = new WrappedApplication(4, 314159265358979L, "yak", 3); + wa.initApplication(); + wa.initContainer(-1); + assertEquals(ApplicationState.INITING, wa.app.getApplicationState()); + wa.applicationInited(); + assertEquals(ApplicationState.RUNNING, wa.app.getApplicationState()); + wa.containerFinished(0); + assertEquals(ApplicationState.RUNNING, wa.app.getApplicationState()); + wa.appFinished(); + assertEquals(ApplicationState.FINISHING_CONTAINERS_WAIT, + wa.app.getApplicationState()); + wa.containerFinished(1); + assertEquals(ApplicationState.FINISHING_CONTAINERS_WAIT, + wa.app.getApplicationState()); + wa.containerFinished(2); + // All containers finished. Cleanup should be called. + assertEquals(ApplicationState.APPLICATION_RESOURCES_CLEANINGUP, + wa.app.getApplicationState()); + wa.appLogsAggregatedFinished(); + assertEquals(ApplicationState.FINISHED, wa.app.getApplicationState()); + + } catch (Exception ex) { + Assert.fail("Should not throw any exceptions"); + }finally { + if (wa != null) + wa.finished(); + } + } + private class ContainerKillMatcher extends ArgumentMatcher { private ContainerId cId; @@ -570,6 +642,12 @@ public void appResourcesCleanedup() { drainDispatcherEvents(); } + public void appLogsAggregatedFinished() { + app.handle(new ApplicationEvent(appId, + ApplicationEventType.APPLICATION_LOG_HANDLING_FINISHED)); + drainDispatcherEvents(); + } + public ContainerTokenIdentifier getContainerTokenIdentifier( ContainerId containerId) { return this.containerTokenIdentifierMap.get(containerId);