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.planning.ldm.trigger;
028:
029: import java.util.Enumeration;
030:
031: import org.cougaar.core.agent.service.alarm.Alarm;
032: import org.cougaar.core.blackboard.IncrementalSubscription;
033: import org.cougaar.core.blackboard.Subscription;
034: import org.cougaar.planning.plugin.legacy.Assessor;
035: import org.cougaar.planning.plugin.legacy.PluginDelegate;
036: import org.cougaar.planning.plugin.legacy.SimplifiedFatPlugin;
037: import org.cougaar.util.UnaryPredicate;
038:
039: /**
040: * This plugin manages triggers that have been created in a given
041: * agent. It sets up a subscription for all policies, and
042: * subscribes to them. It then generates subscriptions for
043: * predicate-based Monitors and sets up timers for time-based
044: * Monitors. When the execute method is called, it Executes any
045: * trigger that is ready to run.
046: **/
047: public class TriggerManagerPlugin extends SimplifiedFatPlugin implements
048: Assessor {
049:
050: /** Will never wait less than this many msecs for time-based alarms. **/
051: private static long minWaitTime = 1000L;
052:
053: private static int verbosity = 0;
054: static {
055: verbosity = Integer.getInteger("org.cougaar.trigger.verbosity",
056: 0).intValue();
057: minWaitTime = Long
058: .getLong("org.cougaar.trigger.minWait", 1000L)
059: .longValue();
060: }
061:
062: private IncrementalSubscription triggerSub;
063: private Alarm alarm = null;
064:
065: public void setupSubscriptions() {
066: getBlackboardService().setShouldBePersisted(false);
067: // Subscribe to all triggers, to maintain list
068: triggerSub = (IncrementalSubscription) subscribe(triggerPred);
069: }
070:
071: public void execute() {
072: // Check if the trigger subscription has fired
073: if (triggerSub.hasChanged()) {
074: // initialize any new triggers
075: Enumeration newtriggers = triggerSub.getAddedList();
076: while (newtriggers.hasMoreElements()) {
077: Trigger anewtrigger = (Trigger) newtriggers
078: .nextElement();
079: TriggerMonitor newmonitor = anewtrigger.getMonitor();
080:
081: // If its a TriggerPredicateBasedMonitor, establish its subscription
082: if (newmonitor instanceof TriggerPredicateBasedMonitor) {
083: TriggerPredicateBasedMonitor mon = (TriggerPredicateBasedMonitor) newmonitor;
084: UnaryPredicate anewpred = mon.getPredicate();
085: IncrementalSubscription anewsub = (IncrementalSubscription) subscribe(anewpred);
086: mon.EstablishSubscription(anewsub);
087: }
088: if (verbosity > 1)
089: System.err.println("Added trigger " + anewtrigger
090: + " at " + getMessageAddress());
091: }
092:
093: Enumeration removedtriggers = triggerSub.getRemovedList();
094: while (removedtriggers.hasMoreElements()) {
095: Trigger rtrigger = (Trigger) removedtriggers
096: .nextElement();
097: TriggerMonitor rmonitor = rtrigger.getMonitor();
098: if (rmonitor instanceof TriggerPredicateBasedMonitor) {
099: Subscription unsub = ((TriggerPredicateBasedMonitor) rmonitor)
100: .getSubscription();
101: unsubscribe(unsub);
102: if (verbosity > 1)
103: System.err
104: .println("TriggerManager cleaning up "
105: + rtrigger);
106: }
107: }
108: }
109:
110: // run all that need running
111: long waittime = runTriggers();
112:
113: if (waittime < 0) {
114: // nothing needs wake service.
115: if (alarm != null) {
116: alarm.cancel(); // cancel the outstanding alarm
117: alarm = null;
118: }
119: } else {
120: if (waittime < minWaitTime)
121: waittime = minWaitTime;
122: if (alarm != null && !alarm.hasExpired()) { // have an alarm still waiting?
123: if (verbosity > 1)
124: System.err.println("TriggerManager Cancelling "
125: + alarm);
126: alarm.cancel(); // cancel it
127: }
128:
129: if (verbosity > 1)
130: System.err.println("TriggerManager sleeping for "
131: + waittime);
132: alarm = wakeAfterRealTime(waittime);
133: }
134: }
135:
136: /** check all likely triggers, running those that are ready.
137: * returns the next alarm interval to wait for time-based triggers.
138: * @return msec to wait for time-based triggers or -1 if there are none.
139: * Any time-based triggers which should already have expired will be reset to 0.
140: */
141: private long runTriggers() {
142: PluginDelegate delegate = getDelegate();
143: long minwait = Long.MAX_VALUE;
144: boolean anywait = false;
145:
146: for (Enumeration rlit = triggers(); rlit.hasMoreElements();) {
147: Trigger trig = (Trigger) rlit.nextElement();
148:
149: if (trig.ReadyToRun(delegate)) {
150: if (verbosity > 1)
151: System.err
152: .println("TriggerManager Running " + trig);
153: trig.Execute(delegate);
154: }
155:
156: // check times - we do this in the loop to prevent consuming all
157: // cpu time servicing short alarms.
158: TriggerMonitor mon = trig.getMonitor();
159: if (mon instanceof TriggerTimeBasedMonitor) {
160: TriggerTimeBasedMonitor tmon = (TriggerTimeBasedMonitor) mon;
161: long left = tmon.getRemainingTime();
162: if (verbosity > 1)
163: System.err.println("Trigger " + trig + " has "
164: + left + "msec left");
165: if (left < 0)
166: left = 0;
167: if (left < minwait)
168: minwait = left;
169: anywait = true;
170: }
171: }
172: return anywait ? minwait : -1;
173: }
174:
175: private Enumeration triggers() {
176: return triggerSub.elements();
177: }
178:
179: private static UnaryPredicate triggerPred = new UnaryPredicate() {
180: public boolean execute(Object o) {
181: return (o instanceof Trigger);
182: }
183: };
184:
185: }
|