From 370e08cb0b5c6b9fb9b651a54c3edcb7805fd2c2 Mon Sep 17 00:00:00 2001 From: Sunil G Date: Thu, 16 Nov 2017 22:34:23 +0530 Subject: [PATCH] YARN-7469. Capacity Scheduler Intra-queue preemption: User can starve if newest app is exactly at user limit. Contributed by Eric Payne. (cherry picked from commit 61ace174cdcbca9d22abce7aa0aa71148f37ad55) (cherry picked from commit b53d244b7960b161a6efe664364c7f8895973671) --- .../FifoIntraQueuePreemptionPlugin.java | 6 ++++ ...CapacityPreemptionPolicyMockFramework.java | 3 ++ ...tyPreemptionPolicyIntraQueueUserLimit.java | 35 +++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/FifoIntraQueuePreemptionPlugin.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/FifoIntraQueuePreemptionPlugin.java index 00ae3dacb9e..3332f2a985a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/FifoIntraQueuePreemptionPlugin.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/FifoIntraQueuePreemptionPlugin.java @@ -203,6 +203,12 @@ public class FifoIntraQueuePreemptionPlugin Resources.subtractFromNonNegative(preemtableFromApp, tmpApp.selected); Resources.subtractFromNonNegative(preemtableFromApp, tmpApp.getAMUsed()); + if (context.getIntraQueuePreemptionOrderPolicy() + .equals(IntraQueuePreemptionOrderPolicy.USERLIMIT_FIRST)) { + Resources.subtractFromNonNegative(preemtableFromApp, + tmpApp.getFiCaSchedulerApp().getCSLeafQueue().getMinimumAllocation()); + } + // Calculate toBePreempted from apps as follows: // app.preemptable = min(max(app.used - app.selected - app.ideal, 0), // intra_q_preemptable) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/ProportionalCapacityPreemptionPolicyMockFramework.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/ProportionalCapacityPreemptionPolicyMockFramework.java index 87c6af1dbab..d4a4ff8afc1 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/ProportionalCapacityPreemptionPolicyMockFramework.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/ProportionalCapacityPreemptionPolicyMockFramework.java @@ -350,6 +350,9 @@ public class ProportionalCapacityPreemptionPolicyMockFramework { queue = (LeafQueue) nameToCSQueues.get(queueName); queue.getApplications().add(app); queue.getAllApplications().add(app); + when(queue.getMinimumAllocation()) + .thenReturn(Resource.newInstance(1,1)); + when(app.getCSLeafQueue()).thenReturn(queue); HashSet users = userMap.get(queueName); if (null == users) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/TestProportionalCapacityPreemptionPolicyIntraQueueUserLimit.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/TestProportionalCapacityPreemptionPolicyIntraQueueUserLimit.java index 7df52f9e4a0..0440db321b1 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/TestProportionalCapacityPreemptionPolicyIntraQueueUserLimit.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/monitor/capacity/TestProportionalCapacityPreemptionPolicyIntraQueueUserLimit.java @@ -896,4 +896,39 @@ public class TestProportionalCapacityPreemptionPolicyIntraQueueUserLimit new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor( getAppAttemptId(1)))); } + + @Test + public void testSimpleIntraQueuePreemptionOneUserUnderOneUserAtOneUserAbove() + throws IOException { + conf.setFloat(CapacitySchedulerConfiguration. + INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT, + (float) 0.5); + + String labelsConfig = "=100,true;"; + String nodesConfig = // n1 has no label + "n1= res=100"; + String queuesConfig = + // guaranteed,max,used,pending,reserved + "root(=[100 100 100 1 0]);" + // root + "-a(=[100 100 100 1 0])"; // a + + String appsConfig = + // queueName\t(priority,resource,host,expression,#repeat,reserved,pending) + "a\t" // app1 in a + + "(1,1,n1,,65,false,0,user1);" + + "a\t" // app2 in a + + "(1,1,n1,,35,false,0,user2);" + + "a\t" // app3 in a + + "(1,1,n1,,0,false,1,user3)" + ; + + buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig); + policy.editSchedule(); + + // app2 is right at its user limit and app1 needs one resource. Should + // preempt 1 container. + verify(mDisp, times(1)).handle(argThat( + new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor( + getAppAttemptId(1)))); + } }