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/FairScheduler.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java index 1ace604..be052a8 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java @@ -1049,7 +1049,8 @@ private synchronized void attemptScheduling(FSSchedulerNode node) { FSQueue queue = reservedAppSchedulable.getQueue(); if (!reservedAppSchedulable.hasContainerForNode(reservedPriority, node) - || !fitInMaxShare(queue)) { + || !fitsInMaxShare(queue, + node.getReservedContainer().getReservedResource())) { // Don't hold the reservation if app can no longer use it LOG.info("Releasing reservation that cannot be satisfied for application " + reservedAppSchedulable.getApplicationAttemptId() @@ -1084,14 +1085,17 @@ private synchronized void attemptScheduling(FSSchedulerNode node) { updateRootQueueMetrics(); } - private boolean fitInMaxShare(FSQueue queue) { - if (Resources.fitsIn(queue.getResourceUsage(), queue.getMaxShare())) { + private boolean fitsInMaxShare(FSQueue queue, Resource reservationResource) { + Resource reservationPlusUsage = + Resources.add(queue.getResourceUsage(), reservationResource); + + if (!Resources.fitsIn(reservationPlusUsage, queue.getMaxShare())) { return false; } FSQueue parentQueue = queue.getParent(); if (parentQueue != null) { - return fitInMaxShare(parentQueue); + return fitsInMaxShare(parentQueue, reservationResource); } return true; } 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 5d079a3..a5b0567 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 @@ -784,7 +784,7 @@ public void testSimpleContainerReservation() throws Exception { } - @Test (timeout = 5000) + @Test (timeout = 500000) public void testContainerReservationNotExceedingQueueMax() throws Exception { conf.set(FairSchedulerConfiguration.ALLOCATION_FILE, ALLOC_FILE); PrintWriter out = new PrintWriter(new FileWriter(ALLOC_FILE)); @@ -793,7 +793,7 @@ public void testContainerReservationNotExceedingQueueMax() throws Exception { out.println(""); out.println(""); out.println("1024mb,5vcores"); - out.println("2048mb,10vcores"); + out.println("3072mb,10vcores"); out.println(""); out.println(""); out.println("1024mb,5vcores"); @@ -806,7 +806,7 @@ public void testContainerReservationNotExceedingQueueMax() throws Exception { scheduler.init(conf); scheduler.start(); scheduler.reinitialize(conf, resourceManager.getRMContext()); - + // Add a node RMNode node1 = MockNodes @@ -837,22 +837,36 @@ public void testContainerReservationNotExceedingQueueMax() throws Exception { scheduler.update(); scheduler.handle(updateEvent); - // Make sure queue 1 is waiting with a reservation - assertEquals(1024, scheduler.getSchedulerApp(attId1) - .getCurrentReservation().getMemory()); + createSchedulingRequest(1024, "queue2", "user2", 1); + scheduler.handle(updateEvent); - // Now remove app of queue2 - AppAttemptRemovedSchedulerEvent appRemovedEvent1 = new AppAttemptRemovedSchedulerEvent( - attId, RMAppAttemptState.FINISHED, false); - scheduler.update(); - scheduler.handle(appRemovedEvent1); + // Ensure the reservation still exists as allocated memory of queue1 doesn't + // exceed max + assertEquals(1024, scheduler.getSchedulerApp(attId1). + getCurrentReservation().getMemory()); + + // Now reduce max Resources of queue1 down to 2048 + out = new PrintWriter(new FileWriter(ALLOC_FILE)); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println("1024mb,5vcores"); + out.println("2048mb,10vcores"); + out.println(""); + out.println(""); + out.println("1024mb,5vcores"); + out.println("2048mb,10vcores"); + out.println(""); + out.println(""); + out.println(""); + out.close(); + + scheduler.reinitialize(conf, resourceManager.getRMContext()); - // Queue should have no apps - assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). - getResourceUsage().getMemory()); - createSchedulingRequest(1024, "queue2", "user2", 1); scheduler.handle(updateEvent); + // Make sure allocated memory of queue1 doesn't exceed its maximum assertEquals(2048, scheduler.getQueueManager().getQueue("queue1"). getResourceUsage().getMemory()); @@ -2257,10 +2271,9 @@ public void testReservationWhileMultiplePriorities() throws IOException { scheduler.handle(updateEvent); assertEquals(1, app.getLiveContainers().size()); - // Reserved container should will be at higher priority, - // since old reservation cannot be satisfied + // Reserved container should still be at lower priority for (RMContainer container : app.getReservedContainers()) { - assertEquals(1, container.getReservedPriority().getPriority()); + assertEquals(2, container.getReservedPriority().getPriority()); } // Complete container @@ -2273,11 +2286,12 @@ public void testReservationWhileMultiplePriorities() throws IOException { scheduler.update(); scheduler.handle(updateEvent); - // Reserved container (at higher priority) should be run + // Reserved container (at lower priority) should be run Collection liveContainers = app.getLiveContainers(); assertEquals(1, liveContainers.size()); for (RMContainer liveContainer : liveContainers) { - Assert.assertEquals(1, liveContainer.getContainer().getPriority().getPriority()); + Assert.assertEquals(2, liveContainer.getContainer().getPriority() + .getPriority()); } assertEquals(0, scheduler.getRootQueueMetrics().getAvailableMB()); assertEquals(0, scheduler.getRootQueueMetrics().getAvailableVirtualCores());