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

Open Mash Cross Reference
mash/tcl/indiva/lib/ascp-manager.tcl

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

  1 # ascp-manager.tcl --

  2 #

  3 #       AnnounceListenManager for Indiva Host Manager.  It handles

  4 #       messages from other host managers and clients.

  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/indiva/lib/ascp-manager.tcl,v 1.3 2002/08/08 22:32:24 weitsang Exp $

 33 
 34 import ASCP
 35 import IHMAgent
 36 import MashLog
 37 import MashRNG
 38 import MashTimer
 39 import MashSystem
 40 import MashSoftTable/Adaptive
 41 
 42 #--------------------------------------------------------------------------

 43 # Class:

 44 #   ASCP/Manager

 45 # Description:

 46 #

 47 # Members:

 48 #   tid_ --

 49 #     An array of timers indexed by service instance.

 50 #

 51 #   launched_ --

 52 #     An array of services launched, indexed by service instance.

 53 #--------------------------------------------------------------------------

 54 Class ASCP/Manager -superclass ASCP
 55 
 56 ASCP/Manager instproc init { spec bw } {
 57     $self next $spec $bw
 58 
 59     $self instvar script_loader_ 
 60     set script_loader_ [new IHMScriptLoader]
 61 
 62     $self instvar alive_timer_
 63     set alive_timer_ [new MashTimer/ConstBW 5000 "$self announce_alive" $bw]
 64 
 65     $self instvar service_table_
 66     set service_table_ [new MashSoftTable/Adaptive 5000]
 67 }
 68 
 69 
 70 ASCP/Manager instproc agent_type { } {
 71     return "m"
 72 }
 73 
 74 
 75 #--------------------------------------------------------------------------

 76 # Method:

 77 #   ASCP/Manager process_packet

 78 # Description:

 79 #   Process a message from other alm.  If we get a client message, we

 80 #   schedule a launch if current cpu load is less than a threshold. 

 81 #   If we get a launch message from another hm, we cancel our scheduled

 82 #   launch.  If we get an update message from another hm from the same 

 83 #   host, we kill one of the hm.  Ignore server messages.

 84 #--------------------------------------------------------------------------

 85 
 86 ASCP/Manager instproc process_packet { addr packet } {
 87     set agent_type [$packet agent_type]
 88     set operation [$packet operation]
 89     set agent_id [$packet agent_id]
 90     set service_instance [$packet service_instance]
 91     set service_location [$packet service_location]
 92     set service_type [$packet service_type]
 93     set precond [$packet precondition]
 94     set msg [$packet args]
 95     switch $agent_type {
 96         m {
 97             switch $operation {
 98                 alive {
 99                     # Check if there's another hm on this host

100                     if { $addr == [localaddr] } {
101                         $self kill_dup_hm $agent_id
102                     }
103                 }
104                 offer -
105                 launch_ok {
106                     $self suppress_timer $service_instance
107                 }
108             }
109         }
110         c {
111             switch -exact -- $operation {
112                 "request" {
113                     MashLog info "recv request $service_location from $addr"
114                     if {[$self check_precond $precond]} {
115                         set load [MashSystem get_load]
116                         set hiload [$self get_option highLoad]
117                         if {[$self get_option noLoad] == "" &&  $load >= $hiload } {
118                             MashLog info "HI LOAD load=$load $hiload"
119                         } else {
120                             # Wait a couple seconds to prevent any race conditions

121                             # between gateway announcement prompted by client

122                             # message and hm check.

123                             after 100 "$self handle_request $service_type $service_location $service_instance [gettimeofday] $msg"
124                         }
125                     } else {
126                         MashLog info "Precond failed: $precond"
127                     }
128                 }
129                 "launch_now" {
130                     $self instvar service_table_
131                     if {[$service_table_ get $service_instance] == ""} {
132                         if {[$self check_precond $precond]} {
133                             set args [join [split $msg \n]]
134                             $self launch $service_type $service_location $service_instance $args
135                         } else {
136                             # MashLog info "PRECOND FAILED $precond"

137                         }
138                     } else {
139                         MashLog info "Already servicing $service_location [$service_table_ get $service_instance]"
140                     }
141                 }
142                 "launch" {
143                     MashLog info "recv launch $service_location from $addr"
144                     if {[$self check_precond $precond]} {
145                         set load [MashSystem get_load]
146                         set hiload [$self get_option highLoad]
147                         if {[$self get_option noLoad] == "" &&  $load >= $hiload } {
148                             MashLog info "HI LOAD load=$load $hiload"
149                         } else {
150                             # Wait a couple seconds to prevent any race conditions

151                             # between gateway announcement prompted by client

152                             # message and hm check.

153                             after 100 "$self handle_launch $service_type $service_location $service_instance [gettimeofday] $msg"
154                         }
155                     } else {
156                         MashLog info "Precond failed: $precond"
157                     }
158                 }
159                 "alive" {
160                     # For services. Ignore.

161                 }
162                 default {
163                     MashLog error "unrecorgnize operation $operation"
164                 }
165             }
166         }
167         s {
168             $self instvar service_table_
169             switch -exact -- $operation {
170                 "alive" {
171                     if [$service_table_ has $service_instance] {
172                         #MashLog info "$service_instance is alive"

173                         $service_table_ refresh $service_instance
174                     }
175                 }
176             }
177             #delete $packet

178         }
179     }
180 }
181 
182 
183 #--------------------------------------------------------------------------

