source: trunk/p2p/foreman.tcl @ 1273

Last change on this file since 1273 was 1273, checked in by mmc, 16 years ago

Major reorganization of p2p code, and support for solicit/proffer
messages.

File size: 7.9 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 "workers"
122    } else {
123        error "can't connect to any authority\nAUTHORITY LIST: [p2p::options get authority_hosts]"
124    }
125}
126
127# sit here after we've gotten a list of workers
128# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
129foreman-solicit state informed
130
131# when moving to the fetching state, connect to the authority
132# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
133foreman-solicit transition fetching->informed -onchange {
134    # connect to the authority and request a list of peers
135    if {"" != [statedata authoritycnx]} {
136        catch {itcl::delete object [statedata authoritycnx]}
137        statedata authoritycnx ""
138    }
139    after idle {foreman-solicit goto connected}
140}
141
142# sit here when we're connected to the p2p network
143# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
144foreman-solicit state connected
145
146# when moving to the connected state, connect to the p2p worker
147# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
148foreman-solicit transition informed->connected -onchange {
149    # connect to the p2p network and send a solicitation
150    global workers
151    statedata workercnx ""
152    foreach addr [randomize $workers 100] {
153        if {[catch {p2p::client -address $addr \
154            -sendprotocol hubzero:worker<-foreman/1 \
155            -receiveprotocol hubzero:foreman<-worker/1} result] == 0} {
156            statedata workercnx $result
157            break
158        }
159    }
160
161    if {"" != [statedata workercnx]} {
162        [statedata workercnx] send "solicit -job [expr {rand()}]"
163    } else {
164        after 2000 {foreman-solicit goto connected}
165        error "can't connect to any worker in the p2p network"
166    }
167}
168
169# when moving back to the informed state, disconnect from p2p network
170# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
171foreman-solicit transition connected->informed -onchange {
172    # have an open connection? then close it
173    if {"" != [statedata workercnx]} {
174        catch {itcl::delete object [statedata workercnx]}
175        statedata workercnx ""
176    }
177}
178
179# ----------------------------------------------------------------------
180#  API
181# ----------------------------------------------------------------------
182namespace eval Rappture::foreman { # forward declaration }
183
184# ----------------------------------------------------------------------
185#  COMMAND:  Rappture::foreman::bids -callback <command>
186#
187#  Clients use this to solicit bids for jobs.  Connects to an
188#  authority, if necessary, to determine a list of workers, and then
189#  connects to one of the workers to kick off the bid process.
190# ----------------------------------------------------------------------
191proc Rappture::foreman::bids {args} {
192    global workers
193
194    if {![info exists workers] || [llength $workers] == 0} {
195        foreman-solicit goto fetching
196    } else {
197        foreman-solicit goto connected
198    }
199}
Note: See TracBrowser for help on using the repository browser.