/**
* 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.common.credential.impl.Irods;
import edu.isi.pegasus.common.credential.impl.Proxy;
import edu.isi.pegasus.common.credential.impl.S3CFG;
import edu.isi.pegasus.common.credential.impl.Ssh;
import edu.isi.pegasus.common.credential.impl.BotoConfig;
import edu.isi.pegasus.common.credential.impl.GoogleP12;
import edu.isi.pegasus.planner.classes.Profile;
import edu.isi.pegasus.planner.catalog.classes.Profiles;
import edu.isi.pegasus.planner.common.PegasusProperties;
import edu.isi.pegasus.planner.namespace.aggregator.Aggregator;
import edu.isi.pegasus.planner.namespace.aggregator.MAX;
import edu.isi.pegasus.planner.namespace.aggregator.UniqueMerge;
import edu.isi.pegasus.planner.namespace.aggregator.Sum;
import edu.isi.pegasus.planner.namespace.aggregator.Update;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
/**
* A Planner specific namespace. It defines profiles that are used to fine
* tune Pegasus behaviour on a per job basis if required.
*
* @author Karan Vahi
* @author Gaurang Mehta
* @version $Revision$
*/
public class Pegasus extends Namespace {
/**
* The name of the namespace that this class implements.
*/
public static final String NAMESPACE_NAME = Profile.VDS;
/**
* Key to indicate that the site filesystem is accessible on the local site,
* and hence auxillary jobs for the site can be run on local site
*/
public static final String LOCAL_VISIBLE_KEY = "auxillary.local";
/**
* The name of the key that sets a remote initial dir for a condor globus
* job.
*/
public static final String REMOTE_INITIALDIR_KEY = "workdir";
/**
* The name of the key that if set, determines the number of super jobs
* that are made corresponding to a logical transformation and an execution
* pool. It overrides the collapse key if set.
*
* @see #COLLAPSE_KEY
*/
public static final String BUNDLE_KEY = "clusters.num";
/**
* The name of the key that if set in the Pegasus namespace determines the
* number of jobs that are collapsed into the super job.
*/
public static final String COLLAPSE_KEY = "clusters.size";
/**
* The name of the key that if set in the Pegasus namespace specifies the
* maximum amount of time for which a cluster should run. This key is used
* while clustering jobs horizontally. Only those jobs are grouped together
* whose combined runtime is less than or equal to the max runtime.
*/
public static final String MAX_RUN_TIME = "clusters.maxruntime";
/**
* The name of the key that determines the clusterig executable to be used
* to run the merged/collapsed job.
*/
public static final String JOB_AGGREGATOR_KEY= "job.aggregator";
/**
* The name of the key that determines the collapser executable to be used
* to run the merged/collapsed job.
*
* @deprecated
*/
public static final String COLLAPSER_KEY = "collapser";
/**
* The name of the profile key in vds namespace that does the grouping.
*/
public static final String GROUP_KEY = "group";
/**
* The name of the profile key in vds namespace that does the labelling
* by default.
*/
public static final String LABEL_KEY = "label";
/**
* The name of the profile key that determines the launching executable
* to be used to launch a job on the grid.
*/
public static final String GRIDSTART_KEY = "gridstart";
/**
* The name of the profile key, that determines the arguments with which
* the GridStart that is used to launch a job on the remote site is invoked
* with. The arguments are appended to the ones constructed by default
* by the GridStart implementation.
*/
public static final String GRIDSTART_ARGUMENTS_KEY = "gridstart.arguments";
/**
* The name of the profile key that designates the path to a gridstart.
*/
public static final String GRIDSTART_PATH_KEY = "gridstart.path";
/**
* The message to look for while detecting failures condor job's stdout/stderr
*/
public static final String EXITCODE_FAILURE_MESSAGE = "exitcode.failuremsg";
/**
* the message to look for while detecting success in condor job's stdout/stderr
*/
public static final String EXITCODE_SUCCESS_MESSAGE = "exitcode.successmsg";
/**
* The deprecated change dir key.
* @see #CHANGE_DIR_KEY
*/
public static final String DEPRECATED_CHANGE_DIR_KEY = "change_dir";
/**
* The name of the profile key that triggers the kickstart to change directory
* before launching an executable instead of launching the executable from
* the directory where kickstart is being run.
*/
public static final String CHANGE_DIR_KEY = "change.dir";
/**
* The name of the profile key that triggers the kickstart to create and
* then the working directory to it before launching an executable.
*/
public static final String CREATE_AND_CHANGE_DIR_KEY = "create.dir";
/**
* The deprecated bundle stagein key.
* @see #CHANGE_DIR_KEY
*/
public static final String DEPRECATED_BUNDLE_STAGE_IN_KEY = "bundle.stagein";
/**
* The name of the key that determines the bundling parameter for the
* stagein transfer node.
*/
public static final String BUNDLE_STAGE_IN_KEY = "stagein.clusters";
/**
* The name of the key that determines the bundling parameter for the
* remote stagein transfer node.
*/
public static final String BUNDLE_REMOTE_STAGE_IN_KEY = "stagein.remote.clusters";
/**
* The name of the key that determines the bundling parameter for the
* local stagein transfer node.
*/
public static final String BUNDLE_LOCAL_STAGE_IN_KEY = "stagein.local.clusters";
/**
* The name of the key that determines the bundling parameter for the
* remote stagein transfer node.
*/
public static final String BUNDLE_REMOTE_STAGE_OUT_KEY = "stageout.remote.clusters";
/**
* The name of the key that determines the bundling parameter for the
* local stagein transfer node.
*/
public static final String BUNDLE_LOCAL_STAGE_OUT_KEY = "stageout.local.clusters";
/**
* The name of the key that determines the bundling parameter for the
* stageout transfer node.
*/
public static final String BUNDLE_STAGE_OUT_KEY = "stageout.clusters";
/**
* The name of the key that determines the clustering parameter for the
* stagein transfer node.
*/
public static final String CLUSTER_STAGE_IN_KEY = "stagein.clusters";
/**
* The name of the key that determines the clustering parameter for the
* stagein transfer node.
*/
public static final String CLUSTER_REMOTE_STAGE_IN_KEY = "stagein.remote.clusters";
/**
* The name of the key that determines the cluster parameter for the
* local stagein transfer node.
*/
public static final String CLUSTER_LOCAL_STAGE_IN_KEY = "stagein.local.clusters";
/**
* The name of the key that determines the clustering parameter for the
* stageout transfer node.
*/
public static final String CLUSTER_STAGE_OUT_KEY = "stageout.clusters";
/**
* The name of the key that determines the bundling parameter for the
* remote stagein transfer node.
*/
public static final String CLUSTER_REMOTE_STAGE_OUT_KEY = "stageout.remote.clusters";
/**
* The name of the key that determines the cluster parameter for the
* local stagein transfer node.
*/
public static final String CLUSTER_LOCAL_STAGE_OUT_KEY = "stageout.local.clusters";
/**
* The name of the key that determines the number of chains of stagein
* nodes that are to be created per site.
*/
public static final String CHAIN_STAGE_IN_KEY = "chain.stagein";
/**
* The name of the profile key if associated with a job, results in an explicit
* transfer of the proxy from the submit host to the remote site, instead of
* banking upon CondorG to transfer the proxy.
*/
public static final String TRANSFER_PROXY_KEY = "transfer.proxy";
/**
* The name of the profile key, that when associated with transfer jobs
* determines the arguments with which the transfer executable is invoked.
*/
public static final String TRANSFER_ARGUMENTS_KEY = "transfer.arguments";
/**
* The name of the profile key, that when associated with transfer jobs
* determines the number of threads that pegasus-transfer uses to do the transfer
*/
public static final String TRANSFER_THREADS_KEY = "transfer.threads";
/**
* The name of the profile key, that when associated with transfer jobs
* determines the arguments with which the transfer executable is invoked.
*/
public static final String TRANSFER_SLS_ARGUMENTS_KEY = "transfer.lite.arguments";
/**
* The name of the profile key, that when associated with transfer jobs
* determines the number of threads that pegasus-transfer uses to do the transfer
*/
public static final String TRANSFER_SLS_THREADS_KEY = "transfer.lite.threads";
/**
* The directory in which job needs to execute on worker node tmp.
*/
public static final String WORKER_NODE_DIRECTORY_KEY = "wntmp";
/**
* Arguments that need to be passed to the clustering executable.
*/
public static final String CLUSTER_ARGUMENTS = "cluster.arguments";
/**
* The name of the key, that denotes the style of the dag that is constructed.
* Possible styles can be
* -condor(glidein,flocking,submitting directly to condor pool)
* -globus(condorg)
*/
public static final String STYLE_KEY = "style";
/**
* The name of the key that denotes the type of the job. Whether it is
* recursive or not. Still protypical.
*/
public static final String TYPE_KEY = "type";
/**
* The style indicating that the submit files are to be generated for
* a vanilla condor execution.
*/
public static final String CONDOR_STYLE = "condor";
/**
* The style indicating that the submit files are to be generated for
* a CondorC submission to remote schedds.
*/
public static final String CONDORC_STYLE = "condorc";
/**
* The style indicating that the submit files are to be generated for
* a creamce submission
*/
public static final String CREAMCE_STYLE = "cream";
/**
* The style indicating that the submit files are to be generated for
* a CondorG execution.
*/
public static final String GLOBUS_STYLE = "globus";
/**
* The style indicating that the submit files are to be generated for a
* glidein execution.
*/
public static final String GLIDEIN_STYLE = "glidein";
/**
* The style indicating that the submit files are to be generated for a
* glideinwms execution.
*/
public static final String GLIDEINWMS_STYLE = "glideinwms";
/**
* The style indicating that the submit files are to be generated for a
* glite execution.
*/
public static final String GLITE_STYLE = "glite";
/**
* The style indicating that the submit files are to be generated for a
* direct ssh submission
*/
public static final String SSH_STYLE = "ssh";
/**
* A key to designate the memory required by a job in MB by pegasus-mpi-cluster.
*/
public static final String PMC_REQUEST_MEMORY_KEY = "pmc_request_memory";
/**
* A key to designate the number of CPU's requested by pegasus-mpi-cluster.
*/
public static final String PMC_REQUEST_CPUS_KEY = "pmc_request_cpus";
/**
* A key to designate a priority to the jobs run by pegasus-mpi-cluster.
*/
public static final String PMC_PRIORITY_KEY = "pmc_priority";
/**
* Arguments that need to be passed to the PMC clustering executable.
*/
public static final String PMC_TASK_ARGUMENTS = "pmc_task_arguments";
/**
* Key indicating whether to consider job for data reuse in the partial mode.
*/
public static final String ENABLE_FOR_DATA_REUSE_KEY = "enable_for_data_reuse";
/**
* Key indicating indicating time in minutes after which kickstart sends out a
* TERM signal to a job indicating that is should create a checkpoint file.
*/
public static final String CHECKPOINT_TIME_KEY = "checkpoint.time";
/**
* Key indicating indicating time in seconds after which kickstart sends out a
* TERM signal to a job indicating that is should create a checkpoint file.
*/
public static final String DEPRECATED_CHECKPOINT_TIME_KEY = "checkpoint_time";
/**
* Key indicating max walltime for a job in minutes
*/
public static final String MAX_WALLTIME = "maxwalltime";
//PM-962 resource requirements
/**
* The name of the profile key when associated with a transformation in the
* transformation catalog gives expected runtime in seconds.
*/
public static final String RUNTIME_KEY = "runtime";
/**
* The name of the key that if set in the Pegasus namespace specifies the
* approximate runtime of the job. This key is used in while clustering jobs
* according to run times.
*/
public static final String DEPRECATED_RUNTIME_KEY = "job.runtime";
/**
* The number of cores that are associated with the job. To be used for
* multiplying the job runtimes accordingly.
*/
public static final String CORES_KEY = "cores";
/**
* Key indicating max diskspace used by a job a in MB
*/
public static final String DISKSPACE_KEY = "diskspace";
/**
* Key indicating the number of nodes a job requires
*/
public static final String NODES_KEY = "nodes";
/**
* Key indicating the number of processors per node to be used
*/
public static final String PPN_KEY = "ppn";
/**
* Key indicating max memory used by a job a in MB
*/
public static final String MEMORY_KEY = "memory";
/**
* The queue to use.
*/
public static final String QUEUE_KEY = "queue";
/**
* The project for the job to be associated with.
*/
public static final String PROJECT_KEY = "project";
/**
* Key indicating data configuration property.
*/
public static final String DATA_CONFIGURATION_KEY = "data.configuration";
/**
* Users specified arguments for the local LRMS that we pass through glite and
* add to the eventual qsub file.
*/
public static final String GLITE_ARGUMENTS_KEY = "glite.arguments";
/**
* Profile key to determine condor quoting for a job.
*/
public static final String CONDOR_QUOTE_ARGUMENTS_KEY = "condor.arguments.quote";
//credential related constant keys
private static final String S3CFG_FILE_VARIABLE = S3CFG.S3CFG_FILE_VARIABLE.toLowerCase();
private static final String SSH_PRIVATE_KEY_VARIABLE = Ssh.SSH_PRIVATE_KEY_VARIABLE.toLowerCase();
private static final String IRODSENVFILE = Irods.IRODSENVFILE.toLowerCase();
private static final String X509_USER_PROXY_KEY = Proxy.X509_USER_PROXY_KEY.toLowerCase();
private static final String BOTOCONFIG = BotoConfig.BOTO_CONFIG_FILE_VARIABLE.toLowerCase();
private static final String GOOGLEP12 = GoogleP12.GOOGLEP12_FILE_VARIABLE.toLowerCase();
/**
* Static Handle to the delimiter aggregator.
*/
private static Aggregator ERROR_MESSAGE_AGGREGATOR = new UniqueMerge();
/**
* Static Handle to the delimiter aggregator.
*/
private static Aggregator SUCCESS_MESSAGE_AGGREGATOR = new UniqueMerge();
/**
* The name of the implementing namespace. It should be one of the valid
* namespaces always.
*
* @see Namespace#isNamespaceValid(String)
*/
protected String mNamespace;
/**
* The table containing the mapping of the deprecated keys to the newer keys.
*/
protected static Map mDeprecatedTable = null;
private static Map<String,Aggregator> mAggregatorTable;
/**
* The default aggregator to be used for profile aggregation, if none specified
* in the aggregator table;
*/
public static Aggregator mDefaultAggregator = new Update();
/**
* Initializer block that populates the Aggregator table just once.
*/
static{
mAggregatorTable = new HashMap( 5 );
Aggregator max = new MAX();
Aggregator sum = new Sum();
mAggregatorTable.put( Pegasus.EXITCODE_FAILURE_MESSAGE , ERROR_MESSAGE_AGGREGATOR );
mAggregatorTable.put( Pegasus.EXITCODE_SUCCESS_MESSAGE , SUCCESS_MESSAGE_AGGREGATOR );
//all the times need to be added
mAggregatorTable.put( Pegasus.RUNTIME_KEY , sum );
mAggregatorTable.put( Pegasus.MAX_WALLTIME , sum );
//for the memory rsl params we take max
mAggregatorTable.put( Pegasus.MEMORY_KEY, max );
}
/**
* The default constructor.
* Note that the map is not allocated memory at this stage. It is done so
* in the overloaded construct function.
*/
public Pegasus() {
mProfileMap = null;
mNamespace = NAMESPACE_NAME;
}
/**
* The overloaded constructor.
*
* @param mp the initial map.
*/
public Pegasus(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;
}
/**
* 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. It converts the key to lower case before storing.
*
* @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.toLowerCase(), value);
}
/**
* This checks whether the key passed by the user is valid in the current
* namespace or not.
*
* @param key (left hand side)
* @param value (right hand side)
*
* @return Namespace.VALID_KEY
* Namespace.UNKNOWN_KEY
* Namespace.EMPTY_KEY
* Namespace.MERGE_KEY
*
*/
public int checkKey(String key, String value) {
int res = 0;
if (key == null || key.length() < 2 ) {
res = MALFORMED_KEY ;
return res;
}
if( value == null || value.length() < 1 ){
res = EMPTY_KEY;
return res;
}
//convert key to lower case
key = key.toLowerCase();
switch (key.charAt(0)) {
case 'a':
if( key.compareTo( LOCAL_VISIBLE_KEY ) == 0 ){
res = VALID_KEY;
}else {
res = UNKNOWN_KEY;
}
break;
case 'b':
if (
(key.compareTo(BUNDLE_STAGE_IN_KEY) == 0) ||
(key.compareTo(BUNDLE_STAGE_OUT_KEY) == 0 ) ||
(key.compareTo( BUNDLE_REMOTE_STAGE_IN_KEY) == 0 ) ||
(key.compareTo(BOTOCONFIG) == 0)) {
res = VALID_KEY;
}
else if( key.compareTo(DEPRECATED_BUNDLE_STAGE_IN_KEY) == 0){
res = DEPRECATED_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'c':
if (
(key.compareTo( BUNDLE_KEY) == 0) ||
(key.compareTo( COLLAPSE_KEY ) == 0) ||
(key.compareTo( CHANGE_DIR_KEY ) == 0) ||
(key.compareTo( CHAIN_STAGE_IN_KEY ) == 0) ||
(key.compareTo( MAX_RUN_TIME ) == 0) ||
(key.compareTo( CREATE_AND_CHANGE_DIR_KEY ) == 0 ) ||
(key.compareTo( CLUSTER_ARGUMENTS) == 0 ) ||
(key.compareTo( CORES_KEY ) == 0 ) ||
(key.compareTo( Pegasus.CHECKPOINT_TIME_KEY) == 0 )||
(key.compareTo( Pegasus.DEPRECATED_CHECKPOINT_TIME_KEY) == 0 ) ||
(key.compareTo( Pegasus.CONDOR_QUOTE_ARGUMENTS_KEY) == 0 ) ) {
res = VALID_KEY;
}
else if(key.compareTo(DEPRECATED_CHANGE_DIR_KEY) == 0 ||
(key.compareTo( COLLAPSER_KEY ) == 0)){
res = DEPRECATED_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'd':
if ( (key.compareTo( DATA_CONFIGURATION_KEY ) == 0) ||
( key.compareTo( DISKSPACE_KEY) == 0 )
){
res = VALID_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'e':
if ((key.compareTo( Pegasus.EXITCODE_FAILURE_MESSAGE ) == 0) ||
(key.compareTo( Pegasus.EXITCODE_SUCCESS_MESSAGE ) == 0) ) {
res = MERGE_KEY;
}
else if ( (key.compareTo( Pegasus.ENABLE_FOR_DATA_REUSE_KEY ) == 0 )){
res = VALID_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'g':
if (key.compareTo( GROUP_KEY ) == 0 ||
key.compareTo( GRIDSTART_KEY ) == 0 ||
key.compareTo( GRIDSTART_PATH_KEY ) == 0 ||
key.compareTo( GRIDSTART_ARGUMENTS_KEY ) == 0 ||
key.compareTo( GOOGLEP12 ) == 0 ||
key.compareTo( GLITE_ARGUMENTS_KEY ) == 0 ) {
res = VALID_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'i':
if (key.compareTo( IRODSENVFILE ) == 0) {
res = VALID_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'j':
if (key.compareTo(DEPRECATED_RUNTIME_KEY ) == 0) {
res = DEPRECATED_KEY;
}
else if ( key.compareTo( JOB_AGGREGATOR_KEY ) == 0 ){
res = VALID_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'l':
if( key.compareTo( LABEL_KEY ) == 0 ){
res = VALID_KEY;
}
else{
res = UNKNOWN_KEY;
}
break;
case 'm':
if( key.compareTo( MAX_WALLTIME ) == 0 ||
key.compareTo( MEMORY_KEY ) == 0 ){
res = VALID_KEY;
}
else{
res = UNKNOWN_KEY;
}
break;
case 'n':
if (key.compareTo(NODES_KEY ) == 0) {
res = VALID_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'p':
if(
key.compareTo( PMC_REQUEST_MEMORY_KEY ) == 0 ||
key.compareTo( PMC_REQUEST_CPUS_KEY ) == 0 ||
key.compareTo( PMC_PRIORITY_KEY ) == 0 ||
key.compareTo( PMC_TASK_ARGUMENTS) == 0 ||
key.compareTo( PPN_KEY ) == 0 ||
key.compareTo( PROJECT_KEY) == 0 ) {
res = VALID_KEY;
}
else{
res = UNKNOWN_KEY;
}
break;
case 'q':
if( key.compareTo( QUEUE_KEY ) == 0 ){
res = VALID_KEY;
}
else{
res = UNKNOWN_KEY;
}
break;
case 'r':
if( key.compareTo( RUNTIME_KEY ) == 0 ){
res = VALID_KEY;
}
else{
res = UNKNOWN_KEY;
}
break;
case 's':
if( key.compareTo( STYLE_KEY ) == 0 ||
key.compareTo( S3CFG_FILE_VARIABLE ) == 0 ||
key.compareTo( SSH_PRIVATE_KEY_VARIABLE ) == 0 ||
key.compareTo( CLUSTER_STAGE_IN_KEY ) == 0 ||
key.compareTo( CLUSTER_REMOTE_STAGE_IN_KEY ) == 0 ||
key.compareTo( CLUSTER_LOCAL_STAGE_IN_KEY ) == 0 ||
key.compareTo( CLUSTER_STAGE_OUT_KEY ) == 0 ||
key.compareTo( CLUSTER_REMOTE_STAGE_OUT_KEY ) == 0 ||
key.compareTo( CLUSTER_LOCAL_STAGE_OUT_KEY ) == 0 ){
res = VALID_KEY;
}
else{
res = UNKNOWN_KEY;
}
break;
case 't':
if ( ( key.compareTo( TRANSFER_PROXY_KEY ) == 0) ||
( key.compareTo( TRANSFER_ARGUMENTS_KEY ) == 0) ||
( key.compareTo( TRANSFER_THREADS_KEY ) == 0) ||
( key.compareTo( TRANSFER_SLS_ARGUMENTS_KEY ) == 0) ||
( key.compareTo( TRANSFER_SLS_THREADS_KEY ) == 0) ||
( key.compareTo( TYPE_KEY ) == 0) ){
res = VALID_KEY;
}
else{
res = UNKNOWN_KEY;
}
break;
case 'w':
if ( (key.compareTo(REMOTE_INITIALDIR_KEY) == 0) ||
(key.compareTo(WORKER_NODE_DIRECTORY_KEY) == 0) ) {
res = VALID_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
case 'x':
if ( key.compareTo( X509_USER_PROXY_KEY ) == 0) {
res = VALID_KEY;
}
else {
res = UNKNOWN_KEY;
}
break;
default:
res = UNKNOWN_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.
* This is used to load the appropriate collapser for the job.
* Any preexisting profile is preferred over the one in the property file.
*
* @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.
*
* @see #COLLAPSER_KEY
* @see #TRANSFER_PROXY_KEY
*/
public void checkKeyInNS(PegasusProperties properties, String pool){
this.assimilate( properties ,Profiles.NAMESPACES.pegasus ) ;
}
/**
* Merges key value to an existing value if it exists
*
* @param key
* @param value
*/
public void mergeKey(String key, String value) {
/*String existing = this.getStringValue(key);
if( key.equals( Pegasus.EXITCODE_FAILURE_MESSAGE) || key.equals( Pegasus.EXITCODE_SUCCESS_MESSAGE) ){
existing = ( existing == null )?
value:
existing + UniqueMerge.DEFAULT_DELIMITER + value;
this.construct(key, existing);
}*/
if( key.equals( Pegasus.EXITCODE_FAILURE_MESSAGE) ){
this.construct( key,
ERROR_MESSAGE_AGGREGATOR.compute((String)get( key ), value, null )
);
}
else if( key.equals( Pegasus.EXITCODE_SUCCESS_MESSAGE) ){
this.construct( key,
SUCCESS_MESSAGE_AGGREGATOR.compute((String)get( key ), value, null )
);
}
else{
throw new RuntimeException( "Merge operation not supported for pegasus profile key " + key );
}
}
/**
* UniqueMerge the profiles in the namespace in a controlled manner.
* In case of intersection, the new profile value (except for key runtime where
* the values are summed ) 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 Pegasus )){
//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();
Aggregator agg = this.aggregator( key );
//load the appropriate aggregator to merge the profiles
this.construct( key,
agg.compute( (String)get( key ), (String)profiles.get( key ), "0" ) );
}
}
/**
* Returns the aggregator to be used for the profile key while merging.
* If no aggregator is found, the then default Aggregator (Update) is used.
*
* @param key the key for which the aggregator is found.
*
* @return the aggregator for the profile key.
*/
protected Aggregator aggregator( String key ){
Object aggregator = this.mAggregatorTable.get( key );
return ( aggregator == null )? mDefaultAggregator : (Aggregator)aggregator;
}
/**
* 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.TreeMap();
mDeprecatedTable.put(DEPRECATED_BUNDLE_STAGE_IN_KEY,
BUNDLE_STAGE_IN_KEY);
mDeprecatedTable.put(DEPRECATED_CHANGE_DIR_KEY,
CHANGE_DIR_KEY);
mDeprecatedTable.put( DEPRECATED_RUNTIME_KEY, RUNTIME_KEY );
}
return mDeprecatedTable;
}
/**
* Converts the contents of the map into the string that can be put in the
* Condor file for printing.
*
* @return the textual description.
*/
public String toCondor() {
StringBuffer st = new StringBuffer();
String key = null;
String value = null;
if(mProfileMap == null)
return "";
Iterator it = mProfileMap.keySet().iterator();
while(it.hasNext()){
key = (String)it.next();
value = (String)mProfileMap.get(key);
st.append(key).append(" = ").append(value).append("\n");
}
return st.toString();
}
/**
* Warns about an unknown profile key and constructs it anyway.
* Constructs a new RSL element of the format (key=value).
*
* @param key is the left-hand-side
* @param value is the right hand side
*/
public void unknownKey(String key, String value) {
//mLogger.log("unknown profile " + mNamespace + "." + key +
// ", using anyway", LogManager.DEBUG_MESSAGE_LEVEL);
//Starting 4.4 unknown keys are not added to jobs. this will help
//in reducing the number of profiles associated with the jobs, as
//not all pegasus properties are handled as profiles.
//construct(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);
}
/**
* Returns the value to which this namespace maps the specified key.
* Returns null if the map contains no mapping for this key. A return value
* of null does not necessarily indicate that the map contains no mapping for
* the key; it's also possible that the map explicitly maps the key to null.
* The containsKey operation may be used to distinguish these two cases.
*
* @param key The key whose value you want.
*
* @return the object
*/
public Object get(Object key){
return (mProfileMap == null) ? null : mProfileMap.get(key);
}
/**
* Returns a int value, that a particular key is mapped to in this
* namespace. If the key is mapped to a non integer, then the
* default value is returned
*
* @param key The key whose boolean value you desire.
*
* @return boolean
*/
public boolean getBooleanValue(Object key){
boolean value = false;
if(mProfileMap != null && mProfileMap.containsKey(key)){
value = Boolean.valueOf((String)mProfileMap.get(key)).booleanValue();
}
return value;
}
/**
* Returns a String value, that a particular key is mapped to in this
* namespace. If is not populated in the namespace null is returned.
*
* @param key The key whose boolean value you desire.
*
* @return String if key is in the namespace
* null otherwise.
*/
public String getStringValue(Object key){
return containsKey(key)?
get(key).toString():
null;
}
/**
* Returns a copy of the current namespace object
*
* @return the Cloned object
*/
public Object clone() {
return (mProfileMap == null)?new Pegasus() : new Pegasus(this.mProfileMap);
}
}