1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package zeus.actors;
29
30 import java.util.*;
31 import zeus.util.*;
32 import zeus.concepts.*;
33 import zeus.actors.rtn.Engine;
34 import zeus.actors.event.*;
35
36 /***
37 * This component controls the invocation of the domain functions that
38 * implement the agent's task abilities. Domain functions are typically
39 * external program code or legacy systems that implement the methods of the
40 * {@link ZeusTask} interface. A domain function is invoked with the task's
41 * preconditions as its input arguments, and upon completion its declared
42 * effects will be passed back to the agent through this component. <p>
43 *
44 * Another important role of the Execution Monitor is to detect failure during
45 * the scheduled execution of a plan. This can occur for a number of reasons:
46 * <ol>
47 * <li> a resource reserved by an task might have been deleted,
48 * <li> an operator might begin execution but fail to complete for some reason,
49 * <li> an operator might successfully complete execution but return the wrong
50 * or incomplete results, or
51 * <li> some promised resource from another agent might not arrive on time
52 * </ol> <p>
53 * Should any of the above occur, the Execution Monitor will trigger remedial
54 * action, which may involve replanning.
55 */
56
57 public class ExecutionMonitor extends Thread {
58 public static final int TICK = 0;
59 public static final double UPDATE_FRACTION = 0.25;
60
61 private HSet[] eventMonitor = new HSet[1];
62 protected boolean monitoring;
63 protected AgentContext context = null;
64
65
66
67
68 public ExecutionMonitor () {
69 ;
70 }
71
72 public ExecutionMonitor(AgentContext context) {
73 Assert.notNull(context);
74 this.context = context;
75 context.set(this);
76
77 for(int i = 0; i < eventMonitor.length; i++ )
78 eventMonitor[i] = new HSet();
79 this.setName("ExecutionMonitor");
80 this.start();
81 }
82
83 public AgentContext getAgentContext() { return context; }
84 public void stopMonitoring() { monitoring = false; }
85
86 public void run() {
87 double now;
88 long timeout;
89 long incr = context.getClockStep();
90 int prev = (int) context.now();
91
92 monitoring = true;
93 this.setPriority(Thread.NORM_PRIORITY);
94 while( monitoring ) {
95 Planner table = context.Planner();
96
97 now = context.now();
98 timeout = now < prev + 1 && now + UPDATE_FRACTION > prev + 1 ?
99 (long) ((prev+1-now)*incr) :
100 (long) (UPDATE_FRACTION*incr);
101 if ( ((int) now) == prev + 1 ) {
102 prev = (int) now;
103 notifyMonitors(prev,TICK);
104
105 Engine engine = context.getEngine();
106 if ( table != null ) engine.callShuffle();
107 }
108 if ( table != null ) {
109 Engine engine = context.getEngine ();
110 engine.callCheckRecords();}
111 try {
112
113 if (timeout < 100) timeout = 10;
114 sleep(timeout);
115 }
116 catch(InterruptedException e) {
117 e.printStackTrace();
118 }
119 yield();
120 }
121 }
122
123
124 public void addClockMonitor(ClockMonitor monitor, long type) {
125 Assert.notNull(monitor);
126 if ( (type & ClockEvent.TICK_MASK) != 0 )
127 eventMonitor[TICK].add(monitor);
128 }
129
130
131 public void removeClockMonitor(ClockMonitor monitor, long type) {
132 Assert.notNull(monitor);
133 if ( (type & ClockEvent.TICK_MASK) != 0 )
134 eventMonitor[TICK].remove(monitor);
135 }
136
137
138 protected void notifyMonitors(int tick, int event_type) {
139 if ( eventMonitor[event_type].isEmpty() ) return;
140
141 Enumeration enum = eventMonitor[event_type].elements();
142 ClockMonitor monitor;
143 ClockEvent event;
144 switch(event_type) {
145 case TICK:
146 event = new ClockEvent(this,tick,ClockEvent.TICK_MASK);
147 while( enum.hasMoreElements() ) {
148 monitor = (ClockMonitor)enum.nextElement();
149 monitor.clockTickEvent(event);
150 }
151 break;
152 }
153 }
154 }