184 # Method:

185 #   ASCP/Manager kill_dup_hm

186 # Description:

187 #   Kill self if pid is less than the other (duplicated) hm.

188 #--------------------------------------------------------------------------

189 ASCP/Manager instproc kill_dup_hm { name } {
190     # A duplicate hm - break the tie with pids.

191     if { [string compare $name [$self agent_id]] < 0 } {
192         MashLog info "duplicate hm: $name [$self agent_id] - exiting."
193         # XXX : define doexit

194         $self doexit
195     }
196 }
197 
198 
199 #--------------------------------------------------------------------------

200 # Method:

201 #   ASCP/Manager handle_request

202 # Description:

203 #   Checks if another service for this client is running, if not schedule

204 #   a launch.

205 #--------------------------------------------------------------------------

206 ASCP/Manager instproc handle_request { srv_name srv_loc srv_inst curr_time {msg ""}} {
207     if [$self is_pending $srv_inst] {
208         MashLog info "already pending $srv_inst"
209         return
210     }
211 
212     $self instvar service_table_
213 
214     # If we don't have a record of a gateway for this session,

215     # launch one.

216     if {[$service_table_ get $srv_inst] == ""} {
217         # Can't find a service record.  Set launch timer.

218         $self sched_offer_service $srv_name $srv_loc $srv_inst $msg
219     }
220 }
221 
222 
223 #--------------------------------------------------------------------------

224 # Method:

225 #   ASCP/Manager handle_launch

226 # Description:

227 #   Checks if another service for this client is running, if not schedule

228 #   a launch.

229 #--------------------------------------------------------------------------

230 ASCP/Manager instproc handle_launch { srv_name srv_loc srv_inst curr_time args} {
231     if [$self is_pending $srv_inst] {
232         MashLog info "already pending $srv_inst"
233         return
234     }
235 
236     $self instvar service_table_
237 
238     # If we don't have a record of a gateway for this session,

239     # launch one.

240     if {[$service_table_ get $srv_inst] == ""} {
241         # Can't find a service record.  Set launch timer.

242         $self sched_launch $srv_name $srv_loc $srv_inst $args
243     }
244 }
245 
246 
247 
248 #-----------------------------------------------------------------------

249 # Method:

250 #   ASCP/Manager sched_offer_service

251 # Description:

252 #   Schedule an offer announcement. 

253 #-----------------------------------------------------------------------

