You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@reef.apache.org by we...@apache.org on 2015/07/01 19:31:18 UTC

incubator-reef git commit: [REEF-416] Create API to specify racks in EvaluatorRequests

Repository: incubator-reef
Updated Branches:
  refs/heads/master d3cf5d598 -> 85ce1ee69


[REEF-416] Create API to specify racks in EvaluatorRequests

With this commit, evaluators can now be asked to run in different nodes or
racks. Nodes should be node names. Racks can be fully qualified names. Also the
star wildcard can be used at the end. For example, in order to ask for
evaluators in any rack in datacenter 2, you can do /dc2/* It includes a new
EvaluatorRequest constructor, and it deprecates the descriptor interface.
Updated UTs (which also helped in fixing a bug)

JIRA:
  [REEF-416](https://issues.apache.org/jira/browse/REEF-416)

Pull Request:
  This Closes #266


Project: http://git-wip-us.apache.org/repos/asf/incubator-reef/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-reef/commit/85ce1ee6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-reef/tree/85ce1ee6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-reef/diff/85ce1ee6

Branch: refs/heads/master
Commit: 85ce1ee6901173d0a77592108d14a758a0d9ae58
Parents: d3cf5d5
Author: Ignacio Cano <na...@gmail.com>
Authored: Tue Jun 30 13:32:59 2015 -0700
Committer: Markus Weimer <we...@apache.org>
Committed: Wed Jul 1 10:30:24 2015 -0700

----------------------------------------------------------------------
 .../reef/driver/evaluator/EvaluatorRequest.java | 101 +++++++++++++++++--
 .../common/driver/EvaluatorRequestorImpl.java   |  33 +++---
 .../driver/api/ResourceRequestEventImpl.java    |  22 ++++
 .../runtime/local/driver/ContainerManager.java  |  10 +-
 .../OnDriverStartedAllocateOneInRack.java       |  51 ++++++++++
 .../rack/awareness/RackAwareEvaluatorTest.java  |  12 +--
 6 files changed, 189 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/85ce1ee6/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorRequest.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorRequest.java b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorRequest.java
index 878edfd..26dd34e 100644
--- a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorRequest.java
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorRequest.java
@@ -22,6 +22,9 @@ import org.apache.reef.annotations.Provided;
 import org.apache.reef.annotations.audience.DriverSide;
 import org.apache.reef.annotations.audience.Public;
 import org.apache.reef.driver.catalog.ResourceCatalog;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * A request for one ore more Evaluators.
@@ -34,16 +37,43 @@ public final class EvaluatorRequest {
   private final int megaBytes;
   private final int number;
   private final int cores;
+  /**
+   * @deprecated since 0.12.0, should use instead
+   *             {@link EvaluatorRequest#nodeNames} and
+   *             {@link EvaluatorRequest#rackNames}
+   */
+  @Deprecated
   private final ResourceCatalog.Descriptor descriptor;
+  private final List<String> nodeNames;
+  private final List<String> rackNames;
 
+  /**
+   * Deprecated constructor. ResourceCatalog.Descriptor should not be used
+   * anymore. In order to specify the rack names and node names where evaluators
+   * should run on, you should use nodeNames and rackNames lists
+   *
+   * @deprecated since 0.12.0, use constructor with node
+   *             names and rack names as parameters
+   */
+  @Deprecated
   EvaluatorRequest(final int number,
                    final int megaBytes,
                    final int cores,
                    final ResourceCatalog.Descriptor descriptor) {
+    this(number, megaBytes, cores, new ArrayList<String>(), new ArrayList<String>());
+  }
+
+  EvaluatorRequest(final int number,
+      final int megaBytes,
+      final int cores,
+      final List<String> nodeNames,
+      final List<String> rackNames) {
     this.number = number;
     this.megaBytes = megaBytes;
     this.cores = cores;
-    this.descriptor = descriptor;
+    this.nodeNames = nodeNames;
+    this.rackNames = rackNames;
+    this.descriptor = null;
   }
 
   /**
@@ -80,12 +110,16 @@ public final class EvaluatorRequest {
   }
 
   /**
-   * Access the {@link org.apache.reef.driver.catalog.NodeDescriptor} used as the template for this
-   * {@link EvaluatorRequest}.
+   * Access the {@link org.apache.reef.driver.catalog.NodeDescriptor} used as
+   * the template for this {@link EvaluatorRequest}.
    *
-   * @return the {@link org.apache.reef.driver.catalog.NodeDescriptor} used as the template for this
-   * {@link EvaluatorRequest}.
+   * @return the {@link org.apache.reef.driver.catalog.NodeDescriptor} used as
+   *         the template for this {@link EvaluatorRequest}.
+   * @deprecated since 0.12.0. Should use instead
+   *             {@link EvaluatorRequest#getNodeNames()} and
+   *             {@link EvaluatorRequest#getRackNames()}
    */
