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