/** * 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.classes; import edu.isi.pegasus.planner.catalog.replica.ReplicaCatalogEntry; import edu.isi.pegasus.planner.common.PegRandom; import edu.isi.pegasus.planner.namespace.Metadata; import java.io.File; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * This is a container for the storing the transfers that are required in * between sites. It refers to one lfn, but can contains more than one source * and destination urls. All the source url's are presumed to be identical. * The destination urls, can in effect be used to refer to TFN's for a lfn on * different sites. * * @author Karan Vahi * @author Gaurang Mehta * @version $Revision$ * */ public class FileTransfer extends PegasusFile { /** * The logical name of the asssociated VDS super node, with which the file * is associated. The name of the job can be of the job that generates that * file(while doing intersite or transferring output files to output site) * or of a job for which the file is an input(getting an input file from the * Replica Services). */ private String mJob; /** * The map containing all the source urls keyed by the site id/name. * Corresponding to each site, a list of url's is stored that contain * the URL's for that site. All url's not associated with a site, are * associated with a undefined site. */ private Map<String,List<ReplicaCatalogEntry>> mSourceMap; /** * The map containing all the destination urls keyed by the site id/name. * Corresponding to each site, a list of url's is stored that contain * the URL's for that site. All url's not associated with a site, are * associated with a undefined site. */ private Map<String,List<ReplicaCatalogEntry>> mDestMap; /** * The registration URL for the file */ private String mURLForRegistrationOnDestination; /** * A priority associated with the FileTransfer */ private int mPriority; /** * Default constructor. */ public FileTransfer(){ super(); mJob = ""; mFlags = new BitSet(NO_OF_TRANSIENT_FLAGS); mSourceMap = new LinkedHashMap<String,List<ReplicaCatalogEntry>>(); mDestMap = new LinkedHashMap<String,List<ReplicaCatalogEntry>>(); mPriority = 0; mURLForRegistrationOnDestination = null; } /** * The overloaded constructor. * * @param pf <code>PegasusFile</code> object containing the transiency * attributes, and the logical name of the file. */ public FileTransfer(PegasusFile pf){ this.mLogicalFile = pf.mLogicalFile; this.mTransferFlag = pf.mTransferFlag; this.mSize = pf.mSize; this.mFlags = pf.getFlags(); this.mType = pf.getType(); this.mJob = ""; this.mSourceMap = new LinkedHashMap<String,List<ReplicaCatalogEntry>>(); this.mDestMap = new LinkedHashMap<String,List<ReplicaCatalogEntry>>(); this.mPriority = 0; this.mURLForRegistrationOnDestination = null; this.mMetadata = pf.getAllMetadata(); } /** * The overloaded constructor. * * @param lfn The logical name of the file that has to be transferred. * @param job The name of the job with which the transfer is * associated with. */ public FileTransfer(String lfn, String job){ super(lfn); mJob = job; mSourceMap = new LinkedHashMap<String,List<ReplicaCatalogEntry>>(); mDestMap = new LinkedHashMap<String,List<ReplicaCatalogEntry>>(); this.mPriority = 0; this.mURLForRegistrationOnDestination = null; } /** * The overloaded constructor. * * @param lfn The logical name of the file that has to be transferred. * @param job The name of the job with which the transfer is * associated with. * @param flags the BitSet flags. */ public FileTransfer(String lfn, String job, BitSet flags){ mLogicalFile = lfn; mJob = job; mSourceMap = new LinkedHashMap<String,List<ReplicaCatalogEntry>>(); mDestMap = new LinkedHashMap<String,List<ReplicaCatalogEntry>>(); mFlags = (BitSet)flags.clone(); this.mPriority = 0; this.mURLForRegistrationOnDestination = null; } /** * It returns the name of the main/compute job making up the VDS supernode * with which this transfer is related. * * @return the name of associated job */ public String getJobName(){ return this.mJob; } /** * Adds a source URL for the transfer. * * @param nv the NameValue object containing the name of the site as the key * and URL as the value. */ public void addSource(NameValue nv){ this.addSource(nv.getKey(),nv.getValue()); } /** * Adds a source URL for the transfer. * * @param site the site from which the source file is being transferred. * @param url the source url. */ public void addSource(String site, String url){ this.addSource( new ReplicaCatalogEntry(url, site)); } /** * Adds a source URL for the transfer. * * @param rce ReplicaCatalogEntry object */ public void addSource(ReplicaCatalogEntry rce){ List<ReplicaCatalogEntry> l = null; if(mSourceMap.containsKey(rce.getResourceHandle())){ //add the url to the existing list l = (List)mSourceMap.get(rce.getResourceHandle()); //add the entry to the list l.add(rce); } else{ //add a new list l = new ArrayList(3); l.add( rce ); mSourceMap.put(rce.getResourceHandle(),l); } } /** * Adds a destination URL for the transfer. * * @param nv the NameValue object containing the name of the site as the key * and URL as the value. */ public void addDestination(NameValue nv){ this.addDestination(nv.getKey(),nv.getValue()); } /** * Adds a destination URL for the transfer. * * @param site the site to which the destination file is being transferred. * @param url the destination url. */ public void addDestination(String site, String url){ this.addDestination( new ReplicaCatalogEntry(url, site)); } /** * Adds a destination URL for the transfer. * * @param rce ReplicaCatalogEntry object */ public void addDestination(ReplicaCatalogEntry rce){ List<ReplicaCatalogEntry> l = null; if(mDestMap.containsKey(rce.getResourceHandle())){ //add the url to the existing list l = (List)mDestMap.get(rce.getResourceHandle()); //add the entry to the list l.add(rce); } else{ //add a new list l = new ArrayList(3); l.add( rce ); mDestMap.put(rce.getResourceHandle(),l); } } /** * Sets the registration url for the destination. * * @param url the url */ public void setURLForRegistrationOnDestination( String url ){ this.mURLForRegistrationOnDestination = url; } /** * Sets the registration url for the destination. * * @return the destination url */ public String getURLForRegistrationOnDestination( ){ return this.mURLForRegistrationOnDestination ; } /** * Sets the priority for the File Transfer * * @param priority the priority associated with the FileTransfer */ public void setPriority( int priority ){ this.mPriority = priority; } /** * Sets the priority for the File Transfer * * @return the priority associated with the FileTransfer */ public int getPriority( ){ return this.mPriority; } /** * Returns all the sites where the LFN exists * * @return Collection of site names */ public Collection<String> getSourceSites( ){ return mSourceMap.keySet(); } /** * Returns all the source URLS associated with the transfer object for a particular site * * @return List<ReplicaCatalogEntry> urls */ public List<ReplicaCatalogEntry> getSourceURLs( String site ){ return ( mSourceMap.containsKey(site) )? mSourceMap.get(site): new ArrayList(); } /** * Returns number of source URL's associated with the FileTransfer * * @return count */ public int getSourceURLCount( ){ int count = 0; for( String site: getSourceSites()){ count += this.getSourceURLs(site).size(); } return count; } /** * Returns a single source url associated with the transfer. * The source url returned is first entry from the key set of the * underlying map. * * @return NameValue where the name would be the site on which the URL is * and value the URL. * null if no urls are assoiciated with the object. */ public NameValue getSourceURL(){ return getSourceURL( false ); } /** * Returns a single source url associated with the transfer. * If random is set to false, thensource url returned is first entry from * the key set of the underlying map. * * @param random boolean indicating if a random entry needs to be picked. * * @return NameValue where the name would be the site on which the URL is * and value the URL. * null if no urls are assoiciated with the object. */ public NameValue getSourceURL( boolean random ){ return getURL( mSourceMap , random ); } /** * Returns a single destination url associated with the transfer. * The destination url returned is first entry from the key set of the * underlying map. * * @return NameValue where the name would be the site on which the URL is * and value the URL. * null if no urls are assoiciated with the object. */ public NameValue getDestURL(){ return getDestURL( false ); } /** * Returns a single destination url associated with the transfer. * If random is set to false, then dest url returned is first entry from * the key set of the underlying map. * * @param random boolean indicating if a random entry needs to be picked. * * @return NameValue where the name would be the site on which the URL is * and value the URL. * null if no urls are assoiciated with the object. */ public NameValue getDestURL( boolean random ){ return getURL( mDestMap, random ); } /** * Removes a single source url associated with the transfer. * The source url removed is first entry from the key set of the * underlying map. * * @return NameValue where the name would be the site on which the URL is * and value the URL. * null if no urls are assoiciated with the object. */ public NameValue removeSourceURL(){ return removeURL(mSourceMap); } /** * Removes a single destination url associated with the transfer. * The destination url removed is first entry from the key set of the * underlying map. * * @return NameValue where the name would be the site on which the URL is * and value the URL. * null if no urls are assoiciated with the object. */ public NameValue removeDestURL(){ return removeURL(mDestMap); } /** * Returns a boolean indicating if a file that is being staged is an * executable or not (i.e is a data file). * * @return boolean indicating whether a file is executable or not. */ public boolean isTransferringExecutableFile(){ return this.isExecutable(); } /** * Returns a single url from the map passed. If the random parameter is set, * then a random url is returned from the values for the first site. * * Fix Me: Random set to true, shud also lead to randomness on the sites. * * @param m the map containing the url's * @param random boolean indicating that a random url to be picked up. * * @return NameValue where the name would be the site on which the URL is * and value the URL. * null if no urls are assoiciated with the object. */ private NameValue getURL( Map<String,List<ReplicaCatalogEntry>> m, boolean random ){ if(m == null || m.keySet().isEmpty()){ return null; } //Return the first url from the EntrySet Iterator it = m.entrySet().iterator(); Map.Entry entry = ( Map.Entry )it.next(); List<ReplicaCatalogEntry> urls = ( List )entry.getValue(); String site = ( String )entry.getKey(); ReplicaCatalogEntry rce = ( random ) ? //pick a random value urls.get( PegRandom.getInteger( 0, urls.size() -1 )): //returning the first element. No need for a check as //population of the list is controlled urls.get(0); return ( rce == null)? null: new NameValue( rce.getResourceHandle(), rce.getPFN()); } /** * Removes a single url from the map passed. * * @param m the map containing the url's * * @return NameValue where the name would be the site on which the URL is * and value the URL. * null if no urls are assoiciated with the object. */ private NameValue removeURL(Map<String,List<ReplicaCatalogEntry>> m){ if(m == null || m.keySet().isEmpty()){ return null; } //Return the first url from the EntrySet Iterator it = m.entrySet().iterator(); Map.Entry<String,List<ReplicaCatalogEntry>> entry = (Map.Entry)it.next(); //remove this entry it.remove(); //returning the first element. No need for a check as //population of the list is controlled return new NameValue( entry.getKey(), entry.getValue().get(0).getPFN() ); } /** * Returns a clone of the object. * * @return clone of the object. */ public Object clone() { FileTransfer ft = new FileTransfer(); ft.mLogicalFile = new String(this.mLogicalFile); ft.mFlags = (BitSet)this.mFlags.clone(); ft.mTransferFlag = this.mTransferFlag; ft.mSize = this.mSize; ft.mType = this.mType; ft.mJob = new String(this.mJob); ft.mPriority = this.mPriority; ft.mURLForRegistrationOnDestination = this.mURLForRegistrationOnDestination; ft.mMetadata = (Metadata) this.mMetadata.clone(); //the maps are not cloned underneath return ft; } /** * Determines whether the transfer contained in this container is valid or * not. It is deemed valid if there is at least one source url and one * destination url. * * @return true if valid, else false. */ public boolean isValid(){ return !(mSourceMap.isEmpty() || mDestMap.isEmpty()); } /** * Returns a textual interpretation of the object. The method outputs * in a T2 compatible format. Each FileTransfer object can refer to one * section in the T2 format. * * @return the textual description. */ public String toString() { StringBuffer sb = new StringBuffer(); String mode = (mTransferFlag == FileTransfer.TRANSFER_OPTIONAL)? "optional" : "any"; Iterator it = null; Map.Entry<String,List<ReplicaCatalogEntry>> entry = null; List l = null; sb.append(mLogicalFile).append(" ").append(mode); //writing out all the sources it = mSourceMap.entrySet().iterator(); //sb.append("\n").append(" "); while(it.hasNext()){ entry = (Map.Entry) it.next(); //inserting the source site sb.append("\n").append("#").append(entry.getKey()); l = (List<ReplicaCatalogEntry>)entry.getValue(); Iterator it1 = l.iterator(); while(it1.hasNext()){ //write out the source url's //each line starts with a single whitespace sb.append("\n").append(" ").append(it1.next()); } } //writing out all the destinations it = mDestMap.entrySet().iterator(); //sb.append("\n").append(" "); while(it.hasNext()){ entry = (Map.Entry) it.next(); //inserting the destination site sb.append("\n").append("# ").append(entry.getKey()); l = (List<ReplicaCatalogEntry>)entry.getValue(); Iterator it1 = l.iterator(); while(it1.hasNext()){ //write out the source url's //each line starts with a two whitespaces sb.append("\n").append(" ").append(" ").append(it1.next()); } } return sb.toString(); } }