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/ResourceUsage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/ResourceUsage.java index 6f0c7d2..ab4b742 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/ResourceUsage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/ResourceUsage.java @@ -62,7 +62,7 @@ public ResourceUsage() { //CACHED_USED and CACHED_PENDING may be read by anyone, but must only //be written by ordering policies USED(0), PENDING(1), AMUSED(2), RESERVED(3), CACHED_USED(4), - CACHED_PENDING(5), AMLIMIT(6); + CACHED_PENDING(5), AMLIMIT(6), USERAMLIMIT(7); private int idx; @@ -434,4 +434,20 @@ public String toString() { readLock.unlock(); } } + + public Resource getUserAMLimit() { + return getAMLimit(NL); + } + + public Resource getUserAMLimit(String label) { + return _get(label, ResourceType.USERAMLIMIT); + } + + public void setUserAMLimit(Resource res) { + setAMLimit(NL, res); + } + + public void setUserAMLimit(String label, Resource res) { + _set(label, ResourceType.USERAMLIMIT, res); + } } 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 3915b1e..86def8b 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 @@ -625,6 +625,7 @@ public synchronized Resource getUserAMResourceLimitPerPartition( effectiveUserLimit = Math.max(userLimit / 100.0f, 1.0f / Math.max(getActiveUsersManager().getNumActiveUsers(), 1)); } + float preWeightedUserLimit = effectiveUserLimit; effectiveUserLimit = Math.min(effectiveUserLimit * userWeight, 1.0f); Resource queuePartitionResource = Resources.multiplyAndNormalizeUp( @@ -636,10 +637,29 @@ public synchronized Resource getUserAMResourceLimitPerPartition( queuePartitionResource, queueCapacities.getMaxAMResourcePercentage(nodePartition) * effectiveUserLimit * userLimitFactor, minimumAllocation); - return Resources.lessThanOrEqual(resourceCalculator, lastClusterResource, + userAMLimit = + Resources.lessThanOrEqual(resourceCalculator, lastClusterResource, userAMLimit, getAMResourceLimitPerPartition(nodePartition)) ? userAMLimit : getAMResourceLimitPerPartition(nodePartition); + + Resource preWeighteduserAMLimit = Resources.multiplyAndNormalizeUp( + resourceCalculator, queuePartitionResource, + queueCapacities.getMaxAMResourcePercentage(nodePartition) + * preWeightedUserLimit * userLimitFactor, + minimumAllocation); + preWeighteduserAMLimit = + Resources.min(resourceCalculator, lastClusterResource, + preWeighteduserAMLimit, + getAMResourceLimitPerPartition(nodePartition)); + queueUsage.setUserAMLimit(nodePartition, preWeighteduserAMLimit); + + if (LOG.isDebugEnabled()) { + LOG.debug("Effective user AM limit for \"" + userName + "\":" + + preWeighteduserAMLimit + ". " + "Effective weighted user AM limit: " + + userAMLimit + ". User weight: " + userWeight); + } + return userAMLimit; } public synchronized Resource calculateAndGetAMResourceLimitPerPartition( 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 46639ff..5c840d8 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 @@ -142,13 +142,13 @@ private void renderQueueCapacityInfo(ResponseInfo ri, String label) { // Get UserInfo from first user to calculate AM Resource Limit per user. ResourceInfo userAMResourceLimit = null; ArrayList usersList = lqinfo.getUsers().getUsersList(); - if (usersList.isEmpty()) { - // If no users are present, consider AM Limit for that queue. + if (!usersList.isEmpty()) { + userAMResourceLimit = resourceUsages.getUserAmLimit(); + } + // If no users are present or if AM limit per user doesn't exist, retrieve + // AM Limit for that queue. + if (userAMResourceLimit == null) { userAMResourceLimit = resourceUsages.getAMLimit(); - } else { - userAMResourceLimit = usersList.get(0) - .getResourceUsageInfo().getPartitionResourceUsageInfo(label) - .getAMLimit(); } ResourceInfo amUsed = (resourceUsages.getAmUsed() == null) ? new ResourceInfo(Resources.none()) @@ -217,11 +217,25 @@ protected void render(Block html) { .$class("ui-state-default")._("Non-Schedulable Apps")._()._()._() .tbody(); + PartitionResourcesInfo queueUsageResources = + lqinfo.getResources().getPartitionResourceUsageInfo( + nodeLabel == null ? "" : nodeLabel); + ArrayList users = lqinfo.getUsers().getUsersList(); for (UserInfo userInfo : users) { ResourceInfo resourcesUsed = userInfo.getResourcesUsed(); - PartitionResourcesInfo resourceUsages = userInfo.getResourceUsageInfo() - .getPartitionResourceUsageInfo((nodeLabel == null) ? "" : nodeLabel); + ResourceInfo userAMLimitPerPartition = + queueUsageResources.getUserAmLimit(); + // If AM limit per user is null, use the AM limit for the queue level. + if (userAMLimitPerPartition == null) { + userAMLimitPerPartition = queueUsageResources.getAMLimit(); + } + if (userInfo.getUserWeight() != 1.0) { + userAMLimitPerPartition = + new ResourceInfo( + Resources.multiply(userAMLimitPerPartition.getResource(), + userInfo.getUserWeight())); + } if (nodeLabel != null) { resourcesUsed = userInfo.getResourceUsageInfo() .getPartitionResourceUsageInfo(nodeLabel).getUsed(); @@ -236,7 +250,7 @@ protected void render(Block html) { .td(userInfo.getUserResourceLimit().toString()) .td(String.valueOf(userInfo.getUserWeight())) .td(resourcesUsed.toString()) - .td(resourceUsages.getAMLimit().toString()) + .td(userAMLimitPerPartition.toString()) .td(amUsed.toString()) .td(Integer.toString(userInfo.getNumActiveApplications())) .td(Integer.toString(userInfo.getNumPendingApplications()))._(); 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/PartitionResourcesInfo.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/PartitionResourcesInfo.java index 8b43f5d..6f4c49d 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/PartitionResourcesInfo.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/PartitionResourcesInfo.java @@ -33,13 +33,15 @@ private ResourceInfo pending; private ResourceInfo amUsed; private ResourceInfo amLimit = new ResourceInfo(); + private ResourceInfo userAmLimit; public PartitionResourcesInfo() { } public PartitionResourcesInfo(String partitionName, ResourceInfo used, ResourceInfo reserved, ResourceInfo pending, - ResourceInfo amResourceUsed, ResourceInfo amResourceLimit) { + ResourceInfo amResourceUsed, ResourceInfo amResourceLimit, + ResourceInfo perUserAmResourceLimit) { super(); this.partitionName = partitionName; this.used = used; @@ -47,6 +49,7 @@ public PartitionResourcesInfo(String partitionName, ResourceInfo used, this.pending = pending; this.amUsed = amResourceUsed; this.amLimit = amResourceLimit; + this.userAmLimit = perUserAmResourceLimit; } public String getPartitionName() { @@ -96,4 +99,18 @@ public ResourceInfo getAMLimit() { public void setAMLimit(ResourceInfo amLimit) { this.amLimit = amLimit; } + + /** + * @return the userAmLimit + */ + public ResourceInfo getUserAmLimit() { + return userAmLimit; + } + + /** + * @param userAmLimit the userAmLimit to set + */ + public void setUserAmLimit(ResourceInfo userAmLimit) { + this.userAmLimit = userAmLimit; + } } 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/ResourceInfo.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/ResourceInfo.java index d198bb9..df3d1f0 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/ResourceInfo.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/ResourceInfo.java @@ -27,6 +27,7 @@ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class ResourceInfo { + Resource res; long memory; int vCores; @@ -34,6 +35,7 @@ public ResourceInfo() { } public ResourceInfo(Resource res) { + this.res = res; memory = res.getMemorySize(); vCores = res.getVirtualCores(); } @@ -58,4 +60,8 @@ public void setMemory(int memory) { public void setvCores(int vCores) { this.vCores = vCores; } + + public Resource getResource() { + return res; + } } 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/ResourcesInfo.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/ResourcesInfo.java index 4f1e1c9..1d96f79 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/ResourcesInfo.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/ResourcesInfo.java @@ -51,7 +51,9 @@ public ResourcesInfo(ResourceUsage resourceUsage, considerAMUsage ? new ResourceInfo(resourceUsage .getAMUsed(partitionName)) : null, considerAMUsage ? new ResourceInfo(resourceUsage - .getAMLimit(partitionName)) : null)); + .getAMLimit(partitionName)) : null, + considerAMUsage ? new ResourceInfo(resourceUsage + .getUserAMLimit(partitionName)) : null)); } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesForCSWithPartitions.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesForCSWithPartitions.java index 8087e33..058c49d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesForCSWithPartitions.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesForCSWithPartitions.java @@ -501,13 +501,13 @@ private void verifySchedulerInfoJson(JSONObject json) partitionInfo = partitionsCapsArray.getJSONObject(0); partitionName = partitionInfo.getString("partitionName"); verifyPartitionCapacityInfoJson(partitionInfo, 30, 0, 50, 30, 0, 50); - assertEquals("incorrect number of elements", 6, + assertEquals("incorrect number of elements", 7, partitionsResourcesArray.getJSONObject(0).length()); break; case QUEUE_B: assertEquals("Invalid default Label expression", LABEL_LX, queueJson.getString("defaultNodeLabelExpression")); - assertEquals("incorrect number of elements", 6, + assertEquals("incorrect number of elements", 7, partitionsResourcesArray.getJSONObject(0).length()); verifyAccesibleNodeLabels(queueJson, ImmutableSet.of(LABEL_LX)); assertEquals("incorrect number of partitions", 2,