All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.stratosphere.nephele.taskmanager.Task Maven / Gradle / Ivy

The newest version!
/***********************************************************************************************************************
 * 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 registeredListeners = new ConcurrentLinkedQueue();

	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 true/code> if the task shall be canceled, false 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 TERMINATED.
	 * 
	 * @return true if the state of this thread which is associated with this task is
	 *         TERMINATED, false 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 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 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 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;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy