Mercurial > hg > FederatedLinda
comparison tools/python-PE/CompactRouting/Routing.py @ 8:6c40056777be
Initial revision
author | fuchita |
---|---|
date | Sat, 16 Feb 2008 13:18:02 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
7:1809e2b05824 | 8:6c40056777be |
---|---|
1 import string | |
2 import struct | |
3 import time | |
4 | |
5 import xml.dom.minidom | |
6 import FederatedLinda | |
7 import LinkConfiguration | |
8 | |
9 TUPLE_ID_LINKCONFIG = 1 | |
10 TUPLE_ID_ROUTING = 2 | |
11 | |
12 ROUTING_HEADER_FORMAT = "!I" | |
13 | |
14 ROUTING_COMMAND_CONNECT = 1 | |
15 ROUTING_COMMAND_DISCONNECT = 2 | |
16 ROUTING_COMMAND_TRANSFER = 3 | |
17 ROUTING_COMMAND_UPDATE_TABLE = 4 | |
18 | |
19 class TSInfo: | |
20 def __init__(self, tsid, hopnum, ttl, nexthop): | |
21 self.tsid = tsid # tuple space id, like 'host:port' | |
22 self.hopnum = hopnum # hop number | |
23 self.ttl = ttl # | |
24 self.nexthop = nexthop # next hop (tuple space id) | |
25 | |
26 | |
27 """ XML format is as follows | |
28 <RoutingTable name="localhost:10000"> | |
29 <ts hopnum="1" tsid="localhost:10002" ttl="0"/> | |
30 <ts hopnum="1" tsid="localhost:10001" ttl="256"/> | |
31 <ts hopnum="0" tsid="localhost:10000" ttl="0"/> | |
32 </RoutingTable> | |
33 """ | |
34 class RoutingTable: | |
35 def __init__(self, name): | |
36 self.tslist = {} | |
37 self.name = name | |
38 | |
39 def register(self, tsid, hopnum, ttl, nexthop): | |
40 if (self.tslist.has_key(tsid)): | |
41 del self.tslist[tsid] | |
42 self.tslist[tsid] = TSInfo(tsid, hopnum, ttl, nexthop) | |
43 | |
44 def deregister(self, tsid): | |
45 for t in self.tslist.keys(): | |
46 if self.tslist[t].nexthop == tsid: | |
47 del self.tslist[t] | |
48 | |
49 def update(self, xmldoc, ts): | |
50 rt = xml.dom.minidom.parseString(xmldoc).childNodes[0] | |
51 tslist = rt.childNodes | |
52 updateflag = False | |
53 | |
54 tmplist = [] | |
55 | |
56 # append tuplespace | |
57 for t in tslist: | |
58 if t.nodeType == t.ELEMENT_NODE and t.localName == 'ts': | |
59 tsattr = t.attributes | |
60 tsid = tsattr['tsid'].nodeValue | |
61 hopnum = int( tsattr['hopnum'].nodeValue ) | |
62 ttl = int( tsattr['ttl'].nodeValue ) | |
63 nexthop = ts | |
64 | |
65 tmplist.append(tsid) | |
66 | |
67 if ((not self.tslist.has_key(tsid)) or | |
68 (self.tslist[tsid].hopnum > hopnum+1)): | |
69 self.register(tsid, hopnum+1, ttl, nexthop) | |
70 updateflag = True | |
71 | |
72 # delete tuplespace | |
73 for t in self.tslist.values(): | |
74 if ( not t.tsid in tmplist ): | |
75 updateflag = True | |
76 if (t.nexthop == ts): | |
77 del self.tslist[t.tsid] | |
78 | |
79 return updateflag | |
80 | |
81 def getxmldoc(self): | |
82 doc = xml.dom.minidom.Document() | |
83 rt = doc.createElement('RoutingTable') | |
84 rt.setAttribute('name', self.name) | |
85 for tskey in self.tslist.keys(): | |
86 elem = doc.createElement('ts') | |
87 elem.setAttribute('tsid', self.tslist[tskey].tsid) | |
88 elem.setAttribute('hopnum', str(self.tslist[tskey].hopnum)) | |
89 elem.setAttribute('ttl', str(self.tslist[tskey].ttl)) | |
90 rt.appendChild(elem) | |
91 | |
92 return rt | |
93 | |
94 def getxml(self): | |
95 rt = self.getxmldoc() | |
96 return rt.toxml() | |
97 | |
98 def printxml(self): | |
99 rt = self.getxmldoc() | |
100 print rt.toprettyxml() | |
101 end = time.time() | |
102 print "passed time ",end | |
103 | |
104 def getdstname(self, xmltext): | |
105 rt = xml.dom.minidom.parseString(xmltext).childNodes[0] | |
106 return rt.attributes['name'].nodeValue | |
107 | |
108 class Routing: | |
109 def __init__(self, headerFormat = ROUTING_HEADER_FORMAT): | |
110 self.flinda = FederatedLinda.FederatedLinda() | |
111 self.linda = None | |
112 self.tsid = None | |
113 self.neighbors = {} # key is tsid ("host:port"), value is Linda object | |
114 self.headerFormat = headerFormat # struct.pack's format | |
115 self.rt = None | |
116 | |
117 def __del__(self): | |
118 self.linda.close() | |
119 for ts in self.neighbors.values(): | |
120 ts.close() | |
121 | |
122 def connect(self, tsid): | |
123 host, port = string.split(tsid, ':', 1) | |
124 ts = self.flinda.open(host, int(port)) | |
125 if not ts: | |
126 return None | |
127 | |
128 ts.getid() | |
129 self.addNeighbor(ts, tsid) | |
130 | |
131 return ts | |
132 | |
133 def disconnect(self, tsid): | |
134 if ( self.neighbors.has_key(tsid) ): | |
135 self.delNeighbor(tsid) | |
136 | |
137 def addNeighbor(self, ts, tsid): | |
138 self.neighbors[tsid] = ts | |
139 return ts | |
140 | |
141 def delNeighbor(self, tsid): | |
142 del self.neighbors[tsid] | |
143 | |
144 def pack(self, data, cmd): | |
145 return struct.pack(self.headerFormat, cmd) + data | |
146 | |
147 def unpack(self, packet): | |
148 r = struct.unpack(self.headerFormat + | |
149 str(len(packet)-struct.calcsize(self.headerFormat)) + | |
150 "s", packet) | |
151 return r | |
152 | |
153 def LinkConfig(self, mytsid, packet): | |
154 self.tsid = mytsid | |
155 lcparser = LinkConfiguration.LinkConfigParser() | |
156 linkConfig = lcparser.parseLinkConfig(self.tsid, packet) | |
157 mydstlist = linkConfig.getDstlist(linkConfig.label) | |
158 | |
159 for n in mydstlist: | |
160 tsid = linkConfig.linklist[n].tsid | |
161 if ( tsid and not self.neighbors.has_key(tsid) ): | |
162 ts = self.connect(tsid) | |
163 ts.Out(TUPLE_ID_LINKCONFIG, packet) | |
164 ts.Out(TUPLE_ID_ROUTING, self.pack(self.tsid, ROUTING_COMMAND_CONNECT)) | |
165 pass | |
166 | |
167 def RoutingConnect(self, data): | |
168 print "connect" | |
169 if ( not self.neighbors.has_key(data) ): | |
170 ts = self.connect(data) | |
171 ts.Out(TUPLE_ID_ROUTING, self.pack(self.tsid, ROUTING_COMMAND_CONNECT)) | |
172 | |
173 self.rt.register(data, 1, 16, data) | |
174 upedxml = self.rt.getxml() | |
175 # print "Gen XML ",upedxml | |
176 # print "Neighbors ",self.neighbors | |
177 for nts in self.neighbors.values(): | |
178 nts.Out(TUPLE_ID_ROUTING, self.pack(upedxml, ROUTING_COMMAND_UPDATE_TABLE)) | |
179 pass | |
180 | |
181 def RoutingDisconnect(self, data): | |
182 print "disconnect" | |
183 if ( self.neighbors.has_key(data) ): | |
184 ts = self.neighbors[data] | |
185 ts.Out(TUPLE_ID_ROUTING, self.pack(self.tsid, ROUTING_COMMAND_DISCONNECT)) | |
186 self.disconnect(data) | |
187 | |
188 self.rt.deregister(data) | |
189 upedxml = self.rt.getxml() | |
190 for nts in self.neighbors.values(): | |
191 nts.Out(TUPLE_ID_ROUTING, self.pack(upedxml, ROUTING_COMMAND_UPDATE_TABLE)) | |
192 pass | |
193 | |
194 def RoutingTransfer(self, data): | |
195 #print "transfer" | |
196 # ReplyTuple is "DstTSID,TupleID,SrcTSID,DATA" | |
197 # Src/DstTSID is "hostname:portnum" | |
198 | |
199 dsttsid, tid, srctsid, pdata = string.split(data,',',3) | |
200 print "transfer tuple:" | |
201 print "dsttsid=>",dsttsid, "tid=>",tid, "srctsid=>",srctsid, "data=>",pdata | |
202 if ( dsttsid == self.rt.name ): | |
203 self.linda.Out(int(tid), data) | |
204 else: | |
205 dstts = self.neighbors[self.rt.tslist[dsttsid].nexthop] | |
206 dstts.Out(TUPLE_ID_ROUTING, self.pack(data, ROUTING_COMMAND_TRANSFER)) | |
207 pass | |
208 | |
209 def RoutingTableUpdate(self, data): | |
210 print "update" | |
211 srcname = self.rt.getdstname(data) | |
212 | |
213 if ( self.rt.update(data, srcname) ): | |
214 # Send Update Info to Neighbors | |
215 upedxml = self.rt.getxml() | |
216 for n in self.neighbors.values(): | |
217 n.Out(TUPLE_ID_ROUTING, self.pack(upedxml, ROUTING_COMMAND_UPDATE_TABLE)) | |
218 | |
219 pass | |
220 | |
221 def run(self, mytsid): | |
222 self.tsid = mytsid | |
223 hostname, port = string.split(mytsid, ':', 1) | |
224 self.linda = self.flinda.open(hostname, int(port)) | |
225 if not self.linda: | |
226 return | |
227 | |
228 self.rt = RoutingTable(mytsid) | |
229 self.rt.register(self.rt.name, 0, 0, None) | |
230 | |
231 self.linda.getid() # get client id from Tuple Space (ldserv) | |
232 | |
233 linkConfigReply = self.linda.In(TUPLE_ID_LINKCONFIG) | |
234 routingReply = self.linda.In(TUPLE_ID_ROUTING) | |
235 | |
236 self.flinda.sync() | |
237 | |
238 while (True): | |
239 # Link Configuration | |
240 rep = linkConfigReply.reply() | |
241 if (rep): | |
242 linkConfigReply = self.linda.In(TUPLE_ID_LINKCONFIG) | |
243 | |
244 # Link Configuration main | |
245 self.LinkConfig(self.tsid, rep) | |
246 | |
247 # Routing Protocol | |
248 rep = routingReply.reply() | |
249 if (rep): | |
250 routingReply = self.linda.In(TUPLE_ID_ROUTING) | |
251 cmd , data = self.unpack(rep) | |
252 | |
253 # connect to other tuplespace | |
254 if (cmd == ROUTING_COMMAND_CONNECT): | |
255 # connect main | |
256 self.RoutingConnect(data) | |
257 | |
258 # disconnect other tuplespace | |
259 elif (cmd == ROUTING_COMMAND_DISCONNECT): | |
260 # disconnect main | |
261 self.RoutingDisconnect(data) | |
262 | |
263 # transfer tuple | |
264 elif (cmd == ROUTING_COMMAND_TRANSFER): | |
265 # transfer main | |
266 self.RoutingTransfer(data) | |
267 | |
268 # update own routing table | |
269 elif (cmd == ROUTING_COMMAND_UPDATE_TABLE): | |
270 #routing table main | |
271 self.RoutingTableUpdate(data) | |
272 else: | |
273 pass | |
274 | |
275 print self.rt.printxml() | |
276 | |
277 self.flinda.sync() | |
278 # end while | |
279 | |
280 if __name__ == '__main__': | |
281 import sys | |
282 if (len(sys.argv) != 2) : | |
283 print "Usage : %s <hostname:portnum>" % sys.argv[0] | |
284 sys.exit(1) | |
285 | |
286 mytsid = sys.argv[1] | |
287 | |
288 routing = Routing() | |
289 routing.run(mytsid) | |
290 |