1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.yarn.server.resourcemanager.scheduler; 20 21 import java.util.HashMap; 22 import java.util.Map; 23 import java.util.concurrent.locks.ReentrantReadWriteLock; 24 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; 25 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; 26 27 import org.apache.hadoop.yarn.api.records.Resource; 28 import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager; 29 import org.apache.hadoop.yarn.util.resource.Resources; 30 31 /** 32 * Resource Usage by Labels for following fields by label - AM resource (to 33 * enforce max-am-resource-by-label after YARN-2637) - Used resource (includes 34 * AM resource usage) - Reserved resource - Pending resource - Headroom 35 * 36 * This class can be used to track resource usage in queue/user/app. 37 * 38 * And it is thread-safe 39 */ 40 public class ResourceUsage { 41 private ReadLock readLock; 42 private WriteLock writeLock; 43 private Map<String, UsageByLabel> usages; 44 // short for no-label :) 45 private static final String NL = CommonNodeLabelsManager.NO_LABEL; 46 ResourceUsage()47 public ResourceUsage() { 48 ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 49 readLock = lock.readLock(); 50 writeLock = lock.writeLock(); 51 52 usages = new HashMap<String, UsageByLabel>(); 53 usages.put(NL, new UsageByLabel(NL)); 54 } 55 56 // Usage enum here to make implement cleaner 57 private enum ResourceType { 58 USED(0), PENDING(1), AMUSED(2), RESERVED(3); 59 60 private int idx; 61 ResourceType(int value)62 private ResourceType(int value) { 63 this.idx = value; 64 } 65 } 66 67 private static class UsageByLabel { 68 // usage by label, contains all UsageType 69 private Resource[] resArr; 70 UsageByLabel(String label)71 public UsageByLabel(String label) { 72 resArr = new Resource[ResourceType.values().length]; 73 for (int i = 0; i < resArr.length; i++) { 74 resArr[i] = Resource.newInstance(0, 0); 75 }; 76 } 77 78 @Override toString()79 public String toString() { 80 StringBuilder sb = new StringBuilder(); 81 sb.append("{used=" + resArr[0] + "%, "); 82 sb.append("pending=" + resArr[1] + "%, "); 83 sb.append("am_used=" + resArr[2] + "%, "); 84 sb.append("reserved=" + resArr[3] + "%, "); 85 sb.append("headroom=" + resArr[4] + "%}"); 86 return sb.toString(); 87 } 88 } 89 90 /* 91 * Used 92 */ getUsed()93 public Resource getUsed() { 94 return getUsed(NL); 95 } 96 getUsed(String label)97 public Resource getUsed(String label) { 98 return _get(label, ResourceType.USED); 99 } 100 incUsed(String label, Resource res)101 public void incUsed(String label, Resource res) { 102 _inc(label, ResourceType.USED, res); 103 } 104 incUsed(Resource res)105 public void incUsed(Resource res) { 106 incUsed(NL, res); 107 } 108 decUsed(Resource res)109 public void decUsed(Resource res) { 110 decUsed(NL, res); 111 } 112 decUsed(String label, Resource res)113 public void decUsed(String label, Resource res) { 114 _dec(label, ResourceType.USED, res); 115 } 116 setUsed(Resource res)117 public void setUsed(Resource res) { 118 setUsed(NL, res); 119 } 120 setUsed(String label, Resource res)121 public void setUsed(String label, Resource res) { 122 _set(label, ResourceType.USED, res); 123 } 124 125 /* 126 * Pending 127 */ getPending()128 public Resource getPending() { 129 return getPending(NL); 130 } 131 getPending(String label)132 public Resource getPending(String label) { 133 return _get(label, ResourceType.PENDING); 134 } 135 incPending(String label, Resource res)136 public void incPending(String label, Resource res) { 137 _inc(label, ResourceType.PENDING, res); 138 } 139 incPending(Resource res)140 public void incPending(Resource res) { 141 incPending(NL, res); 142 } 143 decPending(Resource res)144 public void decPending(Resource res) { 145 decPending(NL, res); 146 } 147 decPending(String label, Resource res)148 public void decPending(String label, Resource res) { 149 _dec(label, ResourceType.PENDING, res); 150 } 151 setPending(Resource res)152 public void setPending(Resource res) { 153 setPending(NL, res); 154 } 155 setPending(String label, Resource res)156 public void setPending(String label, Resource res) { 157 _set(label, ResourceType.PENDING, res); 158 } 159 160 /* 161 * Reserved 162 */ getReserved()163 public Resource getReserved() { 164 return getReserved(NL); 165 } 166 getReserved(String label)167 public Resource getReserved(String label) { 168 return _get(label, ResourceType.RESERVED); 169 } 170 incReserved(String label, Resource res)171 public void incReserved(String label, Resource res) { 172 _inc(label, ResourceType.RESERVED, res); 173 } 174 incReserved(Resource res)175 public void incReserved(Resource res) { 176 incReserved(NL, res); 177 } 178 decReserved(Resource res)179 public void decReserved(Resource res) { 180 decReserved(NL, res); 181 } 182 decReserved(String label, Resource res)183 public void decReserved(String label, Resource res) { 184 _dec(label, ResourceType.RESERVED, res); 185 } 186 setReserved(Resource res)187 public void setReserved(Resource res) { 188 setReserved(NL, res); 189 } 190 setReserved(String label, Resource res)191 public void setReserved(String label, Resource res) { 192 _set(label, ResourceType.RESERVED, res); 193 } 194 195 /* 196 * AM-Used 197 */ getAMUsed()198 public Resource getAMUsed() { 199 return getAMUsed(NL); 200 } 201 getAMUsed(String label)202 public Resource getAMUsed(String label) { 203 return _get(label, ResourceType.AMUSED); 204 } 205 incAMUsed(String label, Resource res)206 public void incAMUsed(String label, Resource res) { 207 _inc(label, ResourceType.AMUSED, res); 208 } 209 incAMUsed(Resource res)210 public void incAMUsed(Resource res) { 211 incAMUsed(NL, res); 212 } 213 decAMUsed(Resource res)214 public void decAMUsed(Resource res) { 215 decAMUsed(NL, res); 216 } 217 decAMUsed(String label, Resource res)218 public void decAMUsed(String label, Resource res) { 219 _dec(label, ResourceType.AMUSED, res); 220 } 221 setAMUsed(Resource res)222 public void setAMUsed(Resource res) { 223 setAMUsed(NL, res); 224 } 225 setAMUsed(String label, Resource res)226 public void setAMUsed(String label, Resource res) { 227 _set(label, ResourceType.AMUSED, res); 228 } 229 normalize(Resource res)230 private static Resource normalize(Resource res) { 231 if (res == null) { 232 return Resources.none(); 233 } 234 return res; 235 } 236 _get(String label, ResourceType type)237 private Resource _get(String label, ResourceType type) { 238 try { 239 readLock.lock(); 240 UsageByLabel usage = usages.get(label); 241 if (null == usage) { 242 return Resources.none(); 243 } 244 return normalize(usage.resArr[type.idx]); 245 } finally { 246 readLock.unlock(); 247 } 248 } 249 getAndAddIfMissing(String label)250 private UsageByLabel getAndAddIfMissing(String label) { 251 if (!usages.containsKey(label)) { 252 UsageByLabel u = new UsageByLabel(label); 253 usages.put(label, u); 254 return u; 255 } 256 257 return usages.get(label); 258 } 259 _set(String label, ResourceType type, Resource res)260 private void _set(String label, ResourceType type, Resource res) { 261 try { 262 writeLock.lock(); 263 UsageByLabel usage = getAndAddIfMissing(label); 264 usage.resArr[type.idx] = res; 265 } finally { 266 writeLock.unlock(); 267 } 268 } 269 _inc(String label, ResourceType type, Resource res)270 private void _inc(String label, ResourceType type, Resource res) { 271 try { 272 writeLock.lock(); 273 UsageByLabel usage = getAndAddIfMissing(label); 274 Resources.addTo(usage.resArr[type.idx], res); 275 } finally { 276 writeLock.unlock(); 277 } 278 } 279 _dec(String label, ResourceType type, Resource res)280 private void _dec(String label, ResourceType type, Resource res) { 281 try { 282 writeLock.lock(); 283 UsageByLabel usage = getAndAddIfMissing(label); 284 Resources.subtractFrom(usage.resArr[type.idx], res); 285 } finally { 286 writeLock.unlock(); 287 } 288 } 289 290 @Override toString()291 public String toString() { 292 try { 293 readLock.lock(); 294 return usages.toString(); 295 } finally { 296 readLock.unlock(); 297 } 298 } 299 } 300