Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.yarn.api.records; import java.io.Serializable; import org.apache.hadoop.classification.InterfaceAudience.Public; import org.apache.hadoop.classification.InterfaceStability.Evolving; import org.apache.hadoop.classification.InterfaceStability.Stable; import org.apache.hadoop.classification.InterfaceStability.Unstable; import org.apache.hadoop.yarn.api.ApplicationMasterProtocol; import org.apache.hadoop.yarn.util.Records; /** * {@code ResourceRequest} represents the request made * by an application to the {@code ResourceManager} * to obtain various {@code Container} allocations. * <p> * It includes: * <ul> * <li>{@link Priority} of the request.</li> * <li> * The <em>name</em> of the host or rack on which the allocation is * desired. A special value of <em>*</em> signifies that * <em>any</em> host/rack is acceptable to the application. * </li> * <li>{@link Resource} required for each request.</li> * <li> * Number of containers, of above specifications, which are required * by the application. * </li> * <li> * A boolean <em>relaxLocality</em> flag, defaulting to {@code true}, * which tells the {@code ResourceManager} if the application wants * locality to be loose (i.e. allows fall-through to rack or <em>any</em>) * or strict (i.e. specify hard constraint on resource allocation). * </li> * </ul> * * @see Resource * @see ApplicationMasterProtocol#allocate(org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest) */ @Public @Stable public abstract class ResourceRequest implements Comparable<ResourceRequest> { @Public @Stable public static ResourceRequest newInstance(Priority priority, String hostName, Resource capability, int numContainers) { return ResourceRequest.newBuilder().priority(priority).resourceName(hostName).capability(capability) .numContainers(numContainers).build(); } @Public @Stable public static ResourceRequest newInstance(Priority priority, String hostName, Resource capability, int numContainers, boolean relaxLocality) { return ResourceRequest.newBuilder().priority(priority).resourceName(hostName).capability(capability) .numContainers(numContainers).relaxLocality(relaxLocality).build(); } @Public @Stable public static ResourceRequest newInstance(Priority priority, String hostName, Resource capability, int numContainers, boolean relaxLocality, String labelExpression) { return ResourceRequest.newBuilder().priority(priority).resourceName(hostName).capability(capability) .numContainers(numContainers).relaxLocality(relaxLocality).nodeLabelExpression(labelExpression) .build(); } @Public @Evolving public static ResourceRequest newInstance(Priority priority, String hostName, Resource capability, int numContainers, boolean relaxLocality, String labelExpression, ExecutionTypeRequest executionTypeRequest) { return ResourceRequest.newBuilder().priority(priority).resourceName(hostName).capability(capability) .numContainers(numContainers).relaxLocality(relaxLocality).nodeLabelExpression(labelExpression) .executionTypeRequest(executionTypeRequest).build(); } /** * Clone a ResourceRequest object (shallow copy). Please keep it loaded with * all (new) fields * * @param rr the object to copy from * @return the copied object */ @Public @Evolving public static ResourceRequest clone(ResourceRequest rr) { // Please keep it loaded with all (new) fields return ResourceRequest.newBuilder().priority(rr.getPriority()).resourceName(rr.getResourceName()) .capability(rr.getCapability()).numContainers(rr.getNumContainers()) .relaxLocality(rr.getRelaxLocality()).nodeLabelExpression(rr.getNodeLabelExpression()) .executionTypeRequest(rr.getExecutionTypeRequest()).allocationRequestId(rr.getAllocationRequestId()) .build(); } @Public @Unstable public static ResourceRequestBuilder newBuilder() { return new ResourceRequestBuilder(); } /** * Class to construct instances of {@link ResourceRequest} with specific * options. */ @Public @Stable public static final class ResourceRequestBuilder { private ResourceRequest resourceRequest = Records.newRecord(ResourceRequest.class); private ResourceRequestBuilder() { resourceRequest.setResourceName(ANY); resourceRequest.setNumContainers(1); resourceRequest.setPriority(Priority.newInstance(0)); resourceRequest.setRelaxLocality(true); resourceRequest.setExecutionTypeRequest(ExecutionTypeRequest.newInstance()); } /** * Set the <code>priority</code> of the request. * @see ResourceRequest#setPriority(Priority) * @param priority <code>priority</code> of the request * @return {@link ResourceRequestBuilder} */ @Public @Stable public ResourceRequestBuilder priority(Priority priority) { resourceRequest.setPriority(priority); return this; } /** * Set the <code>resourceName</code> of the request. * @see ResourceRequest#setResourceName(String) * @param resourceName <code>resourceName</code> of the request * @return {@link ResourceRequestBuilder} */ @Public @Stable public ResourceRequestBuilder resourceName(String resourceName) { resourceRequest.setResourceName(resourceName); return this; } /** * Set the <code>capability</code> of the request. * @see ResourceRequest#setCapability(Resource) * @param capability <code>capability</code> of the request * @return {@link ResourceRequestBuilder} */ @Public @Stable public ResourceRequestBuilder capability(Resource capability) { resourceRequest.setCapability(capability); return this; } /** * Set the <code>numContainers</code> of the request. * @see ResourceRequest#setNumContainers(int) * @param numContainers <code>numContainers</code> of the request * @return {@link ResourceRequestBuilder} */ @Public @Stable public ResourceRequestBuilder numContainers(int numContainers) { resourceRequest.setNumContainers(numContainers); return this; } /** * Set the <code>relaxLocality</code> of the request. * @see ResourceRequest#setRelaxLocality(boolean) * @param relaxLocality <code>relaxLocality</code> of the request * @return {@link ResourceRequestBuilder} */ @Public @Stable public ResourceRequestBuilder relaxLocality(boolean relaxLocality) { resourceRequest.setRelaxLocality(relaxLocality); return this; } /** * Set the <code>nodeLabelExpression</code> of the request. * @see ResourceRequest#setNodeLabelExpression(String) * @param nodeLabelExpression * <code>nodeLabelExpression</code> of the request * @return {@link ResourceRequestBuilder} */ @Public @Evolving public ResourceRequestBuilder nodeLabelExpression(String nodeLabelExpression) { resourceRequest.setNodeLabelExpression(nodeLabelExpression); return this; } /** * Set the <code>executionTypeRequest</code> of the request. * @see ResourceRequest#setExecutionTypeRequest( * ExecutionTypeRequest) * @param executionTypeRequest * <code>executionTypeRequest</code> of the request * @return {@link ResourceRequestBuilder} */ @Public @Evolving public ResourceRequestBuilder executionTypeRequest(ExecutionTypeRequest executionTypeRequest) { resourceRequest.setExecutionTypeRequest(executionTypeRequest); return this; } /** * Set the <code>executionTypeRequest</code> of the request with 'ensure * execution type' flag set to true. * @see ResourceRequest#setExecutionTypeRequest( * ExecutionTypeRequest) * @param executionType <code>executionType</code> of the request. * @return {@link ResourceRequestBuilder} */ @Public @Evolving public ResourceRequestBuilder executionType(ExecutionType executionType) { resourceRequest.setExecutionTypeRequest(ExecutionTypeRequest.newInstance(executionType, true)); return this; } /** * Set the <code>allocationRequestId</code> of the request. * @see ResourceRequest#setAllocationRequestId(long) * @param allocationRequestId * <code>allocationRequestId</code> of the request * @return {@link ResourceRequestBuilder} */ @Public @Evolving public ResourceRequestBuilder allocationRequestId(long allocationRequestId) { resourceRequest.setAllocationRequestId(allocationRequestId); return this; } /** * Return generated {@link ResourceRequest} object. * @return {@link ResourceRequest} */ @Public @Stable public ResourceRequest build() { return resourceRequest; } } @Public @Stable public static class ResourceRequestComparator implements java.util.Comparator<ResourceRequest>, Serializable { private static final long serialVersionUID = 1L; @Override public int compare(ResourceRequest r1, ResourceRequest r2) { // Compare priority, host and capability int ret = r1.getPriority().compareTo(r2.getPriority()); if (ret == 0) { ret = Long.compare(r1.getAllocationRequestId(), r2.getAllocationRequestId()); } if (ret == 0) { String h1 = r1.getResourceName(); String h2 = r2.getResourceName(); ret = h1.compareTo(h2); } if (ret == 0) { ret = r1.getExecutionTypeRequest().compareTo(r2.getExecutionTypeRequest()); } if (ret == 0) { ret = r1.getCapability().compareTo(r2.getCapability()); } return ret; } } /** * The constant string representing no locality. * It should be used by all references that want to pass an arbitrary host * name in. */ public static final String ANY = "*"; /** * Check whether the given <em>host/rack</em> string represents an arbitrary * host name. * * @param hostName <em>host/rack</em> on which the allocation is desired * @return whether the given <em>host/rack</em> string represents an arbitrary * host name */ @Public @Stable public static boolean isAnyLocation(String hostName) { return ANY.equals(hostName); } /** * Get the <code>Priority</code> of the request. * @return <code>Priority</code> of the request */ @Public @Stable public abstract Priority getPriority(); /** * Set the <code>Priority</code> of the request * @param priority <code>Priority</code> of the request */ @Public @Stable public abstract void setPriority(Priority priority); /** * Get the resource (e.g. <em>host/rack</em>) on which the allocation * is desired. * * A special value of <em>*</em> signifies that <em>any</em> resource * (host/rack) is acceptable. * * @return resource (e.g. <em>host/rack</em>) on which the allocation * is desired */ @Public @Stable public abstract String getResourceName(); /** * Set the resource name (e.g. <em>host/rack</em>) on which the allocation * is desired. * * A special value of <em>*</em> signifies that <em>any</em> resource name * (e.g. host/rack) is acceptable. * * @param resourceName (e.g. <em>host/rack</em>) on which the * allocation is desired */ @Public @Stable public abstract void setResourceName(String resourceName); /** * Get the number of containers required with the given specifications. * @return number of containers required with the given specifications */ @Public @Stable public abstract int getNumContainers(); /** * Set the number of containers required with the given specifications * @param numContainers number of containers required with the given * specifications */ @Public @Stable public abstract void setNumContainers(int numContainers); /** * Get whether locality relaxation is enabled with this * <code>ResourceRequest</code>. Defaults to true. * * @return whether locality relaxation is enabled with this * <code>ResourceRequest</code>. */ @Public @Stable public abstract boolean getRelaxLocality(); /** * Set the <code>ExecutionTypeRequest</code> of the requested container. * * @param execSpec * ExecutionTypeRequest of the requested container */ @Public @Evolving public void setExecutionTypeRequest(ExecutionTypeRequest execSpec) { throw new UnsupportedOperationException(); } /** * Get whether locality relaxation is enabled with this * <code>ResourceRequest</code>. Defaults to true. * * @return whether locality relaxation is enabled with this * <code>ResourceRequest</code>. */ @Public @Evolving public ExecutionTypeRequest getExecutionTypeRequest() { throw new UnsupportedOperationException(); } /** * <p>For a request at a network hierarchy level, set whether locality can be relaxed * to that level and beyond.<p> * * <p>If the flag is off on a rack-level <code>ResourceRequest</code>, * containers at that request's priority will not be assigned to nodes on that * request's rack unless requests specifically for those nodes have also been * submitted.<p> * * <p>If the flag is off on an {@link ResourceRequest#ANY}-level * <code>ResourceRequest</code>, containers at that request's priority will * only be assigned on racks for which specific requests have also been * submitted.<p> * * <p>For example, to request a container strictly on a specific node, the * corresponding rack-level and any-level requests should have locality * relaxation set to false. Similarly, to request a container strictly on a * specific rack, the corresponding any-level request should have locality * relaxation set to false.<p> * * @param relaxLocality whether locality relaxation is enabled with this * <code>ResourceRequest</code>. */ @Public @Stable public abstract void setRelaxLocality(boolean relaxLocality); /** * Get node-label-expression for this Resource Request. If this is set, all * containers allocated to satisfy this resource-request will be only on those * nodes that satisfy this node-label-expression. * * Please note that node label expression now can only take effect when the * resource request has resourceName = ANY * * @return node-label-expression */ @Public @Evolving public abstract String getNodeLabelExpression(); /** * Set node label expression of this resource request. Now only support * specifying a single node label. In the future we will support more complex * node label expression specification like {@code AND(&&), OR(||)}, etc. * * Any please note that node label expression now can only take effect when * the resource request has resourceName = ANY * * @param nodelabelExpression * node-label-expression of this ResourceRequest */ @Public @Evolving public abstract void setNodeLabelExpression(String nodelabelExpression); /** * Get the optional <em>ID</em> corresponding to this allocation request. This * ID is an identifier for different {@code ResourceRequest}s from the <b>same * application</b>. The allocated {@code Container}(s) received as part of the * {@code AllocateResponse} response will have the ID corresponding to the * original {@code ResourceRequest} for which the RM made the allocation. * <p> * The scheduler may return multiple {@code AllocateResponse}s corresponding * to the same ID as and when scheduler allocates {@code Container}(s). * <b>Applications</b> can continue to completely ignore the returned ID in * the response and use the allocation for any of their outstanding requests. * <p> * If one wishes to replace an entire {@code ResourceRequest} corresponding to * a specific ID, they can simply cancel the corresponding {@code * ResourceRequest} and submit a new one afresh. * * @return the <em>ID</em> corresponding to this allocation request. */ @Public @Evolving public long getAllocationRequestId() { throw new UnsupportedOperationException(); } /** * Set the optional <em>ID</em> corresponding to this allocation request. This * ID is an identifier for different {@code ResourceRequest}s from the <b>same * application</b>. The allocated {@code Container}(s) received as part of the * {@code AllocateResponse} response will have the ID corresponding to the * original {@code ResourceRequest} for which the RM made the allocation. * <p> * The scheduler may return multiple {@code AllocateResponse}s corresponding * to the same ID as and when scheduler allocates {@code Container}(s). * <b>Applications</b> can continue to completely ignore the returned ID in * the response and use the allocation for any of their outstanding requests. * <p> * If one wishes to replace an entire {@code ResourceRequest} corresponding to * a specific ID, they can simply cancel the corresponding {@code * ResourceRequest} and submit a new one afresh. * <p> * If the ID is not set, scheduler will continue to work as previously and all * allocated {@code Container}(s) will have the default ID, -1. * * @param allocationRequestID the <em>ID</em> corresponding to this allocation * request. */ @Public @Evolving public void setAllocationRequestId(long allocationRequestID) { throw new UnsupportedOperationException(); } /** * Set the <code>Resource</code> capability of the request. * @param capability <code>Resource</code> capability of the request */ @Public @Stable public abstract void setCapability(Resource capability); /** * Get the <code>Resource</code> capability of the request. * @return <code>Resource</code> capability of the request */ @Public @Stable public abstract Resource getCapability(); @Override public int hashCode() { final int prime = 2153; int result = 2459; Resource capability = getCapability(); String hostName = getResourceName(); Priority priority = getPriority(); result = prime * result + ((capability == null) ? 0 : capability.hashCode()); result = prime * result + ((hostName == null) ? 0 : hostName.hashCode()); result = prime * result + getNumContainers(); result = prime * result + ((priority == null) ? 0 : priority.hashCode()); result = prime * result + Long.valueOf(getAllocationRequestId()).hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ResourceRequest other = (ResourceRequest) obj; Resource capability = getCapability(); if (capability == null) { if (other.getCapability() != null) return false; } else if (!capability.equals(other.getCapability())) return false; String hostName = getResourceName(); if (hostName == null) { if (other.getResourceName() != null) return false; } else if (!hostName.equals(other.getResourceName())) return false; if (getNumContainers() != other.getNumContainers()) return false; Priority priority = getPriority(); if (priority == null) { if (other.getPriority() != null) return false; } else if (!priority.equals(other.getPriority())) return false; ExecutionTypeRequest execTypeRequest = getExecutionTypeRequest(); if (execTypeRequest == null) { if (other.getExecutionTypeRequest() != null) { return false; } } else if (!execTypeRequest.equals(other.getExecutionTypeRequest())) { return false; } if (getAllocationRequestId() != other.getAllocationRequestId()) { return false; } if (getNodeLabelExpression() == null) { if (other.getNodeLabelExpression() != null) { return false; } } else { // do normalize on label expression before compare String label1 = getNodeLabelExpression().replaceAll("[\\t ]", ""); String label2 = other.getNodeLabelExpression() == null ? null : other.getNodeLabelExpression().replaceAll("[\\t ]", ""); if (!label1.equals(label2)) { return false; } } return true; } @Override public int compareTo(ResourceRequest other) { int priorityComparison = this.getPriority().compareTo(other.getPriority()); if (priorityComparison == 0) { int hostNameComparison = this.getResourceName().compareTo(other.getResourceName()); if (hostNameComparison == 0) { int execTypeReqComparison = this.getExecutionTypeRequest() .compareTo(other.getExecutionTypeRequest()); if (execTypeReqComparison == 0) { int capabilityComparison = this.getCapability().compareTo(other.getCapability()); if (capabilityComparison == 0) { int numContainerComparison = this.getNumContainers() - other.getNumContainers(); if (numContainerComparison == 0) { return Long.compare(getAllocationRequestId(), other.getAllocationRequestId()); } else { return numContainerComparison; } } else { return capabilityComparison; } } else { return execTypeReqComparison; } } else { return hostNameComparison; } } else { return priorityComparison; } } }