/** * 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.namespace; import edu.isi.pegasus.planner.catalog.classes.Profiles; import edu.isi.pegasus.planner.classes.Profile; import edu.isi.pegasus.planner.common.PegasusProperties; import java.util.Map; import java.util.TreeMap; import java.util.Iterator; /** * An empty mechanical implementation for the * namespace. At present we do not * know what the meaning is. The meaning is * is determined at the point of writing the * submit files. * * @author Karan Vahi * @author Gaurang Mehta * @version $Revision$ */ public class Hints extends Namespace { /** * The name of the namespace that this class implements. */ public static final String NAMESPACE_NAME = Profile.HINTS; /** * The jobmanager universe key. */ public static final String GRID_JOB_TYPE_KEY = "grid.jobtype"; /** * The deprecated execution site key */ public static final String DEPRECATED_EXECUTION_SITE_KEY = "executionPool"; /** * The execution pool key */ public static final String EXECUTION_SITE_KEY = "execution.site"; /** * The pfnHint key */ public static final String DEPRECATED_PFN_HINT_KEY = "pfnHint"; /** * The pfnHint key */ public static final String PFN_HINT_KEY = "pfn"; /** * The table containing the mapping of the deprecated keys to the newer keys. */ protected static Map mDeprecatedTable = null; /** * The name of the implementing namespace. It should be one of the valid * namespaces always. * * @see Namespace#isNamespaceValid(String) */ protected String mNamespace; /** * The default constructor. * Note that the map is not allocated memory at this stage. It is done so * in the overloaded construct function. */ public Hints() { mProfileMap = null; mNamespace = NAMESPACE_NAME; } /** * The overloaded constructor. * * @param mp the map containing the profiles to be prepopulated with. */ public Hints(Map mp) { mProfileMap = new TreeMap(mp); mNamespace = NAMESPACE_NAME; } /** * Returns the name of the namespace associated with the profile implementations. * * @return the namespace name. * @see #NAMESPACE_NAME */ public String namespaceName(){ return mNamespace; } /** * Provides an iterator to traverse the profiles by their keys. * * @return an iterator over the keys to walk the profile list. */ public Iterator getProfileKeyIterator() { return ( this.mProfileMap == null ) ? new EmptyIterator() : this.mProfileMap.keySet().iterator(); } /** * Constructs a new element of the format (key=value). It first checks if * the map has been initialised or not. If not then allocates memory first. * * @param key is the left-hand-side. * @param value is the right hand side. */ public void construct(String key, String value) { if(mProfileMap == null) mProfileMap = new TreeMap(); mProfileMap.put(key, value); } /** * Returns true if the namespace contains a mapping for the specified key. * More formally, returns true if and only if this map contains at a mapping * for a key k such that (key==null ? k==null : key.equals(k)). * (There can be at most one such mapping.) * It also returns false if the map does not exist. * * @param key The key that you want to search for * in the namespace. * * @return boolean */ public boolean containsKey(Object key){ return (mProfileMap == null)? false : mProfileMap.containsKey(key); } /** * This checks whether the key passed by the user is valid in the current * namespace or not. At present, for this namespace only a limited number of * keys have been assigned semantics. * * @param key (left hand side) * @param value (right hand side) * * @return Namespace.VALID_KEY * @return Namespace.NOT_PERMITTED_KEY * */ public int checkKey(String key, String value) { // sanity checks first int res = 0; if (key == null || key.length() < 2 || value == null || value.length() < 2) { res = MALFORMED_KEY ; } switch (key.charAt(0)) { case 'e': if (key.compareTo( Hints.EXECUTION_SITE_KEY ) == 0 ) { res = VALID_KEY; } else if (key.compareTo(Hints.DEPRECATED_EXECUTION_SITE_KEY ) == 0) { res = DEPRECATED_KEY; } else { res = NOT_PERMITTED_KEY; } break; case 'g': if (key.compareTo( Hints.GRID_JOB_TYPE_KEY ) == 0 ) { res = VALID_KEY; } else { res = NOT_PERMITTED_KEY; } break; case 'p': if (key.compareTo( Hints.PFN_HINT_KEY ) == 0 /*|| key.compareTo("pfnUniverse") == 0*/) { res = VALID_KEY; } else if (key.compareTo( Hints.DEPRECATED_PFN_HINT_KEY ) == 0 ) { res = DEPRECATED_KEY; } else { res = NOT_PERMITTED_KEY; } break; default: res = NOT_PERMITTED_KEY; } return res; } /** * It puts in the namespace specific information specified in the properties * file into the namespace. The name of the pool is also passed, as many of * the properties specified in the properties file are on a per pool basis. * An empty implementation for the timebeing. * * @param properties the <code>PegasusProperties</code> object containing * all the properties that the user specified at various * places (like .chimerarc, properties file, command line). * @param pool the pool name where the job is scheduled to run. */ public void checkKeyInNS(PegasusProperties properties, String pool){ //retrieve the relevant profiles from properties //and merge them into the existing. this.assimilate( properties, Profiles.NAMESPACES.hints ); } /** * Singleton access to the deprecated table that holds the deprecated keys, * and the keys that replace them. * * @return Map */ public java.util.Map deprecatedTable() { if ( mDeprecatedTable == null ) { // only initialize once and only once, as needed. mDeprecatedTable = new java.util.HashMap(); mDeprecatedTable.put( DEPRECATED_EXECUTION_SITE_KEY, EXECUTION_SITE_KEY ); mDeprecatedTable.put( DEPRECATED_PFN_HINT_KEY, PFN_HINT_KEY ); } return mDeprecatedTable; } /** * Merge the profiles in the namespace in a controlled manner. * In case of intersection, the new profile value overrides, the existing * profile value. * * @param profiles the <code>Namespace</code> object containing the profiles. */ public void merge( Namespace profiles ){ //check if we are merging profiles of same type if (!(profiles instanceof Hints )){ //throw an error throw new IllegalArgumentException( "Profiles mismatch while merging" ); } String key; for ( Iterator it = profiles.getProfileKeyIterator(); it.hasNext(); ){ //construct directly. bypassing the checks! key = (String)it.next(); this.construct( key, (String)profiles.get( key ) ); } } /** * Converts the contents of the map into the string that can be put in the * Condor file for printing. * * @return String */ public String toCondor() { StringBuffer st = new StringBuffer(); String key = null; String value = null; if(mProfileMap == null) return ""; for ( Iterator it = mProfileMap.keySet().iterator(); it.hasNext(); ){ key = (String)it.next(); value = (String)mProfileMap.get(key); st.append(key).append(" = ").append(value).append("\n"); } return st.toString(); } /** * Returns a copy of the current namespace object. * * @return the Cloned object */ public Object clone() { return (mProfileMap == null)?new Hints():new Hints(this.mProfileMap); } }