/**
* Copyright 2007-2008 University Of Southern California
*
* 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 edu.isi.pegasus.planner.classes;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import edu.isi.pegasus.common.credential.CredentialHandler;
import edu.isi.pegasus.planner.catalog.classes.Profiles;
import edu.isi.pegasus.planner.catalog.classes.Profiles.NAMESPACES;
import edu.isi.pegasus.planner.namespace.Namespace;
import edu.isi.pegasus.planner.namespace.Condor;
import edu.isi.pegasus.planner.namespace.Dagman;
import edu.isi.pegasus.planner.namespace.ENV;
import edu.isi.pegasus.planner.namespace.Globus;
import edu.isi.pegasus.planner.namespace.Hints;
import edu.isi.pegasus.planner.namespace.Pegasus;
import edu.isi.pegasus.common.logging.LogManager;
import edu.isi.pegasus.planner.common.PegasusProperties;
import edu.isi.pegasus.planner.partitioner.graph.GraphNodeContent;
import edu.isi.pegasus.planner.catalog.transformation.TransformationCatalogEntry;
import edu.isi.pegasus.common.util.Separator;
import edu.isi.pegasus.planner.catalog.site.classes.GridGateway;
import edu.isi.pegasus.planner.dax.Invoke;
import edu.isi.pegasus.planner.namespace.Metadata;
import edu.isi.pegasus.planner.partitioner.graph.GraphNode;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.io.Writer;
import java.io.StringWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* The object of this class holds the information to generate a submit file about
* one particular job making the Dag.
*
* @author Karan Vahi
* @author Gaurang Mehta
* @version $Revision$
*/
public class Job extends Data implements GraphNodeContent{
/**
* Denotes a job that does not fall into the other categories. It might
* denote an error condition or a faulty logic in the planner.
*/
public static final int UNASSIGNED_JOB = 0;
/**
* Denotes a compute job. Generally these are the jobs that are specified in
* the DAX.
*/
public static final int COMPUTE_JOB = 1;
/**
* Denotes a job that is used to stage in the input files for a compute job.
*/
public static final int STAGE_IN_JOB = 2;
/**
* Denotes a job that transfers the date generated by a compute job to the
* output pool specified by the user.
*/
public static final int STAGE_OUT_JOB = 3;
/**
* Denotes a job that registers in the replica mechanism the materialized
* files.
*/
public static final int REPLICA_REG_JOB = 4;
/**
* Denotes a job that transfers the output of a compute node to the site
* where the child compute node is to be generated.
*/
public static final int INTER_POOL_JOB = 5;
/**
* Denotes a job that creates directories at the remote pools.
*/
public static final int CREATE_DIR_JOB = 6;
/**
* Denotes a job that stages the worker package.
*/
public static final int STAGE_IN_WORKER_PACKAGE_JOB = 7;
/**
* Denotes a job for which the executable has been staged as part of the
* workflow.
*/
// public static final int STAGED_COMPUTE_JOB = 7;
/**
* Denotes a cleanup job, that removes the files that from the remote
* working directories of the remote sites.
*/
public static final int CLEANUP_JOB = 8;
/**
* Denotes a chmod job that sets the xbit on the remote end.
*/
public static final int CHMOD_JOB = 9;
/**
* Denotes a chmod job that sets the xbit on the remote end.
*/
public static final int DAX_JOB = 10;
/**
* Denotes a chmod job that sets the xbit on the remote end.
*/
public static final int DAG_JOB = 11;
/**
* Returns an appropriate grid gateway job type corresponding to a job type
*
* @param type the job type
*
* @return corresponding GridGateway job type
*/
private static GridGateway.JOB_TYPE jobType2GridGatewayJobType( int type ){
//sanity check
if ( !( typeInRange(type) ) ){
throw new IllegalArgumentException("Invalid Job type " + type);
}
GridGateway.JOB_TYPE jtype ;
switch( type ){
case Job.COMPUTE_JOB:
case Job.DAG_JOB:
case Job.DAX_JOB:
jtype = GridGateway.JOB_TYPE.compute;
break;
case Job.STAGE_IN_JOB:
jtype = GridGateway.JOB_TYPE.transfer;
break;
case Job.STAGE_OUT_JOB:
jtype = GridGateway.JOB_TYPE.transfer;
break;
case Job.REPLICA_REG_JOB:
jtype = GridGateway.JOB_TYPE.register;
break;
case Job.INTER_POOL_JOB:
jtype = GridGateway.JOB_TYPE.transfer;
break;
case Job.CREATE_DIR_JOB:
case Job.CHMOD_JOB:
jtype = GridGateway.JOB_TYPE.auxillary;
break;
case Job.CLEANUP_JOB:
jtype = GridGateway.JOB_TYPE.cleanup;
break;
/*
case Job.SYMLINK_STAGE_IN_JOB:
jtype = GridGateway.JOB_TYPE.transfer;
break;
*/
case Job.UNASSIGNED_JOB:
default:
jtype = GridGateway.JOB_TYPE.compute;
}
return jtype;
}
/**
* The delimiter that has to be used to combine the name for the staged
* executable.
*/
private static String DELIMITER =
PegasusProperties.getInstance().getStagingDelimiter();
/**
* The type of the job. Pegasus tags the jobs according to the function of
* the job. The jobs are tagged according to the functionality they serve in
* the Pegasus super node. The job class can be
*
* unassigned
* compute job
* stage-in
* stage-out
* replica registration
* inter-pool transfer
* create-dir job
* staged-compute job
*/
public int jobClass;
/**
* Identifies of which Pegasus Super Node is a job associated with.
* Pegasus Supernode is identified by the jobName of the compute node in the
* super node.
*/
public String jobID;
/**
* The name of the job.
*/
public String jobName;
/**
* The logical name of the transformation which is executed as a part of
* this job. Note: The tc is looked up by namespace__logicalName_version.
*/
public String logicalName;
/**
* The logical id of the job as referred to in the dax.
*/
public String logicalId;
/**
* The namespace to which the transformation is bound.
*/
public String namespace;
/**
* The version of the transformation.
*/
public String version;
/**
* The name of the derivation in Chimera that generated the job.
*/
public String dvName;
/**
* The namespace to which the derivation is bound.
*
*/
public String dvNamespace;
/**
* The version of the derivation.
*/
public String dvVersion;
/**
* The globus Scheduler for the job.
*/
public String globusScheduler;
/**
* The path of the executable on the machine at which the job is executed.
*/
public String executable;
/**
* The universe in which the job has to be executed. Can be standard,
* vanilla or globus.
*/
public String condorUniverse;
/**
* File which contains stdin (keyboard input).
*/
public String stdIn;
/**
* File which contains stdout.
*/
public String stdOut;
/**
* File which contains standard error.
*/
public String stdErr;
/**
* The arguements for the job. It is the contains the arguments for the
* job. This string is put in the arguments in Condor Submit File.
*/
public String strargs;
/**
* Contains the input files for the submit file. They are vector of
* PegasusFile Objects which store the transiency information of each
* logical file.
*
* @see org.griphyn.cPlanner.classes.PegasusFile
*/
public Set inputFiles;
/**
* Contains the output files for the submit file. They are vector of
* PegasusFile Objects which store the transiency information of each logical
* file.
*
* @see org.griphyn.cPlanner.classes.PegasusFile
*/
public Set outputFiles;
/**
* The pool on which this job has been decided to be executed by the
* Interpool Engine.
*
*/
public String executionPool;
//the namespace variables
/**
* The namespace object containing the globus rsl attributes which the user
* specifies in the dax, or the pool file or the properties file.
*/
public Globus globusRSL;
/**
* For Condor Namespace. This contains the extra Condor options which one
* may want to specify. These are copied straightaway to the Submit file.
*/
public Condor condorVariables;
/**
* To accomodate the environment variables which might needed to be set.
*/
public ENV envVariables;
/**
* The DAGMAN namespace profile variable holding the dagman profiles.
* It holds the prescript and the postscripts for the jobs.
*/
public Dagman dagmanVariables;
/**
* To accomodate all the hints that maybe passed through the DAX.
*/
public Hints hints;
/**
* The Pegasus namespace variable.
*/
public Pegasus vdsNS;
/**
* the metadata namespace
*/
@Expose @SerializedName( "metadata" )
private Metadata mMetadataAttributes;
/**
* Identifies the level of the job in the dax. The level is bottom up
* from the final child node.
*/
public int level;
/**
* The expected runtime for a job.
*/
private double mRuntime;
/**
* Boolean indicating whether the job executables were staged for it or not.
*/
private boolean mJobExecutablesStaged;
/**
* All the notifications associated with the job
*/
private Notifications mNotifications;
/**
* The staging site associated with the job
*/
private String mStagingSite;
/**
* The directory in which the job should run.
*/
private String mDirectory;
/**
* The relative path to the submit directory for the job, from the workflows
* base submit directory.
*/
// private String submitDirectory;
/**
* The credential to use for job submission if required.
*/
private CredentialHandler.TYPE mSubmissionCredential;
/**
* Set of credential types required by a job to execute remotely.
*/
private Map<String, Set<CredentialHandler.TYPE>> mCredentialsType;
/**
* The node label
*/
private String mNodeLabel;
private String mSubmitDir;
/**
* The node containing the job.
*/
private GraphNode mGraphNode;
/**
* Intialises the member variables.
*/
public Job() {
jobName = "";
namespace = "";
logicalName = "";
logicalId = "";
version = "";
dvName = null;
dvNamespace = null;
dvVersion = null;
jobID = "";
globusScheduler = "";
executable = "";
condorUniverse = "";
stdIn = "";
stdOut = "";
stdErr = "";
inputFiles = new HashSet();
outputFiles = new HashSet();
strargs = "";
envVariables = new ENV();
executionPool = new String();
globusRSL = new Globus();
condorVariables = new Condor();
dagmanVariables = new Dagman();
hints = new Hints();
vdsNS = new Pegasus();
mMetadataAttributes = new Metadata();
jobClass = UNASSIGNED_JOB;
level = -1;
mRuntime = -1;
mJobExecutablesStaged = false;
mNotifications = new Notifications();
mStagingSite = null;
mDirectory = null;
mCredentialsType = new HashMap<String, Set<CredentialHandler.TYPE> >();
mSubmissionCredential = null;
mNodeLabel = null;
mGraphNode = null;
}
/**
* Overloaded constructor. Does a shallow copy of the job object passed.
*
* @param job the <code>Job</code> object containing the job description.
*/
public Job(Job job){
jobName = job.jobName;
namespace = job.namespace;
logicalName = job.logicalName;
logicalId = job.logicalId;
version = job.version;
dvName = job.dvName;
dvNamespace = job.dvNamespace;
dvVersion = job.dvVersion;
jobID = job.jobID;
globusScheduler = job.globusScheduler;
executable = job.executable;
condorUniverse = job.condorUniverse;
stdIn = job.stdIn;
stdOut = job.stdOut;
stdErr = job.stdErr;
inputFiles = job.inputFiles;
outputFiles = job.outputFiles;
strargs = job.strargs;
envVariables = job.envVariables;
executionPool = job.executionPool;
globusRSL = job.globusRSL;
condorVariables = job.condorVariables;
dagmanVariables = job.dagmanVariables;
hints = job.hints;
vdsNS = job.vdsNS;
mMetadataAttributes = job.mMetadataAttributes;
jobClass = job.getJobType();
level = job.level;
mRuntime = job.mRuntime;
mJobExecutablesStaged = job.mJobExecutablesStaged;
mNotifications = job.mNotifications;
mStagingSite = job.mStagingSite;
mDirectory = job.mDirectory;
mSubmissionCredential = job.mSubmissionCredential;
mCredentialsType = new HashMap<String, Set<CredentialHandler.TYPE>>();
mNodeLabel = null;
mGraphNode = job.getGraphNodeReference();
}
/**
* Returns a new copy of the Object.
*
* @return clone of the object.
*/
public Object clone(){
Job newSub = new Job();
newSub.condorUniverse = this.condorUniverse;
newSub.envVariables = (ENV)this.envVariables.clone();
newSub.executable = this.executable;
newSub.globusScheduler= this.globusScheduler;
for(Iterator it = this.inputFiles.iterator(); it.hasNext(); ){
newSub.addInputFile( (PegasusFile)((PegasusFile)it.next()).clone());
}
for(Iterator it = this.outputFiles.iterator(); it.hasNext(); ){
newSub.addOutputFile( (PegasusFile)((PegasusFile)it.next()).clone());
}
newSub.jobName = this.jobName;
newSub.logicalName = this.logicalName;
newSub.logicalId = this.logicalId;
newSub.stdErr = this.stdErr;
newSub.stdIn = this.stdIn;
newSub.stdOut = this.stdOut;
newSub.strargs = this.strargs;
newSub.executionPool = this.executionPool;
newSub.globusRSL = this.globusRSL == null ? null : (Globus)this.globusRSL.clone();
newSub.condorVariables= this.condorVariables == null ? null :
(Condor)this.condorVariables.clone();
newSub.dagmanVariables= this.dagmanVariables == null ? null :
(Dagman)this.dagmanVariables.clone();
newSub.vdsNS = this.vdsNS == null ? null :(Pegasus)this.vdsNS.clone();
newSub.mMetadataAttributes = this.mMetadataAttributes == null ? null :(Metadata)this.mMetadataAttributes.clone();
newSub.hints = (Hints)this.hints.clone();
newSub.jobID = this.jobID;
newSub.jobClass = this.jobClass;
newSub.dvName = this.dvName;
newSub.namespace = this.namespace;
newSub.version = this.version;
newSub.dvNamespace = this.dvNamespace;
newSub.dvVersion = this.dvVersion;
newSub.level = this.level;
newSub.mRuntime = this.mRuntime;
// newSub.submitDirectory = this.submitDirectory == null ? null : new String(this.submitDirectory);
newSub.mJobExecutablesStaged = this.mJobExecutablesStaged;
newSub.mNotifications = (Notifications)this.getNotifications().clone();
newSub.mStagingSite = this.mStagingSite;
newSub.mDirectory = this.mDirectory;
newSub.mSubmissionCredential = this.mSubmissionCredential;
for( Map.Entry<String,Set<CredentialHandler.TYPE>> entry : this.getCredentialTypes().entrySet() ){
String site = entry.getKey();
for( CredentialHandler.TYPE cred: entry.getValue()){
newSub.addCredentialType( site, cred );
}
}
newSub.mNodeLabel = this.mNodeLabel;
//explicitly unset the reference to containing graph node
newSub.setGraphNodeReference( null );
return newSub;
}
/**
* Sets the expected runtime for the job.
*
* @param runtime the runtime for the job.
*/
public void setRuntime( String runtime ) {
if( runtime == null ){
mRuntime = -1;
}
else{
mRuntime = Double.parseDouble( runtime );
}
}
/**
* Sets the expected runtime for the job.
*
* @param runtime the runtime for the job.
*/
public void setRuntime( double runtime ) {
mRuntime = runtime;
}
/**
* Returns the expected runtime for the job that is set using the
* setRuntime method.
*
* @return the runtime for the job.
*/
public double getRuntime( ) {
return mRuntime;
}
/**
* Returns the runtime associated with the job. If the runtime variable with
* the job is set to -ve then, it also attempts to check on the value
* specified in Pegasus Profile key runtime for the job. If there is
* a value associated with profile key, that the runtime value is set to that
* using setRuntime( String ) function.
*
* @return the expected runtime.
* @see org.griphyn.cPlanner.namespace.Pegasus#RUNTIME_KEY
*/
public double computeRuntime( ){
if( mRuntime < 0 ){
//attempt to look up the value from pegasus profile
String value = this.vdsNS.getStringValue( Pegasus.RUNTIME_KEY );
if( value == null ){
return -1;
}
else{
setRuntime( value );
}
}
return mRuntime;
}
/**
* Set the universe associated with the job.
*
* @param universe the universe to be associated.
*/
public void setUniverse( String universe ){
this.condorUniverse = universe;
}
/**
* Returns the universe associated with the job.
*
* @return the universe associate with job .
*/
public String getUniverse( ){
return this.condorUniverse;
}
/**
* Sets the executable staging flag in the job to the value passed.
*
* @param value the boolean value.
*/
public void setExecutableStagingForJob( boolean value ){
mJobExecutablesStaged = value;
}
/**
* Returns whether user executables need to be staged for job or not.
*
* @return user executable staging.
*/
public boolean userExecutablesStagedForJob(){
return mJobExecutablesStaged ;
}
/**
* Adds an input file to the underlying collection of input files
* associated with the job.
*
* @param file the <code>PegasusFile</code> containing the input file.
*/
public void addInputFile(PegasusFile file){
this.inputFiles.add(file);
}
/**
* Sets the input files associated with the job.
*
* @param ipFiles Set of <code>PegasusFile</code> objects containing the input files.
*/
public void setInputFiles( Set<PegasusFile> ipFiles ){
this.inputFiles = ipFiles;
}
/**
* Returns the set of input files associated with the job.
*
* @return Set of <code>PegasusFile</code> objects containing the input files.
*/
public Set<PegasusFile> getInputFiles( ){
return this.inputFiles;
}
/**
* Resets the notifications associated with the job
*/
public void resetNotifications( ){
this.mNotifications = new Notifications();
}
/**
* Adds a Invoke object correpsonding to a notification.
*
* @param invoke the invoke object containing the notification
*/
public void addNotification( Invoke invoke ){
this.mNotifications.add(invoke);
}
/**
* Adds all the notifications specfied in the TransformationCatalogEntry
* to the underlying job notifications.
*
* @param entry the TransformationCatalogEntry object
*/
public void addNotifications( TransformationCatalogEntry entry ){
this.mNotifications.addAll( entry.getNotifications() );
}
/**
* Adds all the notifications passed to the underlying container.
*
* @param invokes the notifications to be added
*/
public void addNotifications( Notifications invokes ){
this.mNotifications.addAll(invokes);
}
/**
* Returns a collection of all the notifications that need to be
* done for a particular condition
*
* @param when the condition
*
* @return
*/
public Collection<Invoke> getNotifications( Invoke.WHEN when ){
return this.mNotifications.getNotifications(when);
}
/**
* Returns all the notifications associated with the job.
*
* @return the notifications
*/
public Notifications getNotifications( ){
return this.mNotifications;
}
/**
* Sets the credential to use for job submission.
*
* @param cred the job submission credential
*/
public void setSubmissionCredential( CredentialHandler.TYPE cred ){
this.mSubmissionCredential = cred;
}
/**
* Looks at a URL to determine whether a credential should be associated with
* a job or not.
*
* @param site the site with which the credential is associated
* @param url the url for which a credential needs to be added
*/
public void addCredentialType( String site, String url ){
//sanity check
if( url == null ){
return;
}
if( url.startsWith( "gsiftp" ) || url.startsWith( "xroot") ||
url.startsWith( "root" ) || url.startsWith( "srm") ||
url.startsWith( "go" ) ){
this.addCredentialType( site, CredentialHandler.TYPE.x509 );
}
else if( url.startsWith( "gsiscp" ) ){
// is this the correct place to verify the URL?
if (url.indexOf("@") == -1) {
throw new RuntimeException("Detected a gsiscp transfer without" +
" username. Please specify a username in the URL." +
" For example:" +
" gsiftp://username@somehost.org:22/path/file");
}
this.addCredentialType( site, CredentialHandler.TYPE.x509 );
}
else if( url.startsWith( "sshftp" ) ){
// is this the correct place to verify the URL?
if (url.indexOf("@") == -1) {
throw new RuntimeException("Detected a sshftp transfer without" +
" username. Please specify a username in the URL." +
" For example:" +
" sshftp://username@somehost.org/path/file");
}
this.addCredentialType( site, CredentialHandler.TYPE.ssh );
}
else if( url.startsWith( "s3" ) ){
this.addCredentialType( site, CredentialHandler.TYPE.s3 );
}
else if( url.startsWith( "gs" ) ){
this.addCredentialType( site, CredentialHandler.TYPE.boto );
this.addCredentialType( site, CredentialHandler.TYPE.googlep12 );
}
else if( url.startsWith( "irods" ) ){
this.addCredentialType( site, CredentialHandler.TYPE.irods );
}
else if( url.startsWith( "scp" ) ){
// is this the correct place to verify the URL?
if (url.indexOf("@") == -1) {
throw new RuntimeException("Detected a scp transfer without" +
" username. Please specify a username in the URL." +
" For example:" +
" scp://username@somehost.org/path/file");
}
this.addCredentialType( site, CredentialHandler.TYPE.ssh );
}
}
/**
* Adds a type of credential that will be required by a job.
*
* @param type the credential type.
*/
public void addCredentialType( String site, CredentialHandler.TYPE type ){
Set<CredentialHandler.TYPE> set = null;
if ( this.mCredentialsType.containsKey( site ) ){
set = this.mCredentialsType.get( site );
}
else{
set = new HashSet();
this.mCredentialsType.put(site, set);
}
set.add(type);
}
/**
* A boolean method indicating whether credentials are associated with the
* job
*
* @return boolean
*/
public boolean requiresCredentials(){
return this.mSubmissionCredential != null ||//job requires a submission credential
!(this.mCredentialsType == null || this.mCredentialsType.isEmpty());//additional credentials associated
}
/**
* Sets the credential to use for job submission.
*
* @return the credential to use for job submission
*/
public CredentialHandler.TYPE getSubmissionCredential( ){
return this.mSubmissionCredential;
}
/**
* Returns the various credential types required by a job indexed by a site
* from which to pick up the credential
*
* @return the set of credentials required.
*/
public Map<String, Set<CredentialHandler.TYPE>> getCredentialTypes( ){
return this.mCredentialsType;
}
/**
* Resets the credential types required by a job.
*
*/
public void resetCredentialTypes(){
this.mCredentialsType.clear();
}
/**
* Adds an output file to the underlying collection of output files
* associated with the job.
*
* @param file the <code>PegasusFile</code> containing the output file.
*/
public void addOutputFile(PegasusFile file){
this.outputFiles.add(file);
}
/**
* Sets the output files associated with the job.
*
* @param opFiles Set of <code>PegasusFile</code> objects containing the
* output files.
*/
public void setOutputFiles( Set<PegasusFile> opFiles ){
this.outputFiles = opFiles;
}
/**
* Returns the set of output files associated with the job.
*
* @return Set of <code>PegasusFile</code> objects containing the output files.
*/
public Set<PegasusFile> getOutputFiles( ){
return this.outputFiles;
}
/**
* Sets the type of the job.
*
* @param type the type of the job.
* @exception IllegalArgumentException if the job type is outside its legal
* range.
*
* @see #UNASSIGNED_JOB
* @see #COMPUTE_JOB
* @see #STAGE_IN_JOB
* @see #STAGE_OUT_JOB
* @see #REPLICA_REG_JOB
* @see #INTER_POOL_JOB
* @see #CREATE_DIR_JOB
* @see #STAGED_COMPUTE_JOB
* @see #CLEANUP_JOB
*/
public void setJobType(int type){
if(typeInRange(type)){
jobClass = type;
}
else{
throw new IllegalArgumentException("Invalid Job type " + type);
}
}
/**
* Sets the site handle of the site, where teh job is to be executed
*
* @param site the site handle.
*/
public void setSiteHandle(String site){
this.executionPool = site;
}
/**
* Returns the handle of the site where the job is scheduled.
*
* @return site handle.
*/
public String getSiteHandle(){
return executionPool;
}
/**
* Sets the path to the executable on the remote grid site. This executable
* is invoked whenever a job is run on the remote grid site.
*
* @param path the path to the underlying transformation on the remote grid
* site.
*
* @see #getSiteHandle()
*/
public void setRemoteExecutable( String path ){
this.executable = path;
}
/**
* Returns the path of the underlying executable on the remote grid site.
*
* @return the path to the executable if set.
*/
public String getRemoteExecutable( ){
return this.executable;
}
/**
* Sets the remote jobmanager on which the job has to run.
*
* @param jobmanager the jobmanager url.
*
* @see #getJobManager()
*/
public void setJobManager( String jobmanager ){
this.globusScheduler = jobmanager;
}
/**
* Returnss the remote jobmanager on which the job has to run.
*
* @return the jobmanager url.
*
* @see #setJobManager(java.lang.String)
*/
public String getJobManager( ){
return this.globusScheduler;
}
/**
* Sets the file to which the stdout of the job needs to be written to
* at the remote grid site. Should be just the basename. The file appears
* in the remote working directory for that job.
*
* @param fileName the basename of the file.
*/
public void setStdOut( String fileName ){
this.stdOut = fileName;
}
/**
* Returns the file to which the stdout of the job is written to.
*
* @return the basename of the file.
*/
public String getStdOut( ){
return this.stdOut;
}
/**
* Sets the file to which the stderr of the job needs to be written to
* at the remote grid site. Should be just the basename. The file appears
* in the remote working directory for that job.
*
* @param fileName the basename of the file.
*/
public void setStdErr( String fileName ){
this.stdErr = fileName;
}
/**
* Returns the file to which the stderr of the job is written to.
*
* @return the basename of the file.
*/
public String getStdErr( ){
return this.stdErr;
}
/**
* Sets the file to from which to pick up the stdin for the job. The file
* is tracked via Replica Catalog, and is staged to the remote grid site.
*
* @param fileName the basename of the file.
*/
public void setStdIn( String fileName ){
this.stdIn = fileName;
}
/**
* Returns the file from which the stdin is picked up.
*
* @return the basename of the file.
*/
public String getStdIn( ){
return this.stdIn;
}
/**
* Returns the ID associated with the job. Unfortunately currently it is
* the job name.
*
* @return the ID of the job.
*/
public String getID(){
return getName();
}
/**
* Sets the staging site.
*
* @param site the staging
*/
public void setStagingSiteHandle( String site ){
this.mStagingSite = site;
}
/**
* Returns the staging site.
*
* @return the staging
*/
public String getStagingSiteHandle( ){
return this.mStagingSite;
}
/**
* Returns the name of the job.
*
* @return String
*/
public String getName(){
return jobName;
}
/**
* Setter method to set the name of the job.
*
* @param name the name of the job.
*/
public void setName(String name){
jobName = name;
}
/**
* Get the node label for the job
*
* @return the label
*/
public String getNodeLabel( ) {
return mNodeLabel;
}
/**
* Sets the node label for the job
*
* @param label the label value specified
*/
public void setNodeLabel(String label) {
mNodeLabel = label;
}
/**
* Returns the directory where the job runs.
*
* @return String
*/
public String getDirectory(){
return mDirectory ;
}
/**
* Setter method to set the name of the job.
*
* @param name the name of the job.
*/
public void setDirectory( String directory ){
mDirectory = directory;
}
/**
* Returns the logical id of the job.
*
* @return String
*/
public String getLogicalID(){
return logicalId;
}
/**
* Returns the DAX ID for the job if it appeared in the DAX, else null
*
* @return the id of the job in the DAX if present , else null
*/
public String getDAXID(){
StringBuffer sb = new StringBuffer();
int type = this.getJobType();
if( type == Job.COMPUTE_JOB ||
type == Job.DAG_JOB ||
type == Job.DAX_JOB ) {
//dax and dag jobs actually are never launched
//via kickstart as of now.
//pass the logical id in the DAX
sb.append( this.getLogicalID() );
}
else{
//for all auxillary jobs pass null
sb.append( (String)null );
}
return sb.toString();
}
/**
* Setter method to set the logical id of the job.
*
* @param id the logical id of the job.
*/
public void setLogicalID(String id){
logicalId = id;
}
/**
* Returns the name of the compute job of Pegasus supernode containing this job.
*
* @return String
*/
public String getVDSSuperNode(){
return this.jobID;
}
/**
* Setter method to the name of the compute job of Pegasus supernode containing
* this job.
*
* @param name the name of the job.
*/
public void setVDSSuperNode( String name ){
this.jobID = name;
}
/**
* Returns the type of the job. Returns the value matching the jobClass.
*
* @return int value of job class.
*/
public int getJobType(){
return this.jobClass;
}
/**
* Returns the corresponding grid gateway job type
*
* @return grid gateway job type
*/
public GridGateway.JOB_TYPE getGridGatewayJobType(){
// JIRA PM-277
// return Job.jobType2GridGatewayJobType( this.getJobType() );
return this.hints.containsKey( Hints.GRID_JOB_TYPE_KEY ) ?
GridGateway.JOB_TYPE.valueOf( (String)this.hints.get( Hints.GRID_JOB_TYPE_KEY ) ):
Job.jobType2GridGatewayJobType( this.getJobType() );
}
/**
* Gets the textual description of the type associated with the job.
*
* @return the textual description of the type associated with the job.
*/
public String getJobTypeDescription(){
return getJobTypeDescription(this.jobClass);
}
/**
* Gets the textual description of the type that can be associated
* with a job.
*
* @param type the type of the job.
*
* @return the textual description of the type associated with the job.
*/
public String getJobTypeDescription(int type){
String desc = null;
switch (type){
case COMPUTE_JOB:
desc = "compute";
break;
case STAGE_IN_JOB:
desc = "stage-in-tx";
break;
case STAGE_OUT_JOB:
desc = "stage-out-tx";
break;
case INTER_POOL_JOB:
desc = "inter-site-tx";
break;
case REPLICA_REG_JOB:
desc = "registration";
break;
case UNASSIGNED_JOB:
desc = "unassigned";
break;
case CREATE_DIR_JOB:
desc = "create-dir";
break;
case CLEANUP_JOB:
desc = "cleanup";
break;
case CHMOD_JOB:
desc = "chmod";
break;
case DAX_JOB:
desc = "dax";
break;
case DAG_JOB:
desc = "dag";
break;
default:
desc = "unknown";
break;
}
return desc;
}
/**
* Returns the namespace of the underlying transformation.
*
* @return namespace
*/
public String getTXNamespace(){
return namespace;
}
/**
* Sets the transformation namespace to be associated with the job.
*
* @param ns the namespace.
*/
public void setTXNamespace( String ns ){
this.namespace = ns;
}
/**
* Returns the name of the underlying transformation.
*
* @return name
*/
public String getTXName(){
return logicalName;
}
/**
* Sets the transformation name of the underlying transformation.
*
* @param name the logical name of the transformation.
*/
public void setTXName(String name){
this.logicalName = name;
}
/**
* Returns the version of the underlying transformation.
*
* @return version
*/
public String getTXVersion(){
return version;
}
/**
* Sets the version of the underlying transformation.
*
* @param vs the version.
*/
public void setTXVersion(String vs){
this.version = vs;
}
/**
* Sets the various attributes of underlying transformation.
*
* @param ns the namespace of the transformation.
* @param name the logical name of the transformation.
* @param vs the version of the transformation.
*/
public void setTransformation( String ns, String name, String vs){
this.setTXNamespace(ns);
this.setTXName(name);
this.setTXVersion(vs);
}
/**
* Constructs the fully qualified name of a transformation with
* which to query the TC, including the namespace and version.
*
* @return the complete tranformation name.
*/
public String getCompleteTCName(){
return Separator.combine(namespace,logicalName,version);
}
/**
* Returns the namespace of the underlying derivation.
*
* @return namespace
*/
public String getDVNamespace(){
return dvNamespace;
}
/**
* Sets the derivation namespace to be associated with the job.
*
* @param ns the namespace.
*/
public void setDVNamespace( String ns ){
this.dvNamespace = ns;
}
/**
* Returns the name of the underlying derivation.
*
* @return name
*/
public String getDVName(){
return dvName;
}
/**
* Sets the derivation name of the underlying derivation.
*
* @param name the logical name of the derivation.
*/
public void setDVName(String name){
this.dvName = name;
}
/**
* Returns the version of the underlying derivation.
*
* @return version
*/
public String getDVVersion(){
return dvVersion;
}
/**
* Sets the version of the underlying derivation.
*
* @param vs the version.
*/
public void setDVVersion(String vs){
this.dvVersion = vs;
}
/**
* Sets the various attributes of underlying derivation.
*
* @param ns the namespace of the derivation.
* @param name the logical name of the derivation.
* @param vs the version of the derivation.
*/
public void setDerivation( String ns, String name, String vs){
this.setDVNamespace(ns);
this.setDVName(name);
this.setDVVersion(vs);
}
/**
* Returns the level associated with the job.
*
* @return int designating the level
*/
public int getLevel( ){
return level;
}
/**
* Sets the level for the job.
*
* @param value the level
*/
public void setLevel( int value ){
level = value;
}
/**
* Constructs the fully qualified name of the corresponding derivation used
* to generate this job in Chimera including the namespace and version.
*
* @return the complete derivation name.
*/
public String getCompleteDVName(){
return (dvName == null) ?
null:
Separator.combine(dvNamespace,dvName,dvVersion);
}
/**
* Returns the basename for the staged executable corresponding to the
* job.
*
* @return the staged executable basename
*/
public String getStagedExecutableBaseName(){
return getStagedExecutableBaseName( namespace, logicalName, version );
}
/**
* Returns the basename for the staged executable corresponding to the
* job.
*
* @param txNamespace is the namespace in which the TR resides, may be null.
* @param txName is the base name of the transformation, must not be null.
* @param txVersion is the version of the TR, may be null
*
* @return the staged executable basename
*/
public static String getStagedExecutableBaseName( String txNamespace, String txName, String txVersion ){
return combine( txNamespace, txName, txVersion);
}
/**
* Returns the submit directory path relative to the workflow submit
* directory.
*
* @return the directory name, if set else null.
*/
// public String getSubmitDirectory(){
// return this.submitDirectory;
// }
/**
* Sets the submit directory path relative to the workflow submit
* directory.
*
* @param directory the directory name.
*/
// public void setSubmitDirectory(String directory){
// this.submitDirectory = directory;
// }
/**
* Returns the argument string with which the job has to be invoked.
*
* @return the argument string.
*/
public String getArguments(){
return this.strargs;
}
/**
* Sets the argument string with which the job has to be invoked.
*
* @param arguments the argument string.
*/
public void setArguments(String arguments){
this.strargs = arguments;
}
/**
* Combines the three components together into a single string as
* namespace-name-version.
*
* @param namespace is the namespace in which the TR resides, may be null.
* @param name is the base name of the transformation, must not be null.
* @param version is the version of the TR, may be null.
*
* @return the concatenated form .
*/
private static String combine(String namespace,
String name,
String version) {
StringBuffer result = new StringBuffer(32);
if ( namespace != null && namespace.length() > 0 ) {
result.append( namespace ).append( DELIMITER);
}
result.append(name);
if (version != null && version.length() > 0 ) {
result.append( DELIMITER ).append( version );
}
return result.toString();
}
/**
* It sets the prescript for the job. The argument string is assumed to be
* empty.
*
* @param path the path to the script that has to be run as a prescript.
*/
public void setPreScript(String path) {
setPreScript( path , "");
}
/**
* It sets the prescript for the job.
*
* @param path the path to the script that has to be run as a prescript.
* @param arguments the arguments to the prescript,
*/
public void setPreScript(String path, String arguments){
//this.preScript = script;
//construct directly as we know keys are valid.
dagmanVariables.construct( Dagman.PRE_SCRIPT_KEY, path );
dagmanVariables.construct( Dagman.PRE_SCRIPT_ARGUMENTS_KEY, arguments);
}
/**
* Returns the meta data attributes associated with the job
*
* @return
*/
public Namespace getMetadata(){
return this.mMetadataAttributes;
}
/**
* Returns the path to the prescript for the job if set.
*
* @return the path to the script that has to be run as a prescript, else
* null if no prescript has been set.
*/
public String getPreScriptPath(){
Object obj = dagmanVariables.get( Dagman.PRE_SCRIPT_KEY );
return (obj == null)? null: (String)obj;
}
/**
* Returns the arguments to the prescript for the job if set.
*
* @return the argumetns to the prescript script that has to be run as a
* prescript, else null if no prescript has been set.
*/
public String getPreScriptArguments(){
Object obj = dagmanVariables.get( Dagman.PRE_SCRIPT_ARGUMENTS_KEY );
return (obj == null)? null: (String)obj;
}
/**
* Returns whether the job is recursive or not.
*
* @return boolean
*/
public boolean typeRecursive(){
return this.vdsNS.containsKey( Pegasus.TYPE_KEY )?
this.vdsNS.getStringValue( Pegasus.TYPE_KEY ).equals( "recursive" ):
false;
}
/**
* Sets the job to be recursive.
*/
public void setTypeRecursive(){
this.vdsNS.construct( Pegasus.TYPE_KEY, "recursive" );
}
/**
* Returns whether the job type value for the job is in range or not.
*
* @param type the job type.
*
* @return true if the value is in range.
* false if the value is not in range.
*/
public static boolean typeInRange(int type){
return ( type >= Job.UNASSIGNED_JOB &&
type <= Job.DAG_JOB );
}
/**
* Updates all the profile namespaces with the information associated in
* the transformation catalog for this job.
* It ends up updating already existing information, and adds supplemental
* new information if present in the transformation catalog.
* The method does not explicitly check whehter the data object passed refers
* to this job or not. The calling method should ensure this.
*
* @param entry the <code>TCEntry</code> object corresponding to the
* entry in the Transformation Catalog for the job.
*/
public void updateProfiles(TransformationCatalogEntry entry){
condorVariables.checkKeyInNS(entry);
dagmanVariables.checkKeyInNS(entry);
globusRSL.checkKeyInNS(entry);
envVariables.checkKeyInNS(entry);
vdsNS.checkKeyInNS(entry);
hints.checkKeyInNS(entry);
mMetadataAttributes.checkKeyInNS(entry);
}
/**
* Updates all the profile namespaces with the information specified by the
* user in the properties file, that apply to this job.
* It ends up updating already existing information, and adds supplemental
* new information if present in the properties file.
* The method does not explicitly check whehter the data object passed refers
* to this job or not. The calling method should ensure this.
*
* @param properties the <code>PegasusProperties</code> object containing
* the user properties.
*/
public void updateProfiles(PegasusProperties properties){
condorVariables.checkKeyInNS(properties,executionPool);
dagmanVariables.checkKeyInNS(properties,executionPool);
globusRSL.checkKeyInNS(properties,executionPool);
envVariables.checkKeyInNS(properties,executionPool);
vdsNS.checkKeyInNS(properties,executionPool);
hints.checkKeyInNS(properties, executionPool );
mMetadataAttributes.checkKeyInNS(properties, executionPool );
}
/**
* Updates all the profile namespaces with the information specified in
* list of profile objects passed. Pool catalog returns profile information
* as a list of <code>Profile</code> objects that need to be propogated to
* the job.
* It ends up updating already existing information, and adds supplemental
* new information if present in the properties file.
*
*
* @param profiles The <code>Profiles</code> that need to be incorporated in
* the jobs profile namespaces.
*/
public void updateProfiles( Profiles profiles){
if( profiles == null ){
//nothing to put in the namespaces
return;
}
String key = null;
Namespace n = profiles.get( NAMESPACES.condor );
for( Iterator it = n.getProfileKeyIterator(); it.hasNext(); ){
key = (String)it.next();
condorVariables.checkKeyInNS( key, (String)n.get( key ) );
}
n = profiles.get( NAMESPACES.globus );
for( Iterator it = n.getProfileKeyIterator(); it.hasNext(); ){
key = (String)it.next();
globusRSL.checkKeyInNS( key, (String)n.get( key ) );
}
n = profiles.get( NAMESPACES.env );
for( Iterator it = n.getProfileKeyIterator(); it.hasNext(); ){
key = (String)it.next();
envVariables.checkKeyInNS( key, (String)n.get( key ) );
}
n = profiles.get( NAMESPACES.pegasus );
for( Iterator it = n.getProfileKeyIterator(); it.hasNext(); ){
key = (String)it.next();
vdsNS.checkKeyInNS( key, (String)n.get( key ) );
}
n = profiles.get( NAMESPACES.dagman );
for( Iterator it = n.getProfileKeyIterator(); it.hasNext(); ){
key = (String)it.next();
dagmanVariables.checkKeyInNS( key, (String)n.get( key ) );
}
n = profiles.get( NAMESPACES.hints );
for( Iterator it = n.getProfileKeyIterator(); it.hasNext(); ){
key = (String)it.next();
hints.checkKeyInNS( key, (String)n.get( key ) );
}
n = profiles.get( NAMESPACES.metadata );
for( Iterator it = n.getProfileKeyIterator(); it.hasNext(); ){
key = (String)it.next();
this.mMetadataAttributes.checkKeyInNS( key, (String)n.get( key ) );
}
}
/**
* Updates all the profile namespaces with the information specified in
* list of profile objects passed. Pool catalog returns profile information
* as a list of <code>Profile</code> objects that need to be propogated to
* the job.
* It ends up updating already existing information, and adds supplemental
* new information if present in the properties file.
*
*
* @param profiles the list of <code>Profile</code> objects that need to be
* incorporated in the jobs profile namespaces.
*/
public void updateProfiles(List profiles){
if(profiles == null || profiles.isEmpty()){
//nothing to put in the namespaces
return;
}
Profile profile = null;
for( Iterator it = profiles.iterator(); it.hasNext(); ){
profile = (Profile)it.next();
if(profile.getProfileNamespace().equals(Profile.CONDOR)){
condorVariables.checkKeyInNS(profile);
}
else if(profile.getProfileNamespace().equals(Profile.GLOBUS)){
globusRSL.checkKeyInNS(profile);
}
else if(profile.getProfileNamespace().equals(Profile.ENV)){
envVariables.checkKeyInNS(profile);
}
else if(profile.getProfileNamespace().equals(Profile.VDS)){
vdsNS.checkKeyInNS(profile);
}
else if(profile.getProfileNamespace().equals(Profile.DAGMAN)){
dagmanVariables.checkKeyInNS(profile);
}
else if(profile.getProfileNamespace().equals(Profile.HINTS)){
hints.checkKeyInNS(profile);
}
else if(profile.getProfileNamespace().equals(Profile.METADATA)){
this.mMetadataAttributes.checkKeyInNS(profile);
}
else{
//unknown profile.
mLogger.log("Unknown Profile: " + profile + " for job" +
this.jobName,LogManager.WARNING_MESSAGE_LEVEL);
}
}
}
/**
* Merges profiles from another job to this job in a controlled fashion.
* The merging of the profile is dependant upon the namespace to which it
* belongs. Some profiles maybe overriden, others maybe summed up etc.
*
* @param job the <code>Job</code> object containing the job description
* for the job whose profiles have to be merged into this job.
*
*/
public void mergeProfiles( Job job ){
this.globusRSL.merge( job.globusRSL );
this.envVariables.merge( job.envVariables );
this.condorVariables.merge( job.condorVariables );
this.dagmanVariables.merge( job.dagmanVariables );
this.vdsNS.merge( job.vdsNS );
this.hints.merge( job.hints );
this.mMetadataAttributes.merge( job.mMetadataAttributes );
}
/**
* Checks if an object is similar to the one referred to by this class.
* We compare the primary key to determine if it is the same or not.
*
* @param obj the object for which equalsto is applied.
*
* @return true if the primary key (jobName) match.
* else false.
*/
public boolean equals(Object obj){
if(obj instanceof Job){
Job job = (Job) obj;
return job.jobName.equals(this.jobName) ?
true :
false;
}
//objects are of different type. cannot be compared
return false;
}
/**
* Returns a boolean value denoting whether the job is MPI or not.
* If no job type is specified in the globus rsl for the job, the job is
* assumed to be non mpi.
*
* @return boolean true if jobtype=mpi set in the globus rsl.
* false in all other cases.
*/
public boolean isMPIJob(){
boolean mpi = false;
//sanity checks
if(this.globusRSL == null || !(globusRSL.containsKey("jobtype")) ){
return false;
}
return( ((String)globusRSL.get("jobtype")).equalsIgnoreCase("mpi") )?
true : //the job type is set to mpi
false;
}
/**
* Returns whether a job should be run in the work directory or not.
* If a job is not run in the work directory, then it should be run
* in the submit directory. That would be the case if the job has been
* scheduled to site "local" and the class of the job coressponds to the
* auxillary jobs that have been created by Pegasus.
*
* @return boolean true to indicate job can run in work directory,
* false job cant be run.
*/
public boolean runInWorkDirectory(){
return !(executionPool != null &&
executionPool.equalsIgnoreCase("local") &&
(jobClass > this.COMPUTE_JOB &&
jobClass <= this.CREATE_DIR_JOB));
}
/**
* Resets all the profiles associated with the job.
*/
public void resetProfiles(){
envVariables = new ENV();
globusRSL = new Globus();
condorVariables = new Condor();
dagmanVariables = new Dagman();
hints = new Hints();
vdsNS = new Pegasus();
mMetadataAttributes = new Metadata();
}
/**
* Returns a textual description of the object.
*
* @return textual description of the job.
*/
public String toString(){
String str = this.globusRSL == null ? null : this.globusRSL.toString();
String cVar = this.condorVariables == null ? null : this.condorVariables.toString();
String envStr = this.envVariables == null ? null : this.envVariables.toString();
StringBuffer sb = new StringBuffer();
String newline = System.getProperty( "line.separator", "\r\n" );
sb.append("[");
append( sb, "Job Name", this.jobName , newline );
append( sb, "Logical Id", this.logicalId , newline );
append( sb, "Transformation", this.getCompleteTCName() , newline );
append( sb, "Derivation", this.getCompleteDVName() , newline );
append( sb, "Node Label", this.getNodeLabel(), newline );
append( sb, "Level", new Integer(this.level).toString() , newline );
append( sb, "Job Type Description", getJobTypeDescription(this.jobClass) , newline );
append( sb, "Job Id" , this.jobID , newline );
append( sb, "Runtime", this.mRuntime, newline );
append( sb, "Executable" , this.executable , newline );
append( sb, "Directory", this.mDirectory, newline );
append( sb, "Condor Universe" , this.condorUniverse , newline );
append( sb, "Globus Scheduler" , this.globusScheduler , newline );
append( sb, "Standard Output" , this.stdOut , newline );
append( sb, "Standard Input" , this.stdIn , newline );
append( sb, "Standard Error" , this.stdErr , newline );
append( sb, "Argument String" , this.strargs , newline );
append( sb, "Execution Site", this.executionPool , newline );
append( sb, "Staging Site", this.mStagingSite , newline );
append( sb, "Globus RSL" , str , newline );
append( sb, "Environment Variables" , envStr , newline );
append( sb, "Dagman Variables" , this.dagmanVariables , newline );
append( sb, "Hints" , this.hints , newline );
append( sb, "Input Files " , this.inputFiles , newline );
append( sb, "Output Files ", this.outputFiles , newline );
append( sb, "Condor Variables\n" , cVar , newline );
append( sb, "VDS Profiles" , vdsNS , newline );
append( sb, "Notifications", this.mNotifications, newline );
append( sb, "Credentials", this.mCredentialsType, newline );
sb.append("]");
return sb.toString();
}
/**
* Returns the DOT description of the object. This is used for visualizing
* the workflow.
*
* @return String containing the Partition object in XML.
*
* @exception IOException if something fishy happens to the stream.
*/
public String toDOT() throws IOException{
Writer writer = new StringWriter(32);
toDOT( writer, "" );
return writer.toString();
}
/**
* Returns the DOT description of the object. This is used for visualizing
* the workflow.
*
* @param stream is a stream opened and ready for writing. This can also
* be a StringWriter for efficient output.
* @param indent is a <code>String</code> of spaces used for pretty
* printing. The initial amount of spaces should be an empty
* string. The parameter is used internally for the recursive
* traversal.
*
*
* @exception IOException if something fishy happens to the stream.
*/
public void toDOT( Writer stream, String indent ) throws IOException {
String newLine = System.getProperty( "line.separator", "\r\n" );
//write out the node
stream.write( indent );
stream.write( "\"" );
stream.write( getID() );
stream.write( "\"" );
stream.write( " " );
stream.write( "[" );
//write out the color for the node
stream.write( "color=" );
stream.write( getDOTColor() );
stream.write( "," );
//write out the style
stream.write( "style=filled," );
//write out the label
stream.write( "label=" );
stream.write( "\"" );
stream.write( getID() );
stream.write( "\"" );
stream.write( "]" );
stream.write( newLine );
stream.flush();
}
/**
* Returns the color with which DOT should color the node representing the
* job.
*
* @return the color.
*/
protected String getDOTColor(){
int type = this.getJobType();
String color;
switch ( type ){
case 1: //this.COMPUTE_JOB:
color = "blueviolet";
break;
case 2: //this.STAGE_IN_JOB:
color = "gold";
break;
case 3: //this.STAGE_OUT_JOB:
color = "goldenrod";
break;
case 5: //this.INTER_POOL_JOB:
color = "goldenrod4";
break;
case 4: //this.REPLICA_REG_JOB:
color = "orange";
break;
case 6: //this.CREATE_DIR_JOB:
color = "darkturquoise";
break;
case 7: //this.STAGED_COMPUTE_JOB:
color = "violet";
break;
case 8: //this.CLEANUP_JOB:
color = "deepskyblue";
break;
default:
color = "grey";
}
return color;
}
/**
* Appends a key value mapping to the StringBuffer.
*
* @param sb StringBuffer to which the mapping has to be appended.
* @param key the field.
* @param value the value of the field.
* @param newLine the newLineSeparator to be used.
*/
private void append(StringBuffer sb, String key, Object value, String newLine){
String openingBrace = "{";
String closingBrace = "}";
String pointsTo = " -> ";
String separator = ",";
sb.append(newLine).append(openingBrace).append(key).append(pointsTo).
append(value).append(closingBrace).append(separator);
}
/**
* Convenience method to add metadata to the job
*
* @param key
* @param value
*/
public void addMetadata( String key, String value ){
this.addProfile( new Profile( Metadata.NAMESPACE_NAME, key, value ));
}
/**
* Adds a profile to the job object
*
* @param p the profile to be added
*/
public void addProfile( Profile p ) {
String namespace = p.getProfileNamespace();
String key = p.getProfileKey();
String value = p.getProfileValue();
switch( namespace.charAt(0) ){
case 'c'://condor
this.condorVariables.checkKeyInNS( key, value );
break;
case 'd'://dagman
this.dagmanVariables.checkKeyInNS(key, value );
break;
case 'e'://env
this.envVariables.checkKeyInNS(key, value );
break;
case 'g'://globus
this.globusRSL.checkKeyInNS(key, value );
break;
case 'h'://hint
this.hints.checkKeyInNS(key, value );
break;
case 'p'://pegasus
this.vdsNS.checkKeyInNS(key, value );
break;
case 'm'://metadata
this.mMetadataAttributes.checkKeyInNS( key, value );
break;
default:
//ignore should not come here ever.
mLogger.log("Namespace not supported. ignoring "+ namespace,
LogManager.WARNING_MESSAGE_LEVEL);
break;
}
}
/**
* Sets the relative submit directory for the job.
* The directory is relative to the top level directory where the workflow
* files are placed
*
* @param dir the directory
*/
public void setRelativeSubmitDirectory(String dir) {
mSubmitDir = dir;
}
/**
* Sets the relative submit directory for the job.
* The directory is relative to the top level directory where the workflow
* files are placed
*
* @param dir the directory
*/
public void setRelativeSubmitDirectory(File dir) {
mSubmitDir = dir.getPath();
}
/**
* Returns the relative submit directory for the job.
*
* @return
*/
public String getRelativeSubmitDirectory() {
return mSubmitDir;
}
/**
* Returns the full path for a job related file.
*
* @param submitDir the submit directory where the .dag file for the workflow resides.
* @param suffix the suffix to be attached.
*
* @return the full path for the file
*/
public String getFileFullPath(String submitDir, String suffix ){
StringBuilder sb = new StringBuilder();
String relative = this.getRelativeSubmitDirectory();
//PM-833
sb.append( submitDir ).append( File.separator);
if( relative != null ){
sb.append( relative ).append( File.separator);
}
sb.append( this.getFileBaseName( suffix) );
return sb.toString();
}
/**
* Returns the relative path for a job related file, relative to the
* submit directory of the workflow
*
* @param suffix the suffix to be attached.
*
* @return the full path for the file
*/
public String getFileRelativePath( String suffix ){
StringBuilder sb = new StringBuilder();
String relative = this.getRelativeSubmitDirectory();
if( relative != null ){
sb.append( relative ).append( File.separator);
}
else{
sb.append( "." ).append( File.separator );
}
sb.append( this.getFileBaseName( suffix) );
return sb.toString();
}
/**
* Returns the basename of the file to which the job is written to.
*
* @param suffix the suffix to be attached.
*
* @return the basename of the file.
*/
public String getFileBaseName( String suffix ){
StringBuilder sb = new StringBuilder();
sb.append( this.getID() ).append( suffix );
return sb.toString();
}
/**
* Set the containing GraphNode object
*
* @param node
*/
public void setGraphNodeReference(GraphNode node) {
this.mGraphNode = node;
}
/**
* Returns the containing GraphNode object
*
* @return node
*/
public GraphNode getGraphNodeReference() {
return this.mGraphNode;
}
}