001: /*
002: * This file or a portion of this file is licensed under the terms of
003: * the Globus Toolkit Public License, found in file GTPL, or at
004: * http://www.globus.org/toolkit/download/license.html. This notice must
005: * appear in redistributions of this file, with or without modification.
006: *
007: * Redistributions of this Software, with or without modification, must
008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009: * some other similar material which is provided with the Software (if
010: * any).
011: *
012: * Copyright 1999-2004 University of Chicago and The University of
013: * Southern California. All rights reserved.
014: */
015:
016: package org.griphyn.cPlanner.selector.site;
017:
018: import org.griphyn.cPlanner.classes.SubInfo;
019: import org.griphyn.cPlanner.classes.PegasusBag;
020:
021: import org.griphyn.cPlanner.common.LogManager;
022:
023: import org.griphyn.cPlanner.namespace.VDS;
024:
025: import org.griphyn.cPlanner.partitioner.graph.Graph;
026: import org.griphyn.cPlanner.partitioner.graph.GraphNode;
027:
028: import java.util.Iterator;
029: import java.util.LinkedList;
030: import java.util.List;
031: import java.util.Map;
032: import java.util.TreeMap;
033:
034: /**
035: * A site selector than ends up doing grouping jobs together on the basis of
036: * an identifier specifed in the dax for the jobs, and schedules them on to the
037: * same site. Currently, the identifier is key <code>group</code> in the vds
038: * profile namespace. All the jobs that do not have a group associated with them
039: * are put in one default group and end up being scheduled on the same pool.
040: * A limitation of this site selector is that it does not check whether all the
041: * jobs can be scheduled on a particular pool or not. It just checks whether
042: * the first job can be or not. The reason for that is after the grouping the
043: * the selector just hands the first job in each group to the other site selectors
044: * that work on jobs. Currently, it hands it to the Random Site Selector.
045: *
046: *
047: * @author Karan Vahi
048: * @author Gaurang Mehta
049: * @author Mei-Hui Su
050: *
051: * @version $Revision: 298 $
052: */
053:
054: public class Group extends Abstract {
055:
056: /**
057: * The description of the site selector.
058: */
059: private static final String mDescription = "Site selector doing clustering on the basis of key group in pegasus namespace";
060:
061: /**
062: * The name of the group into which jobs are grouped if no group is
063: * specified in the dax.
064: */
065: private static final String mDefaultGroup = "default";
066:
067: /**
068: * The map containing the the jobs grouped by the key group.
069: */
070: private Map mGroupMap;
071:
072: /**
073: * The handle to the internal site selector that is used to schedule jobs
074: * amongst the groups.
075: */
076: private AbstractPerJob mSelector;
077:
078: /**
079: * The default constructor.
080: */
081: public Group() {
082: mGroupMap = new TreeMap();
083: mSelector = new Random();
084: mLogger = LogManager.getInstance();
085: }
086:
087: /**
088: * Initializes the site selector.
089: *
090: * @param bag the bag of objects that is useful for initialization.
091: *
092: */
093: public void initialize(PegasusBag bag) {
094: super .initialize(bag);
095: mSelector.initialize(bag);
096: }
097:
098: /**
099: * Returns the description of the site selector.
100: *
101: * @return description.
102: */
103: public String description() {
104: return mDescription;
105: }
106:
107: /**
108: * The call out to map a list of jobs on to the execution pools. A default
109: * implementation is provided that internally calls mapJob2ExecPool(SubInfo,
110: * String,String,String) to map each of the jobs sequentially to an execution site.
111: * The reason for this method is to support site selectors that
112: * make their decision on a group of jobs i.e use backtracking to reach a good
113: * decision.
114: * The implementation that calls out to an executable using Runtime does not
115: * implement this method, but relies on the default implementation defined
116: * here.
117: *
118: * @param workflow the workflow that needs to be scheduled.
119: * @param sites the list of <code>String</code> objects representing the
120: * execution pools that can be used.
121: *
122: */
123: public void mapWorkflow(Graph workflow, List sites) {
124: SubInfo job;
125: List l = null;
126:
127: int i = 0;
128: for (Iterator it = workflow.nodeIterator(); it.hasNext();) {
129: GraphNode node = (GraphNode) it.next();
130: job = (SubInfo) node.getContent();
131: //put the jobs into the map grouped by key VDS_GROUP_KEY
132: insert(job);
133: }
134:
135: //traverse through the group map and send off the first job
136: //in each group to the internal site selector.
137: for (Iterator it = mGroupMap.entrySet().iterator(); it
138: .hasNext();) {
139: Map.Entry entry = (Map.Entry) it.next();
140: boolean defaultGroup = entry.getKey().equals(mDefaultGroup);
141: mLogger.log("[Group Selector]Mapping jobs in group "
142: + entry.getKey(), LogManager.DEBUG_MESSAGE_LEVEL);
143:
144: l = (List) entry.getValue();
145: String msg = "\t{";
146: boolean first = true;
147: for (Iterator it1 = l.iterator(); it1.hasNext();) {
148: msg += (first) ? "" : ",";
149: msg += ((SubInfo) it1.next()).jobName;
150: first = false;
151: }
152: msg += "}";
153: mLogger.log(msg, LogManager.DEBUG_MESSAGE_LEVEL);
154: //hand of the first job to the internal selector
155: job = (SubInfo) l.get(0);
156: mSelector.mapJob(job, sites);
157:
158: //traverse thru the remaining jobs in the group
159: for (Iterator it1 = l.iterator(); it1.hasNext();) {
160: SubInfo j = (SubInfo) it1.next();
161: if (defaultGroup) {
162: //each job in the group has to be
163: //mapped individually
164: mSelector.mapJob(j, sites);
165: } else {
166: //mapping same as the one for
167: //for the first job in group
168: j.setSiteHandle(job.getSiteHandle());
169: }
170: }
171: }
172: }
173:
174: /**
175: * Inserts the job into the group map.
176: *
177: * @param job the job to be inserted.
178: */
179: private void insert(SubInfo job) {
180: Object obj = job.vdsNS.get(VDS.GROUP_KEY);
181: if (obj != null
182: && ((String) obj).equalsIgnoreCase(mDefaultGroup)) {
183: //throw an exception?
184: throw new RuntimeException("The group name "
185: + mDefaultGroup
186: + " is a reserved keyword for the selector."
187: + " Use another group name in your DAX");
188: }
189: String key = (obj == null) ?
190: //no group specified. set to default
191: mDefaultGroup
192: :
193: //get the value from the profile
194: (String) obj;
195:
196: if (mGroupMap.containsKey(key)) {
197: //there is already a group associated.
198: List l = (List) mGroupMap.get(key);
199: l.add(job);
200: } else {
201: //insert a new entry to the map
202: List l = new LinkedList();
203: l.add(job);
204: mGroupMap.put(key, l);
205: }
206: }
207:
208: }
|