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  package zeus.actors.rtn;
25  
26  import java.util.*;
27  
28  
29  import zeus.util.*;
30  import zeus.concepts.*;
31  import zeus.actors.*;
32  import zeus.actors.event.*;
33  import zeus.actors.graphs.*;
34  import zeus.actors.rtn.util.*;
35  
36  class NodeWaitTable extends Hashtable implements Runnable {
37     protected zeus.util.Queue queue = null;
38     protected Engine engine;
39     protected Vector dont_add_list = new Vector();
40     protected long sleep_until = Long.MAX_VALUE;
41  
42     public NodeWaitTable(Engine engine, Queue queue) {
43        this.engine = engine;
44        this.queue = queue;
45     }
46  
47  
48     public void run() {
49       Thread.currentThread().setName ("NodeWaitTable"); 
50        for(;;) {
51  	 try {
52              Core.DEBUG(3,"Before Wakeup\n" + this);
53              wakeup();
54              long duration = sleep_period();
55              Core.DEBUG(3,engine.getAgentContext().whoami() +
56  	                 " sleeping for " + duration);
57              Core.DEBUG(3,"After Wakeup\n" + this);
58              synchronized(this) {
59                 wait(duration);
60              }
61           }
62           catch(InterruptedException e) {
63           }
64        }
65     }
66  
67     protected synchronized long sleep_period() {
68        long timeout = Long.MAX_VALUE;
69        Node node;
70        Vector list;
71        double t;
72  
73        // compute timeout
74        if ( !this.isEmpty() ) {
75           t = Double.MAX_VALUE; 
76           Enumeration enum = this.elements();
77           while( enum.hasMoreElements() ) {
78              list = (Vector)enum.nextElement();
79              for(int i = 0; i < list.size(); i++ ) {
80                 node = (Node)list.elementAt(i);
81                 t = Math.min(t,node.getTimeout());
82              }
83           }
84           t = t - engine.getAgentContext().now();
85           timeout = (long)(t*engine.getAgentContext().getClockStep());
86        }
87        timeout = Math.max(timeout,0);
88  
89        sleep_until = (timeout == Long.MAX_VALUE) ? timeout :
90                     System.currentTimeMillis() + timeout;
91        return timeout;
92     }
93  
94     public synchronized void wakeup() {
95        Node node;
96        Vector list;
97        String key;
98  
99        double now = engine.getAgentContext().now();
100       Core.DEBUG (4,"wakeup>> now == " + String.valueOf(now) ); 
101       
102       
103       Enumeration enum = this.keys();
104       while( enum.hasMoreElements() ) {
105         Core.DEBUG(4, "in while - keys >= !"); 
106          key = (String)enum.nextElement();
107          list = (Vector)this.get(key);
108          for(int i = 0; i < list.size(); i++ ) {
109             node = (Node)list.elementAt(i);
110             Core.DEBUG (4,"Timeout == " + node.getTimeout()); 
111             if ( now >= node.getTimeout() ) {
112                queue.enqueue(node);
113                list.removeElementAt(i);
114             }
115          }
116          if ( list.isEmpty() )
117             this.remove(key);
118       }
119       notifyAll();
120    }
121 
122    public synchronized void wakeup(String key) {
123       Node node;
124       Vector list;
125 
126       list = (Vector)this.remove(key);
127 
128       if ( list == null ) {
129          /*
130           special case: the results have been returned before
131           we can store the query
132          */
133          dont_add_list.addElement(key);
134          return;
135       }
136 
137       for(int i = 0; i < list.size(); i++ ) {
138          node = (Node)list.elementAt(i);
139          queue.enqueue(node);
140       }
141       list = null; // GC
142       notify();
143    }
144 
145    public synchronized void add(Node node) {
146       String key = node.getMsgWaitKey();
147       Core.DEBUG(3,"Adding wait_node: " + node.getDescription() + "[" + key + "]");
148 
149       // check special case first;
150       if ( dont_add_list.contains(key) ) {
151          dont_add_list.removeElement(key);
152          queue.enqueue(node);
153          return;
154       }
155 
156       Vector list = (Vector)this.get(key);
157       if ( list == null ) {
158          list = new Vector();
159          this.put(key,list);
160       }
161       list.addElement(node);
162 
163       double t = node.getTimeout();
164       t = t - engine.getAgentContext().now();
165       long duration = (long)(t*engine.getAgentContext().getClockStep());
166       if ( System.currentTimeMillis() + duration < sleep_until ) {
167          Core.DEBUG(3,"Will notify... ");
168          notify();
169       }
170       else
171          Core.DEBUG(3,"No notify: sleeping for " + (sleep_until - System.currentTimeMillis()));
172 
173    }
174 
175    public String toString() {
176       double now = engine.getAgentContext().now();
177       String out = "NodeWaitTable: now = " + Misc.decimalPlaces(now,4) + "\n";
178 
179       synchronized(this) {
180          Enumeration enum = this.keys();
181          Vector List;
182          Node node;
183          String key;
184          while( enum.hasMoreElements() ) {
185             key = (String)enum.nextElement();
186             List = (Vector)this.get(key);
187             out += "\t" + key + "\n";
188             for(int i = 0; i < List.size(); i++) {
189                node = (Node)List.elementAt(i);
190                out += "\t\t" + node +
191 	              "\t" + Misc.decimalPlaces(node.getTimeout(),4) + "\n";
192             }
193          }
194       }
195       return out;
196    }
197 }