001: /*
002: * <copyright>
003: *
004: * Copyright 1997-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:
027: package org.cougaar.lib.filter;
028:
029: import java.util.Collection;
030: import java.util.Enumeration;
031: import java.util.Iterator;
032: import java.util.Vector;
033:
034: import org.cougaar.lib.callback.UTILAllocationCallback;
035: import org.cougaar.lib.callback.UTILAssetCallback;
036: import org.cougaar.lib.callback.UTILFilterCallback;
037: import org.cougaar.lib.callback.UTILGenericListener;
038: import org.cougaar.lib.callback.UTILWorkflowCallback;
039: import org.cougaar.lib.util.UTILAllocate;
040: import org.cougaar.planning.ldm.asset.Asset;
041: import org.cougaar.planning.ldm.plan.Allocation;
042: import org.cougaar.planning.ldm.plan.Task;
043:
044: /**
045: * <pre>
046: * By default listens for all Assets (please override
047: * createAssetCallback to make more specific).
048: * Also listens for allocations.
049: *
050: * Fill in empty functions as needed to add functionality
051: *
052: * Abstract because these are undefined:
053: *
054: * processTasks -- different for each plugin flavor
055: *
056: * </pre>
057: */
058:
059: public abstract class UTILAllocatorPluginAdapter extends
060: UTILBufferingPluginAdapter implements UTILAllocatorPlugin {
061:
062: /** Reads delayBeforeAllocRemoval from environment files. */
063: public void getEnvData() {
064: super .getEnvData();
065:
066: alloc = new UTILAllocate(logger);
067:
068: // try{delayBeforeAllocRemoval = myParams.getLongParam("delayBeforeAllocRemoval");}
069: // catch(Exception e){delayBeforeAllocRemoval = 0;}
070: }
071:
072: /**
073: * <pre>
074: * The idea is to add subscriptions (via the filterCallback), and when
075: * they change, to have the callback react to the change, and tell
076: * the listener (many times the plugin) what to do.
077: *
078: * Override and call super to add new filters, or override
079: * createXXXCallback to change callback behaviour.
080: *
081: * By default adds asset callback and allocation callback after
082: * creating them.
083: *
084: * </pre>
085: * @see #createAssetCallback
086: * @see #createAllocCallback
087: */
088: public void setupFilters() {
089: super .setupFilters();
090:
091: if (isInfoEnabled())
092: info(getName() + " : Filtering for generic Assets...");
093:
094: addFilter(myAssetCallback = createAssetCallback());
095:
096: if (isInfoEnabled())
097: info(getName() + " : Filtering for Allocations...");
098:
099: addFilter(myAllocCallback = createAllocCallback());
100: }
101:
102: /**
103: * Provide the callback that is paired with the buffering thread, which is a
104: * listener. The buffering thread is the listener to the callback
105: *
106: * @return a WorkflowCallback with the buffering thread as its listener
107: */
108: protected UTILFilterCallback createThreadCallback(
109: UTILGenericListener bufferingThread) {
110: if (isInfoEnabled())
111: info(getName() + " Filtering for Generic Workflows...");
112:
113: myWorkflowCallback = new UTILWorkflowCallback(bufferingThread,
114: logger);
115: return myWorkflowCallback;
116: }
117:
118: protected UTILFilterCallback getWorkflowCallback() {
119: return myWorkflowCallback;
120: }
121:
122: protected UTILAssetCallback getAssetCallback() {
123: return myAssetCallback;
124: }
125:
126: /**
127: * <pre>
128: * Override to replace with a callback that has a different predicate
129: * or different behaviour when triggered.
130: *
131: * PLEASE override this -- this is mainly here for backward compatibility.
132: * I.e. we shouldn't get all the assets of the cluster and then iterate over
133: * them, testing them with instanceof to get the assets we want. We should
134: * use a more specific callback filter/predicate.
135: *
136: * </pre>
137: */
138: protected UTILAssetCallback createAssetCallback() {
139: return new UTILAssetCallback(this , logger);
140: }
141:
142: protected UTILAllocationCallback getAllocCallback() {
143: return myAllocCallback;
144: }
145:
146: /**
147: * Override to replace with a callback that has a different predicate
148: * or different behaviour when triggered.
149: */
150: protected UTILAllocationCallback createAllocCallback() {
151: UTILAllocationCallback allocCallback = new UTILAllocationCallback(
152: this , logger);
153: return allocCallback;
154: }
155:
156: /**
157: * <pre>
158: * Implemented for UTILBufferingPlugin
159: *
160: * Got an ill-formed task, now handle it, by
161: * publishing a failed allocation for the task.
162: * </pre>
163: * @param t badly-formed task to handle
164: */
165: public void handleIllFormedTask(Task t) {
166: reportIllFormedTask(t);
167: blackboard.publishAdd(alloc
168: .makeFailedDisposition(null, ldmf, t));
169: }
170:
171: /**
172: * <pre>
173: * Implemented for UTILAllocationListener
174: *
175: * OVERRIDE to see which task notifications you
176: * think are interesting
177: * </pre>
178: * @param t task to check for notification
179: * @return boolean true if task is interesting
180: */
181: public boolean interestingNotification(Task t) {
182: return interestingTask(t);
183: }
184:
185: /**
186: * <pre>
187: * Implemented for UTILAssetListener
188: *
189: * OVERRIDE to see which assets you
190: * think are interesting
191: * </pre>
192: * @param a asset to check for notification
193: * @return boolean true if asset is interesting
194: */
195: public boolean interestingAsset(Asset a) {
196: return true;
197: }
198:
199: /**
200: * <pre>
201: * Place to handle new assets.
202: *
203: * Does nothing by default.
204: *
205: * </pre>
206: * @param newAssets new assets found in the container
207: */
208: public void handleNewAssets(Enumeration newAssets) {
209: }
210:
211: /**
212: * <pre>
213: * Place to handle changed assets.
214: *
215: * Does nothing by default.
216: *
217: * </pre>
218: * @param changedAssets changed assets found in the container
219: */
220: public void handleChangedAssets(Enumeration changedAssets) {
221: }
222:
223: /**
224: * <pre>
225: * Implemented for UTILAllocationListener
226: *
227: * Defines conditions for rescinding tasks.
228: *
229: * When returns TRUE, handleRescindedAlloc is called. Returns
230: * TRUE when downstream, a FailedAllocation is made.
231: *
232: * WARNING WARNING WARNING: returning TRUE can easily lead
233: * to an infinite loop consisting of try again-fail-try again, etc.
234: * Subclasses should return FALSE even when the allocation
235: * fails if they can't do anything differently the second time.
236: * Returning FALSE makes the failure get reported to its
237: * superior.
238: *
239: * If in making an allocation, a preference
240: * threshold is exceeded, the returned plan element will be
241: * a FailedAllocation (see UTILAllocate.makeAllocation ()).
242: *
243: * TOPS does not create any allocations with
244: * AllocationResults w/ isSuccess = false, but COUGAAR will roll
245: * up the results of a workflow, and create an AllocResult
246: * w/ isSuccess = False if it contains a FailedAllocation.
247: *
248: * Called by UTILAllocationCallback.reactToChangedAlloc.
249: *
250: * </pre>
251: * @param alloc the allocation to check
252: * @return boolean true if the allocation need to be rescinded
253: * Also returns false if there is no report alloc result
254: * attached to allocation
255: * @see #handleRescindedAlloc
256: * @see org.cougaar.lib.callback.UTILAllocationCallback#reactToChangedAlloc
257: * @see org.cougaar.lib.util.UTILAllocate#makeAllocation
258: * @see org.cougaar.lib.util.UTILAllocate#isFailedPE
259: */
260: public boolean needToRescind(Allocation alloc) {
261: return false;
262: }
263:
264: /**
265: * <pre>
266: * Implemented for UTILAllocationListener
267: *
268: * Public version of publishRemove
269: *
270: * Called by UTILAllocationCallback.reactToChangedAlloc.
271: *
272: * FIXIT! -- if you remove the try-catch block, sometimes will see
273: * reset claim exceptions.
274: *
275: * </pre>
276: * @param alloc Allocation to remove from cluster's memory
277: * @see org.cougaar.lib.callback.UTILAllocationCallback#reactToChangedAlloc
278: */
279: public void publishRemovalOfAllocation(Allocation alloc) {
280: if (isInfoEnabled())
281: info(getName() + " : removing allocation for task "
282: + alloc.getTask().getUID());
283:
284: try {
285: blackboard.publishRemove(alloc);
286: } catch (Exception e) {
287: if (isInfoEnabled())
288: info(getName()
289: + " : publishRemovalOfAllocation - got reset claim exception, ignoring...");
290: }
291: }
292:
293: /**
294: * <pre>
295: * Implemented for UTILAllocationListener
296: *
297: * Defines re-allocation of a rescinded task.
298: * Overriders need to take into consideration that
299: * the asset chosen last time is not available this time.
300: *
301: * Note that updateAllocationResult is called automatically by
302: * the UTILAllocationCallback if the allocation has changed
303: * (typically if its allocation result has changed)
304: * but it does NOT need to be rescinded.
305: *
306: * Called by UTILAllocationCallback.reactToChangedAlloc.
307: *
308: * Only called when needToRescind returns TRUE.
309: * See comment on needToRescind.
310: *
311: * Does nothing by default.
312: *
313: * </pre>
314: * @param alloc the allocation that should be rescinded
315:
316: * @see org.cougaar.lib.callback.UTILAllocationCallback#reactToChangedAlloc
317: * @see #needToRescind
318: */
319: public boolean handleRescindedAlloc(Allocation alloc) {
320: /*
321: if (isInfoEnabled())
322: info(getName () +
323: " : handling rescinded allocation for task " +
324: alloc.getTask ().getUID ());
325: if (isInfoEnabled())
326: info (getName () + " : waiting " +
327: delayBeforeAllocRemoval/1000 +
328: " seconds after removing alloc for task " +
329: alloc.getTask ().getUID () +
330: "\n\tnow " + new Date ());
331: try {
332: Thread.sleep (delayBeforeAllocRemoval);
333: } catch (Exception e) {}
334:
335: if (isInfoEnabled())
336: info ("\t resuming at " + new Date ());
337: */
338:
339: return false;
340: }
341:
342: /**
343: * <pre>
344: * Implemented for UTILAllocationListener
345: *
346: * Called automatically by the UTILAllocationCallback
347: * if the allocation has changed but it does NOT need
348: * to be rescinded.
349: * updateAllocationResult is called first and then this method
350: * gets called.
351: *
352: * Called by UTILAllocationCallback.reactToChangedAlloc.
353: *
354: * Only called when needToRescind returns FALSE.
355: * See comment on needToRescind.
356: *
357: * Does nothing by default.
358: *
359: * </pre>
360: * @param alloc the allocation that was successful
361: * @see UTILPluginAdapter#updateAllocationResult
362: * @see org.cougaar.lib.callback.UTILAllocationCallback#reactToChangedAlloc
363: * @see #needToRescind
364: */
365: public void handleSuccessfulAlloc(Allocation alloc) {
366: /*
367: if (isDebugEnabled())
368: info(getName () +
369: " : handling successful allocation for task " +
370: alloc.getTask ().getUID () +
371: " by doing nothing.");
372: */
373: }
374:
375: /**
376: * <pre>
377: * Called when an allocation is removed from the cluster.
378: * I.e. an upstream cluster removed an allocation, and this
379: * rescind has resulted in this allocation being removed.
380: *
381: * If the plugin maintains some local state of the availability
382: * of assets, it should update them here.
383: *
384: * Does nothing by default.
385: * </pre>
386: */
387: public void handleRemovedAlloc(Allocation alloc) {
388: if (isDebugEnabled()) {
389: String unit = "Undefined";//(UTILPrepPhrase.hasPrepNamed(alloc.getTask (), Constants.Preposition.FOR)) ?
390: //("" + UTILPrepPhrase.getPrepNamed(alloc.getTask (), Constants.Preposition.FOR)) : "nonUnit";
391: debug(getName()
392: + ".handleRemovedAlloc : alloc was removed for task "
393: + alloc.getTask().getUID() + " w/ d.o. "
394: + alloc.getTask().getDirectObject() + " from "
395: + unit);
396: }
397: }
398:
399: /**
400: * <pre>
401: * Utility method for finding all resource assets.
402: *
403: * In general, it would be better if plugins could use more
404: * specific filters and so this call would return a restricted set of
405: * assets.
406: *
407: * At the very least,
408: * cluster assets can be divided between organizational assets
409: * and physical assets.
410: *
411: * @return Enumeration of ALL assets found in container
412: * </pre>
413: */
414: protected final Iterator getAssets() {
415: Collection assets = getAssetCallback().getSubscription()
416: .getCollection();
417:
418: if (assets.size() != 0) {
419: return assets.iterator();
420: }
421: return null;
422: }
423:
424: protected UTILWorkflowCallback myWorkflowCallback;
425: protected UTILAssetCallback myAssetCallback;
426: protected UTILAllocationCallback myAllocCallback;
427: protected UTILAllocate alloc;
428:
429: // protected long delayBeforeAllocRemoval = 0; //millis
430: }
|