+  @Deprecated
   public ResourceCatalog.Descriptor getDescriptor() {
     return this.descriptor;
   }
@@ -98,14 +132,36 @@ public final class EvaluatorRequest {
   }
 
   /**
+   * @return the node names that we prefer the Evaluator to run on
+   */
+  public List<String> getNodeNames() {
+    return Collections.unmodifiableList(nodeNames);
+  }
+
+  /**
+   * @return the rack names that we prefer the Evaluator to run on
+   */
+  public List<String> getRackNames() {
+    return Collections.unmodifiableList(rackNames);
+  }
+
+  /**
    * {@link EvaluatorRequest}s are build using this Builder.
    */
   public static final class Builder implements org.apache.reef.util.Builder<EvaluatorRequest> {
 
     private int n = 1;
+    /**
+     * @deprecated since 0.12.0, should use instead
+     *             {@link EvaluatorRequest.Builder#nodeNames} and
+     *             {@link EvaluatorRequest.Builder#rackNames}
+     */
+    @Deprecated
     private ResourceCatalog.Descriptor descriptor = null;
     private int megaBytes = -1;
     private int cores = 1; //if not set, default to 1
+    private final List<String> nodeNames = new ArrayList<>();
+    private final List<String> rackNames = new ArrayList<>();
 
     private Builder() {
     }
@@ -147,21 +203,48 @@ public final class EvaluatorRequest {
     }
 
     /**
+     * Adds a node name.It is the preferred location where the evaluator should
+     * run on. If the node is available, the RM will try to allocate the
+     * evaluator there
+     */
+    public Builder addNodeName(final String nodeName) {
+      this.nodeNames.add(nodeName);
+      return this;
+    }
+
+    /**
+     * Adds a rack name. It is the preferred location where the evaluator should
+     * run on. If the rack is available, the RM will try to allocate the
+     * evaluator in one of its nodes. The RM will try to match node names first,
+     * and then fallback to rack names
+     */
+    public Builder addRackName(final String rackName) {
+      this.rackNames.add(rackName);
+      return this;
+    }
+
+    /**
      * Builds the {@link EvaluatorRequest}.
      */
     @Override
     public EvaluatorRequest build() {
-      return new EvaluatorRequest(this.n, this.megaBytes, this.cores, this.descriptor);
+      return new EvaluatorRequest(this.n, this.megaBytes, this.cores, this.nodeNames, this.rackNames);
     }
 
     /**
      * Pre-fill this {@link EvaluatorRequest} from the given
-     * {@link org.apache.reef.driver.catalog.NodeDescriptor}. Any value not changed in subsequent calls to
-     * this Builder will be taken from the given descriptor.
+     * {@link org.apache.reef.driver.catalog.NodeDescriptor}. Any value not
+     * changed in subsequent calls to this Builder will be taken from the given
+     * descriptor.
      *
-     * @param rd the descriptor used to pre-fill this request.
+     * @param rd
+     *          the descriptor used to pre-fill this request.
+     * @deprecated since 0.12.0. Replace with
+     *             {@link EvaluatorRequest.Builder#addRackName} and
+     *             {@link EvaluatorRequest.Builder#addNodeName}
      * @return this
      */
+    @Deprecated
     public Builder fromDescriptor(final ResourceCatalog.Descriptor rd) {
       this.descriptor = rd;
       return this;

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/85ce1ee6/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/EvaluatorRequestorImpl.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/EvaluatorRequestorImpl.java b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/EvaluatorRequestorImpl.java
index 723d8c8..ef3294a 100644
--- a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/EvaluatorRequestorImpl.java
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/EvaluatorRequestorImpl.java
@@ -18,11 +18,10 @@
  */
 package org.apache.reef.runtime.common.driver;
 
-import org.apache.reef.driver.catalog.NodeDescriptor;
-import org.apache.reef.driver.catalog.RackDescriptor;
 import org.apache.reef.driver.catalog.ResourceCatalog;
 import org.apache.reef.driver.evaluator.EvaluatorRequest;
 import org.apache.reef.driver.evaluator.EvaluatorRequestor;
+import org.apache.reef.runtime.common.driver.api.ResourceRequestEvent;
 import org.apache.reef.runtime.common.driver.api.ResourceRequestEventImpl;
 import org.apache.reef.runtime.common.driver.api.ResourceRequestHandler;
 import org.apache.reef.util.logging.LoggingScope;
@@ -59,7 +58,8 @@ public final class EvaluatorRequestorImpl implements EvaluatorRequestor {
 
   @Override
   public synchronized void submit(final EvaluatorRequest req) {
-    LOG.log(Level.FINEST, "Got an EvaluatorRequest: number: {0}, memory = {1}, cores = {2}.", new Object[]{req.getNumber(), req.getMegaBytes(), req.getNumberOfCores()});
+    LOG.log(Level.FINEST, "Got an EvaluatorRequest: number: {0}, memory = {1}, cores = {2}.",
+        new Object[] {req.getNumber(), req.getMegaBytes(), req.getNumberOfCores()});
 
     if (req.getMegaBytes() <= 0) {
       throw new IllegalArgumentException("Given an unsupported memory size: " + req.getMegaBytes());
@@ -70,26 +70,23 @@ public final class EvaluatorRequestorImpl implements EvaluatorRequestor {
     if (req.getNumber() <= 0) {
       throw new IllegalArgumentException("Given an unsupported number of evaluators: " + req.getNumber());
     }
+    if (req.getNodeNames() == null) {
+      throw new IllegalArgumentException("Node names cannot be null");
+    }
+    if (req.getRackNames() == null) {
+      throw new IllegalArgumentException("Rack names cannot be null");
+    }
 
     try (LoggingScope ls = loggingScopeFactory.evaluatorSubmit(req.getNumber())) {
-      final ResourceRequestEventImpl.Builder request = ResourceRequestEventImpl
+      final ResourceRequestEvent request = ResourceRequestEventImpl
           .newBuilder()
           .setResourceCount(req.getNumber())
           .setVirtualCores(req.getNumberOfCores())
-          .setMemorySize(req.getMegaBytes());
-
-      final ResourceCatalog.Descriptor descriptor = req.getDescriptor();
-      if (descriptor != null) {
-        if (descriptor instanceof RackDescriptor) {
-          request.addRackName(descriptor.getName());
-        } else if (descriptor instanceof NodeDescriptor) {
-          request.addNodeName(descriptor.getName());
-        } else {
-          throw new IllegalArgumentException("Unable to operate on descriptors of type " + descriptor.getClass().getName());
-        }
-      }
-
-      this.resourceRequestHandler.onNext(request.build());
+          .setMemorySize(req.getMegaBytes())
+          .addNodeNames(req.getNodeNames())
+          .addRackNames(req.getRackNames())
+          .build();
+      this.resourceRequestHandler.onNext(request);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/85ce1ee6/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/api/ResourceRequestEventImpl.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/api/ResourceRequestEventImpl.java b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/api/ResourceRequestEventImpl.java
index cf4a225..169554e 100644
--- a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/api/ResourceRequestEventImpl.java
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/api/ResourceRequestEventImpl.java
@@ -130,6 +130,17 @@ public final class ResourceRequestEventImpl implements ResourceRequestEvent {
     }
 
     /**
+     * Add a list of node names.
+     * @see {@link ResourceRequestEventImpl.Builder#addNodeName}
+     */
+    public Builder addNodeNames(final List<String> nodeNames) {
+      for (final String nodeName : nodeNames) {
+        addNodeName(nodeName);
+      }
+      return this;
+    }
+
+    /**
      * Add an entry to rackNameList.
      * @see ResourceRequestEvent#getRackNameList()
      */
@@ -139,6 +150,17 @@ public final class ResourceRequestEventImpl implements ResourceRequestEvent {
     }
 
     /**
+     * Add a list of rack names.
+     * @see {@link ResourceRequestEventImpl.Builder#addRackName}
+     */
+    public Builder addRackNames(final List<String> rackNames) {
+      for (final String rackName : rackNames) {
+        addRackName(rackName);
+      }
+      return this;
+    }
+
+    /**
      * @see ResourceRequestEvent#getMemorySize()
      */
     public Builder setMemorySize(final int memorySize) {

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/85ce1ee6/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ContainerManager.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ContainerManager.java b/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ContainerManager.java
index 9ca1f09..34b1146 100644
--- a/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ContainerManager.java
+++ b/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ContainerManager.java
@@ -161,7 +161,7 @@ final class ContainerManager implements AutoCloseable {
       }
     });
 
-    init(rackNames);
+    init();
 
     LOG.log(Level.FINE, "Initialized Container Manager with {0} containers", capacity);
   }
@@ -202,13 +202,13 @@ final class ContainerManager implements AutoCloseable {
     return normalizedRackNames;
   }
 
-  private void init(final Set<String> rackNames) {
+  private void init() {
     // evenly distribute the containers among the racks
     // if rack names are not specified, the default rack will be used, so the denominator will always be > 0
-    final int capacityPerRack = capacity / rackNames.size();
-    int missing = capacity % rackNames.size();
+    final int capacityPerRack = capacity / availableRacks.size();
+    int missing = capacity % availableRacks.size();
     // initialize the freeNodesPerRackList and the capacityPerRack
-    for (final String rackName : rackNames) {
+    for (final String rackName : availableRacks) {
       this.freeNodesPerRack.put(rackName, new HashMap<String, Boolean>());
       this.capacitiesPerRack.put(rackName, capacityPerRack);
       if (missing > 0) {

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/85ce1ee6/lang/java/reef-tests/src/main/java/org/apache/reef/tests/rack/awareness/OnDriverStartedAllocateOneInRack.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tests/src/main/java/org/apache/reef/tests/rack/awareness/OnDriverStartedAllocateOneInRack.java b/lang/java/reef-tests/src/main/java/org/apache/reef/tests/rack/awareness/OnDriverStartedAllocateOneInRack.java
new file mode 100644
index 0000000..7dff828
--- /dev/null
+++ b/lang/java/reef-tests/src/main/java/org/apache/reef/tests/rack/awareness/OnDriverStartedAllocateOneInRack.java
@@ -0,0 +1,51 @@
+/*
+ * 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.reef.tests.rack.awareness;
+
+import org.apache.reef.driver.evaluator.EvaluatorRequest;
+import org.apache.reef.driver.evaluator.EvaluatorRequestor;
+import org.apache.reef.tang.annotations.Parameter;
+import org.apache.reef.wake.EventHandler;
+import org.apache.reef.wake.time.event.StartTime;
+
+import javax.inject.Inject;
+
+/**
+ * A Driver start handler that requests a single Evaluator of size 64MB in the
+ * specified rack.
+ */
+public final class OnDriverStartedAllocateOneInRack implements EventHandler<StartTime> {
+
+  private final EvaluatorRequestor requestor;
+  private final String rackName;
+
+  @Inject
+  OnDriverStartedAllocateOneInRack(
+      final EvaluatorRequestor requestor,
+      @Parameter(RackNameParameter.class) final String rackName) {
+    this.requestor = requestor;
+    this.rackName = rackName;
+  }
+
+  @Override
+  public void onNext(final StartTime startTime) {
+    this.requestor.submit(EvaluatorRequest.newBuilder().setMemory(64).setNumber(1).setNumberOfCores(1)
+        .addRackName(rackName).build());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/85ce1ee6/lang/java/reef-tests/src/test/java/org/apache/reef/tests/rack/awareness/RackAwareEvaluatorTest.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tests/src/test/java/org/apache/reef/tests/rack/awareness/RackAwareEvaluatorTest.java b/lang/java/reef-tests/src/test/java/org/apache/reef/tests/rack/awareness/RackAwareEvaluatorTest.java
index 0f6c0a1..472b284 100644
--- a/lang/java/reef-tests/src/test/java/org/apache/reef/tests/rack/awareness/RackAwareEvaluatorTest.java
+++ b/lang/java/reef-tests/src/test/java/org/apache/reef/tests/rack/awareness/RackAwareEvaluatorTest.java
@@ -40,7 +40,7 @@ import org.junit.Test;
  */
 public final class RackAwareEvaluatorTest {
 
-  private static final String RACK1 = "rack1";
+  private static final String RACK1 = "/rack1";
   // runs on the local runtime
   private final TestEnvironment testEnvironment = new LocalTestEnvironment();
 
@@ -77,20 +77,16 @@ public final class RackAwareEvaluatorTest {
 
   /**
    * Test whether the runtime passes the rack information to the driver.
-   * The success scenario is if it receives rack1, fails otherwise
+   * The success scenario is if it receives /rack1, fails otherwise
    */
-  //@Test
-  // TODO Re-enable once we define the API to specify the information where
-  // resources should run on (JIRA REEF-416)
-  // OnDriverStartedAllocateOne will need to be replaced, and contain that it
-  // wants to run in RACK1, which will be the only one available
+  @Test
   public void testRackAwareEvaluatorRunningOnRack1() throws InjectionException {
     //Given
     final Configuration driverConfiguration = DriverConfiguration.CONF
         .set(DriverConfiguration.DRIVER_IDENTIFIER, "TEST_RackAwareEvaluator")
         .set(DriverConfiguration.GLOBAL_LIBRARIES,
             EnvironmentUtils.getClassLocation(RackAwareEvaluatorTestDriver.class))
-        .set(DriverConfiguration.ON_DRIVER_STARTED, OnDriverStartedAllocateOne.class)
+        .set(DriverConfiguration.ON_DRIVER_STARTED, OnDriverStartedAllocateOneInRack.class)
         .set(DriverConfiguration.ON_EVALUATOR_ALLOCATED, RackAwareEvaluatorTestDriver.EvaluatorAllocatedHandler.class)
         .build();