001: /*
002: * <copyright>
003: *
004: * Copyright 2003-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.lib.vishnu.client;
027:
028: import org.cougaar.lib.param.ParamMap;
029: import org.cougaar.util.log.Logger;
030: import org.w3c.dom.Document;
031:
032: import java.util.ArrayList;
033: import java.util.Collection;
034: import java.util.Date;
035: import java.util.Enumeration;
036: import java.util.List;
037: import java.util.Map;
038:
039: /**
040: * External mode.
041: * <p>
042: * Talks to a web server to orchestrate scheduling.
043: */
044: public class ExternalMode extends PluginHelper implements
045: SchedulerLifecycle {
046: public ExternalMode(ModeListener parent, VishnuComm comm,
047: XMLProcessor xmlProcessor, VishnuDomUtil domUtil,
048: VishnuConfig config, ResultHandler resultHandler,
049: ParamMap myParamTable, Logger logger) {
050: super (parent, comm, xmlProcessor, domUtil, config,
051: myParamTable, logger);
052: this .resultHandler = resultHandler;
053: localSetup();
054: }
055:
056: /** sets local parameters */
057: protected void localSetup() {
058: super .localSetup();
059:
060: try {
061: sendDataChunkSize = getMyParams().getIntParam(
062: "sendDataChunkSize");
063: } catch (Exception e) {
064: sendDataChunkSize = 100;
065: }
066:
067: try {
068: alwaysClearDatabase = getMyParams().getBooleanParam(
069: "alwaysClearDatabase");
070: } catch (Exception e) {
071: alwaysClearDatabase = true;
072: }
073:
074: try {
075: incrementalScheduling = getMyParams().getBooleanParam(
076: "incrementalScheduling");
077: } catch (Exception e) {
078: incrementalScheduling = false;
079: }
080:
081: // Don't clear database on each send if scheduling incrementally
082: if (incrementalScheduling)
083: alwaysClearDatabase = false;
084: }
085:
086: /**
087: * Implemented for SchedulerLifecycle -- already done in VishnuPlugin.prepareObjectFormat
088: * so does nothing.
089: *
090: * @see VishnuPlugin#prepareObjectFormat
091: */
092: public void initializeWithFormat() {
093: }
094:
095: /** just calls sendDataToVishnu */
096: public void prepareData(List stuffToSend, Document objectFormatDoc) {
097: sendDataToVishnu(stuffToSend, myNameToDescrip,
098: alwaysClearDatabase, false, // send assets as NEWOBJECTS
099: singleAssetClassName);
100: }
101:
102: /**
103: * Send the data section of the problem to the postdata URL.<p>
104: *
105: * Chunks data into <code>sendDataChunkSize</code> chunks of tasks.<p>
106: *
107: * Handles sending changed objects.
108: *
109: * @param tasks -- a collection of all the tasks and resources
110: * @param nameToDescrip - Maping of names to newnames on fields, objects
111: * @param clearDatabase - send clear database command to Vishnu
112: * @param sendingChangedObjects -- controls whether assets will be sent
113: * inside of <CHANGEDOBJECT> tags
114: */
115: protected void sendDataToVishnu(List tasks, Map nameToDescrip,
116: boolean clearDatabase, boolean sendingChangedObjects,
117: String assetClassName) {
118: int totalSent = 0;
119:
120: XMLizer dataXMLizer = xmlProcessor.getDataXMLizer();
121:
122: if (logger.isInfoEnabled())
123: logger
124: .info(getName()
125: + ".sendDataToVishnu - Num tasks/assets before adding changed "
126: + tasks.size());
127: tasks.addAll(parent.getChangedAssets());
128: if (logger.isInfoEnabled())
129: logger
130: .info(getName()
131: + ".sendDataToVishnu - Num tasks/assets after adding changed "
132: + tasks.size());
133: int totalTasks = tasks.size();
134:
135: while (totalSent < totalTasks) {
136: int toIndex = totalSent + sendDataChunkSize;
137: if (toIndex > totalTasks)
138: toIndex = totalTasks;
139:
140: Collection chunk = new ArrayList(tasks.subList(totalSent,
141: toIndex));
142:
143: if (logger.isInfoEnabled())
144: logger.info(getName() + ".sendDataToVishnu, from "
145: + totalSent + " to " + toIndex);
146:
147: Document docToSend = xmlProcessor.prepareDocument(chunk,
148: parent.getChangedAssets(), dataXMLizer,
149: clearDatabase, sendingChangedObjects,
150: assetClassName);
151:
152: serializeAndPostDoc(docToSend);
153:
154: if (clearDatabase)
155: clearDatabase = false; // flip bit after first one
156: totalSent += sendDataChunkSize;
157: }
158: parent.clearChangedAssets();
159:
160: sendOtherData();
161: }
162:
163: /** ask VishnuComm to serialize and post the data
164: * @see org.cougaar.lib.vishnu.client.VishnuComm#serializeAndPostData
165: */
166: protected void serializeAndPostDoc(Document doc) {
167: comm.serializeAndPostData(doc);
168: }
169:
170: /**
171: * Send other data, if it hasn't already been sent
172: * @see org.cougaar.lib.vishnu.client.VishnuComm#serializeAndPostData
173: */
174: protected void sendOtherData() {
175: if (!sentOtherDataAlready
176: && xmlProcessor.otherDataFileExists(config
177: .getOtherData()))
178: comm.serializeAndPostData(xmlProcessor
179: .getOtherDataDoc(config.getOtherData()));
180:
181: if (incrementalScheduling)
182: sentOtherDataAlready = true;
183: }
184:
185: /** scheduler is created as a separate process by whoever sets up Vishnu system */
186: public void setupScheduler() {
187: }
188:
189: /**
190: * Place to handle rescinded tasks.
191: *
192: * Sends XML to unfreeze the task assignment and delete it.
193: * @param removedTasks changed assets found in the container
194: */
195: public void handleRemovedTasks(Enumeration removedTasks) {
196: if (incrementalScheduling) {
197: Document docToSend = xmlProcessor.prepareRescind(
198: removedTasks, parent.getTaskName());
199: comm.serializeAndPostData(docToSend);
200: }
201: }
202:
203: public void unfreezeTasks(Collection tasks) {
204: if (incrementalScheduling) {
205: Document docToSend = xmlProcessor.prepareUnfreeze(tasks);
206: comm.serializeAndPostData(docToSend);
207: }
208: }
209:
210: public Collection getTaskKeys() {
211: logger.error("ExternalMode.getTaskKeys - not implemented.");
212: return null;
213: }
214:
215: /**
216: * Run externally.
217: * <p>
218: * Trigger the start of scheduling and wait until it's finished.
219: * @see #waitTillFinished
220: */
221: public void run() {
222: comm.startScheduling();
223:
224: if (!waitTillFinished())
225: showTimedOutMessage();
226: }
227:
228: /** wait until the scheduler is done. Parse the answer if there was one. */
229: protected boolean waitTillFinished() {
230: Date start = new Date();
231:
232: boolean gotAnswer = comm.waitTillFinished();
233:
234: if (!alwaysClearDatabase) {
235: comm.serializeAndPostData(xmlProcessor.prepareFreezeAll());
236: }
237:
238: if (showTiming)
239: domUtil.reportTime(
240: " - Vishnu received answer, was waiting for ",
241: start);
242:
243: if (gotAnswer)
244: ((XMLResultHandler) resultHandler).parseAnswer();
245:
246: return gotAnswer;
247: }
248:
249: /** timed out waiting for scheduler to do its job */
250: private void showTimedOutMessage() {
251: logger
252: .error(getName()
253: + ".processTasks -- ERROR -- "
254: + "Timed out waiting for scheduler to finish.\n"
255: + "Is there a scheduler running?\n"
256: + "See vishnu/scripts/runScheduler in the vishnu distribution.\n"
257: + "It's good to set the machines property to include only\n"
258: + "those machines you are running from, or else the scheduler\n"
259: + "could process any job posted by anyone to the web server.\n"
260: + "For more information, contact gvidaver@bbn.com or dmontana@bbn.com");
261: }
262:
263: /** used by sendDataToVishnu */
264: public void setNameToDescrip(Map map) {
265: myNameToDescrip = map;
266: }
267:
268: /** used by sendDataToVishnu */
269: public void setSingleAssetClassName(String name) {
270: singleAssetClassName = name;
271: }
272:
273: /** name of this object */
274: protected String getName() {
275: return "ExternalMode";
276: }
277:
278: /** queries the scheduler to get a full specification of the problem
279: * (including specs, logic, gaspecs, objects, assignments, etc)
280: *
281: * placeholder in external mode (for now)
282: */
283: public String dumpToXML() {
284: return "";
285: }
286:
287: Map myNameToDescrip;
288: String singleAssetClassName;
289: boolean alwaysClearDatabase;
290: protected int sendDataChunkSize;
291: ResultHandler resultHandler;
292: protected boolean incrementalScheduling;
293: protected boolean sentOtherDataAlready = false;
294: }
|