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

Open Mash Cross Reference
mash/tcl/indiva/ihm/ihm-agent.tcl

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

  1 # ihm-agent.tcl --
  2 #
  3 #   Agent for Indiva Host Manager.  
  4 #
  5 # Copyright (c) 1996-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 # @(#) $Header: /usr/mash/src/repository/mash/mash-1/tcl/indiva/ihm/ihm-agent.tcl,v 1.2 2002/03/13 23:39:51 weitsang Exp $
 32 
 33 import MashSystem
 34 import ServiceCreator ServiceCreator/MeGa
 35 import CoordinationBus MeGa
 36 import ASCP/Manager
 37 import IHMScriptLoader
 38 
 39 #-----------------------------------------------------------------------
 40 # Class: 
 41 #   IHMAgent
 42 #
 43 # Description:
 44 #   Host Manager Agent, part of the AS1 framework
 45 #  
 46 #   Changes from HM : 
 47 #   - chaining of hm not supported.
 48 #   - glunix not supported
 49 #
 50 # Members:
 51 #   uniqid_ --
 52 #     A unique id used to create temporary filename for downloaded
 53 #     servlets. Initialized to 0 and is incremented by 1 everytime
 54 #     a temp file is created.
 55 # 
 56 #   app_ --
 57 #     The HM Application.
 58 #
 59 #   cbchannel_ --
 60 #     Channel ID for coordination bus.
 61 #
 62 #   hmhosts_ --
 63 #     A list of other hosts eligible to run hm.
 64 #-----------------------------------------------------------------------
 65 Class IHMAgent
 66 
 67 IHMAgent instproc init { app } {
 68 
 69     $self next
 70 
 71     $self instvar app_ cbchannel_ ascp_
 72 
 73     $self set cbchannel_ 3
 74     $self set app_ $app
 75     $self set uniqid_ 0
 76 
 77     MashLog info "Start"
 78 
 79     set as_spec [$self get_option as_spec]
 80     set as_bw [$self get_option as_bw]
 81 
 82     $self instvar ascp_
 83     set ascp_ [new ASCP/Manager $as_spec $as_bw]
 84     $ascp_ start
 85 
 86     #if { [$self get_option loadBalance] != "" } {
 87     #    $ascp_ start
 88     #    $self read_hmhosts
 89     #    $self init_load_check
 90     #} elseif { [$self get_option targetNum] != "" } {
 91     #    $ascp_ start
 92     #    $self set trgtnum_ [$self get_option targetNum]
 93 #        $self read_hmhosts
 94 #        IHMAgent instproc timeout {} { $self target_check }
 95 #        $self randomize yes
 96 #        set a [$self get_option checkFactor]
 97 #        $self msched [expr $a * [$self get_option checkInterval]]
 98 #    } else {
 99         # Modified so that hm's always announce, even if there's only 1
100 #
101 #    }
102 }
103 
104 
105 IHMAgent public announce_launch { srv_inst } {
106     $self instvar ascp_
107     MashLog info "announce_launch $srv_inst"
108     $ascp_ announce_launch $srv_inst
109 }
110 
111 
112 #-----------------------------------------------------------------------
113 # Method:
114 #   IHMAgent target_check
115 # Description:
116 #   Checks if the total number of hm meets the desired number.
117 #-----------------------------------------------------------------------
118 IHMAgent instproc target_check {} {
119     $self instvar trgtnum_ ascp_
120     set n [$ascp_ get_num_of_hms]
121     # count ourselves
122     incr n
123 
124     set r [expr [random]/double(0x7fffffff)]
125     if { $n < $trgtnum_ } {
126         # set p [expr double($trgtnum_ - $n) / $trgtnum_]
127         set p [expr double($trgtnum_ - $n) / $n]
128         # p could be > 1, but this code is correct since we want
129         # p = min(1, N/n - 1)
130         if { $r < $p } {
131             $self spawn
132         }
133     } elseif { $n > $trgtnum_ } {
134         set p [expr double($n - $trgtnum_) / $n]
135         if { $r < $p } {
136             $self doexit
137             return
138         }
139     }
140     # want the max here probably...
141     #   set t [$ascp_ get_timer]
142     #   $self msched [$t set interval_]
143     $self msched [$self get_option checkInterval]
144 }
145 
146 
147 #-----------------------------------------------------------------------
148 # Method:
149 #   IHMAgent doexit
150 # Description:
151 #   Tell everyone we are quiting, and then quit.
152 #-----------------------------------------------------------------------
153 IHMAgent instproc doexit {} {
154     $self instvar ascp_
155     $ascp_ announce_death
156     exit 0
157 }
158 
159 
160 #-----------------------------------------------------------------------
161 # Method:
162 #   IHMAgent destroy
163 # Description:
164 #-----------------------------------------------------------------------
165 IHMAgent instproc destroy {} {
166     $self next
167 }
168 
169 
170 #-----------------------------------------------------------------------
171 # Method:
172 #   IHMAgent unregister
173 # Description:
174 #   Remove a handler.
175 # Arguments:
176 #   aspec -- "<pid>@<hostname>", this uniquely identifies a handler.
177 #   msg -- Ununsed junk.
178 #-----------------------------------------------------------------------
179 IHMAgent instproc unregister { aspec msg } {
180     $self instvar handlers_
181     if ![info exists handlers_] {
182         return
183     }
184     set i 0
185     # FIXME
186     set pid [lindex [split $aspec @] 0]
187     foreach h $handlers_ {
188         if { [$h set pid_] == $pid } {
189             delete $h
190             set handlers_ [lreplace $handlers_ $i $i]
191             return
192         }
193         incr i
194     }
195 }
196 
197 #
198 # Exponential launch timer
199 # F(x) = 1/(exp(lambda) - 1) * (exp(lambda/T * x) - 1)
200 #
201 # => x = T/lambda log((exp(lambda) - 1) F(x) + 1)
202 #
203 # IHMAgent proc exp_timer { lambda T } {
204 #    set r [expr [random]/double(0x7fffffff)]
205 #     set o [expr ($T/$lambda) * log((exp($lambda) - 1)*$r + 1)]
206 #     return [expr int($o+0.5)]
207 # }
208 
209 
210 #-----------------------------------------------------------------------
211 # Method:
212 #   IHMAgent open_cb
213 #   IHMAgent close_cb
214 # Description:
215 #   Open and close a coordination bus.
216 # Arguments:
217 #   cb -- Coordination bus to close.
218 #   handler -- Unused junk.
219 #-----------------------------------------------------------------------
220 IHMAgent instproc close_cb cb {
221     set c [$cb set channel_]
222 
223     $self instvar chanmap_
224     incr chanmap_($c) -1
225     if { $chanmap_($c) <= 0 } {
226         delete $cb
227         unset chanmap_($c)
228     }
229 }
230 
231 IHMAgent instproc open_cb { handler } {
232     $self instvar cbchannel_ chanmap_
233     set cb [new CoordinationBus -channel $cbchannel_]
234     set chanmap_($cbchannel_) 1
235 
236     # FIXME
237     incr cbchannel_
238 
239     return $cb
240 }
241 
242 
243 #-----------------------------------------------------------------------
244 # Method:
245 #   IHMAgent read_hmhosts
246 # Description:
247 #   Read a file called "hmhosts", which contains a list of hosts hm can
248 #   run on.  The list of hosts are stored into a list called hmhosts_.
249 #-----------------------------------------------------------------------
250 IHMAgent instproc read_hmhosts {} {
251     $self instvar hmhosts_ 
252 
253     set path [$self get_option execPath]
254 
255     set f "$path/hmhosts"
256     if { $f == "" } {
257         MashLog warn "hm: warning: no host file - disabling load_check"
258         return
259     }
260 
261     set fd [open $f r]
262     if { $fd <  0 } {
263         MashLog warn "hm: problems opening $f"
264         return
265     }
266 
267     while { [gets $fd line] > 0 } {
268         if { [intoa [lookup_host_addr $line]] != [localaddr] } {
269             lappend hmhosts_ $line
270         }
271     }
272     close $fd
273 }
274 
275 
276 #-----------------------------------------------------------------------
277 # Method:
278 #   IHMAgent init_load_check
279 # Description:
280 #   Create a time to call method load_check{ } periodically.
281 #-----------------------------------------------------------------------
282 IHMAgent instproc init_load_check {} {
283 
284     set low_ 0
285     set high_ 0
286 
287     set t [$self get_option checkInterval]
288     after $t "$self load_check"
289 }
290 
291 
292 #-----------------------------------------------------------------------
293 # Method:
294 #   IHMAgent load_check
295 # Description:
296 #   Checks the current load on this machine.  If the load is too high,
297 #   Sheds some load by randomly killing of servents (see shed_load{}).
298 #   If the load is too low, kill self. (Huh?).
299 #-----------------------------------------------------------------------
300 IHMAgent instproc load_check {} {
301     $self instvar app_ low_ high_ ascp_
302 
303     set load [MashSystem get_load]
304     set nsamples [$self get_option loadSamples]
305     if { $load > [$self get_option highLoad] } {
306         incr high_
307         if { $high_ >= $nsamples } {
308             if { [$self spawn] != 0 } {
309                 $self shed_load
310             }
311         }
312     } elseif { $load < [$self get_option lowLoad] } {
313         incr low_
314         if { $low_ >= $nsamples } {
315             # Don't die if the number of hm's is at the minimum.
316             set minhm [$self get_option minHmNum]
317             set hmnum [$ascp_ get_num_of_hms]
318             # count ourselves
319             incr hmnum
320             if { $hmnum > $minhm } {
321                 $self die
322                 return
323             }
324         }
325     } else {
326         set low_ 0
327         set high_ 0
328     }
329 
330     set t [$self get_option checkInterval]
331     after $t "$self load_check"
332 }
333 
334 
335 #-----------------------------------------------------------------------
336 # Method:
337 #   IHMAgent spawn
338 # Description:
339 #   Spawn a copy of hm on another random host.
340 #-----------------------------------------------------------------------
341 IHMAgent instproc spawn {} {
342     $self instvar hmhosts_ app_ ascp_
343 
344     # build hmhosts_ - hmlist
345     set hmlist [$ascp_ hmaddrs]
346 
347     if { [$self get_option glunix] != "" } {
348         set tlist [eval exec "glustat -s l -l"]
349     } else {
350         set tlist $hmhosts_
351     }
352     # remove any local entries we may have
353     set i [lsearch -exact $tlist [localaddr]]
354     set tlist [lreplace $tlist $i $i]
355 
356     foreach h $hmlist {
357         set i [lsearch -exact $tlist $h]
358         set tlist [lreplace $tlist $i $i]
359     }
360     set n [llength $tlist]
361     if { $n == 0 } {
362         # no hosts to spawn to
363         return 0
364     }
365     if { [$self get_option glunix] != "" } {
366         # glustat already sorted by load.
367         set r 0
368     } else {
369         set r [expr [random] % $n]
370     }
371     set shost [lindex $tlist $r]
372 
373     $self dospawn $shost
374 
375     return 1
376 }
377 
378 
379 #-----------------------------------------------------------------------
380 # Method:
381 #   IHMAgent dospawn
382 # Description:
383 #   Called by spawn{}, spawn a copy of hm on $shost.
384 #-----------------------------------------------------------------------
385 IHMAgent private dospawn { shost } {
386     $self instvar app_ 
387     set path [$self get_option execPath]
388     set argv [$self get_option execArgs]
389     set cmd [$self get_option execCmd]
390 
391     MashLog info "eval exec $cmd $shost $path/smash $path/hm $argv >& /dev/null &"
392     if { [catch "eval exec $cmd $shost $path/smash $path/hm $argv >& /dev/null &" t] != 0 } {
393         MashLog warn "catch error: $t"
394     }
395 }
396 
397 
398 #-----------------------------------------------------------------------
399 # Method:
400 #   IHMAgent shed_load
401 # Description:
402 #   Randomly kills of servents.
403 #-----------------------------------------------------------------------
404 IHMAgent instproc shed_load {} {
405     $self instvar handlers_
406     foreach h $handlers_ {
407         set pid [$h set pid_]
408         # Shed 50% of the load randomly.
409         set r [expr [random]/double(0x7fffffff)]
410         if { $r < 0.5 } {
411             MashLog info "exec kill -9 $pid"
412             catch "eval exec kill -9 $pid"
413         }
414     }
415 }
416 
417 
418 #-----------------------------------------------------------------------
419 # Method:
420 #   IHMAgent die
421 # Description:
422 #   Schedule a callback to kill self.
423 #-----------------------------------------------------------------------
424 IHMAgent instproc die {} {
425     $self instvar dying_ app_
426 
427     set t [$self get_option deathInterval]
428     set minwait [$self get_option minDeathWait]
429     set r [expr ([random] % $t) + $minwait]
430     set dying_ [after $r "$self really_die"]
431 }
432 
433 
434 #-----------------------------------------------------------------------
435 # Method:
436 #   IHMAgent really_die
437 # Description:
438 #   Really kill self.
439 #-----------------------------------------------------------------------
440 IHMAgent instproc really_die {} {
441     $self instvar app_ dying_ low_ high_ ascp_
442 
443     $ascp_ announce_death
444     set minhm [$self get_option minHmNum]
445     set hmnum [$ascp_ get_num_of_hms]
446     # count ourselves
447     incr hmnum
448     # one last check
449     set load [MashSystem get_load]
450     if { $hmnum > $minhm && $load < [$self get_option lowLoad] } {
451         MashLog info "exit 0"
452         $self doexit
453     }
454     # get back in the mix!
455     unset dying_
456     set low_ 0
457     set high_ 0
458     $self load_check
459 }
460 
461 
462 #-----------------------------------------------------------------------
463 # Method:
464 #   IHMAgent recv_death
465 # Description:
466 #   If someone has already kill itself, it is possible that we do not
467 #   have to kill ourself.  Recheck.
468 #-----------------------------------------------------------------------
469 IHMAgent instproc recv_death {} {
470     $self instvar dying_ low_ high_
471 
472     if ![info exists dying_] {
473         return
474     }
475 
476     # Someone else is dying, we get a reprieve...
477     after cancel $dying_
478     unset dying_
479     set low_ 0
480     set high_ 0
481     $self load_check
482 }
483 
484 #vim:ts=8:sw=4:expandtab
485 
486 

~ [ 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.