source: trunk/p2p/foreman.tcl @ 4503

Last change on this file since 4503 was 3177, checked in by mmc, 8 years ago

Updated all of the copyright notices to reference the transfer to
the new HUBzero Foundation, LLC.

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) 2004-2012  HUBzero Foundation, LLC
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.