/** * 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.partitioner; import edu.isi.pegasus.common.logging.LogManagerFactory; import edu.isi.pegasus.common.logging.LogManager; import edu.isi.pegasus.planner.common.PegasusProperties; import edu.isi.pegasus.common.util.DynamicLoader; import edu.isi.pegasus.common.util.FactoryException; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; /** * The abstract class that identifies the interface for writing out a dax * corresponding to a partition. The interface stipulates that the jobs making * up the partition and relations between those jobs in the partition are * identified when invoking it. However all the job details are to be gotten * by the implementing classes by parsing the original dax. * * @author Karan Vahi * @version $Revision$ */ public abstract class DAXWriter { /** * The prefix added to the name of the dax to identify it is a partitioned * dax. */ public static final String PARTITION_PREFIX = "partition_"; /** * The name of the package in which the writers are implemented. */ public static final String PACKAGE_NAME = "org.griphyn.cPlanner.partitioner"; /** * The dax file that is being partitioned. The dax file is the repository * for all the jobs in the partitioned daxes. */ protected String mDaxFile; /** * The directory in which the daxes corresponding to the partition are * generated. */ protected String mPDAXDirectory; /** * The name of the partition dax that are generated. */ protected String mPartitionName; /** * The handle to the logging object. */ protected LogManager mLogger; /** * The write handle to the xml file being written. */ protected PrintWriter mWriteHandle; /** * The default constructor */ protected DAXWriter(){ mDaxFile = null; mPDAXDirectory = null; mLogger = LogManagerFactory.loadSingletonInstance(); mPartitionName = null; } /** * The overloaded constructor. * * @param daxFile the path to the dax file that is being partitioned. * @param directory the directory in which the partitioned daxes are to be * generated. */ protected DAXWriter(String daxFile, String directory) { mLogger = LogManagerFactory.loadSingletonInstance(); mDaxFile = daxFile; mPDAXDirectory = directory; mPartitionName = null; } /** * It writes out a dax consisting of the jobs as specified in the partition. * * @param partition the partition object containing the relations and id's * of the jobs making up the partition. * * @return boolean true if dax successfully generated and written. * false in case of error. */ public boolean writePartitionDax( Partition partition ){ return writePartitionDax( partition, partition.getIndex() ); } /** * It writes out a dax consisting of the jobs as specified in the partition. * * @param partition the partition object containing the relations and id's * of the jobs making up the partition. * @param index the index of the partition. * * @return boolean true if dax successfully generated and written. * false in case of error. */ public abstract boolean writePartitionDax( Partition partition, int index ); /** * The ends up loading the PDAXWriter. It selects the writer as specified by * the vds.partition.parse.mode property. * * @param properties the handle to the properties visible to Pegasus. * @param daxFile the path to the dax file that is being partitioned. * @param directory the directory in which the partitioned daxes are to be * generated. */ public static DAXWriter loadInstance( PegasusProperties properties, String daxFile, String directory) { String className = properties.getPartitionParsingMode(); className = (className.equalsIgnoreCase("single"))?"SingleLook": (className.equalsIgnoreCase("multiple"))?"MultipleLook": className; return loadInstance( className, properties, daxFile, directory ); } /** * Loads the implementing PDAXWriter. The name of the class that is to be * loaded is passed and can be complete(with package name) or just the name * of the class, in which case the class is loaded from the default package. * * @param properties the handle to the properties visible to Pegasus. * @param className the name of the class with or without the package name. * @param daxFile the path to the dax file that is being partitioned. * @param directory the directory in which the partitioned daxes are to be * generated. * * @throws FactoryException that nests any error that * might occur during the instantiation of the implementation. */ public static DAXWriter loadInstance( String className, PegasusProperties properties, String daxFile, String directory) throws FactoryException{ if(className.indexOf('.') == -1){ //prepend the default package name className = PACKAGE_NAME + "." + className; } //sanity and default checks directory = (directory == null)? "." : directory; //try loading the class dynamically DAXWriter writer = null; DynamicLoader dl = new DynamicLoader( className); try { Object argList[] = new Object[2]; argList[0] = daxFile; argList[1] = directory; writer = (DAXWriter) dl.instantiate(argList); } catch ( Exception e ) { throw new FactoryException( "Instantiating DAXWriter", className, e ); } return writer; } /** * It constructs the name of the partitioned dax file that has to be written * corresponding to a partition of the dax. The dax name returned has no * prefix added to it. * * @param daxName the name attribute in the adag element of the dax. * @param index the partition number of the partition. */ public static String getPDAXFilename(String daxName, int index){ return getPDAXFilename(daxName,index,false); } /** * It constructs the name of the partitioned dax file that has to be written * corresponding to a partition of the dax. * * @param daxName the name attribute in the adag element of the dax. * @param index the partition number of the partition. * @param addPrefix whether you want to addPrefix or not. */ public static String getPDAXFilename(String daxName, int index, boolean addPrefix){ StringBuffer sb = new StringBuffer(32); //get the partition name sb.append(constructPartitionName(daxName,addPrefix)); //add the suffix sb.append("_").append(index).append(".dax"); return sb.toString(); } /** * It constructs the partition name given the daxName. It only ends up adding * the prefix if the addPrefix parameter is set. * * @param daxName the name attribute in the adag element of the dax. * @param addPrefix whether to add prefix or not. */ private static String constructPartitionName(String daxName, boolean addPrefix){ StringBuffer sb = new StringBuffer(); //append the partition prefix to it. if(addPrefix) sb.append(PARTITION_PREFIX); //construct a partition name sb = (daxName == null)? // set it to the default name sb.append("test") : sb.append(daxName); return sb.toString(); } /** * It sets the name of the partition in the dax that is generated. It suffixes * PARTITION_PREFIX to the name of the dax. * * @param daxName the name attribute in the adag element of the dax. */ public void setPartitionName(String daxName){ //yes we want the partition prefix to be added mPartitionName = constructPartitionName(daxName,true); } /** * It returns the name of the partitioned dax, that the object is * currently writing or initialized to write. By the name, one means the * value that is set to the name attribute in the adag element. */ public String getPartitionName(){ return mPartitionName; } /** * This initializes the write handle a file in directory specified * when creating the instance of this class. The name of the file is * constructed by default, by looking at the partition name that is * assigned to the name attribute for the adag element. * * @param index the partition number of the partition. */ public void initializeWriteHandle(int index){ //check if partition name is set if(mPartitionName == null){ //set it to default setPartitionName(null); } String name = mPartitionName + "_" + index + ".dax"; initializeWriteHandle(name); } /** * This initializes the write handle to the file in directory specified * when creating the instance of this class. * * @param fileName the name of the file that is to be written in the * directory. */ public void initializeWriteHandle(String fileName){ String completeName = mPDAXDirectory + File.separator + fileName; try{ //if the write handle was not explicitly closed, closing it if(mWriteHandle != null) this.close(); mWriteHandle = new PrintWriter(new BufferedWriter(new FileWriter(completeName))); } catch(IOException e){ throw new RuntimeException( "Unable to write to file " + completeName + " :", e); } } /** * Writes out to the file. */ public void writeln(String st){ mWriteHandle.println(st); } /** * Close the write handle to the file that is written. */ public void close(){ if( mWriteHandle != null ){ mWriteHandle.close(); mWriteHandle = null; } } }