/**
* 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.LogFormatterFactory;
import edu.isi.pegasus.common.logging.LogFormatter;
import edu.isi.pegasus.common.logging.LogManager;
import edu.isi.pegasus.common.logging.LoggingKeys;
import edu.isi.pegasus.planner.classes.ADag;
import edu.isi.pegasus.planner.classes.AggregatedJob;
import edu.isi.pegasus.planner.classes.Job;
import edu.isi.pegasus.planner.partitioner.graph.GraphNode;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
/**
* This class can write out the job mappings that link jobs with jobs in the DAX
* to a Writer stream in the netlogger format.
*
* @author Karan Vahi
* @version $Revision$
*/
public class NetloggerJobMapper{
public static final String NETLOGGER_LOG_FORMATTER_IMPLEMENTOR = "Netlogger";
/**
* The handle to the netlogger log formatter.
*/
private LogFormatter mLogFormatter;
/**
* The handle to pegasus logger used for run.
*/
private LogManager mLogger;
/**
* The default constructor.
*
* @param logger the logger instance to use for logging
*/
public NetloggerJobMapper( LogManager logger ){
mLogFormatter = LogFormatterFactory.loadInstance( NETLOGGER_LOG_FORMATTER_IMPLEMENTOR );
mLogger = logger;
}
/**
* Writes out the job mappings for a workflow.
*
* @param writer the writer stream to which to write out the mappings
* @param dag the dag for which to write out the mappings
*
* @throws IOException
*/
public void writeOutMappings( Writer writer , ADag dag ) throws IOException{
for ( Iterator<GraphNode> it = dag.jobIterator(); it.hasNext();) {
GraphNode node = it.next();
Job job = (Job)node.getContent();
int type = job.getJobType();
mLogFormatter.addEvent( "pegasus.job", LoggingKeys.JOB_ID, job.getID() );
mLogFormatter.add( "job.class" , Integer.toString( type ) );
mLogFormatter.add( "job.xform" , job.getCompleteTCName() );
//determine count of jobs
int taskCount = getTaskCount( job );
mLogFormatter.add( "task.count", Integer.toString( taskCount ) );
writer.write( mLogFormatter.createLogMessage() );
writer.write( "\n" );
mLogFormatter.popEvent();
// add mapping events only if task count > 0
if( taskCount > 0 ){
if ( job instanceof AggregatedJob ){
AggregatedJob j = (AggregatedJob)job;
for( Iterator<Job> jit = j.constituentJobsIterator(); jit.hasNext(); ){
Job cJob = jit.next();
mLogFormatter.addEvent( "pegasus.job.map", LoggingKeys.JOB_ID, job.getID() );
writer.write( generateLogEvent( cJob, "task." ) );
writer.write( "\n" );
mLogFormatter.popEvent();
}
}
else{
mLogFormatter.addEvent( "pegasus.job.map", LoggingKeys.JOB_ID, job.getID() );
writer.write( generateLogEvent( job, "task." ) );
writer.write( "\n" );
mLogFormatter.popEvent();
}
}
}
}
/**
* Generates a log event message in the netlogger format for a job
*
* @param job the job
* @param prefix prefix if any to add to the keys
*
* @return netlogger formatted message
*/
private String generateLogEvent ( Job job, String prefix ) {
String result = null;
/*String taskID = (( job.getJobType() == Job.COMPUTE_JOB ||
job.getJobType() == Job.STAGED_COMPUTE_JOB ) &&
!(job instanceof AggregatedJob) )?
job.getLogicalID():
"";
*/
mLogFormatter.add( "task.id" , job.getLogicalID() );
mLogFormatter.add( getKey( prefix, "class" ), Integer.toString( job.getJobType() ) );
mLogFormatter.add( getKey( prefix, "xform" ), job.getCompleteTCName() );
result = mLogFormatter.createLogMessage();
return result;
}
/**
* Adds a prefix to the key and returns it.
*
* @param prefix the prefix to be added
* @param key the key
*
* @return the key with prefix added.
*/
private String getKey( String prefix, String key ){
if( prefix == null || prefix.length() == 0 ){
return key;
}
StringBuffer result = new StringBuffer();
result.append( prefix ).append( key);
return result.toString();
}
/**
* Returns the task count for a job. The task count is the number of
* jobs associated with the job in the DAX
*
* @param job
*
* @return task count
*/
private int getTaskCount( Job job ) {
int count = 0;
int type = job.getJobType();
//explicitly exclude cleanup jobs that are instance
//of aggregated jobs. This is because while creating
//the cleanup job we use the clone method. To be fixed.
//Karan April 17 2009
if ( job instanceof AggregatedJob && type != Job.CLEANUP_JOB ){
//a clustered job the number of constituent is count
count = ((AggregatedJob)job).numberOfConsitutentJobs();
}
else if ( type == Job.COMPUTE_JOB /*|| type == Job.STAGED_COMPUTE_JOB*/ ){
//non clustered job check whether compute or not
//and make sure there is dax job associated with it
if( job.getLogicalID().length() == 0 ){
//takes care of the untar job that is tagged as compute
mLogger.log( "Not creating event pegasus.job.map for job " + job.getID(),
LogManager.DEBUG_MESSAGE_LEVEL );
count = 0;
}
else{
count = 1;
}
}
return count;
}
}