Package eu.stratosphere.nephele.taskmanager

Source Code of eu.stratosphere.nephele.taskmanager.Task

/***********************************************************************************************************************
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* Licensed 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 eu.stratosphere.nephele.taskmanager;

import eu.stratosphere.configuration.Configuration;
import eu.stratosphere.nephele.execution.Environment;
import eu.stratosphere.nephele.execution.ExecutionListener;
import eu.stratosphere.nephele.execution.ExecutionObserver;
import eu.stratosphere.nephele.execution.ExecutionState;
import eu.stratosphere.nephele.execution.ExecutionStateTransition;
import eu.stratosphere.nephele.execution.RuntimeEnvironment;
import eu.stratosphere.nephele.executiongraph.ExecutionVertexID;
import eu.stratosphere.nephele.jobgraph.JobID;
import eu.stratosphere.nephele.profiling.TaskManagerProfiler;
import eu.stratosphere.nephele.services.memorymanager.MemoryManager;
import eu.stratosphere.nephele.template.AbstractInvokable;
import eu.stratosphere.util.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public final class Task implements ExecutionObserver {

  /**
   * The log object used for debugging.
   */
  private static final Log LOG = LogFactory.getLog(Task.class);

  private final ExecutionVertexID vertexID;

  private final RuntimeEnvironment environment;

  private final TaskManager taskManager;

  /**
   * Stores whether the task has been canceled.
   */
  private volatile boolean isCanceled = false;

  /**
   * The current execution state of the task
   */
  private volatile ExecutionState executionState = ExecutionState.STARTING;

  private Queue<ExecutionListener> registeredListeners = new ConcurrentLinkedQueue<ExecutionListener>();

  public Task(ExecutionVertexID vertexID, final RuntimeEnvironment environment, TaskManager taskManager) {
    this.vertexID = vertexID;
    this.environment = environment;
    this.taskManager = taskManager;

    this.environment.setExecutionObserver(this);
  }


  /**
   * Returns the ID of the job this task belongs to.
   *
   * @return the ID of the job this task belongs to
   */
  public JobID getJobID() {
    return this.environment.getJobID();
  }

  /**
   * Returns the ID of this task.
   *
   * @return the ID of this task
   */
  public ExecutionVertexID getVertexID() {
    return this.vertexID;
  }

  /**
   * Returns the environment associated with this task.
   *
   * @return the environment associated with this task
   */
  public Environment getEnvironment() {
    return this.environment;
  }

  /**
   * Marks the task as failed and triggers the appropriate state changes.
   */
  public void markAsFailed() {
    executionStateChanged(ExecutionState.FAILED, "Execution thread died unexpectedly");
  }

  public void cancelExecution() {
    cancelOrKillExecution(true);
  }

  public void killExecution() {
    cancelOrKillExecution(false);
  }

  /**
   * Cancels or kills the task.
   *
   * @param cancel <code>true/code> if the task shall be canceled, <code>false</code> if it shall be killed
   */
  private void cancelOrKillExecution(boolean cancel) {
    final Thread executingThread = this.environment.getExecutingThread();

    if (executingThread == null) {
      return;
    }

    if (this.executionState != ExecutionState.RUNNING && this.executionState != ExecutionState.FINISHING) {
      return;
    }

    LOG.info((cancel ? "Canceling " : "Killing ") + this.environment.getTaskNameWithIndex());

    if (cancel) {
      this.isCanceled = true;
      // Change state
      executionStateChanged(ExecutionState.CANCELING, null);

      // Request user code to shut down
      try {
        final AbstractInvokable invokable = this.environment.getInvokable();
        if (invokable != null) {
          invokable.cancel();
        }
      } catch (Throwable e) {
        LOG.error(StringUtils.stringifyException(e));
      }
    }

    // Continuously interrupt the user thread until it changed to state CANCELED
    while (true) {

      executingThread.interrupt();

      if (!executingThread.isAlive()) {
        break;
      }

      try {
        executingThread.join(1000);
      } catch (InterruptedException e) {}

      if (!executingThread.isAlive()) {
        break;
      }

      if (LOG.isDebugEnabled()) {
        LOG.debug("Sending repeated " + (cancel == true ? "canceling" : "killing") + " signal to " +
            this.environment.getTaskName() + " with state " + this.executionState);
      }
    }
  }

  /**
   * Checks if the state of the thread which is associated with this task is <code>TERMINATED</code>.
   *
   * @return <code>true</code> if the state of this thread which is associated with this task is
   *         <code>TERMINATED</code>, <code>false</code> otherwise
   */
  public boolean isTerminated() {
    final Thread executingThread = this.environment.getExecutingThread();
    if (executingThread.getState() == Thread.State.TERMINATED) {
      return true;
    }

    return false;
  }

  /**
   * Starts the execution of this task.
   */
  public void startExecution() {

    final Thread thread = this.environment.getExecutingThread();
    thread.start();
  }

  /**
   * Registers the task manager profiler with the task.
   *
   * @param taskManagerProfiler
   *        the task manager profiler
   * @param jobConfiguration
   *        the configuration attached to the job
   */
  public void registerProfiler(final TaskManagerProfiler taskManagerProfiler, final Configuration jobConfiguration) {
    taskManagerProfiler.registerExecutionListener(this, jobConfiguration);
  }

  /**
   * Unregisters the task from the central memory manager.
   *
   * @param memoryManager
   *        the central memory manager
   */
  public void unregisterMemoryManager(final MemoryManager memoryManager) {
    if (memoryManager != null) {
      memoryManager.releaseAll(this.environment.getInvokable());
    }
  }

  /**
   * Unregisters the task from the task manager profiler.
   *
   * @param taskManagerProfiler
   *        the task manager profiler
   */
  public void unregisterProfiler(final TaskManagerProfiler taskManagerProfiler) {
    if (taskManagerProfiler != null) {
      taskManagerProfiler.unregisterExecutionListener(this.vertexID);
    }
  }

  /**
   * Returns the current execution state of the task.
   *
   * @return the current execution state of the task
   */
  public ExecutionState getExecutionState() {
    return this.executionState;
  }

  // -----------------------------------------------------------------------------------------------------------------
  //                                        ExecutionObserver methods
  // -----------------------------------------------------------------------------------------------------------------
  @Override
  public void executionStateChanged(final ExecutionState newExecutionState, final String optionalMessage) {

    // Check the state transition
    ExecutionStateTransition.checkTransition(false, getTaskName(), this.executionState, newExecutionState);

    // Make sure the reason for a transition to FAILED appears in the log files
    if (newExecutionState == ExecutionState.FAILED) {
      LOG.error(optionalMessage);
    }

    // Notify all listener objects
    final Iterator<ExecutionListener> it = this.registeredListeners.iterator();
    while (it.hasNext()) {
      it.next().executionStateChanged(this.environment.getJobID(), this.vertexID, newExecutionState,
          optionalMessage);
    }

    // Store the new execution state
    this.executionState = newExecutionState;

    // Finally propagate the state change to the job manager
    this.taskManager.executionStateChanged(this.environment.getJobID(), this.vertexID, newExecutionState,
        optionalMessage);
  }

  /**
   * Returns the name of the task associated with this observer object.
   *
   * @return the name of the task associated with this observer object
   */
  private String getTaskName() {

    return this.environment.getTaskName() + " (" + (this.environment.getIndexInSubtaskGroup() + 1) + "/"
        + this.environment.getCurrentNumberOfSubtasks() + ")";
  }


  @Override
  public void userThreadStarted(final Thread userThread) {

    // Notify the listeners
    final Iterator<ExecutionListener> it = this.registeredListeners.iterator();
    while (it.hasNext()) {
      it.next().userThreadStarted(this.environment.getJobID(), this.vertexID, userThread);
    }
  }


  @Override
  public void userThreadFinished(final Thread userThread) {

    // Notify the listeners
    final Iterator<ExecutionListener> it = this.registeredListeners.iterator();
    while (it.hasNext()) {
      it.next().userThreadFinished(this.environment.getJobID(), this.vertexID, userThread);
    }
  }

  /**
   * Registers the {@link ExecutionListener} object for this task. This object
   * will be notified about important events during the task execution.
   *
   * @param executionListener
   *        the object to be notified for important events during the task execution
   */

  public void registerExecutionListener(final ExecutionListener executionListener) {

    this.registeredListeners.add(executionListener);
  }

  /**
   * Unregisters the {@link ExecutionListener} object for this environment. This object
   * will no longer be notified about important events during the task execution.
   *
   * @param executionListener
   *        the lister object to be unregistered
   */

  public void unregisterExecutionListener(final ExecutionListener executionListener) {

    this.registeredListeners.remove(executionListener);
  }


  @Override
  public boolean isCanceled() {

    return this.isCanceled;
  }

  /**
   * Returns the runtime environment associated with this task.
   *
   * @return the runtime environment associated with this task
   */
  public RuntimeEnvironment getRuntimeEnvironment() {

    return this.environment;
  }
}
TOP

Related Classes of eu.stratosphere.nephele.taskmanager.Task

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.