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/capacity/CapacitySchedulerConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerConfiguration.java index 074e3711ba7..dd2461debe1 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerConfiguration.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerConfiguration.java @@ -636,8 +636,8 @@ public void setMaximumCapacityByLabel(String queue, String label, absoluteResourceCapacity); } - public int getUserLimit(String queue) { - int userLimit = getInt(getQueuePrefix(queue) + USER_LIMIT, + public float getUserLimit(String queue) { + float userLimit = getFloat(getQueuePrefix(queue) + USER_LIMIT, DEFAULT_USER_LIMIT); return userLimit; } @@ -686,8 +686,8 @@ public int getUserLimit(String queue) { return orderingPolicy; } - public void setUserLimit(String queue, int userLimit) { - setInt(getQueuePrefix(queue) + USER_LIMIT, userLimit); + public void setUserLimit(String queue, float userLimit) { + setFloat(getQueuePrefix(queue) + USER_LIMIT, userLimit); LOG.debug("here setUserLimit: queuePrefix={}, userLimit={}", getQueuePrefix(queue), getUserLimit(queue)); } 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/capacity/LeafQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java index 71732f65e34..c76bf98f40c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java @@ -255,7 +255,7 @@ protected void setupQueueConfigs(Resource clusterResource, conf.getDefaultApplicationPriorityConfPerQueue(getQueuePath())); // Validate leaf queue's user's weights. - int queueUL = Math.min(100, conf.getUserLimit(getQueuePath())); + float queueUL = Math.min(100.0f, conf.getUserLimit(getQueuePath())); for (Entry e : getUserWeights().entrySet()) { float val = e.getValue().floatValue(); if (val < 0.0f || val > (100.0f / queueUL)) { @@ -367,17 +367,17 @@ public AbstractUsersManager getAbstractUsersManager() { } /** - * Set user limit - used only for testing. + * Set user limit. * @param userLimit new user limit */ @VisibleForTesting - void setUserLimit(int userLimit) { + void setUserLimit(float userLimit) { usersManager.setUserLimit(userLimit); usersManager.userLimitNeedsRecompute(); } /** - * Set user limit factor - used only for testing. + * Set user limit factor. * @param userLimitFactor new user limit factor */ @VisibleForTesting @@ -444,7 +444,7 @@ public int getNumActiveApplications(String user) { } @Private - public int getUserLimit() { + public float getUserLimit() { return usersManager.getUserLimit(); } 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/capacity/PlanQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/PlanQueue.java index f2b0e5aaf62..c5ae04b02c1 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/PlanQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/PlanQueue.java @@ -38,7 +38,7 @@ private int maxAppsForReservation; private int maxAppsPerUserForReservation; - private int userLimit; + private float userLimit; private float userLimitFactor; protected CapacitySchedulerContext schedulerContext; private boolean showReservationsAsQueues; @@ -60,7 +60,7 @@ public PlanQueue(CapacitySchedulerContext cs, String queueName, DEFAULT_MAXIMUM_SYSTEM_APPLICATIIONS * super .getAbsoluteCapacity()); } - int userLimit = conf.getUserLimit(queuePath); + float userLimit = conf.getUserLimit(queuePath); float userLimitFactor = conf.getUserLimitFactor(queuePath); int maxAppsPerUserForReservation = (int) (maxAppsForReservation * (userLimit / 100.0f) * userLimitFactor); @@ -123,7 +123,7 @@ public void reinitialize(CSQueue newlyParsedQueue, } } - private void updateQuotas(int userLimit, float userLimitFactor, + private void updateQuotas(float userLimit, float userLimitFactor, int maxAppsForReservation, int maxAppsPerUserForReservation) { this.userLimit = userLimit; this.userLimitFactor = userLimitFactor; @@ -155,7 +155,7 @@ public int getMaxApplicationsPerUserForReservation() { * * @return userLimit */ - public int getUserLimitForReservation() { + public float getUserLimitForReservation() { return userLimit; } 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/capacity/ReservationQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/ReservationQueue.java index ebac4c20b67..5a8ce9ac487 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/ReservationQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/ReservationQueue.java @@ -73,7 +73,7 @@ public void reinitialize(CSQueue newlyParsedQueue, } } - private void updateQuotas(int userLimit, float userLimitFactor, + private void updateQuotas(float userLimit, float userLimitFactor, int maxAppsForReservation, int maxAppsPerUserForReservation) { setUserLimit(userLimit); setUserLimitFactor(userLimitFactor); 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/capacity/UsersManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/UsersManager.java index cf9dead1837..853535d5af5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/UsersManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/UsersManager.java @@ -77,7 +77,7 @@ private Map> localVersionOfAllUsersState = new HashMap>(); - private volatile int userLimit; + private volatile float userLimit; private volatile float userLimitFactor; private WriteLock writeLock; @@ -320,7 +320,7 @@ public UsersManager(QueueMetrics metrics, LeafQueue lQueue, * Get configured user-limit. * @return user limit */ - public int getUserLimit() { + public float getUserLimit() { return userLimit; } @@ -328,7 +328,7 @@ public int getUserLimit() { * Set configured user-limit. * @param userLimit user limit */ - public void setUserLimit(int userLimit) { + public void setUserLimit(float userLimit) { this.userLimit = userLimit; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java index 8212a728e4f..9f6aa153a42 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java @@ -202,7 +202,7 @@ private void renderCommonLeafQueueInfo(ResponseInfo ri) { __("Num Containers:", Integer.toString(lqinfo.getNumContainers())). __("Max Applications:", Integer.toString(lqinfo.getMaxApplications())). __("Max Applications Per User:", Integer.toString(lqinfo.getMaxApplicationsPerUser())). - __("Configured Minimum User Limit Percent:", Integer.toString(lqinfo.getUserLimit()) + "%"). + __("Configured Minimum User Limit Percent:", lqinfo.getUserLimit() + "%"). __("Configured User Limit Factor:", lqinfo.getUserLimitFactor()). __("Accessible Node Labels:", StringUtils.join(",", lqinfo.getNodeLabels())). __("Ordering Policy: ", lqinfo.getOrderingPolicyDisplayName()). diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerLeafQueueInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerLeafQueueInfo.java index 16abb991df9..4e9ced8beea 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerLeafQueueInfo.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerLeafQueueInfo.java @@ -43,7 +43,7 @@ protected int numContainers; protected int maxApplications; protected int maxApplicationsPerUser; - protected int userLimit; + protected float userLimit; protected UsersInfo users; // To add another level in the XML protected float userLimitFactor; protected float configuredMaxAMResourceLimit; @@ -130,7 +130,7 @@ public int getMaxApplicationsPerUser() { return maxApplicationsPerUser; } - public int getUserLimit() { + public float getUserLimit() { return userLimit; } 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/capacity/TestLeafQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestLeafQueue.java index f8de445bd68..b60401f892e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestLeafQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestLeafQueue.java @@ -1731,6 +1731,109 @@ public void testUserLimits() throws Exception { 1, a.getAbstractUsersManager().getNumActiveUsers()); } + @Test + public void testDecimalUserLimits() throws Exception { + // Mock the queue + LeafQueue a = stubLeafQueue((LeafQueue)queues.get(A)); + //unset maxCapacity + a.setMaxCapacity(1.0f); + + when(csContext.getClusterResource()) + .thenReturn(Resources.createResource(16 * GB, 32)); + + // Users + final String user_0 = "user_0"; + final String user_1 = "user_1"; + + // Submit applications + final ApplicationAttemptId appAttemptId_0 = + TestUtils.getMockApplicationAttemptId(0, 0); + FiCaSchedulerApp app_0 = + new FiCaSchedulerApp(appAttemptId_0, user_0, a, + a.getAbstractUsersManager(), spyRMContext); + a.submitApplicationAttempt(app_0, user_0); + + final ApplicationAttemptId appAttemptId_1 = + TestUtils.getMockApplicationAttemptId(1, 0); + FiCaSchedulerApp app_1 = + new FiCaSchedulerApp(appAttemptId_1, user_1, a, + a.getAbstractUsersManager(), spyRMContext); + a.submitApplicationAttempt(app_1, user_1); // different user + + // Setup some nodes + String host_0 = "127.0.0.1"; + FiCaSchedulerNode node_0 = TestUtils.getMockNode(host_0, DEFAULT_RACK, 0, 8*GB); + String host_1 = "127.0.0.2"; + FiCaSchedulerNode node_1 = TestUtils.getMockNode(host_1, DEFAULT_RACK, 0, 8*GB); + + final int numNodes = 2; + Resource clusterResource = + Resources.createResource(numNodes * (8*GB), numNodes * 16); + when(csContext.getNumClusterNodes()).thenReturn(numNodes); + root.updateClusterResource(clusterResource, + new ResourceLimits(clusterResource)); + + // Setup resource-requests + Priority priority = TestUtils.createMockPriority(1); + app_0.updateResourceRequests(Collections.singletonList( + TestUtils.createResourceRequest(ResourceRequest.ANY, 3*GB, 2, true, + priority, recordFactory))); + + app_1.updateResourceRequests(Collections.singletonList( + TestUtils.createResourceRequest(ResourceRequest.ANY, 1*GB, 2, true, + priority, recordFactory))); + + Map apps = ImmutableMap.of( + app_0.getApplicationAttemptId(), app_0, app_1.getApplicationAttemptId(), + app_1); + Map nodes = ImmutableMap.of(node_0.getNodeID(), + node_0, node_1.getNodeID(), node_1); + + /** + * Start testing... + */ + + // Set user-limit + a.setUserLimit(50.1f); + a.setUserLimitFactor(2); + root.updateClusterResource(clusterResource, + new ResourceLimits(clusterResource)); + + // There're two active users + assertEquals(2, a.getAbstractUsersManager().getNumActiveUsers()); + + // 1 container to user_0 + applyCSAssignment(clusterResource, + a.assignContainers(clusterResource, node_0, + new ResourceLimits(clusterResource), + SchedulingMode.RESPECT_PARTITION_EXCLUSIVITY), a, nodes, apps); + assertEquals(3*GB, a.getUsedResources().getMemorySize()); + assertEquals(3*GB, app_0.getCurrentConsumption().getMemorySize()); + assertEquals(0*GB, app_1.getCurrentConsumption().getMemorySize()); + + // Allocate another container. Since the user limit is 50.1% it isn't + // reached, app_0 will get another container. + applyCSAssignment(clusterResource, + a.assignContainers(clusterResource, node_0, + new ResourceLimits(clusterResource), + SchedulingMode.RESPECT_PARTITION_EXCLUSIVITY), a, nodes, apps); + assertEquals(6*GB, a.getUsedResources().getMemorySize()); + assertEquals(6*GB, app_0.getCurrentConsumption().getMemorySize()); + assertEquals(0*GB, app_1.getCurrentConsumption().getMemorySize()); + + applyCSAssignment(clusterResource, + a.assignContainers(clusterResource, node_1, + new ResourceLimits(clusterResource), + SchedulingMode.RESPECT_PARTITION_EXCLUSIVITY), a, nodes, apps); + assertEquals(7*GB, a.getUsedResources().getMemorySize()); + assertEquals(6*GB, app_0.getCurrentConsumption().getMemorySize()); + assertEquals(1*GB, app_1.getCurrentConsumption().getMemorySize()); + + // app_0 doesn't have outstanding resources, there's only one active user. + assertEquals("There should only be 1 active user!", + 1, a.getAbstractUsersManager().getNumActiveUsers()); + } + @Test public void testUserSpecificUserLimits() throws Exception { // Mock the queue 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/capacity/TestParentQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestParentQueue.java index 788a7cb28be..8b75a9c126f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestParentQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestParentQueue.java @@ -1164,19 +1164,27 @@ public void testDeriveCapacityFromAbsoluteConfigurations() throws Exception { assertEquals(b.getMaxApplications(), b.getMaxApplicationsPerUser()); // Extra cases for testing maxApplicationsPerUser - int halfPercent = 50; - int oneAndQuarterPercent = 125; + float halfPercent = 50f; + float oneAndQuarterPercent = 125f; + float thirdPercent = 33.3f; a.getUsersManager().setUserLimit(halfPercent); b.getUsersManager().setUserLimit(oneAndQuarterPercent); root.updateClusterResource(clusterResource, new ResourceLimits(clusterResource)); - assertEquals(a.getMaxApplications() * halfPercent / 100, + assertEquals((int) (a.getMaxApplications() * halfPercent / 100), a.getMaxApplicationsPerUser()); // Q_B's limit per user shouldn't be greater // than the whole queue's application limit assertEquals(b.getMaxApplications(), b.getMaxApplicationsPerUser()); + b.getUsersManager().setUserLimit(thirdPercent); + root.updateClusterResource(clusterResource, + new ResourceLimits(clusterResource)); + + assertEquals((int) (b.getMaxApplications() * thirdPercent / 100), + b.getMaxApplicationsPerUser()); + float userLimitFactorQueueA = 0.9f; float userLimitFactorQueueB = 1.1f; a.getUsersManager().setUserLimit(halfPercent);