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,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.reef.driver.evaluator;
020
021import org.apache.reef.annotations.Provided;
022import org.apache.reef.annotations.audience.DriverSide;
023import org.apache.reef.annotations.audience.Private;
024import org.apache.reef.annotations.audience.Public;
025import java.util.ArrayList;
026import java.util.Collections;
027import java.util.List;
028
029/**
030 * A request for one ore more Evaluators.
031 */
032@Public
033@DriverSide
034@Provided
035public final class EvaluatorRequest {
036
037  private final int megaBytes;
038  private final int number;
039  private final int cores;
040  private final List<String> nodeNames;
041  private final List<String> rackNames;
042  private final String runtimeName;
043
044  EvaluatorRequest(final int number,
045                   final int megaBytes,
046                   final int cores,
047                   final List<String> nodeNames,
048                   final List<String> rackNames) {
049    this(number, megaBytes, cores, nodeNames, rackNames, "");
050  }
051
052  EvaluatorRequest(final int number,
053                   final int megaBytes,
054                   final int cores,
055                   final List<String> nodeNames,
056                   final List<String> rackNames,
057                   final String runtimeName) {
058    this.number = number;
059    this.megaBytes = megaBytes;
060    this.cores = cores;
061    this.nodeNames = nodeNames;
062    this.rackNames = rackNames;
063    this.runtimeName = runtimeName;
064  }
065
066  /**
067   * Get a new builder.
068   *
069   * @return a new EvaluatorRequest Builder.
070   */
071  public static Builder newBuilder() {
072    return new Builder();
073  }
074
075  /**
076   * Get a new builder from the existing request.
077   *
078   * @return a new EvaluatorRequest Builder with settings initialized
079   * from an existing request.
080   */
081  public static Builder newBuilder(final EvaluatorRequest request) {
082    return new Builder(request);
083  }
084
085  /**
086   * Access the number of Evaluators requested.
087   *
088   * @return the number of Evaluators requested.
089   */
090  public int getNumber() {
091    return this.number;
092  }
093
094  /**
095   * Access the number of core of Evaluators requested.
096   *
097   * @return the number of cores requested.
098   */
099  public int getNumberOfCores() {
100    return this.cores;
101  }
102
103  /**
104   * Access the number of memory requested.
105   *
106   * @return the minimum size of Evaluator requested.
107   */
108  public int getMegaBytes() {
109    return megaBytes;
110  }
111
112  /**
113   * Access the preferred node.
114   *
115   * @return the node names that we prefer the Evaluator to run on
116   */
117  public List<String> getNodeNames() {
118    return Collections.unmodifiableList(nodeNames);
119  }
120
121  /**
122   * Access the preferred rack name.
123   *
124   * @return the rack names that we prefer the Evaluator to run on
125   */
126  public List<String> getRackNames() {
127    return Collections.unmodifiableList(rackNames);
128  }
129
130  /**
131   * Access the required runtime name.
132   *
133   * @return the runtime name that we need the Evaluator to run on
134   */
135  public String getRuntimeName() {
136    return runtimeName;
137  }
138
139  /**
140   * {@link EvaluatorRequest}s are build using this Builder.
141   */
142  public static class Builder<T extends Builder> implements org.apache.reef.util.Builder<EvaluatorRequest> {
143
144    private int n = 1;
145    private int megaBytes = -1;
146    private int cores = 1; //if not set, default to 1
147    private final List<String> nodeNames = new ArrayList<>();
148    private final List<String> rackNames = new ArrayList<>();
149    private String runtimeName = "";
150
151    @Private
152    public Builder() {
153    }
154
155    /**
156     * Pre-populates the builder with the values extracted from the request.
157     *
158     * @param request the request
159     * @return this Builder
160     */
161    private Builder(final EvaluatorRequest request) {
162      setNumber(request.getNumber());
163      setMemory(request.getMegaBytes());
164      setNumberOfCores(request.getNumberOfCores());
165      setRuntimeName(request.getRuntimeName());
166      for (final String nodeName : request.getNodeNames()) {
167        addNodeName(nodeName);
168      }
169      for (final String rackName : request.getRackNames()) {
170        addRackName(rackName);
171      }
172    }
173
174    /**
175     * Set the amount of memory.
176     *
177     * @param megaBytes the amount of megabytes to request for the Evaluator.
178     * @return this builder
179     */
180    @SuppressWarnings("checkstyle:hiddenfield")
181    public T setMemory(final int megaBytes) {
182      this.megaBytes = megaBytes;
183      return (T) this;
184    }
185
186    /**
187     * Set the name of the desired runtime.
188     *
189     * @param runtimeName to request for the Evaluator.
190     * @return this builder
191     */
192    @SuppressWarnings("checkstyle:hiddenfield")
193    public T setRuntimeName(final String runtimeName) {
194      this.runtimeName = runtimeName;
195      return (T) this;
196    }
197
198    /**
199     * Set number of cores.
200     *
201     * @param cores the number of cores
202     * @return this Builder.
203     */
204    @SuppressWarnings("checkstyle:hiddenfield")
205    public T setNumberOfCores(final int cores) {
206      this.cores = cores;
207      return (T) this;
208    }
209
210    /**
211     * Set the number of Evaluators requested.
212     *
213     * @param n the number of evaluators
214     * @return this Builder.
215     */
216    @SuppressWarnings("checkstyle:hiddenfield")
217    public T setNumber(final int n) {
218      this.n = n;
219      return (T) this;
220    }
221
222    /**
223     * Adds a node name.It is the preferred location where the evaluator should
224     * run on. If the node is available, the RM will try to allocate the
225     * evaluator there
226     *
227     * @param nodeName a preferred node name
228     * @return this Builder.
229     */
230    public T addNodeName(final String nodeName) {
231      this.nodeNames.add(nodeName);
232      return (T) this;
233    }
234
235    /**
236     * Adds a rack name. It is the preferred location where the evaluator should
237     * run on. If the rack is available, the RM will try to allocate the
238     * evaluator in one of its nodes. The RM will try to match node names first,
239     * and then fallback to rack names
240     *
241     * @param rackName a preferred rack name
242     * @return this Builder.
243     */
244    public T addRackName(final String rackName) {
245      this.rackNames.add(rackName);
246      return (T) this;
247    }
248
249    /**
250     * Builds the {@link EvaluatorRequest}.
251     */
252    @Override
253    public EvaluatorRequest build() {
254      return new EvaluatorRequest(this.n, this.megaBytes, this.cores, this.nodeNames, this.rackNames, this.runtimeName);
255    }
256  }
257}