/** * 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.code.generator; import edu.isi.pegasus.common.logging.LogManager; import edu.isi.pegasus.planner.classes.ADag; import edu.isi.pegasus.planner.classes.Job; import edu.isi.pegasus.planner.classes.PlannerOptions; import edu.isi.pegasus.planner.code.CodeGenerator; import edu.isi.pegasus.planner.code.CodeGeneratorException; import edu.isi.pegasus.planner.common.PegasusProperties; import edu.isi.pegasus.planner.classes.PegasusBag; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * An Abstract Base class implementing the CodeGenerator interface. Introduces * helper methods for determining basenames of files, that contain concrete * job descriptions. * * * @author Karan Vahi * @author Gaurang Mehta * * @version $Revision$ */ public abstract class Abstract implements CodeGenerator{ /** * Suffix for the global log file to which exitcode should log to. */ public static final String POSTSCRIPT_LOG_SUFFIX = ".exitcode.log"; /** * The bag of initialization objects. */ protected PegasusBag mBag; /** * The directory where all the submit files are to be generated. */ protected String mSubmitFileDir; /** * The object holding all the properties pertaining to Pegasus. */ protected PegasusProperties mProps; /** * The object containing the command line options specified to the planner * at runtime. */ protected PlannerOptions mPOptions; /** * The LogManager object which is used to log all the messages. */ protected LogManager mLogger; /** * Returns the name of the file on the basis of the metadata associated * with the DAG. * In case of Condor dagman, it is the name of the .dag file that is * written out. The basename of the .dag file is dependant on whether the * basename prefix has been specified at runtime or not by command line * options. * * @param dag the dag for which the .dag file has to be created. * @param suffix the suffix to be applied at the end. * * @return the name of the dagfile. */ protected String getDAGFilename( ADag dag, String suffix ){ return getDAGFilename( mPOptions, dag.getLabel(), dag.getIndex(), suffix ); } /** * Returns the name of the file on the basis of the metadata associated * with the DAG. * In case of Condor dagman, it is the name of the .dag file that is * written out. The basename of the .dag file is dependant on whether the * basename prefix has been specified at runtime or not by command line * options. * * @param options the options passed to the planner. * @param name the name attribute in dax * @param index the index attribute in dax. * @param suffix the suffix to be applied at the end. * * @return the name of the dagfile. */ public static String getDAGFilename( PlannerOptions options, String name, String index, String suffix ){ //constructing the name of the dagfile StringBuffer sb = new StringBuffer(); String bprefix = options.getBasenamePrefix(); if( bprefix != null){ //the prefix is not null using it sb.append(bprefix); } else{ //generate the prefix from the name of the dag sb.append( name ).append("-"). append( index ); } //append the suffix sb.append( suffix ); return sb.toString(); } /** * Initializes the Code Generator implementation. * * @param bag the bag of initialization objects. * * @throws CodeGeneratorException in case of any error occuring code generation. */ public void initialize( PegasusBag bag ) throws CodeGeneratorException{ mBag = bag; mProps = bag.getPegasusProperties(); mPOptions = bag.getPlannerOptions(); mSubmitFileDir = mPOptions.getSubmitDirectory(); mLogger = bag.getLogger(); } /** * Starts monitoring of the workflow by invoking a workflow monitor daemon. * The monitoring should start only after the output files have been generated. * FIXME: It should actually happen after the workflow has been submitted. * Eventually should be a separate monitor interface, and submit writers * should be loaded by an AbstractFactory. * * @return boolean indicating whether could successfully start the monitor * daemon or not. */ public boolean startMonitoring(){ //by default not all code generators support monitoring. return false; } /** * Writes out the workflow metrics file for the workflow. * * @param workflow the workflow whose metrics file needs to be generated. */ /* protected void writeOutWorkflowMetrics( ADag workflow ){ try{ Metrics metrics = new Metrics(); metrics.initialize(mBag); Collection result = metrics.generateCode( workflow ); for( Iterator it = result.iterator(); it.hasNext() ;){ mLogger.log("Written out workflow metrics file to " + it.next(), LogManager.DEBUG_MESSAGE_LEVEL); } } catch(CodeGeneratorException ioe){ //log the message and return mLogger.log("Unable to write out the workflow metrics file ", ioe, LogManager.ERROR_MESSAGE_LEVEL ); } } */ /** * Writes out the stampedeEventGenerator events for the workflow. * * @param workflow the workflow whose metrics file needs to be generated. */ protected void writeOutStampedeEvents( ADag workflow )throws CodeGeneratorException{ Stampede stampedeEventGenerator = new Stampede(); stampedeEventGenerator.initialize(mBag); Collection result = stampedeEventGenerator.generateCode( workflow ); for( Iterator it = result.iterator(); it.hasNext() ;){ mLogger.log("Written out stampede events for the executable workflow to " + it.next(), LogManager.DEBUG_MESSAGE_LEVEL); } } /** * Writes out the metrics file for the workflow * * @param workflow the workflow whose metrics file needs to be generated. */ protected void writeOutBraindump( ADag workflow ){ //generate some extra keys for metrics file Map<String,String> entries = getAdditionalBraindumpEntries( workflow ); try{ Braindump braindump = new Braindump(); braindump.initialize(mBag); Collection result = braindump.generateCode(workflow, entries); for( Iterator it = result.iterator(); it.hasNext() ;){ mLogger.log("Written out braindump to " + it.next(), LogManager.DEBUG_MESSAGE_LEVEL); } } catch(CodeGeneratorException ioe){ //log the message and return mLogger.log("Unable to write out the braindump file for pegasus-monitord", ioe, LogManager.ERROR_MESSAGE_LEVEL ); } } /** * Writes out the DAX replica store * * @param workflow the work-flow */ protected void writeOutDAXReplicaStore( ADag workflow ){ try{ DAXReplicaStore generator = new DAXReplicaStore (); generator.initialize(mBag); Collection <File> result = generator.generateCode(workflow); for( File f : result){ mLogger.log("Written out dax replica store to " + f.getName(), LogManager.DEBUG_MESSAGE_LEVEL); } } catch(CodeGeneratorException ioe){ //log the message and return mLogger.log("Unable to write out the notifications file ", ioe, LogManager.ERROR_MESSAGE_LEVEL ); } } /** * Writes out the generator input file for the work-flow. * * @param workflow the work-flow whose generator files needs to be generated. */ protected void writeOutNotifications( ADag workflow ){ try{ MonitordNotify notifications = new MonitordNotify (); notifications.initialize(mBag); Collection <File> result = notifications.generateCode(workflow); for( File f : result){ mLogger.log("Written out notifications to " + f.getName(), LogManager.DEBUG_MESSAGE_LEVEL); } } catch(CodeGeneratorException ioe){ //log the message and return mLogger.log("Unable to write out the notifications file ", ioe, LogManager.ERROR_MESSAGE_LEVEL ); } } /** * Returns a Map containing additional metrics entries that are specific * to a Code Generator * * @param workflow the workflow whose metrics file needs to be generated. * * @return Map */ public abstract Map<String, String> getAdditionalBraindumpEntries( ADag workflow ); /** * Resets the Code Generator implementation. * * @throws CodeGeneratorException in case of any error occuring code generation. */ public void reset( )throws CodeGeneratorException{ mSubmitFileDir = null; mProps = null; mPOptions = null; } /** * Returns an open stream to the file that is used for writing out the * job information for the job. * * @param job the job whose job information needs to be written. * @param suffix * * @return the writer to the open file. * @exception IOException if unable to open a write handle to the file. */ public PrintWriter getWriter( Job job, String suffix ) throws IOException{ StringBuilder sb = new StringBuilder(); //append the base name of the job sb.append( File.separatorChar ).append( job.getFileFullPath( mSubmitFileDir, suffix) ); // intialize the print stream to the file return new PrintWriter(new BufferedWriter(new FileWriter(sb.toString()))); } }