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: */package org.griphyn.cPlanner.selector.replica;
015:
016: import org.griphyn.cPlanner.classes.ReplicaLocation;
017:
018: import org.griphyn.cPlanner.selector.ReplicaSelector;
019:
020: import org.griphyn.cPlanner.common.LogManager;
021: import org.griphyn.cPlanner.common.PegasusProperties;
022: import org.griphyn.cPlanner.common.PegRandom;
023: import org.griphyn.cPlanner.common.Utility;
024:
025: import org.griphyn.common.catalog.ReplicaCatalogEntry;
026:
027: import java.util.ArrayList;
028: import java.util.Iterator;
029: import java.util.Vector;
030:
031: /**
032: * The default replica selector that is used if non is specifed by the user.
033: * This gives preference to a replica residing on the same site as the site,
034: * where it is required to be staged to. If there is no such replica, then a
035: * random replica is selected.
036: *
037: *
038: * <p>
039: * In order to use the replica selector implemented by this class,
040: * <pre>
041: * - the property pegasus.selector.replica must be set to value Default, or
042: * the property should be left undefined in the properties.
043: * </pre>
044: *
045: * @author Karan Vahi
046: * @version $Revision: 386 $
047: */
048: public class Default implements ReplicaSelector {
049:
050: /**
051: * A short description of the replica selector.
052: */
053: private static String mDescription = "Default";
054:
055: /**
056: * The scheme name for file url.
057: */
058: protected static final String FILE_URL_SCHEME = "file:";
059:
060: /**
061: * This member variable if set causes the source url for the pull nodes from
062: * the RLS to have file:// url if the pool attributed associated with the pfn
063: * is same as a particular jobs execution pool.
064: */
065: protected boolean mUseSymLinks;
066:
067: /**
068: * The handle to the logging object that is used to log the various debug
069: * messages.
070: */
071: protected LogManager mLogger;
072:
073: /**
074: * The properties object containing the properties passed to the planner.
075: */
076: protected PegasusProperties mProps;
077:
078: /**
079: * The overloaded constructor, that is called by load method.
080: *
081: * @param properties the <code>PegasusProperties</code> object containing all
082: * the properties required by Pegasus.
083: *
084: *
085: */
086: public Default(PegasusProperties properties) {
087: mProps = properties;
088: mLogger = LogManager.getInstance();
089: mUseSymLinks = mProps.getUseOfSymbolicLinks();
090: }
091:
092: /**
093: * This chooses a location amongst all the locations returned by the replica
094: * location service. If a location is found with re attribute same as the
095: * preference pool, it is taken. Else a random location is selected and
096: * returned. If more than one location for the lfn is found at the preference
097: * pool, then also a random location amongst the ones at the preference pool
098: * is selected.
099: *
100: * @param rl the <code>ReplicaLocation</code> object containing all
101: * the pfn's associated with that LFN.
102: * @param preferredSite the preffered site for picking up the replicas.
103: *
104: * @return <code>ReplicaCatalogEntry</code> corresponding to the location selected.
105: *
106: * @see org.griphyn.cPlanner.classes.ReplicaLocation
107: */
108: public ReplicaCatalogEntry selectReplica(ReplicaLocation rl,
109: String preferredSite) {
110:
111: ReplicaCatalogEntry rce;
112: ArrayList prefPFNs = new ArrayList();
113: int locSelected;
114: String site = null;
115:
116: // mLogger.log("Selecting a pfn for lfn " + lfn + "\n amongst" + locations ,
117: // LogManager.DEBUG_MESSAGE_LEVEL);
118:
119: for (Iterator it = rl.pfnIterator(); it.hasNext();) {
120: rce = (ReplicaCatalogEntry) it.next();
121: site = rce.getResourceHandle();
122:
123: //check if equal to the execution pool
124: if (site != null && site.equals(preferredSite)) {
125: prefPFNs.add(rce);
126: //return the one with file url for ligo stuff
127: //is temporary till new api coded
128: if (rce.getPFN().startsWith(FILE_URL_SCHEME)) {
129: //this is the one which is reqd for ligo
130: //return instead of break;
131: return rce;
132: }
133: } else {
134: //we again need to check if a location
135: //starts with file url. if it is , we need
136: //to remove it from list, as file urls make sense
137: //only if associated with the preference pool
138: if (rce.getPFN().startsWith(FILE_URL_SCHEME)) {
139: it.remove();
140: }
141: /*
142: mLogger.log(
143: "pool attribute not specified for the location objects" +
144: " in the Replica Catalog",LogManager.WARNING_MESSAGE_LEVEL);
145: */
146: }
147: }
148:
149: int noOfLocs = rl.getPFNCount();
150: if (noOfLocs == 0) {
151: //in all likelihood all the urls were file urls and none
152: //were associated with the preference pool.
153: throw new RuntimeException(
154: "Unable to select any location from "
155: + "the list passed for lfn " + rl.getLFN());
156: }
157:
158: if (prefPFNs.isEmpty()) {
159: //select a random location from
160: //all the matching locations
161: locSelected = PegRandom.getInteger(noOfLocs - 1);
162: rce = (ReplicaCatalogEntry) rl.getPFN(locSelected);
163:
164: } else {
165: //select a random location
166: //amongst the locations
167: //on the preference pool
168: int length = prefPFNs.size();
169: //System.out.println("No of locations found at pool " + prefPool + " are " + length);
170: locSelected = PegRandom.getInteger(length - 1);
171: rce = (ReplicaCatalogEntry) prefPFNs.get(locSelected);
172:
173: //user has specified that
174: //he wants to create symbolic
175: //links instead of going thru the
176: //grid ftp server
177: if (mUseSymLinks) {
178: rce = replaceProtocolFromURL(rce);
179: }
180: }
181:
182: return rce;
183:
184: }
185:
186: /**
187: * This chooses a location amongst all the locations returned by the
188: * Replica Mechanism. If a location is found with re/pool attribute same
189: * as the preference pool, it is taken. This returns all the locations which
190: * match to the preference pool. This function is called to determine if a
191: * file does exist on the output pool or not beforehand. We need all the
192: * location to ensure that we are able to make a match if it so exists.
193: * Else a random location is selected and returned
194: *
195: * @param rl the <code>ReplicaLocation</code> object containing all
196: * the pfn's associated with that LFN.
197: * @param preferredSite the preffered site for picking up the replicas.
198: *
199: * @return <code>ReplicaLocation</code> corresponding to the replicas selected.
200: *
201: * @see org.griphyn.cPlanner.classes.ReplicaLocation
202: */
203: public ReplicaLocation selectReplicas(ReplicaLocation rl,
204: String preferredSite) {
205:
206: String lfn = rl.getLFN();
207: ReplicaLocation result = new ReplicaLocation();
208: result.setLFN(rl.getLFN());
209:
210: ReplicaCatalogEntry rce;
211: String site;
212: String ucAttrib;
213: int noOfLocs = 0;
214:
215: for (Iterator it = rl.pfnIterator(); it.hasNext();) {
216: noOfLocs++;
217: rce = (ReplicaCatalogEntry) it.next();
218: site = rce.getResourceHandle();
219:
220: if (site != null && site.equals(preferredSite)) {
221: result.addPFN(rce);
222: } else if (site == null) {
223: mLogger.log(
224: " pool attribute not specified for the location objects"
225: + " in the Replica Catalog",
226: LogManager.WARNING_MESSAGE_LEVEL);
227: }
228: }
229:
230: if (result.getPFNCount() == 0) {
231: //means we have to choose a random location between 0 and (noOfLocs -1)
232: int locSelected = PegRandom.getInteger(noOfLocs - 1);
233: rce = (ReplicaCatalogEntry) rl.getPFN(locSelected);
234: result.addPFN(rce);
235: }
236: return result;
237:
238: }
239:
240: /**
241: * Replaces the gsiftp URL scheme from the url, and replaces it with the
242: * file url scheme and returns in a new object. The original object
243: * passed as a parameter still remains the same.
244: *
245: * @param rce the <code>ReplicaCatalogEntry</code> object whose url need to be
246: * replaced.
247: *
248: * @return the object with the url replaced.
249: */
250: protected ReplicaCatalogEntry replaceProtocolFromURL(
251: ReplicaCatalogEntry rce) {
252: String pfn = rce.getPFN();
253: StringBuffer newPFN = new StringBuffer();
254: String hostName = Utility.getHostName(pfn);
255:
256: newPFN.append(FILE_URL_SCHEME).append("//");
257: //we want to skip out the hostname
258: newPFN.append(pfn.substring(pfn.indexOf(hostName)
259: + hostName.length()));
260:
261: //we do not need a full clone, just the PFN
262: ReplicaCatalogEntry result = new ReplicaCatalogEntry(newPFN
263: .toString(), rce.getResourceHandle());
264: String key;
265: for (Iterator it = rce.getAttributeIterator(); it.hasNext();) {
266: key = (String) it.next();
267: result.addAttribute(key, rce.getAttribute(key));
268: }
269:
270: return result;
271: }
272:
273: /**
274: * Returns a short description of the replica selector.
275: *
276: * @return string corresponding to the description.
277: */
278: public String description() {
279: return mDescription;
280: }
281:
282: }
|