/**
* 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.cluster.aggregator;
import edu.isi.pegasus.planner.cluster.JobAggregator;
import edu.isi.pegasus.planner.classes.ADag;
import edu.isi.pegasus.planner.classes.Job;
import edu.isi.pegasus.planner.common.PegasusProperties;
import edu.isi.pegasus.planner.namespace.Pegasus;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import edu.isi.pegasus.planner.classes.PegasusBag;
/**
* A JobAggergator factory that caches up the loaded implementations.
* It loads a new implementation only if it has not loaded it earlier.
* However, it is different from a Singleton Factory, as the implementations
* are not stored in static instances. Hence, two different instances of this
* Factory can load different instances of the same implementation.
*
*
* @author Karan Vahi
* @version $Revision$
*
* @see JobAggregatorFactory
*/
public class JobAggregatorInstanceFactory {
/**
* A table that maps, Pegasus style keys to the names of the corresponding classes
* implementing the CondorStyle interface.
*/
private static Map mImplementingClassNameTable;
/**
* A table that maps, Pegasus style keys to appropriate classes implementing the
* JobAggregator interface
*/
private Map mImplementingClassTable ;
/**
* The handle to the properties object holding all the properties.
*/
protected PegasusProperties mProps;
/**
* ADag object containing the jobs that have been scheduled by the site
* selector.
*/
private ADag mDAG;
/**
* A boolean indicating that the factory has been initialized.
*/
private boolean mInitialized;
/**
* The bag of initialization objects
*/
private PegasusBag mBag;
/**
* The default constructor.
*/
public JobAggregatorInstanceFactory() {
mInitialized = false;
mImplementingClassTable = new HashMap(3);
}
/**
* Initializes the Factory. Loads all the implementations just once.
*
* @param dag the workflow that is being clustered.
* @param bag the bag of initialization objects.
*
* @throws JobAggregatorFactoryException that nests any error that
* might occur during the instantiation of the implementation.
*/
public void initialize( ADag dag,
PegasusBag bag
) throws JobAggregatorFactoryException{
mBag = bag;
mProps = bag.getPegasusProperties();
mDAG = dag;
//load all the implementations that correspond to the Pegasus style keys
for( Iterator it = this.implementingClassNameTable().entrySet().iterator(); it.hasNext(); ){
Map.Entry entry = (Map.Entry) it.next();
String aggregator = (String)entry.getKey();
String className = (String)entry.getValue();
//load via reflection. not required in this case though
put( aggregator, JobAggregatorFactory.loadInstance( className, mDAG, mBag ));
}
//we have successfully loaded all implementations
mInitialized = true;
}
/**
* Returns the appropriate handle to the JobAggregator that is to be used
* for a particular type of job. Aggregators for mpiexec and seqexec are
* already loaded in the constructor, and just the reference is returned.
* For any other aggregator it is dynamically loaded.
*
* @param job the job corresponding to which the aggregator is to be
* loaded.
*
* @return the appropriate JobAggregator
*
* @throws JobAggregatorFactoryException that nests any error that
* might occur during the instantiation
*
*/
public JobAggregator loadInstance( Job job ) throws JobAggregatorFactoryException{
//sanity checks first
if( !mInitialized ){
throw new JobAggregatorFactoryException(
"JobAggregatorFactory needs to be initialized first before using" );
}
Object obj;
String jobAggregator = (String)job.vdsNS.get( Pegasus.JOB_AGGREGATOR_KEY );
jobAggregator = ( jobAggregator == null ) ?
//check to see if the deprecated key is specified
(String)job.vdsNS.get(Pegasus.COLLAPSER_KEY):
jobAggregator;
jobAggregator = ( jobAggregator == null)?
//pick the one from the properties
mProps.getJobAggregator():
jobAggregator;
//update the bag to set the flag whether
//PMC was used or not PM-639
if( jobAggregator.equalsIgnoreCase( JobAggregatorFactory.MPI_EXEC_CLASS ) ){
mBag.add( PegasusBag.USES_PMC, Boolean.TRUE );
}
//now look up the job aggregator
Object aggregator = this.get( jobAggregator.toLowerCase() );
if ( aggregator == null ) {
//load via reflection
aggregator = JobAggregatorFactory.loadInstance( jobAggregator, mDAG, mBag );
//throw exception if still null
if (aggregator == null ){
throw new JobAggregatorFactoryException( "Unsupported Job Aggregator " + jobAggregator);
}
//register in cache
this.put( jobAggregator, aggregator );
}
return (JobAggregator)aggregator;
}
/**
* Returns the implementation from the implementing class table.
*
* @param style the aggregator style
*
* @return implementation the class implementing that style, else null
*/
private Object get( String style ){
return mImplementingClassTable.get( style);
}
/**
* Inserts an entry into the implementing class table.
*
* @param style the aggregator style
* @param implementation the class implementing that aggregator.
*/
private void put( String style, Object implementation){
mImplementingClassTable.put( style.toLowerCase(), implementation );
}
/**
* Returns a table that maps, the Pegasus style keys to the names of implementing
* classes.
*
* @return a Map indexed by Pegasus styles, and values as names of implementing
* classes.
*/
private static Map implementingClassNameTable(){
if( mImplementingClassNameTable == null ){
mImplementingClassNameTable = new HashMap(3);
mImplementingClassNameTable.put( JobAggregatorFactory.SEQ_EXEC_CLASS.toLowerCase(),
JobAggregatorFactory.SEQ_EXEC_CLASS);
mImplementingClassNameTable.put( JobAggregatorFactory.MPI_EXEC_CLASS.toLowerCase(),
JobAggregatorFactory.MPI_EXEC_CLASS);
}
return mImplementingClassNameTable;
}
}