source: trunk/p2p/foreman.tcl @ 2760

Last change on this file since 2760 was 2080, checked in by mmc, 14 years ago

Part 1 of a major reorganization of content. Moving "instant" to "builder"
and setting up "builder" more like the "gui" part as a package. Moving the
Rappture::object stuff from the builder into the main installation, so it
can be shared by the tester as well. Moving "driver" into gui/scripts
where it belongs. Creating a new "launcher.tcl" script that decides
which of the three parts to launch based on command line options. Still
need to sort out the Makefiles to get this all right...

File size: 8.0 KB
Line 
1# ----------------------------------------------------------------------
2#  P2P: foreman node in P2P mesh, sending jobs out for execution
3#
4#  This file provides an API for clients to connect to the P2P network,
5#  solicit bids on jobs, and send them off for execution.
6# ----------------------------------------------------------------------
7#  Michael McLennan (mmclennan@purdue.edu)
8# ======================================================================
9#  Copyright (c) 2008  Purdue Research Foundation
10#
11#  See the file "license.terms" for information on usage and
12#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13# ======================================================================
14package require Rappture
15
16# recognize other library files in this same directory
17set dir [file dirname [info script]]
18lappend auto_path $dir
19
20# handle log file for this foreman
21log channel error on
22log channel debug on
23log channel system on
24
25proc ::bgerror {err} { log error "ERROR: $err $::errorInfo" }
26
27# set of connections for authority servers
28p2p::options register authority_hosts 127.0.0.1:9001
29
30# ======================================================================
31#  PROTOCOL: hubzero:foreman<-authority/1
32#
33#  The foreman initiates communication with the authority, and the
34#  authority responds by sending the following messages back.
35# ======================================================================
36p2p::protocol::register hubzero:foreman<-authority/1 {
37    # ------------------------------------------------------------------
38    #  INCOMING: options <key1> <value1> <key2> <value2> ...
39    #  These option settings coming from the authority override the
40    #  option settings built into the client.  The authority probably
41    #  has a more up-to-date list of other authorities and better
42    #  policies for living within the network.
43    # ------------------------------------------------------------------
44    define options {args} {
45        foreach {key val} $args {
46            catch {p2p::options set $key $val}
47        }
48        return ""
49    }
50
51    # ------------------------------------------------------------------
52    #  INCOMING: workers <listOfAddresses>
53    #  This message comes in after this foreman has sent the "workers"
54    #  message to request the current list of workers.  The
55    #  <listOfAddresses> is a list of host:port addresses that this
56    #  foreman should contact to enter the p2p network.
57    # ------------------------------------------------------------------
58    define workers {wlist} {
59        global workers
60        set workers $wlist
61        foreman-solicit goto informed
62        return ""
63    }
64}
65
66# ======================================================================
67#  PROTOCOL: hubzero:foreman<-worker/1
68#
69#  The foreman initiates communication with a worker, and the
70#  worker responds by sending the following messages back.
71# ======================================================================
72p2p::protocol::register hubzero:foreman<-worker/1 {
73    # ------------------------------------------------------------------
74    #  INCOMING: proffer <token> <details>
75    # ------------------------------------------------------------------
76    define proffer {token details} {
77puts "PROFFER:\n$details"
78        after idle {foreman-solicit goto informed}
79        return ""
80    }
81}
82
83# ----------------------------------------------------------------------
84#  PEER-TO-PEER CONNECTION
85#
86#  This is the state machine representing the connection of the foreman
87#  to the peer-to-peer network.  We start in the "init" state, then
88#  move to "fetching" while waiting for an authority to return a list
89#  of workers, then move to "informed".  At any point, we can move
90#  from "informed" to "connected" and connect to one of the workers
91#  in the peer-to-peer network, then move back to "informed" when
92#  the information has been gathered.
93# ----------------------------------------------------------------------
94StateMachine foreman-solicit
95foreman-solicit statedata authoritycnx ""
96foreman-solicit statedata workercnx ""
97
98# sit here whenever we don't have a connection
99# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100foreman-solicit state init
101
102# sit here while we're connected to the authority and fetching data
103# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
104foreman-solicit state fetching
105
106# when moving to the fetching state, connect to the authority
107# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
108foreman-solicit transition init->fetching -onchange {
109    # connect to the authority and request a list of peers
110    statedata authoritycnx ""
111    foreach addr [randomize [p2p::options get authority_hosts]] {
112        if {[catch {p2p::client -address $addr \
113            -sendprotocol hubzero:authority<-foreman/1 \
114            -receiveprotocol hubzero:foreman<-authority/1} result] == 0} {
115            statedata authoritycnx $result
116            break
117        }
118    }
119
120    if {"" != [statedata authoritycnx]} {
121        [statedata authoritycnx] send "identity foreman"
122        [statedata authoritycnx] send "workers"
123    } else {
124        error "can't connect to any authority\nAUTHORITY LIST: [p2p::options get authority_hosts]"
125    }
126}
127
128# sit here after we've gotten a list of workers
129# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
130foreman-solicit state informed
131
132# when moving to the fetching state, connect to the authority
133# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134foreman-solicit transition fetching->informed -onchange {
135    # connect to the authority and request a list of peers
136    if {"" != [statedata authoritycnx]} {
137        catch {itcl::delete object [statedata authoritycnx]}
138        statedata authoritycnx ""
139    }
140    after idle {foreman-solicit goto connected}
141}
142
143# sit here when we're connected to the p2p network
144# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
145foreman-solicit state connected
146
147# when moving to the connected state, connect to the p2p worker
148# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
149foreman-solicit transition informed->connected -onchange {
150    # connect to the p2p network and send a solicitation
151    global workers
152    statedata workercnx ""
153    foreach addr [randomize $workers 100] {
154        if {[catch {p2p::client -address $addr \
155            -sendprotocol hubzero:worker<-foreman/1 \
156            -receiveprotocol hubzero:foreman<-worker/1} result] == 0} {
157            statedata workercnx $result
158            break
159        }
160    }
161
162    if {"" != [statedata workercnx]} {
163        [statedata workercnx] send "identity foreman"
164        [statedata workercnx] send "solicit -job [expr {rand()}]"
165    } else {
166        after 2000 {foreman-solicit goto connected}
167        error "can't connect to any worker in the p2p network"
168    }
169}
170
171# when moving back to the informed state, disconnect from p2p network
172# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
173foreman-solicit transition connected->informed -onchange {
174    # have an open connection? then close it
175    if {"" != [statedata workercnx]} {
176        catch {itcl::delete object [statedata workercnx]}
177        statedata workercnx ""
178    }
179}
180
181# ----------------------------------------------------------------------
182#  API
183# ----------------------------------------------------------------------
184namespace eval Rappture::foreman { # forward declaration }
185
186# ----------------------------------------------------------------------
187#  COMMAND:  Rappture::foreman::bids -callback <command>
188#
189#  Clients use this to solicit bids for jobs.  Connects to an
190#  authority, if necessary, to determine a list of workers, and then
191#  connects to one of the workers to kick off the bid process.
192# ----------------------------------------------------------------------
193proc Rappture::foreman::bids {args} {
194    global workers
195
196    if {![info exists workers] || [llength $workers] == 0} {
197        foreman-solicit goto fetching
198    } else {
199        foreman-solicit goto connected
200    }
201}
Note: See TracBrowser for help on using the repository browser.