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 * <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 061public 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 * Please note that node label expression now can only take effect when the 259 * resource request has resourceName = ANY 260 * 261 * @return node-label-expression 262 */ 263 @Public 264 @Evolving 265 public abstract String getNodeLabelExpression(); 266 267 /** 268 * Set node label expression of this resource request. Now only support 269 * specifying a single node label. In the future we will support more complex 270 * node label expression specification like AND(&&), OR(||), etc. 271 * 272 * Any please note that node label expression now can only take effect when 273 * the resource request has resourceName = ANY 274 * 275 * @param nodelabelExpression 276 * node-label-expression of this ResourceRequest 277 */ 278 @Public 279 @Evolving 280 public abstract void setNodeLabelExpression(String nodelabelExpression); 281 282 @Override 283 public int hashCode() { 284 final int prime = 2153; 285 int result = 2459; 286 Resource capability = getCapability(); 287 String hostName = getResourceName(); 288 Priority priority = getPriority(); 289 result = 290 prime * result + ((capability == null) ? 0 : capability.hashCode()); 291 result = prime * result + ((hostName == null) ? 0 : hostName.hashCode()); 292 result = prime * result + getNumContainers(); 293 result = prime * result + ((priority == null) ? 0 : priority.hashCode()); 294 return result; 295 } 296 297 @Override 298 public boolean equals(Object obj) { 299 if (this == obj) 300 return true; 301 if (obj == null) 302 return false; 303 if (getClass() != obj.getClass()) 304 return false; 305 ResourceRequest other = (ResourceRequest) obj; 306 Resource capability = getCapability(); 307 if (capability == null) { 308 if (other.getCapability() != null) 309 return false; 310 } else if (!capability.equals(other.getCapability())) 311 return false; 312 String hostName = getResourceName(); 313 if (hostName == null) { 314 if (other.getResourceName() != null) 315 return false; 316 } else if (!hostName.equals(other.getResourceName())) 317 return false; 318 if (getNumContainers() != other.getNumContainers()) 319 return false; 320 Priority priority = getPriority(); 321 if (priority == null) { 322 if (other.getPriority() != null) 323 return false; 324 } else if (!priority.equals(other.getPriority())) 325 return false; 326 if (getNodeLabelExpression() == null) { 327 if (other.getNodeLabelExpression() != null) { 328 return false; 329 } 330 } else { 331 // do normalize on label expression before compare 332 String label1 = getNodeLabelExpression().replaceAll("[\\t ]", ""); 333 String label2 = 334 other.getNodeLabelExpression() == null ? null : other 335 .getNodeLabelExpression().replaceAll("[\\t ]", ""); 336 if (!label1.equals(label2)) { 337 return false; 338 } 339 } 340 return true; 341 } 342 343 @Override 344 public int compareTo(ResourceRequest other) { 345 int priorityComparison = this.getPriority().compareTo(other.getPriority()); 346 if (priorityComparison == 0) { 347 int hostNameComparison = 348 this.getResourceName().compareTo(other.getResourceName()); 349 if (hostNameComparison == 0) { 350 int capabilityComparison = 351 this.getCapability().compareTo(other.getCapability()); 352 if (capabilityComparison == 0) { 353 return this.getNumContainers() - other.getNumContainers(); 354 } else { 355 return capabilityComparison; 356 } 357 } else { 358 return hostNameComparison; 359 } 360 } else { 361 return priorityComparison; 362 } 363 } 364}