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 }