/** * 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.refiner.createdir; import edu.isi.pegasus.common.logging.LogManager; import edu.isi.pegasus.planner.catalog.site.classes.FileServer; import edu.isi.pegasus.planner.classes.ADag; import edu.isi.pegasus.planner.classes.DAGJob; import edu.isi.pegasus.planner.classes.DAXJob; import edu.isi.pegasus.planner.classes.Job; import edu.isi.pegasus.planner.classes.PegasusBag; import edu.isi.pegasus.planner.classes.TransferJob; import edu.isi.pegasus.planner.partitioner.graph.GraphNode; import java.util.Iterator; import java.util.Set; /** * This Strategy instance places the create directory jobs at the top of the graph. * However instead of constricting it to an hour glass shape, this class links * it to all the relevant nodes for which the create dir job is necessary. It is * like that it spreads its tentacles all around. This potentially ends up * putting more load on the DagMan with all the dependencies but removes the * restriction of the plan progressing only when all the create directory * jobs have progressed on the remote pools, as in the HourGlass model. * * @author Karan Vahi * @author Gaurang Mehta * * @version $Revision$ */ public class Tentacles extends AbstractStrategy { /** * Intializes the class. * * @param bag bag of initialization objects * @param impl the implementation instance that creates create dir job */ public void initialize( PegasusBag bag, Implementation impl ){ super.initialize( bag , impl ); } /** * Modifies the workflow to add create directory nodes. The workflow passed * is a worklow, where the jobs have been mapped to sites. * * @param dag the workflow to which the nodes have to be added. * * @return the added workflow */ public ADag addCreateDirectoryNodes( ADag dag ){ Set createDirSites = this.getCreateDirSites( dag ); String pool = null; String jobName = null; String parent = null; //for each execution site add //a create directory node. //PM-747 we need to add jobs before we add any edges Job newJob = null; for (Iterator it = createDirSites.iterator();it.hasNext();){ pool = (String)it.next(); jobName = getCreateDirJobName( dag, pool); newJob = mImpl.makeCreateDirJob( pool, jobName, mSiteStore.getExternalWorkDirectoryURL( pool , FileServer.OPERATION.put ) ); dag.add(newJob); } //traverse through the jobs and //looking at their execution pool //and create a dependency to the //the correct create node //we add links first and jobs later //remove the entry for the local pool //set.remove("local"); int type; boolean local; for(Iterator<GraphNode> it = dag.jobIterator();it.hasNext();){ GraphNode node = it.next(); Job job = (Job)node.getContent(); jobName = job.getName(); pool = job.getSiteHandle(); if( job.getJobType() == Job.CREATE_DIR_JOB ){ //PM-747 we have added the create dir jobs beforehand //ignore them so that we don't create self edges continue; } if( job.getJobType() == Job.CHMOD_JOB ){ parent = getCreateDirJobName( dag, job.getSiteHandle() ); } else{ //the parent in case of a transfer job //is the non third party site String site = ( job instanceof TransferJob )? ((TransferJob)job).getNonThirdPartySite(): job.getStagingSiteHandle(); if( site == null ){ //only ok for stage worker jobs if( job instanceof TransferJob ){ mLogger.log( "Not adding edge to create dir job for job " + job.getID(), LogManager.DEBUG_MESSAGE_LEVEL ); continue; } } parent = getCreateDirJobName( dag, site); } //put in the dependency only for transfer jobs that stage in data //or are jobs running on remote sites //or are compute jobs running on local site type = job.getJobType(); local = pool.equals("local"); if( (job instanceof TransferJob && type != Job.STAGE_OUT_JOB ) || (!local || (type == Job.COMPUTE_JOB /*|| type == Job.STAGED_COMPUTE_JOB*/ || job instanceof DAXJob || job instanceof DAGJob ))){ //sanity check if( parent == null ){ //throw an error throw new RuntimeException( "Job not associated with staging site " + job.getID() ); } mLogger.log("Adding relation " + parent + " -> " + jobName, LogManager.DEBUG_MESSAGE_LEVEL); dag.addNewRelation(parent,jobName); } } return dag; } }