254 ASCP/Manager public sched_offer_service { srv_name srv_loc srv_inst msg } {
255 
256     set numhm [$self get_num_of_hms]
257     set T [expr $numhm * 500]
258     set max [$self get_option maxWait]
259     if { $T > $max } {
260         set T $max
261     }
262     # FIXME bias T by load.

263     set t [MashRNG integer $T]
264     MashLog info "timer $srv_name $srv_inst $t"
265 
266     set tid [after $t "$self offer_service $srv_name $srv_loc $srv_inst {$msg}"]
267     $self instvar tid_
268     set tid_($srv_inst) $tid
269 }
270 
271 
272 ASCP/Manager instproc register { addr packet } {
273     set agent_type [$packet agent_type]
274     if { $addr != [localaddr] || $agent_type != "s" } {
275         return
276     }
277     $self cancel_timer [$packet service_instance]
278 }
279 
280 
281 ASCP/Manager instproc unregister { addr packet } {
282     set agent_type [$packet agent_type]
283     if { $addr != [localaddr] || $agent_type != "s" } {
284         return
285     }
286     $self unregister [$packet agent_id] [$packet args]
287 }
288 
289 
290 ASCP/Manager instproc announce_offer { service_instance } {
291 
292     set packet [new ASCPPacket]
293     $packet agent_type [$self agent_type]
294     $packet agent_id [$self agent_id]
295     $packet operation "offer"
296     $packet service_instance $service_instance
297 
298     MashLog info "offer service $service_instance"
299     $self announce [$packet to_string]
300     delete $packet
301 }
302 
303 
304 ASCP/Manager instproc announce_launch_ok { service_instance } {
305 
306     set packet [new ASCPPacket]
307     $packet agent_type [$self agent_type]
308     $packet agent_id [$self agent_id]
309     $packet operation "launch_ok"
310     $packet service_instance $service_instance
311 
312     MashLog info "launch_ok $service_instance"
313     $self announce [$packet to_string]
314     delete $packet
315 
316 }
317 
318 
319 #

320 # We build a simple message since we only use this to announce

321 # our presence.

322 # FIXME: Since this is called periodically, we should reuse the

323 # packet instead of creating a new one everytime.

324 #

325 ASCP/Manager instproc announce_alive {} {
326     set packet [new ASCPPacket]
327     $packet agent_type [$self agent_type]
328     $packet agent_id [$self agent_id]
329     $packet operation "alive"
330 
331     $self announce [$packet to_string]
332     delete $packet
333 }
334 
335 
336 ASCP/Manager public get_num_of_hms {} {
337     return [llength [$self hmaddrs]]
338 }
339 
340 
341 ASCP/Manager private hmaddrs {} {
342     # FIXME

343     $self instvar agents_
344     set aspecs [array names agents_]
345 
346     foreach aspec $aspecs {
347         set addr [lindex $agents_($aspec) 0]
348         # remove duplicate entries

349         set d($addr) 1
350     }
351     return [array names d]
352 }
353 
354 
355 #-----------------------------------------------------------------------

356 # Method:

357 #   ASCP/Manager is_pending

358 # Description:

359 #   Check if there is a timer with id == $tid pending.

360 # Arguments:

361 #   tid -- ID of the timer to check.

362 #-----------------------------------------------------------------------

363 ASCP/Manager instproc is_pending tid {
364     $self instvar tid_
365     return [info exists tid_($tid)]
366 }
367 
368 
369 #-----------------------------------------------------------------------

370 # Method:

371 #   ASCP/Manager cancel_timer

372 # Description:

373 #   Remove the "after" callback and information regarding a scheduled

374 #   launched identified by $tid.

375 # Arguments:

376 #   tid -- ID of the timer to cancel.

377 #-----------------------------------------------------------------------

378 ASCP/Manager instproc cancel_timer {tid} {
379     $self instvar tid_ launched_ 
380     if [info exists launched_($tid)] {
381         unset launched_($tid)
382     }
383     if { [info exists tid_($tid)] } {
384         #MashLog info "cancelled timer $tid"

385         after cancel $tid_($tid)
386         MashLog info "cancel timer for $tid"
387         unset tid_($tid)
388     }
389 }
390 
391 
392 #-----------------------------------------------------------------------

