~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/tcl/as/al-as.tcl

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 # al-as.tcl --
  2 #
  3 #       Base class for Announce/Listen Manager implementation in
  4 #       Active Service Framework.    
  5 #
  6 # Copyright (c) 1998-2002 The Regents of the University of California.
  7 # All rights reserved.
  8 #
  9 # Redistribution and use in source and binary forms, with or without
 10 # modification, are permitted provided that the following conditions are met:
 11 #
 12 # A. Redistributions of source code must retain the above copyright notice,
 13 #    this list of conditions and the following disclaimer.
 14 # B. Redistributions in binary form must reproduce the above copyright notice,
 15 #    this list of conditions and the following disclaimer in the documentation
 16 #    and/or other materials provided with the distribution.
 17 # C. Neither the names of the copyright holders nor the names of its
 18 #    contributors may be used to endorse or promote products derived from this
 19 #    software without specific prior written permission.
 20 #
 21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 22 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 23 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 24 # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 25 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 26 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 27 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 29 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 31 #
 32 # @(#) $Header: /usr/mash/src/repository/mash/mash-1/tcl/as/al-as.tcl,v 1.11 2002/02/26 20:45:11 weitsang Exp $
 33 
 34 
 35 import AnnounceListenManager Timer/Adaptive/ConstBW
 36 
 37 #----------------------------------------------------------------------
 38 # Class:
 39 #   AnnounceListenManager/AS
 40 # Description:
 41 #   Base class for AnnounceListenManager in Active Service Framework.
 42 # Members:
 43 #   atype_ -- 
 44 #       Type of this agent
 45 #   agentbytype_ --
 46 #       An array of list of agents, indexed by type (srv, client, hm).
 47 #   aliveid_ --
 48 #       ID to the "after" callback check_alive{}.
 49 #   lastann_ --
 50 #       An array indexed by agent spec, that contains time the last 
 51 #       announcement was made to the corresponding agent.  Time are
 52 #       stored as absolute time (gettimeofday) and as ascii time (
 53 #       clock format).
 54 #   avgdelta_ --
 55 #       An array indexed by agent spec, that contains average time 
 56 #       between announcement from the corresponding agent.
 57 #----------------------------------------------------------------------
 58 Class AnnounceListenManager/AS -superclass AnnounceListenManager
 59 
 60 
 61 #----------------------------------------------------------------------
 62 # Method:
 63 #   AnnounceListenManager/AS init
 64 # Description:
 65 #   Initialize various members and timer.
 66 #----------------------------------------------------------------------
 67 AnnounceListenManager/AS instproc init { netspec bw atype } {
 68         #
 69         # FIXME Seed the random number generator (0 means use
 70         # a heurstic to derive a seed from system parameters)
 71         # This belongs elsewhere.
 72         #
 73         random 0
 74         $self next $netspec 1024
 75         $self instvar atype_
 76         set atype_ $atype
 77 
 78         $self instvar agentbytype_
 79         set agentbytype_(srv) ""
 80         set agentbytype_(client) ""
 81         set agentbytype_(hm) ""
 82 
 83         # FIXME
 84         set t [new Timer/Adaptive/ConstBW $bw 3000]
 85         $t randomize
 86         $self timer $t
 87 
 88         set o [$self options]
 89         $o add_default startupWait 60
 90         $self instvar aliveid_
 91         set aliveid_ [after [expr [$self get_option startupWait]*1000] "$self check_alive 1"]
 92 }
 93 
 94 
 95 #----------------------------------------------------------------------
 96 # Method:
 97 #   AnnounceListenManager/AS version
 98 # Description:
 99 #   Return the version string of the current Active Service Framework.
