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.Map;
032:
033: import org.cougaar.planning.ldm.plan.Allocation;
034: import org.cougaar.planning.ldm.plan.Task;
035: import org.cougaar.util.UnaryPredicate;
036: import org.cougaar.util.log.Logger;
037:
038: /**
039: * Filter for allocations. Proscribes protocol for dealing with
040: * changed allocations.
041: */
042:
043: public class UTILAllocationCallback extends UTILFilterCallbackAdapter {
044: public UTILAllocationCallback(UTILAllocationListener listener,
045: Logger logger) {
046: super (listener, logger);
047: }
048:
049: protected UnaryPredicate getPredicate() {
050: return new UnaryPredicate() {
051: public boolean execute(Object o) {
052: if (o instanceof Allocation) {
053: Task t = ((Allocation) o).getTask();
054: return ((UTILAllocationListener) myListener)
055: .interestingNotification(t);
056: }
057: return false;
058: }
059: };
060: }
061:
062: public void reactToChangedFilter() {
063: Map seenAllocsHash = new HashMap();
064:
065: if (logger.isDebugEnabled())
066: logger.debug("UTILAllocationCallback " + this
067: + " (listener = " + getClassName() + ") entered.");
068:
069: Enumeration changedallocs = mySub.getChangedList();
070:
071: int i = 0;
072: while (changedallocs.hasMoreElements()) {
073: i++;
074: Allocation alloc = (Allocation) changedallocs.nextElement();
075: if (seenAllocsHash.get(alloc) == null) {
076: reactToChangedAlloc(alloc);
077: seenAllocsHash.put(alloc, alloc);
078: } else if (logger.isDebugEnabled())
079: logger.debug("UTILAllocationCallback : "
080: + "Duplicate changed alloc for task "
081: + alloc.getTask().getUID() + " ignored.");
082: }
083:
084: seenAllocsHash = new HashMap();
085:
086: int j = 0;
087: Enumeration removedallocs;
088: if ((removedallocs = mySub.getRemovedList()).hasMoreElements()) {
089: while (removedallocs.hasMoreElements()) {
090: j++;
091: Allocation alloc = (Allocation) removedallocs
092: .nextElement();
093: if (seenAllocsHash.get(alloc) == null) {
094: ((UTILAllocationListener) myListener)
095: .handleRemovedAlloc(alloc);
096: seenAllocsHash.put(alloc, alloc);
097: } else if (logger.isDebugEnabled())
098: logger.debug("UTILAllocationCallback : "
099: + "Duplicate removed alloc for task "
100: + alloc.getTask().getUID() + " ignored.");
101: }
102: }
103:
104: if (logger.isDebugEnabled()) {
105: if (i > 0 || j > 0)
106: logger.debug("UTILAllocationCallback " + this
107: + " (listener = " + getClassName() + " had "
108: + i + " changed and " + j + " removed allocs");
109:
110: if (mySub.getAddedList().hasMoreElements())
111: logger
112: .debug("UTILAllocationCallback : "
113: + "Allocations were added (ignored by callback).");
114:
115: logger.debug("UTILAllocationCallback " + this
116: + " (listener = " + getClassName() + ") exited.");
117: }
118: }
119:
120: protected String getClassName() {
121: String classname = myListener.getClass().getName();
122: int index = classname.lastIndexOf(".");
123: classname = classname.substring(index + 1, classname.length());
124: return classname;
125: }
126:
127: /**
128: * Defines protocol for dealing with Allocations as they change over time.
129: *
130: * Allocator plugins have two shots at dealing with failed allocations:
131: * 1) immediately, as they happen -- hook here is handleRescindedAlloc
132: * Here the plugin can realloc immediately upon failure.
133: * 2) the next cycle -- when the allocation is removed, the task for that
134: * allocation is now as it was initially, and so ready to allocate.
135: * Perhaps now the plugin can group it with other tasks and allocate
136: * differently.
137: * NOTE : This option can result in infinite loops :
138: * if the plugin doesn't do anything different the second time, the
139: * allocation will fail again, be rescinded, and we're back where we
140: * started.
141: *
142: * @param alloc Allocation to examine
143: */
144: protected void reactToChangedAlloc(Allocation alloc) {
145: UTILAllocationListener listener = (UTILAllocationListener) myListener;
146: if (listener.needToRescind(alloc)) {
147: listener.publishRemovalOfAllocation(alloc);
148: // need to call this instead of allocate(Task) because the cluster
149: // needs to know that the current resource is rejected.
150: listener.handleRescindedAlloc(alloc);
151: } else {
152: listener.updateAllocationResult(alloc);
153: listener.handleSuccessfulAlloc(alloc);
154: }
155: }
156: }
|