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 019package org.apache.hadoop.yarn.api.records; 020 021import java.io.Serializable; 022 023import org.apache.hadoop.classification.InterfaceAudience.Public; 024import org.apache.hadoop.classification.InterfaceStability.Evolving; 025import org.apache.hadoop.classification.InterfaceStability.Stable; 026import org.apache.hadoop.yarn.api.ApplicationMasterProtocol; 027import org.apache.hadoop.yarn.util.Records; 028 029/** 030 * {@code ResourceRequest} represents the request made 031 * by an application to the {@code ResourceManager} 032 * to obtain various {@code Container} allocations. 033 * <p> 034 * 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}, 049 * which tells the {@code ResourceManager} 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 * 055 * @see Resource 056 * @see ApplicationMasterProtocol#allocate(org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest) 057 */ 058@Public 059@Stable 060public abstract class ResourceRequest implements Comparable<ResourceRequest> { 061 062 @Public 063 @Stable 064 public static ResourceRequest newInstance(Priority priority, String hostName, 065 Resource capability, int numContainers) { 066 return newInstance(priority, hostName, capability, numContainers, true); 067 } 068 069 @Public 070 @Stable 071 public static ResourceRequest newInstance(Priority priority, String hostName, 072 Resource capability, int numContainers, boolean relaxLocality) { 073 return newInstance(priority, hostName, capability, numContainers, 074 relaxLocality, null); 075 } 076 077 @Public 078 @Stable 079 public static ResourceRequest newInstance(Priority priority, String hostName, 080 Resource capability, int numContainers, boolean relaxLocality, 081 String labelExpression) { 082 ResourceRequest request = Records.newRecord(ResourceRequest.class); 083 request.setPriority(priority); 084 request.setResourceName(hostName); 085 request.setCapability(capability); 086 request.setNumContainers(numContainers); 087 request.setRelaxLocality(relaxLocality); 088 request.setNodeLabelExpression(labelExpression); 089 return request; 090 } 091 092 @Public 093 @Stable 094 public static class ResourceRequestComparator implements 095 java.util.Comparator<ResourceRequest>, Serializable { 096 097 private static final long serialVersionUID = 1L; 098 099 @Override 100 public int compare(ResourceRequest r1, ResourceRequest r2) { 101 102 // Compare priority, host and capability 103 int ret = r1.getPriority().compareTo(r2.getPriority()); 104 if (ret == 0) { 105 String h1 = r1.getResourceName(); 106 String h2 = r2.getResourceName(); 107 ret = h1.compareTo(h2); 108 } 109 if (ret == 0) { 110 ret = r1.getCapability().compareTo(r2.getCapability()); 111 } 112 return ret; 113 } 114 } 115 116 /** 117 * The constant string representing no locality. 118 * It should be used by all references that want to pass an arbitrary host 119 * name in. 120 */ 121 public static final String ANY = "*"; 122 123 /** 124 * Check whether the given <em>host/rack</em> string represents an arbitrary 125 * host name. 126 * 127 * @param hostName <em>host/rack</em> on which the allocation is desired 128 * @return whether the given <em>host/rack</em> string represents an arbitrary 129 * host name 130 */ 131 @Public 132 @Stable 133 public static boolean isAnyLocation(String hostName) { 134 return ANY.equals(hostName); 135 } 136 137 /** 138 * Get the <code>Priority</code> of the request. 139 * @return <code>Priority</code> of the request 140 */ 141 @Public 142 @Stable 143 public abstract Priority getPriority(); 144 145 /** 146 * Set the <code>Priority</code> of the request 147 * @param priority <code>Priority</code> of the request 148 */ 149 @Public 150 @Stable 151 public abstract void setPriority(Priority priority); 152 153 /** 154 * Get the resource (e.g. <em>host/rack</em>) on which the allocation 155 * is desired. 156 * 157 * A special value of <em>*</em> signifies that <em>any</em> resource 158 * (host/rack) is acceptable. 159 * 160 * @return resource (e.g. <em>host/rack</em>) on which the allocation 161 * is desired 162 */ 163 @Public 164 @Stable 165 public abstract String getResourceName(); 166 167 /** 168 * Set the resource name (e.g. <em>host/rack</em>) on which the allocation 169 * is desired. 170 * 171 * A special value of <em>*</em> signifies that <em>any</em> resource name 172 * (e.g. host/rack) is acceptable. 173 * 174 * @param resourceName (e.g. <em>host/rack</em>) on which the 175 * allocation is desired 176 */ 177 @Public 178 @Stable 179 public abstract void setResourceName(String resourceName); 180 181 /** 182 * Get the <code>Resource</code> capability of the request. 183 * @return <code>Resource</code> capability of the request 184 */ 185 @Public 186 @Stable 187 public abstract Resource getCapability(); 188 189 /** 190 * Set the <code>Resource</code> capability of the request 191 * @param capability <code>Resource</code> capability of the request 192 */ 193 @Public 194 @Stable 195 public abstract void setCapability(Resource capability); 196 197 /** 198 * Get the number of containers required with the given specifications. 199 * @return number of containers required with the given specifications 200 */ 201 @Public 202 @Stable 203 public abstract int getNumContainers(); 204 205 /** 206 * Set the number of containers required with the given specifications 207 * @param numContainers number of containers required with the given 208 * specifications 209 */ 210 @Public 211 @Stable 212 public abstract void setNumContainers(int numContainers); 213 214 /** 215 * Get whether locality relaxation is enabled with this 216 * <code>ResourceRequest</code>. Defaults to true. 217 * 218 * @return whether locality relaxation is enabled with this 219 * <code>ResourceRequest</code>. 220 */ 221 @Public 222 @Stable 223 public abstract boolean getRelaxLocality(); 224 225 /** 226 * <p>For a request at a network hierarchy level, set whether locality can be relaxed 227 * to that level and beyond.<p> 228 * 229 * <p>If the flag is off on a rack-level <code>ResourceRequest</code>, 230 * containers at that request's priority will not be assigned to nodes on that 231 * request's rack unless requests specifically for those nodes have also been 232 * submitted.<p> 233 * 234 * <p>If the flag is off on an {@link ResourceRequest#ANY}-level 235 * <code>ResourceRequest</code>, containers at that request's priority will 236 * only be assigned on racks for which specific requests have also been 237 * submitted.<p> 238 * 239 * <p>For example, to request a container strictly on a specific node, the 240 * corresponding rack-level and any-level requests should have locality 241 * relaxation set to false. Similarly, to request a container strictly on a 242 * specific rack, the corresponding any-level request should have locality 243 * relaxation set to false.<p> 244 * 245 * @param relaxLocality whether locality relaxation is enabled with this 246 * <code>ResourceRequest</code>. 247 */ 248 @Public 249 @Stable 250 public abstract void setRelaxLocality(boolean relaxLocality); 251 252 /** 253 * Get node-label-expression for this Resource Request. If this is set, all 254 * containers allocated to satisfy this resource-request will be only on those 255 * nodes that satisfy this node-label-expression. 256 * 257 * Please note that node label expression now can only take effect when the 258 * resource request has resourceName = ANY 259 * 260 * @return node-label-expression 261 */ 262 @Public 263 @Evolving 264 public abstract String getNodeLabelExpression(); 265 266 /** 267 * Set node label expression of this resource request. Now only support 268 * specifying a single node label. In the future we will support more complex 269 * node label expression specification like {@code AND(&&), OR(||)}, etc. 270 * 271 * Any please note that node label expression now can only take effect when 272 * the resource request has resourceName = ANY 273 * 274 * @param nodelabelExpression 275 * node-label-expression of this ResourceRequest 276 */ 277 @Public 278 @Evolving 279 public abstract void setNodeLabelExpression(String nodelabelExpression); 280 281 @Override 282 public int hashCode() { 283 final int prime = 2153; 284 int result = 2459; 285 Resource capability = getCapability(); 286 String hostName = getResourceName(); 287 Priority priority = getPriority(); 288 result = 289 prime * result + ((capability == null) ? 0 : capability.hashCode()); 290 result = prime * result + ((hostName == null) ? 0 : hostName.hashCode()); 291 result = prime * result + getNumContainers(); 292 result = prime * result + ((priority == null) ? 0 : priority.hashCode()); 293 return result; 294 } 295 296 @Override 297 public boolean equals(Object obj) { 298 if (this == obj) 299 return true; 300 if (obj == null) 301 return false; 302 if (getClass() != obj.getClass()) 303 return false; 304 ResourceRequest other = (ResourceRequest) obj; 305 Resource capability = getCapability(); 306 if (capability == null) { 307 if (other.getCapability() != null) 308 return false; 309 } else if (!capability.equals(other.getCapability())) 310 return false; 311 String hostName = getResourceName(); 312 if (hostName == null) { 313 if (other.getResourceName() != null) 314 return false; 315 } else if (!hostName.equals(other.getResourceName())) 316 return false; 317 if (getNumContainers() != other.getNumContainers()) 318 return false; 319 Priority priority = getPriority(); 320 if (priority == null) { 321 if (other.getPriority() != null) 322 return false; 323 } else if (!priority.equals(other.getPriority())) 324 return false; 325 if (getNodeLabelExpression() == null) { 326 if (other.getNodeLabelExpression() != null) { 327 return false; 328 } 329 } else { 330 // do normalize on label expression before compare 331 String label1 = getNodeLabelExpression().replaceAll("[\\t ]", ""); 332 String label2 = 333 other.getNodeLabelExpression() == null ? null : other 334 .getNodeLabelExpression().replaceAll("[\\t ]", ""); 335 if (!label1.equals(label2)) { 336 return false; 337 } 338 } 339 return true; 340 } 341 342 @Override 343 public int compareTo(ResourceRequest other) { 344 int priorityComparison = this.getPriority().compareTo(other.getPriority()); 345 if (priorityComparison == 0) { 346 int hostNameComparison = 347 this.getResourceName().compareTo(other.getResourceName()); 348 if (hostNameComparison == 0) { 349 int capabilityComparison = 350 this.getCapability().compareTo(other.getCapability()); 351 if (capabilityComparison == 0) { 352 return this.getNumContainers() - other.getNumContainers(); 353 } else { 354 return capabilityComparison; 355 } 356 } else { 357 return hostNameComparison; 358 } 359 } else { 360 return priorityComparison; 361 } 362 } 363}