100 #----------------------------------------------------------------------
101 AnnounceListenManager/AS proc version {} {
102         return 2.0
103 }
104 
105 
106 #----------------------------------------------------------------------
107 # Method:
108 #   AnnounceListenManager/AS send_announcement
109 # Description:
110 #   Construct an announcement, and send it.  Since this method is called
111 #   periodically, we take this chance to check for liveness in other 
112 #   agent by calling "check_alive 0" before exiting.
113 #----------------------------------------------------------------------
114 AnnounceListenManager/AS public send_announcement {} {
115         $self instvar atype_
116 
117         set o "ASCP v[$class version]\n"
118         append o "$atype_\n"
119         append o "[$self agent_instance]\n"
120         append o "[$self service_name]\n"
121         append o "[$self service_location]\n"
122         append o "[$self service_instance]\n"
123         append o "[$self ssg_port]\n"
124         append o "[$self agent_data]\n"
125 
126         $self announce $o
127 
128         $self check_alive 0
129 }
130 
131 
132 #----------------------------------------------------------------------
133 # Method:
134 #   AnnounceListenManager/AS announce_death
135 # Description:
136 #   Construct a BYE announcement and announce it.
137 #----------------------------------------------------------------------
138 AnnounceListenManager/AS instproc announce_death {} {
139         $self instvar id1_ id2_ atype_
140 
141         set o "ASCP v[AnnounceListenManager/AS version]"
142         append o "$atype_\n"
143         append o "[$self agent_instance]\n"
144         append o "bye\n"
145         append o "-\n"
146         append o "-\n"
147         append o "-\n"
148 
149         $self announce $o
150 }
151 
152 
153 #----------------------------------------------------------------------
154 # Method:
155 #   AnnounceListenManager/AS agent_instance
156 # Description:
157 #   Return a string that represent an instance of the current agent.
158 #----------------------------------------------------------------------
159 AnnounceListenManager/AS public agent_instance {} {
160         return "[pid]@[lookup_host_name [localaddr]]"
161 }
162 
163 
164 #----------------------------------------------------------------------
165 # Method:
166 #   AnnounceListenManager/AS agent_data
167 # Description:
168 #   Subclass should overwrite this to return agent specific data.
169 #----------------------------------------------------------------------
170 AnnounceListenManager/AS public agent_data {} {
171         return ""
172 }
173 
174 
175 #----------------------------------------------------------------------
176 # Method:
177 #   AnnounceListenManager/AS ssg_port
178 # Description:
179 #   Subclass should overwrite this to return port number to a soft state
180 #   gateway.
181 #----------------------------------------------------------------------
182 AnnounceListenManager/AS public ssg_port {} {
183         return "-"
184 }
185 
186 
187 #----------------------------------------------------------------------
188 # Method:
189 #   AnnounceListenManager/AS service_location
190 # Description:
191 #   Subclass should overwrite this to return the service location.
192 #----------------------------------------------------------------------
193 AnnounceListenManager/AS instproc service_location {} {
194         return "-"
195 }
196 
197 
198 #----------------------------------------------------------------------
199 # Method:
200 #   AnnounceListenManager/AS destroy
201 # Description:
202 #   Cleanup "after" callback.
203 #----------------------------------------------------------------------
204 AnnounceListenManager/AS instproc destroy {} {
205         $self instvar aliveid_
206         after cancel $aliveid_
207 
208         $self next
209 }
210 
211 
212 #----------------------------------------------------------------------
213 # Method:
214 #   AnnounceListenManager/AS recv_announcement
215 # Description:
216 #   Called when an announcement is received.  The announcement is parsed
217 #   and special cases are handled (DEATH, BYE, wrong version).  The method 
218 #   "recv_msg {}" is then called to process other general messages.
219 # Arguments:
220 #   addr -- The address where this announcement came from.
221 #   port -- The port number where this announcement came from.
222 #   data -- The data contained in this announcement.
223 #   size -- The length of data in bytes.
224 #----------------------------------------------------------------------
225 AnnounceListenManager/AS instproc recv_announcement { addr port data size } {
226         $self instvar lastann_ sdp_ agentbytype_ agenttab_ atype_
227         set t [$self get_timer]
228         $t sample_size $size
229 
230         set o [split $data \n]
231         if { [lindex $o 0] != "ASCP v[$class version]" } {
232                 # FIXME
233                 set msg "$self ($class): received non-ASCP v[$class version] announcement from $addr."
234                 if { $atype_ == "hm" } {
235                         $self instvar agent_
236                         $agent_ log $msg
237                 } else {
238                         puts stderr $msg
239                 }
240 
241                 return
242         }
243         set atype [lindex $o 1]
244         set aspec [lindex $o 2]
245         set srv_name [lindex $o 3]
246         set srv_loc [lindex $o 4]
247         set srv_inst [lindex $o 5]
248         set ssg_port [lindex $o 6]
249         set ad [join [lrange $o 7 end] \n]
250 
251         # Special case death packet.
252         if { $srv_name == "DEATH" } {
253                 set msg "Received death packet from $aspec at $addr - exiting."
254                 if { $srv_loc == $atype_ } {
255                         if { $atype_ == "hm" } {
256                                 $self instvar agent_
257                                 $agent_ log $msg
258                         } else {
259                                 puts stderr $msg
260                         }
261                         $self announce_death
262                         exit 0
263                 }
264                 $self recv_msg $atype $aspec $addr DEATH $srv_loc \
265                         $srv_inst $ssg_port "$ad"
266                 return
267         }
268         # Synchronous bye
269         if { $srv_name == "bye" } {
270                 $self delete_agent $aspec
271                 return
272         }
273 
274         if ![info exists agenttab_($aspec)] {
275                 # new agent
276                 $self instvar avgdelta_
277                 $self register $atype $aspec $addr $srv_name $srv_inst "$ad"
278                 $t incr_nsrcs
279                 set timeout [$self get_option startupWait]
280                 set avgdelta_($aspec) [expr $timeout / 8]
281                 lappend agentbytype_($atype) $aspec
282         } else {
283                 set now [gettimeofday]
284                 set delta [expr $now - $lastann_($aspec,abs)]
285                 $self instvar avgdelta_
286                 set avgdelta_($aspec) \
287                                 [expr 0.875*$avgdelta_($aspec)+0.125*$delta]
288 
289         }
290         set agenttab_($aspec) "$addr {$ad} $atype $srv_name $srv_inst"
291         set lastann_($aspec,abs) [gettimeofday]
292         set lastann_($aspec,ascii) [gettimeofday ascii]
293         $self recv_msg $atype $aspec $addr $srv_name $srv_loc $srv_inst \
294                         $ssg_port "$ad"
295 }
296 
297 
298 #----------------------------------------------------------------------
299 # Method:
300 #   AnnounceListenManager/AS check_alive
301 # Description:
302 #   Go through all agents and delete agents that hasn't been announcing
303 #   for a while.  
304 # Arguments:
305 #   timer -- 
306 #       Specify if this is a one time call (timer == 0), or we are gonna
307 #       doing this periodically (timer == 1)
308 #----------------------------------------------------------------------
309 AnnounceListenManager/AS instproc check_alive { timer } {
310         $self instvar lastann_ agenttab_ avgdelta_
311 
312         set now [gettimeofday]
313         set aspecs [array names agenttab_]
314         foreach aspec $aspecs {
315                 set lastann $lastann_($aspec,abs)
316                 set avgdelta $avgdelta_($aspec)
317 #puts "         set avgdelta $avgdelta_($aspec)"
318 #puts "         set delta [expr $now - $lastann]"
319                 set delta [expr $now - $lastann]
320                 if { $delta > 8 * $avgdelta } {
321                         $self delete_agent $aspec
322                 }
323         }
324         $self instvar aliveid_
325         if { $timer } {
326                 set t [expr [$self get_option startupWait]*1000]
327                 set aliveid_ [after $t "$self check_alive 1"]
328         }
329 }
330 
331 
332 #----------------------------------------------------------------------
333 # Method:
334 #   AnnounceListenManager/AS delete_agent
335 # Description:
336 #   Assume that the agent specified by $aspec is dead.  Clean up all
337 #   states corresponding to that agent.
338 # Arguments:
339 #   aspec -- 
340 #       Specification to the agent to be deleted.
341 #----------------------------------------------------------------------
342 AnnounceListenManager/AS instproc delete_agent { aspec } {
343         $self instvar agentbytype_ agenttab_ lastann_ avgdelta_
344         if ![info exists agenttab_($aspec)] {
345                 # puts "hm: agent $aspec doesn't exist!"
346                 return
347         }
348         set a $agenttab_($aspec)
349 
350         set addr [lindex $a 0]
351         set ad [lindex $a 1]
352         set atype [lindex $a 2]
353         set srv_name [lindex $a 3]
354         set srv_inst [lindex $a 4]
355 
356         unset agenttab_($aspec)
357         unset lastann_($aspec,abs)
358         unset lastann_($aspec,ascii)
359         unset avgdelta_($aspec)
360 
361         set t $agentbytype_($atype)
362         set i [lsearch -exact $t $aspec]
363         set agentbytype_($atype) [lreplace $t $i $i]
364 
365         [$self get_timer] incr_nsrcs -1
366 
367         $self unregister $atype $aspec $addr $srv_name $srv_inst "$ad"
368 }
369 
370 
371 #----------------------------------------------------------------------
372 # Method:
373 #   AnnounceListenManager/AS agenttab
374 # Description:
375 #   Return the agent matching specification $aspec, or return "" if
376 #   no such agent can be found.
377 # Arguments:
378 #   aspec -- 
379 #       Specification to the agent to be retrieve.
380 #----------------------------------------------------------------------
381 AnnounceListenManager/AS instproc agenttab aspec {
382         $self instvar agenttab_
383         if [info exists agenttab_($aspec)] {
384                 return $agenttab_($aspec)
385         }
386         return ""
387 }
388 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.