/** * 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.selector.replica; import edu.isi.pegasus.common.logging.LogManagerFactory; import edu.isi.pegasus.planner.classes.ReplicaLocation; import edu.isi.pegasus.planner.selector.ReplicaSelector; import edu.isi.pegasus.common.logging.LogManager; import edu.isi.pegasus.common.util.PegasusURL; import edu.isi.pegasus.planner.common.PegasusProperties; import edu.isi.pegasus.planner.common.PegRandom; import edu.isi.pegasus.planner.catalog.replica.ReplicaCatalogEntry; import java.util.ArrayList; import java.util.Iterator; /** * This replica selector only prefers replicas from the local host and that * start with a file: URL scheme. It is useful, when you want to stagin * files to a remote site from your submit host using the Condor file transfer * mechanism. * * <p> * In order to use the replica selector implemented by this class, * <pre> * - the property pegasus.selector.replica must be set to value Local * </pre> * * * @see org.griphyn.cPlanner.transfer.implementation.Condor * * @author Karan Vahi * @version $Revision$ */ public class Local implements ReplicaSelector { /** * A short description of the replica selector. */ private static final String mDescription = "Local from submit host"; /** * Sanity Check Error Message. */ public static final String SANITY_CHECK_ERROR_MESSAGE_PREFIX = "Local Replica Selector selects only local file URL's. Set transfers to run on submit host."; /** * The handle to the logging object that is used to log the various debug * messages. */ protected LogManager mLogger; /** * The properties object containing the properties passed to the planner. */ protected PegasusProperties mProps; /** * The overloaded constructor, that is called by load method. * * @param properties the <code>PegasusProperties</code> object containing all * the properties required by Pegasus. * * */ public Local( PegasusProperties properties ){ mProps = properties; mLogger = LogManagerFactory.loadSingletonInstance( properties ); } /** * Selects a random replica from all the replica's that have their * site handle set to local and the pfn's start with a file url scheme. * * @param rl the <code>ReplicaLocation</code> object containing all * the pfn's associated with that LFN. * @param preferredSite the preffered site for picking up the replicas. * @param allowLocalFileURLs indicates whether Replica Selector can select a replica * on the local site / submit host. * * @return <code>ReplicaCatalogEntry</code> corresponding to the location selected. * * @see org.griphyn.cPlanner.classes.ReplicaLocation */ public ReplicaCatalogEntry selectReplica( ReplicaLocation rl, String preferredSite, boolean allowLocalFileURLs ){ //sanity check if( !allowLocalFileURLs && !preferredSite.equals( ReplicaSelector.LOCAL_SITE_HANDLE )){ StringBuffer message = new StringBuffer(); message.append( SANITY_CHECK_ERROR_MESSAGE_PREFIX ). append( "For LFN " ).append( rl.getLFN() ). append( " (preferred site , allow local urls) is set to "). append( "(").append( preferredSite ).append( "," ).append( allowLocalFileURLs ).append( ")" ); throw new RuntimeException( message.toString() ); } ReplicaCatalogEntry rce; ArrayList prefPFNs = new ArrayList(); int locSelected; String site = null; // mLogger.log("Selecting a pfn for lfn " + lfn + "\n amongst" + locations , // LogManager.DEBUG_MESSAGE_LEVEL); for ( Iterator it = rl.pfnIterator(); it.hasNext(); ) { rce = ( ReplicaCatalogEntry ) it.next(); site = rce.getResourceHandle(); if( site == null ){ //skip to next replica continue; } //check if has pool attribute as local, and at same time //start with a file url scheme if( site.equals( "local" ) && rce.getPFN().startsWith( PegasusURL.FILE_URL_SCHEME ) ){ prefPFNs.add( rce ); } } if ( prefPFNs.isEmpty() ) { //select a random location from //all the matching locations //in all likelihood all the urls were file urls and none //were associated with the preference pool. throw new RuntimeException( "Unable to select any location on local site from " + "the list passed for lfn " + rl.getLFN() ); } else { //select a random location //amongst the locations //on the preference pool int length = prefPFNs.size(); //System.out.println("No of locations found at pool " + prefPool + " are " + length); locSelected = PegRandom.getInteger( length - 1 ); rce = ( ReplicaCatalogEntry ) prefPFNs.get( locSelected ); } return rce; } /** * This chooses a location amongst all the locations returned by the * Replica Mechanism. If a location is found with re/pool attribute same * as the preference pool, it is taken. This returns all the locations which * match to the preference pool. This function is called to determine if a * file does exist on the output pool or not beforehand. We need all the * location to ensure that we are able to make a match if it so exists. * Else a random location is selected and returned * * @param rl the <code>ReplicaLocation</code> object containing all * the pfn's associated with that LFN. * @param preferredSite the preffered site for picking up the replicas. * @param allowLocalFileURLs indicates whether Replica Selector can select a replica * on the local site / submit host. * * @return <code>ReplicaLocation</code> corresponding to the replicas selected. * * @see org.griphyn.cPlanner.classes.ReplicaLocation */ public ReplicaLocation selectAndOrderReplicas( ReplicaLocation rl, String preferredSite, boolean allowLocalFileURLs ){ //sanity check if( !allowLocalFileURLs && !preferredSite.equals( ReplicaSelector.LOCAL_SITE_HANDLE )){ StringBuffer message = new StringBuffer(); message.append( SANITY_CHECK_ERROR_MESSAGE_PREFIX ). append( "For LFN " ).append( rl.getLFN() ). append( " (preferred site , allow local urls) is set to "). append( "(").append( preferredSite ).append( "," ).append( allowLocalFileURLs ).append( ")" ); throw new RuntimeException( message.toString() ); } String lfn = rl.getLFN(); ReplicaLocation result = new ReplicaLocation(); result.setLFN( rl.getLFN() ); ReplicaCatalogEntry rce; String site; int noOfLocs = 0; for ( Iterator it = rl.pfnIterator(); it.hasNext(); ) { noOfLocs++; rce = ( ReplicaCatalogEntry ) it.next(); site = rce.getResourceHandle(); if ( site != null && site.equals( preferredSite )) { result.addPFN( rce ); } else if ( site == null ){ mLogger.log( " pool attribute not specified for the location objects" + " in the Replica Catalog", LogManager.WARNING_MESSAGE_LEVEL); } } if ( result.getPFNCount() == 0 ) { //means we have to choose a random location between 0 and (noOfLocs -1) int locSelected = PegRandom.getInteger( noOfLocs - 1 ); rce = ( ReplicaCatalogEntry ) rl.getPFN(locSelected ); result.addPFN( rce ); } return result; } /** * Returns a short description of the replica selector. * * @return string corresponding to the description. */ public String description(){ return mDescription; } }