1 # ascp.tcl --
2 #
3 # An implementation of ASCP v3.0 for Active Service Framework.
4 #
5 # Copyright (c) 1998-2002 The Regents of the University of California.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
10 #
11 # A. Redistributions of source code must retain the above copyright notice,
12 # this list of conditions and the following disclaimer.
13 # B. Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 # C. Neither the names of the copyright holders nor the names of its
17 # contributors may be used to endorse or promote products derived from this
18 # software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
24 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #
31
32 import AnnounceListenManager
33 import ASCPPacket
34
35 #----------------------------------------------------------------------
36 # Class:
37 # ASCP
38 # Description:
39 # Base class for active service control protocol v3 in active
40 # service framework.
41 # Members:
42 # lastann_ --
43 # An array indexed by agent spec, that contains time the last
44 # announcement was made to the corresponding agent. Time are
45 # stored as absolute time (gettimeofday) and as ascii time (
46 # clock format).
47 # avgdelta_ --
48 # An array indexed by agent spec, that contains average time
49 # between announcement from the corresponding agent.
50 #----------------------------------------------------------------------
51 Class ASCP -superclass AnnounceListenManager
52
53 #----------------------------------------------------------------------
54 # Method:
55 # ASCP init
56 # Description:
57 # Initialize various members and timer.
58 # Arguments:
59 # session -- ip address and port number of the target session.
60 # bw -- bandwidth limit of the protocol.
61 #----------------------------------------------------------------------
62 ASCP instproc init { session bw } {
63 set mtu 1024
64
65 $self next $session $mtu
66
67 set o [$self options]
68 $o add_default startupWait 60
69
70 $self instvar as_bw_ as_spec_
71 set as_bw_ $bw
72 set as_spec_ $session
73
74 $self instvar timer_list_
75 set timer_list_ {}
76
77 $self set packet_ [new ASCPPacket]
78 }
79
80
81 #----------------------------------------------------------------------
82 # Method:
83 # ASCP destroy
84 # Description:
85 # Cleanup "after" callback.
86 #----------------------------------------------------------------------
87 ASCP instproc destroy {} {
88 $self instvar agents_
89 foreach id [array names agents_] {
90 $self del_agent $id
91 }
92 $self bye
93 $self next
94 }
95
96
97 #----------------------------------------------------------------------
98 # Method:
99 # ASCP version
100 # Description:
101 # Return the version string of the current Active Service Framework.
102 #----------------------------------------------------------------------
103 ASCP proc version {} {
104 return 3.0
105 }
106
107
108 #----------------------------------------------------------------------
109 # Method:
110 # ASCP version
111 # Description:
112 # Return the version string of the current Active Service Framework.
113 #----------------------------------------------------------------------
114 ASCP instproc bandwidth {} {
115 return [$self set as_bw_]
116 }
117
118 #----------------------------------------------------------------------
119 # Method:
120 # ASCP send_announcement
121 # Description:
122 # Construct an announcement, and send it.
123 #----------------------------------------------------------------------
124 ASCP public send_announcement {} {
125 return
126 }
127
128
129 #----------------------------------------------------------------------
130 # Method:
131 # ASCP bye
132 # Description:
133 # Construct a BYE announcement and announce it.
134 #----------------------------------------------------------------------
135 ASCP instproc bye {} {
136 set packet [new ASCPPacket]
137 $packet agent_type [$self agent_type]
138 $packet agent_type [$self agent_id]
139 $packet operation "bye"
140
141 $self announce [$packet to_string]
142 delete $packet
143 }
144
145
146 #----------------------------------------------------------------------
147 # Method:
148 # ASCP agent_id
149 # Description:
150 # Return a string that represent an instance of the current agent.
151 #----------------------------------------------------------------------
152 ASCP public agent_id {} {
153 return "[pid]@[info hostname]:[$self control_port]"
154 }
155
156
157 #----------------------------------------------------------------------
158 # Method:
159 # ASCP agent_type
160 # Description:
161 # Subclass should overwrite this to return agent type.
162 #----------------------------------------------------------------------
163 ASCP public agent_type {} {
164 return ""
165 }
166
167 #----------------------------------------------------------------------
168 # Method:
169 # ASCP process_packet
170 # Description:
171 # Agent specific handling of message. Subclass should overwrite
172 # this. NOTE: This is responsible for freeing $packet.
173 # Arguments:
174 # addr --
175 # Address where this packet comes from.
176 # packet --
177 # The ASCP packet received.
178 #----------------------------------------------------------------------
179 ASCP public process_packet {addr packet} {
180 # delete $packet
181 return ""
182 }
183
184 #----------------------------------------------------------------------
185 # Method:
186 # ASCP args
187 # Description:
188 # Subclass should overwrite this to return agent specific data.
189 #----------------------------------------------------------------------
190 ASCP public args {} {
191 return ""
192 }
193
194
195 #----------------------------------------------------------------------
196 # Method:
197 # ASCP ssg_port
198 # Description:
199 # Subclass should overwrite this to return port number to a soft state
200 # gateway.
201 #----------------------------------------------------------------------
202 ASCP public ssg_port {} {
203 return "-"
204 }
205
206
207 #----------------------------------------------------------------------
208 # Method:
209 # ASCP service_location
210 # Description:
211 # Subclass should overwrite this to return the service location.
212 #----------------------------------------------------------------------
213 ASCP instproc service_location {} {
214 return "-"
215 }
216
217
218 #----------------------------------------------------------------------
219 # Method:
220 # ASCP service_type
221 # Description:
222 # Subclass should overwrite this to return the service type.
223 #----------------------------------------------------------------------
224 ASCP instproc service_type {} {
225 return "-"
226 }
227
228
229 #----------------------------------------------------------------------
230 # Method:
231 # ASCP service_instance
232 # Description:
233 # Subclass should overwrite this to return the service type.
234 #----------------------------------------------------------------------
235 ASCP instproc service_instance {} {
236 return "-"
237 }
238
239
240
241 #----------------------------------------------------------------------
242 # Method:
243 # ASCP recv_announcement
244 # Description:
245 # Called when an announcement is received. The announcement is parsed
246 # and special cases are handled (DEATH, BYE, wrong version). The method
247 # "process_packet {}" is then called to process other general messages.
248 # Arguments:
249 # addr -- The address where this announcement came from.
250 # port -- The port number where this announcement came from.
251 # data -- The data contained in this announcement.
252 # size -- The length of data in bytes.
253 #----------------------------------------------------------------------
254 ASCP instproc recv_announcement { addr port data size } {
255 $self instvar lastann_ sdp_ agents_ packet_
256
257 # This HAS TO go. We should create one ASCPPacket object, and reuse
258 # it over and over again.
259 set packet $packet_
260
261 set result [$packet from_string $data]
262 if {$result == "invalid version"} {
263 $self error "WARNING: received non-ASCP v[$class version] announcement from $addr."
264 return
265 }
266
267 set agent_type [$packet agent_type]
268 set agent_id [$packet agent_id]
269 set op [$packet operation]
270
271 $self timers add_sample $size
272
273 switch -exact -- $op {
274 "kill" {
275 set arg [$packet args]
276 if { $arg == [$self agent_type] } {
277 $self error "Received death packet from $agent_id at $addr - exiting."
278 $self bye
279 exit 0
280 }
281 $self process_packet $addr $packet
282 }
283 "bye" {
284 $self del_agent $agent_id
285 $self process_packet $addr $packet
286 }
287 default {
288 set srv_name [$packet service_type]
289 set srv_inst [$packet service_instance]
290 set ad [$packet args]
291
292 if {![info exists agents_($agent_id)]} {
293 # new agent
294 $self timers add_src
295 set agents_($agent_id) [new MashSoftState/Adaptive \
296 $addr 10000 "$self del_agent $agent_id" 8]
297 #MashLog info "add agent $agent_id"
298 } else {
299 $agents_($agent_id) refresh
300 #MashLog info "refresh agent $agent_id"
301 }
302 $self process_packet $addr $packet
303 }
304 }
305 }
306
307
308 #----------------------------------------------------------------------
309 # Method:
310 # ASCP del_agent
311 # Description:
312 # Assume that the agent specified by $agent_id is dead. Clean up all
313 # states corresponding to that agent.
314 # Arguments:
315 # agent_id --
316 # Specification to the agent to be deleted.
317 #----------------------------------------------------------------------
318 ASCP instproc del_agent { agent_id } {
319 $self instvar agents_
320 if ![info exists agents_($agent_id)] {
321 # puts "hm: agent $agent_id doesn't exist!"
322 return
323 }
324 # MashLog info "delete agent $agent_id"
325
326 delete $agents_($agent_id)
327 unset agents_($agent_id)
328 $self timers del_src
329 }
330
331
332 #----------------------------------------------------------------------
333 # Method:
334 # ASCP error
335 # Description:
336 # Print an error message. Subclass may want to overwrite this so
337 # that it is printed to somewhere else, for e.g. a log file.
338 # Arguments:
339 # msg --
340 # The error message
341 #----------------------------------------------------------------------
342 ASCP instproc error {msg} {
343 puts stderr $msg
344 }
345
346
347 ASCP instproc as_args {} {
348 $self instvar as_spec_ as_bw_
349 return "-as_spec $as_spec_ -as_bw $as_bw_"
350 }
351
352 ASCP instproc register {addr packet} {
353 # error "register should not be called"
354 }
355 ASCP instproc unregister {addr packet} {
356 # error "unregister should not be called"
357 }
358 # Default control port for rpc
359 # Subclass should override this to use different port.
360 ASCP instproc control_port { } {
361 return 9502
362 }
363 ASCP instproc add_timer {timer} {
364 $self instvar timer_list_
365 if {[lsearch $timer_list_ $timer] == -1} {
366 lappend timer_list_ $timer
367 }
368 }
369 ASCP instproc del_timer {timer} {
370 $self instvar timer_list_
371 set x [lsearch $timer_list_ $timer]
372 if {$x != -1} {
373 set timer_list_ [lreplace $timer_list_ $x $x]
374 }
375 }
376 ASCP instproc timers {op args} {
377 $self instvar timer_list_
378 foreach t $timer_list_ {
379 if {[$t has_method $op]} {
380 eval $t $op $args
381 }
382 }
383 }
384 # vim:ts=8:sw=4:expandtab
385
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.