001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.hadoop.yarn.api.records;
020
021 import java.io.Serializable;
022
023 import org.apache.hadoop.classification.InterfaceAudience.Public;
024 import org.apache.hadoop.classification.InterfaceStability.Evolving;
025 import org.apache.hadoop.classification.InterfaceStability.Stable;
026 import org.apache.hadoop.yarn.api.ApplicationMasterProtocol;
027 import org.apache.hadoop.yarn.util.Records;
028
029 /**
030 * <p><code>ResourceRequest</code> represents the request made by an
031 * application to the <code>ResourceManager</code> to obtain various
032 * <code>Container</code> allocations.</p>
033 *
034 * <p>It includes:
035 * <ul>
036 * <li>{@link Priority} of the request.</li>
037 * <li>
038 * The <em>name</em> of the machine or rack on which the allocation is
039 * desired. A special value of <em>*</em> signifies that
040 * <em>any</em> host/rack is acceptable to the application.
041 * </li>
042 * <li>{@link Resource} required for each request.</li>
043 * <li>
044 * Number of containers, of above specifications, which are required
045 * by the application.
046 * </li>
047 * <li>
048 * A boolean <em>relaxLocality</em> flag, defaulting to <code>true</code>,
049 * which tells the <code>ResourceManager</code> if the application wants
050 * locality to be loose (i.e. allows fall-through to rack or <em>any</em>)
051 * or strict (i.e. specify hard constraint on resource allocation).
052 * </li>
053 * </ul>
054 * </p>
055 *
056 * @see Resource
057 * @see ApplicationMasterProtocol#allocate(org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest)
058 */
059 @Public
060 @Stable
061 public abstract class ResourceRequest implements Comparable<ResourceRequest> {
062
063 @Public
064 @Stable
065 public static ResourceRequest newInstance(Priority priority, String hostName,
066 Resource capability, int numContainers) {
067 return newInstance(priority, hostName, capability, numContainers, true);
068 }
069
070 @Public
071 @Stable
072 public static ResourceRequest newInstance(Priority priority, String hostName,
073 Resource capability, int numContainers, boolean relaxLocality) {
074 return newInstance(priority, hostName, capability, numContainers,
075 relaxLocality, null);
076 }
077
078 @Public
079 @Stable
080 public static ResourceRequest newInstance(Priority priority, String hostName,
081 Resource capability, int numContainers, boolean relaxLocality,
082 String labelExpression) {
083 ResourceRequest request = Records.newRecord(ResourceRequest.class);
084 request.setPriority(priority);
085 request.setResourceName(hostName);
086 request.setCapability(capability);
087 request.setNumContainers(numContainers);
088 request.setRelaxLocality(relaxLocality);
089 request.setNodeLabelExpression(labelExpression);
090 return request;
091 }
092
093 @Public
094 @Stable
095 public static class ResourceRequestComparator implements
096 java.util.Comparator<ResourceRequest>, Serializable {
097
098 private static final long serialVersionUID = 1L;
099
100 @Override
101 public int compare(ResourceRequest r1, ResourceRequest r2) {
102
103 // Compare priority, host and capability
104 int ret = r1.getPriority().compareTo(r2.getPriority());
105 if (ret == 0) {
106 String h1 = r1.getResourceName();
107 String h2 = r2.getResourceName();
108 ret = h1.compareTo(h2);
109 }
110 if (ret == 0) {
111 ret = r1.getCapability().compareTo(r2.getCapability());
112 }
113 return ret;
114 }
115 }
116
117 /**
118 * The constant string representing no locality.
119 * It should be used by all references that want to pass an arbitrary host
120 * name in.
121 */
122 public static final String ANY = "*";
123
124 /**
125 * Check whether the given <em>host/rack</em> string represents an arbitrary
126 * host name.
127 *
128 * @param hostName <em>host/rack</em> on which the allocation is desired
129 * @return whether the given <em>host/rack</em> string represents an arbitrary
130 * host name
131 */
132 @Public
133 @Stable
134 public static boolean isAnyLocation(String hostName) {
135 return ANY.equals(hostName);
136 }
137
138 /**
139 * Get the <code>Priority</code> of the request.
140 * @return <code>Priority</code> of the request
141 */
142 @Public
143 @Stable
144 public abstract Priority getPriority();
145
146 /**
147 * Set the <code>Priority</code> of the request
148 * @param priority <code>Priority</code> of the request
149 */
150 @Public
151 @Stable
152 public abstract void setPriority(Priority priority);
153
154 /**
155 * Get the resource (e.g. <em>host/rack</em>) on which the allocation
156 * is desired.
157 *
158 * A special value of <em>*</em> signifies that <em>any</em> resource
159 * (host/rack) is acceptable.
160 *
161 * @return resource (e.g. <em>host/rack</em>) on which the allocation
162 * is desired
163 */
164 @Public
165 @Stable
166 public abstract String getResourceName();
167
168 /**
169 * Set the resource name (e.g. <em>host/rack</em>) on which the allocation
170 * is desired.
171 *
172 * A special value of <em>*</em> signifies that <em>any</em> resource name
173 * (e.g. host/rack) is acceptable.
174 *
175 * @param resourceName (e.g. <em>host/rack</em>) on which the
176 * allocation is desired
177 */
178 @Public
179 @Stable
180 public abstract void setResourceName(String resourceName);
181
182 /**
183 * Get the <code>Resource</code> capability of the request.
184 * @return <code>Resource</code> capability of the request
185 */
186 @Public
187 @Stable
188 public abstract Resource getCapability();
189
190 /**
191 * Set the <code>Resource</code> capability of the request
192 * @param capability <code>Resource</code> capability of the request
193 */
194 @Public
195 @Stable
196 public abstract void setCapability(Resource capability);
197
198 /**
199 * Get the number of containers required with the given specifications.
200 * @return number of containers required with the given specifications
201 */
202 @Public
203 @Stable
204 public abstract int getNumContainers();
205
206 /**
207 * Set the number of containers required with the given specifications
208 * @param numContainers number of containers required with the given
209 * specifications
210 */
211 @Public
212 @Stable
213 public abstract void setNumContainers(int numContainers);
214
215 /**
216 * Get whether locality relaxation is enabled with this
217 * <code>ResourceRequest</code>. Defaults to true.
218 *
219 * @return whether locality relaxation is enabled with this
220 * <code>ResourceRequest</code>.
221 */
222 @Public
223 @Stable
224 public abstract boolean getRelaxLocality();
225
226 /**
227 * <p>For a request at a network hierarchy level, set whether locality can be relaxed
228 * to that level and beyond.<p>
229 *
230 * <p>If the flag is off on a rack-level <code>ResourceRequest</code>,
231 * containers at that request's priority will not be assigned to nodes on that
232 * request's rack unless requests specifically for those nodes have also been
233 * submitted.<p>
234 *
235 * <p>If the flag is off on an {@link ResourceRequest#ANY}-level
236 * <code>ResourceRequest</code>, containers at that request's priority will
237 * only be assigned on racks for which specific requests have also been
238 * submitted.<p>
239 *
240 * <p>For example, to request a container strictly on a specific node, the
241 * corresponding rack-level and any-level requests should have locality
242 * relaxation set to false. Similarly, to request a container strictly on a
243 * specific rack, the corresponding any-level request should have locality
244 * relaxation set to false.<p>
245 *
246 * @param relaxLocality whether locality relaxation is enabled with this
247 * <code>ResourceRequest</code>.
248 */
249 @Public
250 @Stable
251 public abstract void setRelaxLocality(boolean relaxLocality);
252
253 /**
254 * Get node-label-expression for this Resource Request. If this is set, all
255 * containers allocated to satisfy this resource-request will be only on those
256 * nodes that satisfy this node-label-expression
257 *
258 * @return node-label-expression
259 */
260 @Public
261 @Evolving
262 public abstract String getNodeLabelExpression();
263
264 /**
265 * Set node label expression of this resource request. Now only
266 * support AND(&&), in the future will provide support for OR(||), NOT(!).
267 *
268 * Examples:
269 * - GPU && LARGE_MEM, ask for node has label GPU and LARGE_MEM together
270 * - "" (empty) means ask for node doesn't have label on it, this is default
271 * behavior
272 *
273 * @param nodelabelExpression node-label-expression of this ResourceRequest
274 */
275 @Public
276 @Evolving
277 public abstract void setNodeLabelExpression(String nodelabelExpression);
278
279 @Override
280 public int hashCode() {
281 final int prime = 2153;
282 int result = 2459;
283 Resource capability = getCapability();
284 String hostName = getResourceName();
285 Priority priority = getPriority();
286 result =
287 prime * result + ((capability == null) ? 0 : capability.hashCode());
288 result = prime * result + ((hostName == null) ? 0 : hostName.hashCode());
289 result = prime * result + getNumContainers();
290 result = prime * result + ((priority == null) ? 0 : priority.hashCode());
291 return result;
292 }
293
294 @Override
295 public boolean equals(Object obj) {
296 if (this == obj)
297 return true;
298 if (obj == null)
299 return false;
300 if (getClass() != obj.getClass())
301 return false;
302 ResourceRequest other = (ResourceRequest) obj;
303 Resource capability = getCapability();
304 if (capability == null) {
305 if (other.getCapability() != null)
306 return false;
307 } else if (!capability.equals(other.getCapability()))
308 return false;
309 String hostName = getResourceName();
310 if (hostName == null) {
311 if (other.getResourceName() != null)
312 return false;
313 } else if (!hostName.equals(other.getResourceName()))
314 return false;
315 if (getNumContainers() != other.getNumContainers())
316 return false;
317 Priority priority = getPriority();
318 if (priority == null) {
319 if (other.getPriority() != null)
320 return false;
321 } else if (!priority.equals(other.getPriority()))
322 return false;
323 if (getNodeLabelExpression() == null) {
324 if (other.getNodeLabelExpression() != null) {
325 return false;
326 }
327 } else {
328 // do normalize on label expression before compare
329 String label1 = getNodeLabelExpression().replaceAll("[\\t ]", "");
330 String label2 =
331 other.getNodeLabelExpression() == null ? null : other
332 .getNodeLabelExpression().replaceAll("[\\t ]", "");
333 if (!label1.equals(label2)) {
334 return false;
335 }
336 }
337 return true;
338 }
339
340 @Override
341 public int compareTo(ResourceRequest other) {
342 int priorityComparison = this.getPriority().compareTo(other.getPriority());
343 if (priorityComparison == 0) {
344 int hostNameComparison =
345 this.getResourceName().compareTo(other.getResourceName());
346 if (hostNameComparison == 0) {
347 int capabilityComparison =
348 this.getCapability().compareTo(other.getCapability());
349 if (capabilityComparison == 0) {
350 return this.getNumContainers() - other.getNumContainers();
351 } else {
352 return capabilityComparison;
353 }
354 } else {
355 return hostNameComparison;
356 }
357 } else {
358 return priorityComparison;
359 }
360 }
361 }