diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/policies/ComputeFairShares.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/policies/ComputeFairShares.java index f4fad32..4c8a1ed 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/policies/ComputeFairShares.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/policies/ComputeFairShares.java @@ -113,8 +113,10 @@ private static void computeSharesInternal( Resource totalResources, ResourceType type, boolean isSteadyShare) { Collection schedulables = new ArrayList(); - int takenResources = handleFixedFairShares( - allSchedulables, schedulables, isSteadyShare, type); + boolean noNonZeroWeightActive = noNonZeroWeightActive(allSchedulables, type); + + int takenResources = handleFixedFairShares(allSchedulables, + schedulables, isSteadyShare, type, noNonZeroWeightActive); if (schedulables.isEmpty()) { return; @@ -137,8 +139,8 @@ private static void computeSharesInternal( totalResource = Math.min(totalMaxShare, totalResource); double rMax = 1.0; - while (resourceUsedWithWeightToResourceRatio(rMax, schedulables, type) - < totalResource) { + while (resourceUsedWithWeightToResourceRatio(rMax, schedulables, type, + noNonZeroWeightActive) < totalResource) { rMax *= 2.0; } // Perform the binary search for up to COMPUTE_FAIR_SHARES_ITERATIONS steps @@ -147,7 +149,7 @@ private static void computeSharesInternal( for (int i = 0; i < COMPUTE_FAIR_SHARES_ITERATIONS; i++) { double mid = (left + right) / 2.0; int plannedResourceUsed = resourceUsedWithWeightToResourceRatio( - mid, schedulables, type); + mid, schedulables, type, noNonZeroWeightActive); if (plannedResourceUsed == totalResource) { right = mid; break; @@ -160,24 +162,41 @@ private static void computeSharesInternal( // Set the fair shares based on the value of R we've converged to for (Schedulable sched : schedulables) { if (isSteadyShare) { - setResourceValue(computeShare(sched, right, type), - ((FSQueue) sched).getSteadyFairShare(), type); + setResourceValue(computeShare(sched, right, type, + noNonZeroWeightActive),((FSQueue) sched).getSteadyFairShare(), type); } else { setResourceValue( - computeShare(sched, right, type), sched.getFairShare(), type); + computeShare(sched, right, type, noNonZeroWeightActive), + sched.getFairShare(), type); } } } /** + * Check whether there is NO non-zero weight active Schedulable. + * @return true if there is; false otherwise. + */ + private static boolean noNonZeroWeightActive( + Collection schedulables, ResourceType type) { + for (Schedulable sched : schedulables) { + if ((sched instanceof FSQueue) && ((FSQueue)sched).isActive() && + sched.getWeights().getWeight(type) > 0) { + return false; + } + } + return true; + } + + /** * Compute the resources that would be used given a weight-to-resource ratio * w2rRatio, for use in the computeFairShares algorithm as described in # */ private static int resourceUsedWithWeightToResourceRatio(double w2rRatio, - Collection schedulables, ResourceType type) { + Collection schedulables, ResourceType type, + boolean noNonZeroWeightActive) { int resourcesTaken = 0; for (Schedulable sched : schedulables) { - int share = computeShare(sched, w2rRatio, type); + int share = computeShare(sched, w2rRatio, type, noNonZeroWeightActive); resourcesTaken += share; } return resourcesTaken; @@ -188,8 +207,18 @@ private static int resourceUsedWithWeightToResourceRatio(double w2rRatio, * weight-to-resource ratio w2rRatio. */ private static int computeShare(Schedulable sched, double w2rRatio, - ResourceType type) { - double share = sched.getWeights().getWeight(type) * w2rRatio; + ResourceType type, boolean noNonZeroWeightActive) { + // If there is NO non-zero weight active Schdulable and weight is 0.0, + // use 1 as the weight to avoid zero share. + float weight; + if (noNonZeroWeightActive && + sched.getWeights().getWeight(type) == 0.0) { + weight = 1; + } else { + weight = sched.getWeights().getWeight(type); + } + + double share = weight * w2rRatio; share = Math.max(share, getResourceValue(sched.getMinShare(), type)); share = Math.min(share, getResourceValue(sched.getMaxShare(), type)); return (int) share; @@ -203,11 +232,13 @@ private static int computeShare(Schedulable sched, double w2rRatio, private static int handleFixedFairShares( Collection schedulables, Collection nonFixedSchedulables, - boolean isSteadyShare, ResourceType type) { + boolean isSteadyShare, ResourceType type, + boolean noNonZeroWeightActive) { int totalResource = 0; for (Schedulable sched : schedulables) { - int fixedShare = getFairShareIfFixed(sched, isSteadyShare, type); + int fixedShare = getFairShareIfFixed(sched, isSteadyShare, type, + noNonZeroWeightActive); if (fixedShare < 0) { nonFixedSchedulables.add(sched); } else { @@ -230,7 +261,7 @@ private static int handleFixedFairShares( * or the Schedulable is not active for instantaneous fairshare. */ private static int getFairShareIfFixed(Schedulable sched, - boolean isSteadyShare, ResourceType type) { + boolean isSteadyShare, ResourceType type, boolean noNonZeroWeightActive) { // Check if maxShare is 0 if (getResourceValue(sched.getMaxShare(), type) <= 0) { @@ -243,8 +274,9 @@ private static int getFairShareIfFixed(Schedulable sched, return 0; } - // Check if weight is 0 - if (sched.getWeights().getWeight(type) <= 0) { + // If there is non-zero weight active Schedulable and weight is 0, + // fareshare is fixed; otherwise it isn't fixed. + if (!noNonZeroWeightActive && sched.getWeights().getWeight(type) <= 0) { int minShare = getResourceValue(sched.getMinShare(), type); return (minShare <= 0) ? 0 : minShare; } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java index 5690fa4..c94e3a1 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java @@ -406,14 +406,14 @@ public void testFairShareWithZeroWeight() throws IOException { scheduler.update(); + // all queue weight is 0.0 and no active Non-Zero weight queue, + // so its fair share should be 4096. FSLeafQueue queue = scheduler.getQueueManager().getLeafQueue( "queueA", false); - // queueA's weight is 0.0, so its fair share should be 0. - assertEquals(0, queue.getFairShare().getMemory()); - // queueB's weight is 0.0, so its fair share should be 0. + assertEquals(4096, queue.getFairShare().getMemory()); queue = scheduler.getQueueManager().getLeafQueue( "queueB", false); - assertEquals(0, queue.getFairShare().getMemory()); + assertEquals(4096, queue.getFairShare().getMemory()); } @Test @@ -425,11 +425,11 @@ public void testFairShareWithZeroWeightNoneZeroMinRes() throws IOException { out.println(""); out.println(""); out.println(""); - out.println("1 mb 1 vcores"); + out.println("5120 mb 1 vcores"); out.println("0.0"); out.println(""); out.println(""); - out.println("1 mb 1 vcores"); + out.println("5120 mb 1 vcores"); out.println("0.0"); out.println(""); out.println(""); @@ -455,14 +455,14 @@ public void testFairShareWithZeroWeightNoneZeroMinRes() throws IOException { FSLeafQueue queue = scheduler.getQueueManager().getLeafQueue( "queueA", false); - // queueA's weight is 0.0 and minResources is 1, - // so its fair share should be 1 (minShare). - assertEquals(1, queue.getFairShare().getMemory()); - // queueB's weight is 0.0 and minResources is 1, - // so its fair share should be 1 (minShare). + // queueA's weight is 0.0 and minResources is 5120, + // so its fair share should be 5120 (minShare). + assertEquals(5 * 1024, queue.getFairShare().getMemory()); + // queueB's weight is 0.0 and minResources is 5120, + // so its fair share should be 5120 (minShare). queue = scheduler.getQueueManager().getLeafQueue( "queueB", false); - assertEquals(1, queue.getFairShare().getMemory()); + assertEquals(5 * 1024, queue.getFairShare().getMemory()); } @Test @@ -3378,6 +3378,53 @@ public void testQueueMaxAMShareDefault() throws Exception { } /** + * The test verifies that if there is no non-zero weight active queue, + * zero weight queues can get resources. + */ + @Test + public void testRequestAMResourceInZeroWeightQueue() throws Exception { + conf.set(FairSchedulerConfiguration.ALLOCATION_FILE, ALLOC_FILE); + + PrintWriter out = new PrintWriter(new FileWriter(ALLOC_FILE)); + out.println(""); + out.println(""); + out.println(""); + out.println("0.0"); + out.println(""); + out.println(""); + out.println("2.0"); + out.println(""); + out.println("fair" + + ""); + out.println(""); + out.close(); + + scheduler.init(conf); + scheduler.start(); + scheduler.reinitialize(conf, resourceManager.getRMContext()); + + RMNode node = + MockNodes.newNodeInfo(1, Resources.createResource(8192, 20), + 0, "127.0.0.1"); + NodeAddedSchedulerEvent nodeEvent = new NodeAddedSchedulerEvent(node); + NodeUpdateSchedulerEvent updateEvent = new NodeUpdateSchedulerEvent(node); + scheduler.handle(nodeEvent); + scheduler.update(); + + // Create a Managed AM + Resource amResource1 = Resource.newInstance(1024, 1); + int amPriority = RMAppAttemptImpl.AM_CONTAINER_PRIORITY.getPriority(); + ApplicationAttemptId attId1 = createAppAttemptId(1, 1); + createApplicationWithAMResource(attId1, "root.queue1", "user1", amResource1); + createSchedulingRequestExistingApplication(1024, 1, amPriority, attId1); + FSAppAttempt app1 = scheduler.getSchedulerApp(attId1); + scheduler.update(); + scheduler.handle(updateEvent); + assertEquals("Application 1 should be running", + 1, app1.getLiveContainers().size()); + } + + /** * The test verifies container gets reserved when not over maxAMShare, * reserved container gets unreserved when over maxAMShare, * container doesn't get reserved when over maxAMShare,