393 # Method:

394 #   ASCP/Manager sched_launch

395 # Description:

396 #   Schedule a launch by creating an "after" callback.  The timeout 

397 #   period for launching is randomly, uniformly chosen from [0, 2000*N],

398 #   where N is the estimate number of host manager currently running.

399 # Arguments:

400 #   srv_name -- Name of the service to launch.

401 #   srv_loc  -- Where to find the executable of the service.

402 #   srv_inst -- A unique ID to the service.

403 #   msg -- Data for the service.

404 #-----------------------------------------------------------------------

405 ASCP/Manager public sched_launch { srv_name srv_loc srv_inst msg } {
406     set numhm [$self get_num_of_hms]
407     set T [expr $numhm * 500]
408     set max [$self get_option maxWait]
409     if { $T > $max } {
410         set T $max
411     }
412     # FIXME bias T by load.

413     set t [MashRNG integer $T]
414     MashLog info "timer $srv_name $srv_inst $t"
415 
416     set tid [after $t "$self launch $srv_name $srv_loc $srv_inst {$msg}"]
417     $self instvar tid_
418     set tid_($srv_inst) $tid
419 }
420 
421 
422 #-----------------------------------------------------------------------

423 # Method:

424 #   ASCP/Manager suppress_timer

425 # Description:

426 #   Cancel our own launch, because someone else has already launch the

427 #   same service.

428 # Arguments:

429 #   tid -- ID to the service to cancel.

430 #-----------------------------------------------------------------------

431 ASCP/Manager public suppress_timer { sid } {
432     $self instvar tid_ launched_ 
433     MashLog info "suppress timer $sid"
434     if { [info exists tid_($sid)] && ![info exists launched_($sid)] } {
435         after cancel $tid_($sid)
436         unset tid_($sid)
437     }
438 }
439 
440 #-----------------------------------------------------------------------

441 # Method:

442 #   ASCP/Manager pending_launches

443 # Description:

444 #   Return the number of launches pending.

445 #-----------------------------------------------------------------------

446 ASCP/Manager instproc pending_launches {} {
447     $self instvar launched_
448     return [llength [array names launched_]]
449 }
450 
451 
452 #-----------------------------------------------------------------------

453 # Method:

454 #   ASCP/Manager offer_service

455 # Description:

456 #   Offer a service.  A service is offered only if (1) the number of 

457 #   current pending launches is less than maximum allowable pending 

458 #   launches (configurable through maxPending), (2) current CPU load 

459 #   is less than maximum allowable CPU load (configurable through 

460 #   highLoad).   This method is an "after" callback scheduled by 

461 #   sched_offer_service {} method.

462 # Arguments:

463 #   srv_name -- Name of the service to launch.

464 #   srv_loc  -- Location of the service's executable.

465 #   srv_inst -- ?

466 #   msg -- ?

467 #-----------------------------------------------------------------------

468 ASCP/Manager private offer_service { srv_name srv_loc srv_inst msg } {
469 
470     if { [$self pending_launches] >= [$self get_option maxPending] } {
471         #MashLog info "BACKLOG [$self pending_launches]"

472         $self cancel_timer $srv_inst
473         return
474     }
475     set load [MashSystem get_load]
476     set hiload [$self get_option highLoad]
477     #MashLog info "LAUNCH load=$load $hiload"

478     if { [$self get_option noLoad] == "" &&  $load >= $hiload } {
479         $self cancel_timer $srv_inst
480         return
481     }
482 
483     $self announce_offer $srv_inst
484     $self cancel_timer $srv_inst
485     return 1
486 }
487 
488 
489 #-----------------------------------------------------------------------

490 # Method:

491 #   ASCP/Manager launch

492 # Description:

493 #   Launch a service.  A service is launch only if (1) the number of 

