View Javadoc

1   /*
2   * The contents of this file are subject to the BT "ZEUS" Open Source 
3   * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 
4   * except in compliance with the Licence. You may obtain a copy of the Licence
5   * from $ZEUS_INSTALL/licence.html or alternatively from
6   * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7   * 
8   * Except as stated in Clause 7 of the Licence, software distributed under the
9   * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 
10  * implied. See the Licence for the specific language governing rights and 
11  * limitations under the Licence.
12  * 
13  * The Original Code is within the package zeus.*.
14  * The Initial Developer of the Original Code is British Telecommunications
15  * public limited company, whose registered office is at 81 Newgate Street, 
16  * London, EC1A 7AJ, England. Portions created by British Telecommunications 
17  * public limited company are Copyright 1996-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  
23  
24  /*
25   * @(#)ExecutionMonitor.java 1.00
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     // meaningless init  to allow rearch
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           // continually update Plan Table
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             //1.3 deadlock preventer 
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 }