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: package org.griphyn.cPlanner.selector.site;
016:
017: import org.griphyn.cPlanner.poolinfo.PoolInfoProvider;
018: import org.griphyn.cPlanner.poolinfo.PoolMode;
019:
020: import org.griphyn.cPlanner.selector.SiteSelector;
021:
022: import org.griphyn.cPlanner.classes.SubInfo;
023:
024: import org.griphyn.cPlanner.common.LogManager;
025: import org.griphyn.cPlanner.common.PegasusProperties;
026:
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.ListIterator;
030:
031: /**
032: * This ends up scheduling the jobs in a round robin manner. In order to avoid
033: * starvation, the jobs are scheduled in a round robin manner per level, and
034: * the queue is initialised for each level.
035: *
036: * @author Karan Vahi
037: * @version $Revision: 298 $
038: */
039:
040: public class RoundRobin extends AbstractPerJob {
041:
042: /**
043: * The current level in the abstract workflow. It is level that is designated
044: * by Chimera while constructing the graph bottom up.
045: */
046: private int mCurrentLevel;
047:
048: /**
049: * The list of pools that have been given by the user at run time or has been
050: * authenticated against. At present these are the same as the list of pools
051: * that is passed for site selection at each function.
052: */
053: private java.util.LinkedList mExecPools;
054:
055: /**
056: * The default constructor. Not to be used.
057: */
058: public RoundRobin() {
059: mCurrentLevel = -1;
060: }
061:
062: /**
063: * Returns a brief description of the site selection techinque implemented by
064: * this class.
065: *
066: * @return String
067: */
068: public String description() {
069: String st = "Round Robin Scheduling per level of the workflow";
070: return st;
071: }
072:
073: /**
074: * Maps a job in the workflow to an execution site.
075: *
076: * @param job the job to be mapped.
077: * @param sites the list of <code>String</code> objects representing the
078: * execution sites that can be used.
079: *
080: */
081: public void mapJob(SubInfo job, List sites) {
082: ListIterator it;
083: NameValue current;
084: NameValue next;
085:
086: if (mExecPools == null) {
087: initialiseList(sites);
088: }
089:
090: if (job.level != mCurrentLevel) {
091: //reinitialize stuff
092: mCurrentLevel = job.level;
093: it = mExecPools.listIterator();
094: while (it.hasNext()) {
095: ((NameValue) it.next()).setValue(0);
096: }
097: }
098:
099: //go around the list and schedule it to the first one where it can
100: it = mExecPools.listIterator();
101: String mapping = null;
102: while (it.hasNext()) {
103: current = (NameValue) it.next();
104: //check if job can run on pool
105: if (mTCMapper.isSiteValid(job.namespace, job.logicalName,
106: job.version, current.getName())) {
107: mapping = current.getName();
108: //update the the number of times used and place it at the
109: //correct position in the list
110: current.increment();
111:
112: //the current element stays at it's place if it is the only one
113: //in the list or it's value is less than the next one.
114: if (it.hasNext()) {
115: next = (NameValue) it.next();
116: if (current.getValue() <= next.getValue()) {
117: break;
118: } else {
119: current = (NameValue) it.previous();
120: current = (NameValue) it.previous();
121: System.out.print("");
122: }
123: }
124: it.remove();
125:
126: //now go thru the list and insert in the correct position
127: while (it.hasNext()) {
128: next = (NameValue) it.next();
129:
130: if (current.getValue() <= next.getValue()) {
131: //current has to be inserted before next
132: next = (NameValue) it.previous();
133: it.add(current);
134: break;
135: }
136: }
137: //current goes to the end of the list
138: it.add(current);
139: break;
140: }
141: }
142:
143: //means no pool has been found to which the job could be mapped to.
144: job.setSiteHandle(mapping);
145: }
146:
147: /**
148: * It initialises the internal list. A node in the list corresponds to a pool
149: * that can be used, and has the value associated with it which is the
150: * number of jobs in the current level have been scheduled to it.
151: *
152: * @param pools List
153: */
154: private void initialiseList(List pools) {
155: if (mExecPools == null) {
156: mExecPools = new java.util.LinkedList();
157:
158: Iterator it = pools.iterator();
159: while (it.hasNext()) {
160: mExecPools.add(new NameValue((String) it.next(), 0));
161: }
162: }
163: }
164:
165: /**
166: * A inner name value class that associates a string with an int value.
167: * This is used to populate the round robin list that is used by this
168: * scheduler.
169: */
170: class NameValue {
171: /**
172: * Stores the name of the pair (the left handside of the mapping).
173: */
174: private String name;
175:
176: /**
177: * Stores the corresponding value to the name in the pair.
178: */
179: private int value;
180:
181: /**
182: * The default constructor which initialises the class member variables.
183: */
184: public NameValue() {
185: name = new String();
186: value = -1;
187: }
188:
189: /**
190: * Initialises the class member variables to the values passed in the
191: * arguments.
192: *
193: * @param name corresponds to the name in the NameValue pair
194: *
195: * @param value corresponds to the value for the name in the NameValue pair
196: */
197: public NameValue(String name, int value) {
198: this .name = name;
199: this .value = value;
200: }
201:
202: /**
203: * The set method to set the value.
204: * @param value int
205: */
206: public void setValue(int value) {
207: this .value = value;
208: }
209:
210: /**
211: * Returns the value associated with this pair.
212: * @return int
213: */
214: public int getValue() {
215: return this .value;
216: }
217:
218: /**
219: * Returns the key of this pair, i.e the left hand side of the mapping.
220: * @return String
221: */
222: public String getName() {
223: return this .name;
224: }
225:
226: /**
227: * Increments the int value by one.
228: */
229: public void increment() {
230: value += 1;
231: }
232:
233: /**
234: * Returns a copy of this object.
235: * @return Object
236: */
237: public Object clone() {
238: NameValue nv = new NameValue(this .name, this .value);
239: return nv;
240:
241: }
242:
243: /**
244: * Writes out the contents of the class to a String in form suitable for
245: * displaying.
246: * @return String
247: */
248: public String toString() {
249: String str = name + "-->" + value;
250:
251: return str;
252: }
253:
254: }
255: }
|