494 #   current pending launches is less than maximum allowable pending 

495 #   launches (configurable through maxPending), (2) current CPU load 

496 #   is less than maximum allowable CPU load (configurable through 

497 #   highLoad).   This method is an "after" callback scheduled by 

498 #   schedule_launch {} method.

499 # Arguments:

500 #   srv_name -- Name of the service to launch.

501 #   srv_loc  -- Location of the service's executable.

502 #   srv_inst -- ?

503 #   msg -- ?

504 #-----------------------------------------------------------------------

505 ASCP/Manager private launch { srv_type srv_loc srv_inst arguments } {
506 
507     if {[$self pending_launches] >= [$self get_option maxPending]} {
508         MashLog info "BACKLOG [$self pending_launches]"
509         $self cancel_timer $srv_inst
510         return
511     }
512     set curr_load [MashSystem get_load]
513     set high_load [$self get_option highLoad]
514     if {[$self get_option noLoad] == "" && $curr_load >= $high_load} {
515         $self cancel_timer $srv_inst
516         return
517     }
518     MashLog info "Launch load=$curr_load $high_load"
519  
520 #   $self instvar creators_

521 #   if ![info exists creators_($srv_type)] {

522 #       MashLog info "ERROR unrecorgnize service $srv_type"

523 #       return

524 #   }

525 #   set creator $creators_($srv_type)

526 #   set h [$creator create_handler $srv_inst $msg]

527 
528     $self instvar script_loader_ service_table_
529     set script [$script_loader_ get_script $srv_type $srv_loc]
530     if { $script != "" } {
531         $self exec $script $srv_inst $arguments
532         $service_table_ set $srv_inst [$self agent_id]
533     }
534 
535     $self announce_launch_ok $srv_inst
536 }
537 
538 
539 ASCP/Manager instproc error {msg} {
540     MashLog error "$msg"
541 }
542 
543 
544 ASCP/Manager instproc exec {script service_instance arguments} {
545     # FIXME: as_spec/bw should be abstracted to somewhere else.

546 
547     $self instvar as_spec_ as_bw_
548     global env
549     if [info exists env(MASHWORK)] {
550         set mashpath "$env(MASHWORK)/bin/"
551     } else {
552         set mashpath "" 
553     }
554     if {[catch {eval exec ${mashpath}smash $script $arguments -as_spec $as_spec_ -as_bw $as_bw_ -sid $service_instance >& ${script}[clock clicks -milliseconds].log &} t]} {
555         MashLog info "$self exec ${mashpath}smash $script $arguments -as_spec $as_spec_ -as_bw $as_bw_ -sid $service_instance"
556         MashLog warn "ERROR: $t"
557     } else {
558         MashLog info "$self exec ${mashpath}smash $script $arguments -as_spec $as_spec_ -as_bw $as_bw_ -sid $service_instance"
559     }
560 }
561 
562 
563 #--------------------------------------------------------------------------

564 # Method:

565 #   ASCP/Manager check_precond

566 # Description:

567 #--------------------------------------------------------------------------

568 ASCP/Manager instproc check_precond { precond } {
569     if {$precond == "-" || $precond == ""} {
570         return 1
571     }
572     set precondlist [split $precond :]
573     set prefix [lindex $precondlist 0]
574     set rest [string range $precond [expr {[string length $prefix]+1}] end]
575     switch -exact -- $prefix {
576         tcl {
577             return [eval $rest]
578         }
579         hostname {
580             return [expr [lsearch -exact $rest [info hostname]] != -1]
581         }
582         agentid {
583             if {[$self agent_id] == $rest} {
584                 return 1
585             } else {
586                 return 0
587             }
588         }
589         agenttype {
590             if {[$self agent_type] == $rest} {
591                 return 1
592             } else {
593                 return 0
594             }
595         }
596         default {
597             MashLog error "BAD PRECOND $precond"
598             return 0
599         }
600     }
601 }
602 # vim:ts=8:sw=4:expandtab

603 

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