/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive.scheduler.common.task; import java.io.Serializable; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlTransient; import org.objectweb.proactive.annotation.PublicAPI; import org.ow2.proactive.scheduler.common.SchedulerConstants; import org.ow2.proactive.scheduler.common.job.JobId; import org.ow2.proactive.scheduler.common.task.flow.FlowActionType; import org.ow2.proactive.scheduler.task.SchedulerVars; /** * This class contains all informations about the state of the task. * It also provides methods and static fields to order the tasks if you hold them in a list. * * @author The ProActive Team * @since ProActive Scheduling 0.9 */ @PublicAPI @XmlAccessorType(XmlAccessType.FIELD) public abstract class TaskState extends Task implements Comparable<TaskState> { /** Sorting constant, this will allow the user to sort the descriptor. */ public static final int SORT_BY_ID = 1; public static final int SORT_BY_NAME = 2; public static final int SORT_BY_STATUS = 3; public static final int SORT_BY_DESCRIPTION = 4; public static final int SORT_BY_EXECUTIONLEFT = 5; public static final int SORT_BY_EXECUTIONONFAILURELEFT = 6; public static final int SORT_BY_STARTED_TIME = 8; public static final int SORT_BY_FINISHED_TIME = 9; public static final int SORT_BY_HOST_NAME = 10; public static final int SORT_BY_EXEC_DURATION = 11; public static final int ASC_ORDER = 1; public static final int DESC_ORDER = 2; protected static int currentSort = SORT_BY_ID; protected static int currentOrder = ASC_ORDER; public static final Comparator<TaskState> COMPARE_BY_FINISHED_TIME_ASC = new Comparator<TaskState>() { @Override public int compare(TaskState task1, TaskState task2) { return Long.compare(task1.getFinishedTime(), task2.getFinishedTime()); } }; /** ProActive default constructor */ public TaskState() { } /** * To update this taskState using a taskInfo * * @param taskInfo the taskInfo to set */ public abstract void update(TaskInfo taskInfo); /** * To get the dependences of this task. * Return null if this task has no dependence. * * @return the dependences of this task */ @XmlTransient public abstract List<TaskState> getDependences(); /** * If the Task was submitted, a call to this method will throw a * RuntimeException. The Dependence list should then * be accessed through {@link #getDependences()} * * @return the the list of dependences of the task, or null if this task * has been submitted * @throws IllegalStateException if this task was already submitted to the scheduler */ @Override @XmlTransient public List<Task> getDependencesList() { throw new IllegalStateException("This method cannot be used on a submitted task;" + "use " + this.getClass().getCanonicalName() + "#getDependences()"); } /** * If the Task was submitted, a call to this method will throw a * RuntimeException. Dependences cannot be added to a task at runtime. * * @param task the parent task to add to this task. * @throws IllegalStateException if this task was already submitted to the scheduler */ @Override public void addDependence(Task task) { throw new IllegalStateException("This method cannot be used on a submitted task"); } /** * If the Task was submitted, a call to this method will throw a * RuntimeException. Dependences cannot be added to a task at runtime. * * @param tasks the parent tasks to add to this task. * @throws IllegalStateException if this task was already submitted to the scheduler */ @Override public void addDependences(List<Task> tasks) { throw new IllegalStateException("This method cannot be used on a submitted task"); } /** * Set the field to sort on. * * @param sortBy the field on which the sort will be made. */ public static void setSortingBy(int sortBy) { currentSort = sortBy; } /** * Set the order for the next sort. * * @param order ASC_ORDER or DESC_ORDER */ public static void setSortingOrder(int order) { if ((order == ASC_ORDER) || (order == DESC_ORDER)) { currentOrder = order; } else { currentOrder = ASC_ORDER; } } /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(TaskState task) { switch (currentSort) { case SORT_BY_DESCRIPTION: return (currentOrder == ASC_ORDER) ? (description.compareTo(task.description)) : (task.description.compareTo(description)); case SORT_BY_NAME: return (currentOrder == ASC_ORDER) ? (name.compareTo(task.name)) : (task.name.compareTo(name)); case SORT_BY_STATUS: return (currentOrder == ASC_ORDER) ? (getStatus().compareTo(task.getStatus())) : (task.getStatus().compareTo(getStatus())); case SORT_BY_STARTED_TIME: return (currentOrder == ASC_ORDER) ? ((int) (getStartTime() - task.getStartTime())) : ((int) (task.getStartTime() - getStartTime())); case SORT_BY_FINISHED_TIME: return (currentOrder == ASC_ORDER) ? ((int) (getFinishedTime() - task.getFinishedTime())) : ((int) (task.getFinishedTime() - getFinishedTime())); case SORT_BY_EXECUTIONLEFT: return (currentOrder == ASC_ORDER) ? (Integer.valueOf(getNumberOfExecutionLeft()) .compareTo(Integer.valueOf(task.getNumberOfExecutionLeft()))) : (Integer.valueOf(task.getNumberOfExecutionLeft()) .compareTo(Integer.valueOf(getNumberOfExecutionLeft()))); case SORT_BY_EXECUTIONONFAILURELEFT: return (currentOrder == ASC_ORDER) ? (Integer.valueOf(getNumberOfExecutionOnFailureLeft()) .compareTo(Integer.valueOf(task.getNumberOfExecutionOnFailureLeft()))) : (Integer.valueOf(task.getNumberOfExecutionOnFailureLeft()) .compareTo(Integer.valueOf(getNumberOfExecutionOnFailureLeft()))); case SORT_BY_HOST_NAME: return (currentOrder == ASC_ORDER) ? (getExecutionHostName().compareTo(task.getExecutionHostName())) : (task.getExecutionHostName().compareTo(getExecutionHostName())); case SORT_BY_EXEC_DURATION: return (currentOrder == ASC_ORDER) ? (int) (getExecutionDuration() - task.getExecutionDuration()) : (int) (task.getExecutionDuration() - getExecutionDuration()); default: return (currentOrder == ASC_ORDER) ? (getId().compareTo(task.getId())) : (task.getId().compareTo(getId())); } } /** * To get the taskInfo * * @return the taskInfo */ public abstract TaskInfo getTaskInfo(); /** * Returns true if the task is not alive any more (a task is alive when it's waiting to be executed or being executed * @return true if the task is alive */ public boolean isTaskAlive() { return getTaskInfo().getStatus().isTaskAlive(); } /** * To get the finishedTime * * @return the finishedTime */ public long getFinishedTime() { return getTaskInfo().getFinishedTime(); } /** * To get the jobID * * @return the jobID */ public JobId getJobId() { return getTaskInfo().getJobId(); } /** * To get the startTime * * @return the startTime */ public long getStartTime() { return getTaskInfo().getStartTime(); } /** * To get the scheduledTime * * @return the scheduledTime */ public long getScheduledTime() { return getTaskInfo().getScheduledTime(); } /** * To get the taskId * * @return the taskID */ public TaskId getId() { return getTaskInfo().getTaskId(); } /** * To get the status of this task * * @return the status of this task */ public TaskStatus getStatus() { return getTaskInfo().getStatus(); } /* * <B>This method always returns 0 in Scheduling 2.2.0.</B> */ /** * Return the latest progress value for this task. * Progress value is ranged between 0 and 100. * * @return the latest progress value for this task. */ public int getProgress() { return this.getTaskInfo().getProgress(); } /** * Get the last execution HostName of the task. * * @return the last execution HostName. */ public String getExecutionHostName() { return getTaskInfo().getExecutionHostName(); } /** * To get the list of execution hosts name. * The first element of the returned array is the most recent used host. * * @return the execution Host Name list. */ public String[] getExecutionHostNameList() { return getTaskInfo().getExecutionHostNameList(); } /** * Get the number of execution left. * * @return the number of execution left. */ public int getNumberOfExecutionLeft() { return getTaskInfo().getNumberOfExecutionLeft(); } /** * Get the numberOfExecutionOnFailureLeft value. * * @return the numberOfExecutionOnFailureLeft value. */ public int getNumberOfExecutionOnFailureLeft() { return getTaskInfo().getNumberOfExecutionOnFailureLeft(); } /** * Get the real task duration in millis. It is the CPU time used by the task not including * communication and initialization. * It also include time spent in Pre and Post scripts. * * @return the real task duration in millis */ public long getExecutionDuration() { return getTaskInfo().getExecutionDuration(); } /** * Get the number of execution on failure allowed by the task. * * @return the number of execution on failure allowed by the task */ public abstract int getMaxNumberOfExecutionOnFailure(); /** * @see org.ow2.proactive.scheduler.common.task.Task#getName() */ @Override public String getName() { if (getId() == null || getId().getReadableName().equals(SchedulerConstants.TASK_DEFAULT_NAME)) { return super.getName(); } else { return getId().getReadableName(); } } /** * @see java.lang.Object#toString() */ @Override public String toString() { return getClass().getSimpleName() + "(" + getId() + ")"; } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return getId().hashCode(); } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (TaskState.class.isAssignableFrom(obj.getClass())) { return ((TaskState) obj).getId().equals(getId()); } return false; } /** * Replicates a task * <p> * Deep copies all fields, does not share any reference * * @return the newly created task, cast as a TaskState * @throws Exception */ public abstract TaskState replicate() throws Exception; /** * When Control Flow actions are performed (see {@link #getFlowScript()}), * some tasks are replicated. * A task replicated by a {@link FlowActionType#LOOP} action * is differentiated from the original by an incremented Iteration Index. * * @return the iteration number of this task if it was replicated by a LOOP flow operation ({@code >= 0}) */ public abstract int getIterationIndex(); /** * When Control Flow actions are performed (see {@link #getFlowScript()}), * some tasks are replicated. * A task replicated by a {@link FlowActionType#REPLICATE} action * is differentiated from the original by an incremented Replication Index. * @return the replication number of this task if it was replicated by a REPLICATE flow operations ({@code >= 0}) */ public abstract int getReplicationIndex(); /** * Returns a map containing all scope variables defined in this Task (i.e. all task variables not inherited) * * @return map of variables */ public Map<String, Serializable> getScopeVariables() { Map<String, Serializable> scopeVariables = new HashMap<>(); for (TaskVariable variable : variables.values()) { if (!variable.isJobInherited()) { scopeVariables.put(variable.getName(), variable.getValue()); } } return scopeVariables; } /** * Returns a map containing all variables defined by the system for this task, such as PA_JOB_ID, PA_USER, etc. * @return map of variables */ public Map<String, Serializable> getSystemVariables() { Map<String, Serializable> systemVariables = new HashMap<>(); if (getTaskInfo() != null) { systemVariables.put(SchedulerVars.PA_JOB_ID.toString(), getTaskInfo().getJobId().value()); systemVariables.put(SchedulerVars.PA_JOB_NAME.toString(), getTaskInfo().getJobId().getReadableName()); if (getId() != null) { systemVariables.put(SchedulerVars.PA_TASK_ID.toString(), getId().toString()); systemVariables.put(SchedulerVars.PA_TASK_NAME.toString(), getName()); } systemVariables.put(SchedulerVars.PA_USER.toString(), getTaskInfo().getJobInfo().getJobOwner()); systemVariables.put(SchedulerVars.PA_TASK_ITERATION.toString(), getIterationIndex()); systemVariables.put(SchedulerVars.PA_TASK_REPLICATION.toString(), getReplicationIndex()); } return systemVariables; } /** * Returns a map containing both scope variables and system variables * @return map of variables */ public Map<String, Serializable> getRuntimeVariables() { Map<String, Serializable> runtimeVariables = new HashMap<>(); runtimeVariables.putAll(getScopeVariables()); runtimeVariables.putAll(getSystemVariables()); return runtimeVariables; } /** * Returns a map of generic information, with replacement done from the runtime variables map */ public Map<String, String> getRuntimeGenericInformation() { if (getTaskInfo() == null) { // task is not yet properly initialized return new HashMap<>(); } HashMap<String, String> gInfo = new HashMap<>(); if (genericInformation != null) { Map<String, String> updatedTaskGenericInfo = applyReplacementsOnGenericInformation(genericInformation, getRuntimeVariables()); gInfo.putAll(updatedTaskGenericInfo); } return gInfo; } }