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.callback;
028:
029: import java.util.Enumeration;
030: import java.util.HashMap;
031: import java.util.List;
032: import java.util.Map;
033:
034: import org.cougaar.planning.ldm.plan.Aggregation;
035: import org.cougaar.planning.ldm.plan.Composition;
036: import org.cougaar.planning.ldm.plan.Task;
037: import org.cougaar.util.UnaryPredicate;
038: import org.cougaar.util.log.Logger;
039:
040: /**
041: * Filters for aggregations...
042: */
043:
044: public class UTILAggregationCallback extends UTILFilterCallbackAdapter {
045: public UTILAggregationCallback(UTILAggregationListener listener,
046: Logger logger) {
047: super (listener, logger);
048: }
049:
050: protected UnaryPredicate getPredicate() {
051: return new UnaryPredicate() {
052: public boolean execute(Object o) {
053: if (o instanceof Aggregation) {
054: UTILAggregationListener aggListener = (UTILAggregationListener) myListener;
055: Composition comp = ((Aggregation) o)
056: .getComposition();
057: List parents = comp.getParentTasks();
058: for (int i = 0; i < parents.size(); i++)
059: if (aggListener
060: .interestingParentTask((Task) parents
061: .get(i)))
062: return true;
063:
064: if (parents.isEmpty()) // a failed aggregation has no parents
065: return true;
066: }
067: return false;
068: }
069: };
070: }
071:
072: public void reactToChangedFilter() {
073: Map seenAggsMap = new HashMap();
074: Enumeration changedaggs = mySub.getChangedList();
075:
076: while (changedaggs.hasMoreElements()) {
077: Aggregation agg = (Aggregation) changedaggs.nextElement();
078: if (seenAggsMap.get(agg) == null) {
079: reactToChangedAgg(agg);
080: seenAggsMap.put(agg, agg);
081: } else if (logger.isDebugEnabled())
082: logger.debug("UTILAggregationCallback : "
083: + "Duplicate changed aggregation for task "
084: + agg.getTask().getUID() + " ignored.");
085: }
086:
087: seenAggsMap = new HashMap();
088: Enumeration removedAggs;
089: if ((removedAggs = mySub.getRemovedList()).hasMoreElements()) {
090: UTILAggregationListener listener = (UTILAggregationListener) myListener;
091: while (removedAggs.hasMoreElements()) {
092: Aggregation agg = (Aggregation) removedAggs
093: .nextElement();
094: if (logger.isDebugEnabled())
095: logger.debug("UTILAggregationCallback " + this
096: + " found removed agg " + agg.getUID());
097: if (seenAggsMap.get(agg) == null) {
098: if (logger.isDebugEnabled())
099: logger.debug("UTILAggregationCallback " + this
100: + " telling plugin of agg "
101: + agg.getUID());
102: listener.handleRemovedAggregation(agg);
103: seenAggsMap.put(agg, agg);
104: } else if (logger.isDebugEnabled())
105: logger.debug("UTILAggregationCallback : "
106: + "Duplicate removed agg for task "
107: + agg.getTask().getUID() + " ignored.");
108: }
109: }
110: }
111:
112: /**
113: * Defines protocol for dealing with Aggregations as they change over time.
114: *
115: * Aggregator plugins have two shots at dealing with failed aggregations:
116: * 1) immediately, as they happen -- hook here is handleRescindedAggregation
117: * Here the plugin can realloc immediately upon failure.
118: * 2) the next cycle -- when the aggregation is removed, the task for that
119: * aggregation is now as it was initially, and so ready to allocate.
120: * Perhaps now the plugin can group it with other tasks and allocate
121: * differently.
122: * NOTE : This option can result in infinite loops :
123: * if the plugin doesn't do anything different the second time, the
124: * aggregation will fail again, be rescinded, and we're back where we
125: * started.
126: *
127: * @param agg Aggregation to examine
128: */
129: protected void reactToChangedAgg(Aggregation agg) {
130: UTILAggregationListener listener = (UTILAggregationListener) myListener;
131: if (listener.needToRescind(agg)) {
132: listener.publishRemovalOfAggregation(agg);
133: // need to call this instead of allocate(Task) because the cluster
134: // needs to know that the current resource is rejected.
135: listener.handleRescindedAggregation(agg);
136: } else {
137: listener.reportChangedAggregation(agg);
138: listener.handleSuccessfulAggregation(agg);
139: }
140: }
141:
142: }
|