/*********************************************************************************************************************** * 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.deployment; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import eu.stratosphere.configuration.Configuration; import eu.stratosphere.core.io.IOReadableWritable; import eu.stratosphere.core.io.StringRecord; import eu.stratosphere.nephele.execution.librarycache.LibraryCacheManager; import eu.stratosphere.nephele.executiongraph.ExecutionVertexID; import eu.stratosphere.nephele.jobgraph.JobID; import eu.stratosphere.nephele.template.AbstractInvokable; import eu.stratosphere.nephele.util.SerializableArrayList; import eu.stratosphere.util.StringUtils; /** * A task deployment descriptor contains all the information necessary to deploy a task on a task manager. * <p> * This class is not thread-safe in general. * */ public final class TaskDeploymentDescriptor implements IOReadableWritable { /** * The ID of the job the tasks belongs to. */ private final JobID jobID; /** * The task's execution vertex ID. */ private final ExecutionVertexID vertexID; /** * The task's name. */ private String taskName; /** * The task's index in the subtask group. */ private int indexInSubtaskGroup; /** * The current number of subtasks. */ private int currentNumberOfSubtasks; /** * The configuration of the job the task belongs to. */ private Configuration jobConfiguration; /** * The task's configuration object. */ private Configuration taskConfiguration; /** * The class containing the task code to be executed. */ private Class<? extends AbstractInvokable> invokableClass; /** * The list of output gate deployment descriptors. */ private final SerializableArrayList<GateDeploymentDescriptor> outputGates; /** * The list of input gate deployment descriptors. */ private final SerializableArrayList<GateDeploymentDescriptor> inputGates; /** * Constructs a task deployment descriptor. * * @param jobID * the ID of the job the tasks belongs to * @param vertexID * the task's execution vertex ID * @param taskName * the task's name the task's index in the subtask group * @param indexInSubtaskGroup * he task's index in the subtask group * @param currentNumberOfSubtasks * the current number of subtasks * @param jobConfiguration * the configuration of the job the task belongs to * @param taskConfiguration * the task's configuration object * @param invokableClass * the class containing the task code to be executed * @param outputGates * list of output gate deployment descriptors * @param inputGateIDs * list of input gate deployment descriptors */ public TaskDeploymentDescriptor(final JobID jobID, final ExecutionVertexID vertexID, final String taskName, final int indexInSubtaskGroup, final int currentNumberOfSubtasks, final Configuration jobConfiguration, final Configuration taskConfiguration, final Class<? extends AbstractInvokable> invokableClass, final SerializableArrayList<GateDeploymentDescriptor> outputGates, final SerializableArrayList<GateDeploymentDescriptor> inputGates) { if (jobID == null) { throw new IllegalArgumentException("Argument jobID must not be null"); } if (vertexID == null) { throw new IllegalArgumentException("Argument vertexID must not be null"); } if (taskName == null) { throw new IllegalArgumentException("Argument taskName must not be null"); } if (indexInSubtaskGroup < 0) { throw new IllegalArgumentException("Argument indexInSubtaskGroup must not be smaller than zero"); } if (currentNumberOfSubtasks < indexInSubtaskGroup) { throw new IllegalArgumentException( "Argument currentNumberOfSubtasks must not be smaller than argument indexInSubtaskGroup"); } if (jobConfiguration == null) { throw new IllegalArgumentException("Argument jobConfiguration must not be null"); } if (taskConfiguration == null) { throw new IllegalArgumentException("Argument taskConfiguration must not be null"); } if (invokableClass == null) { throw new IllegalArgumentException("Argument invokableClass must not be null"); } if (outputGates == null) { throw new IllegalArgumentException("Argument outputGates must not be null"); } if (inputGates == null) { throw new IllegalArgumentException("Argument inputGates must not be null"); } this.jobID = jobID; this.vertexID = vertexID; this.taskName = taskName; this.indexInSubtaskGroup = indexInSubtaskGroup; this.currentNumberOfSubtasks = currentNumberOfSubtasks; this.jobConfiguration = jobConfiguration; this.taskConfiguration = taskConfiguration; this.invokableClass = invokableClass; this.outputGates = outputGates; this.inputGates = inputGates; } /** * Default constructor for serialization/deserialization. */ public TaskDeploymentDescriptor() { this.jobID = new JobID(); this.vertexID = new ExecutionVertexID(); this.taskName = null; this.indexInSubtaskGroup = 0; this.currentNumberOfSubtasks = 0; this.jobConfiguration = new Configuration(); this.taskConfiguration = new Configuration(); this.invokableClass = null; this.outputGates = new SerializableArrayList<GateDeploymentDescriptor>(); this.inputGates = new SerializableArrayList<GateDeploymentDescriptor>(); } @Override public void write(final DataOutput out) throws IOException { this.jobID.write(out); this.vertexID.write(out); StringRecord.writeString(out, this.taskName); out.writeInt(this.indexInSubtaskGroup); out.writeInt(this.currentNumberOfSubtasks); // Write out the names of the required jar files final String[] requiredJarFiles = LibraryCacheManager.getRequiredJarFiles(this.jobID); out.writeInt(requiredJarFiles.length); for (int i = 0; i < requiredJarFiles.length; i++) { StringRecord.writeString(out, requiredJarFiles[i]); } // Write out the name of the invokable class if (this.invokableClass == null) { throw new IOException("this.invokableClass is null"); } StringRecord.writeString(out, this.invokableClass.getName()); this.jobConfiguration.write(out); this.taskConfiguration.write(out); this.outputGates.write(out); this.inputGates.write(out); } @SuppressWarnings("unchecked") @Override public void read(final DataInput in) throws IOException { this.jobID.read(in); this.vertexID.read(in); this.taskName = StringRecord.readString(in); this.indexInSubtaskGroup = in.readInt(); this.currentNumberOfSubtasks = in.readInt(); // Read names of required jar files final String[] requiredJarFiles = new String[in.readInt()]; for (int i = 0; i < requiredJarFiles.length; i++) { requiredJarFiles[i] = StringRecord.readString(in); } // Now register data with the library manager LibraryCacheManager.register(this.jobID, requiredJarFiles); // Get ClassLoader from Library Manager final ClassLoader cl = LibraryCacheManager.getClassLoader(this.jobID); // Read the name of the invokable class; final String invokableClassName = StringRecord.readString(in); if (invokableClassName == null) { throw new IOException("invokableClassName is null"); } try { this.invokableClass = (Class<? extends AbstractInvokable>) Class.forName(invokableClassName, true, cl); } catch (ClassNotFoundException cnfe) { throw new IOException("Class " + invokableClassName + " not found in one of the supplied jar files: " + StringUtils.stringifyException(cnfe)); } this.jobConfiguration = new Configuration(cl); this.jobConfiguration.read(in); this.taskConfiguration = new Configuration(cl); this.taskConfiguration.read(in); this.outputGates.read(in); this.inputGates.read(in); } /** * Returns the ID of the job the tasks belongs to. * * @return the ID of the job the tasks belongs to */ public JobID getJobID() { return this.jobID; } /** * Returns the task's execution vertex ID. * * @return the task's execution vertex ID */ public ExecutionVertexID getVertexID() { return this.vertexID; } /** * Returns the task's name. * * @return the task's name */ public String getTaskName() { return this.taskName; } /** * Returns the task's index in the subtask group. * * @return the task's index in the subtask group */ public int getIndexInSubtaskGroup() { return this.indexInSubtaskGroup; } /** * Returns the current number of subtasks. * * @return the current number of subtasks */ public int getCurrentNumberOfSubtasks() { return this.currentNumberOfSubtasks; } /** * Returns the configuration of the job the task belongs to. * * @return the configuration of the job the tasks belongs to */ public Configuration getJobConfiguration() { return this.jobConfiguration; } /** * Returns the task's configuration object. * * @return the task's configuration object */ public Configuration getTaskConfiguration() { return this.taskConfiguration; } /** * Returns the class containing the task code to be executed. * * @return the class containing the task code to be executed */ public Class<? extends AbstractInvokable> getInvokableClass() { return this.invokableClass; } /** * Returns the number of output gate deployment descriptors contained in this task deployment descriptor. * * @return the number of output gate deployment descriptors */ public int getNumberOfOutputGateDescriptors() { return this.outputGates.size(); } /** * Returns the output gate descriptor with the given index * * @param index * the index if the output gate descriptor to return * @return the output gate descriptor with the given index */ public GateDeploymentDescriptor getOutputGateDescriptor(final int index) { return this.outputGates.get(index); } /** * Returns the number of output gate deployment descriptors contained in this task deployment descriptor. * * @return the number of output gate deployment descriptors */ public int getNumberOfInputGateDescriptors() { return this.inputGates.size(); } /** * Returns the input gate descriptor with the given index * * @param index * the index if the input gate descriptor to return * @return the input gate descriptor with the given index */ public GateDeploymentDescriptor getInputGateDescriptor(final int index) { return this.inputGates.get(index); } }