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.Stable;
025    import org.apache.hadoop.yarn.api.ApplicationMasterProtocol;
026    import org.apache.hadoop.yarn.util.Records;
027    
028    /**
029     * <p><code>ResourceRequest</code> represents the request made by an
030     * application to the <code>ResourceManager</code> to obtain various 
031     * <code>Container</code> allocations.</p>
032     * 
033     * <p>It includes:
034     *   <ul>
035     *     <li>{@link Priority} of the request.</li>
036     *     <li>
037     *       The <em>name</em> of the machine or rack on which the allocation is 
038     *       desired. A special value of <em>*</em> signifies that 
039     *       <em>any</em> host/rack is acceptable to the application.
040     *     </li>
041     *     <li>{@link Resource} required for each request.</li>
042     *     <li>
043     *       Number of containers, of above specifications, which are required 
044     *       by the application.
045     *     </li>
046     *     <li>
047     *       A boolean <em>relaxLocality</em> flag, defaulting to <code>true</code>,
048     *       which tells the <code>ResourceManager</code> if the application wants
049     *       locality to be loose (i.e. allows fall-through to rack or <em>any</em>)
050     *       or strict (i.e. specify hard constraint on resource allocation).
051     *     </li>
052     *   </ul>
053     * </p>
054     * 
055     * @see Resource
056     * @see ApplicationMasterProtocol#allocate(org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest)
057     */
058    @Public
059    @Stable
060    public 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        ResourceRequest request = Records.newRecord(ResourceRequest.class);
074        request.setPriority(priority);
075        request.setResourceName(hostName);
076        request.setCapability(capability);
077        request.setNumContainers(numContainers);
078        request.setRelaxLocality(relaxLocality);
079        return request;
080      }
081    
082      @Public
083      @Stable
084      public static class ResourceRequestComparator implements
085          java.util.Comparator<ResourceRequest>, Serializable {
086    
087        private static final long serialVersionUID = 1L;
088    
089        @Override
090        public int compare(ResourceRequest r1, ResourceRequest r2) {
091    
092          // Compare priority, host and capability
093          int ret = r1.getPriority().compareTo(r2.getPriority());
094          if (ret == 0) {
095            String h1 = r1.getResourceName();
096            String h2 = r2.getResourceName();
097            ret = h1.compareTo(h2);
098          }
099          if (ret == 0) {
100            ret = r1.getCapability().compareTo(r2.getCapability());
101          }
102          return ret;
103        }
104      }
105    
106      /**
107       * The constant string representing no locality.
108       * It should be used by all references that want to pass an arbitrary host
109       * name in.
110       */
111      public static final String ANY = "*";
112    
113      /**
114       * Check whether the given <em>host/rack</em> string represents an arbitrary
115       * host name.
116       *
117       * @param hostName <em>host/rack</em> on which the allocation is desired
118       * @return whether the given <em>host/rack</em> string represents an arbitrary
119       * host name
120       */
121      @Public
122      @Stable
123      public static boolean isAnyLocation(String hostName) {
124        return ANY.equals(hostName);
125      }
126    
127      /**
128       * Get the <code>Priority</code> of the request.
129       * @return <code>Priority</code> of the request
130       */
131      @Public
132      @Stable
133      public abstract Priority getPriority();
134    
135      /**
136       * Set the <code>Priority</code> of the request
137       * @param priority <code>Priority</code> of the request
138       */
139      @Public
140      @Stable
141      public abstract void setPriority(Priority priority);
142      
143      /**
144       * Get the resource (e.g. <em>host/rack</em>) on which the allocation 
145       * is desired.
146       * 
147       * A special value of <em>*</em> signifies that <em>any</em> resource 
148       * (host/rack) is acceptable.
149       * 
150       * @return resource (e.g. <em>host/rack</em>) on which the allocation 
151       *                  is desired
152       */
153      @Public
154      @Stable
155      public abstract String getResourceName();
156    
157      /**
158       * Set the resource name (e.g. <em>host/rack</em>) on which the allocation 
159       * is desired.
160       * 
161       * A special value of <em>*</em> signifies that <em>any</em> resource name
162       * (e.g. host/rack) is acceptable. 
163       * 
164       * @param resourceName (e.g. <em>host/rack</em>) on which the 
165       *                     allocation is desired
166       */
167      @Public
168      @Stable
169      public abstract void setResourceName(String resourceName);
170      
171      /**
172       * Get the <code>Resource</code> capability of the request.
173       * @return <code>Resource</code> capability of the request
174       */
175      @Public
176      @Stable
177      public abstract Resource getCapability();
178      
179      /**
180       * Set the <code>Resource</code> capability of the request
181       * @param capability <code>Resource</code> capability of the request
182       */
183      @Public
184      @Stable
185      public abstract void setCapability(Resource capability);
186    
187      /**
188       * Get the number of containers required with the given specifications.
189       * @return number of containers required with the given specifications
190       */
191      @Public
192      @Stable
193      public abstract int getNumContainers();
194      
195      /**
196       * Set the number of containers required with the given specifications
197       * @param numContainers number of containers required with the given 
198       *                      specifications
199       */
200      @Public
201      @Stable
202      public abstract void setNumContainers(int numContainers);
203    
204      /**
205       * Get whether locality relaxation is enabled with this
206       * <code>ResourceRequest</code>. Defaults to true.
207       * 
208       * @return whether locality relaxation is enabled with this
209       * <code>ResourceRequest</code>.
210       */
211      @Public
212      @Stable
213      public abstract boolean getRelaxLocality();
214      
215      /**
216       * <p>For a request at a network hierarchy level, set whether locality can be relaxed
217       * to that level and beyond.<p>
218       * 
219       * <p>If the flag is off on a rack-level <code>ResourceRequest</code>,
220       * containers at that request's priority will not be assigned to nodes on that
221       * request's rack unless requests specifically for those nodes have also been
222       * submitted.<p>
223       * 
224       * <p>If the flag is off on an {@link ResourceRequest#ANY}-level
225       * <code>ResourceRequest</code>, containers at that request's priority will
226       * only be assigned on racks for which specific requests have also been
227       * submitted.<p>
228       * 
229       * <p>For example, to request a container strictly on a specific node, the
230       * corresponding rack-level and any-level requests should have locality
231       * relaxation set to false.  Similarly, to request a container strictly on a
232       * specific rack, the corresponding any-level request should have locality
233       * relaxation set to false.<p>
234       * 
235       * @param relaxLocality whether locality relaxation is enabled with this
236       * <code>ResourceRequest</code>.
237       */
238      @Public
239      @Stable
240      public abstract void setRelaxLocality(boolean relaxLocality);
241      
242      @Override
243      public int hashCode() {
244        final int prime = 2153;
245        int result = 2459;
246        Resource capability = getCapability();
247        String hostName = getResourceName();
248        Priority priority = getPriority();
249        result =
250            prime * result + ((capability == null) ? 0 : capability.hashCode());
251        result = prime * result + ((hostName == null) ? 0 : hostName.hashCode());
252        result = prime * result + getNumContainers();
253        result = prime * result + ((priority == null) ? 0 : priority.hashCode());
254        return result;
255      }
256    
257      @Override
258      public boolean equals(Object obj) {
259        if (this == obj)
260          return true;
261        if (obj == null)
262          return false;
263        if (getClass() != obj.getClass())
264          return false;
265        ResourceRequest other = (ResourceRequest) obj;
266        Resource capability = getCapability();
267        if (capability == null) {
268          if (other.getCapability() != null)
269            return false;
270        } else if (!capability.equals(other.getCapability()))
271          return false;
272        String hostName = getResourceName();
273        if (hostName == null) {
274          if (other.getResourceName() != null)
275            return false;
276        } else if (!hostName.equals(other.getResourceName()))
277          return false;
278        if (getNumContainers() != other.getNumContainers())
279          return false;
280        Priority priority = getPriority();
281        if (priority == null) {
282          if (other.getPriority() != null)
283            return false;
284        } else if (!priority.equals(other.getPriority()))
285          return false;
286        return true;
287      }
288    
289      @Override
290      public int compareTo(ResourceRequest other) {
291        int priorityComparison = this.getPriority().compareTo(other.getPriority());
292        if (priorityComparison == 0) {
293          int hostNameComparison =
294              this.getResourceName().compareTo(other.getResourceName());
295          if (hostNameComparison == 0) {
296            int capabilityComparison =
297                this.getCapability().compareTo(other.getCapability());
298            if (capabilityComparison == 0) {
299              int numContainersComparison =
300                  this.getNumContainers() - other.getNumContainers();
301              if (numContainersComparison == 0) {
302                return 0;
303              } else {
304                return numContainersComparison;
305              }
306            } else {
307              return capabilityComparison;
308            }
309          } else {
310            return hostNameComparison;
311          }
312        } else {
313          return priorityComparison;
314        }
315      }
316    }