From 55bd35921c2bb013e45120bbd1602b658b8b999b Mon Sep 17 00:00:00 2001 From: Giovanni Matteo Fumarola Date: Wed, 15 May 2019 11:50:46 -0700 Subject: [PATCH] YARN-9552. FairScheduler: NODE_UPDATE can cause NoSuchElementException. Contributed by Peter Bacsko. --- .../scheduler/AppSchedulingInfo.java | 9 +++-- .../scheduler/fair/FSAppAttempt.java | 4 +- .../scheduler/fair/TestFSAppAttempt.java | 40 +++++++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/AppSchedulingInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/AppSchedulingInfo.java index d697c6a9f06..c3269fbf7d6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/AppSchedulingInfo.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/AppSchedulingInfo.java @@ -499,12 +499,15 @@ public class AppSchedulingInfo { public PendingAsk getNextPendingAsk() { readLock.lock(); try { - SchedulerRequestKey firstRequestKey = schedulerKeys.first(); - return getPendingAsk(firstRequestKey, ResourceRequest.ANY); + if (!schedulerKeys.isEmpty()) { + SchedulerRequestKey firstRequestKey = schedulerKeys.first(); + return getPendingAsk(firstRequestKey, ResourceRequest.ANY); + } else { + return null; + } } finally { readLock.unlock(); } - } public PendingAsk getPendingAsk(SchedulerRequestKey schedulerKey) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSAppAttempt.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSAppAttempt.java index 966aa281dad..d6fb544ee6b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSAppAttempt.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FSAppAttempt.java @@ -926,8 +926,8 @@ public class FSAppAttempt extends SchedulerApplicationAttempt if (!isAmRunning() && !getUnmanagedAM()) { // Return true if we have not ask, or queue is not be able to run app's AM PendingAsk ask = appSchedulingInfo.getNextPendingAsk(); - if (ask.getCount() == 0 || !getQueue().canRunAppAM( - ask.getPerAllocationResource())) { + if (ask != null && (ask.getCount() == 0 || !getQueue().canRunAppAM( + ask.getPerAllocationResource()))) { return true; } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFSAppAttempt.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFSAppAttempt.java index 3719f748d7f..6d11898cd53 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFSAppAttempt.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFSAppAttempt.java @@ -19,7 +19,10 @@ package org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.records.Resource; @@ -33,9 +36,13 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext; +import org.apache.hadoop.yarn.api.records.LogAggregationContext; import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.server.resourcemanager.RMContext; import org.apache.hadoop.yarn.server.resourcemanager.placement.ApplicationPlacementContext; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.NodeType; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.QueueMetrics; @@ -344,6 +351,39 @@ public class TestFSAppAttempt extends FairSchedulerTestBase { assertEquals(clusterResource, spyApp.getHeadroom()); } + /** + * Ensure that no pending ask request inside appSchedulingInfo + * does not result in an error. + */ + @Test + public void testNoNextPendingAsk() { + FSLeafQueue queue = Mockito.mock(FSLeafQueue.class); + ApplicationAttemptId applicationAttemptId = createAppAttemptId(1, 1); + RMContext rmContext = Mockito.mock(RMContext.class); + ConcurrentMap rmApps = new ConcurrentHashMap<>(); + RMApp rmApp = Mockito.mock(RMApp.class); + rmApps.put(applicationAttemptId.getApplicationId(), rmApp); + ApplicationSubmissionContext appContext = + Mockito.mock(ApplicationSubmissionContext.class); + Mockito.when(appContext.getUnmanagedAM()).thenReturn(false); + Mockito.when(appContext.getLogAggregationContext()) + .thenReturn(Mockito.mock(LogAggregationContext.class)); + Mockito.when(rmApp.getApplicationSchedulingEnvs()) + .thenReturn(new HashMap<>()); + Mockito.when(rmApp.getApplicationSubmissionContext()) + .thenReturn(appContext); + Mockito.when(rmContext.getRMApps()).thenReturn(rmApps); + FSAppAttempt schedulerApp = + new FSAppAttempt(scheduler, applicationAttemptId, "user1", queue, + null, rmContext); + schedulerApp.setAmRunning(false); + FSSchedulerNode schedulerNode = Mockito.mock(FSSchedulerNode.class); + + Resource resource = schedulerApp.assignContainer(schedulerNode); + + assertEquals(Resources.none(), resource); + } + private static long min(long value1, long value2, long value3) { return Math.min(Math.min(value1, value2), value3); }