Mercurial > hg > FederatedLinda
view tools/python-PE/CompactRouting/Routing.py @ 67:264123227f0d
large tuple case (suggestion)
author | one |
---|---|
date | Sat, 06 Jun 2009 14:33:59 +0900 |
parents | 6c40056777be |
children |
line wrap: on
line source
import string import struct import time import xml.dom.minidom import FederatedLinda import LinkConfiguration TUPLE_ID_LINKCONFIG = 1 TUPLE_ID_ROUTING = 2 ROUTING_HEADER_FORMAT = "!I" ROUTING_COMMAND_CONNECT = 1 ROUTING_COMMAND_DISCONNECT = 2 ROUTING_COMMAND_TRANSFER = 3 ROUTING_COMMAND_UPDATE_TABLE = 4 class TSInfo: def __init__(self, tsid, hopnum, ttl, nexthop): self.tsid = tsid # tuple space id, like 'host:port' self.hopnum = hopnum # hop number self.ttl = ttl # self.nexthop = nexthop # next hop (tuple space id) """ XML format is as follows <RoutingTable name="localhost:10000"> <ts hopnum="1" tsid="localhost:10002" ttl="0"/> <ts hopnum="1" tsid="localhost:10001" ttl="256"/> <ts hopnum="0" tsid="localhost:10000" ttl="0"/> </RoutingTable> """ class RoutingTable: def __init__(self, name): self.tslist = {} self.name = name def register(self, tsid, hopnum, ttl, nexthop): if (self.tslist.has_key(tsid)): del self.tslist[tsid] self.tslist[tsid] = TSInfo(tsid, hopnum, ttl, nexthop) def deregister(self, tsid): for t in self.tslist.keys(): if self.tslist[t].nexthop == tsid: del self.tslist[t] def update(self, xmldoc, ts): rt = xml.dom.minidom.parseString(xmldoc).childNodes[0] tslist = rt.childNodes updateflag = False tmplist = [] # append tuplespace for t in tslist: if t.nodeType == t.ELEMENT_NODE and t.localName == 'ts': tsattr = t.attributes tsid = tsattr['tsid'].nodeValue hopnum = int( tsattr['hopnum'].nodeValue ) ttl = int( tsattr['ttl'].nodeValue ) nexthop = ts tmplist.append(tsid) if ((not self.tslist.has_key(tsid)) or (self.tslist[tsid].hopnum > hopnum+1)): self.register(tsid, hopnum+1, ttl, nexthop) updateflag = True # delete tuplespace for t in self.tslist.values(): if ( not t.tsid in tmplist ): updateflag = True if (t.nexthop == ts): del self.tslist[t.tsid] return updateflag def getxmldoc(self): doc = xml.dom.minidom.Document() rt = doc.createElement('RoutingTable') rt.setAttribute('name', self.name) for tskey in self.tslist.keys(): elem = doc.createElement('ts') elem.setAttribute('tsid', self.tslist[tskey].tsid) elem.setAttribute('hopnum', str(self.tslist[tskey].hopnum)) elem.setAttribute('ttl', str(self.tslist[tskey].ttl)) rt.appendChild(elem) return rt def getxml(self): rt = self.getxmldoc() return rt.toxml() def printxml(self): rt = self.getxmldoc() print rt.toprettyxml() end = time.time() print "passed time ",end def getdstname(self, xmltext): rt = xml.dom.minidom.parseString(xmltext).childNodes[0] return rt.attributes['name'].nodeValue class Routing: def __init__(self, headerFormat = ROUTING_HEADER_FORMAT): self.flinda = FederatedLinda.FederatedLinda() self.linda = None self.tsid = None self.neighbors = {} # key is tsid ("host:port"), value is Linda object self.headerFormat = headerFormat # struct.pack's format self.rt = None def __del__(self): self.linda.close() for ts in self.neighbors.values(): ts.close() def connect(self, tsid): host, port = string.split(tsid, ':', 1) ts = self.flinda.open(host, int(port)) if not ts: return None ts.getid() self.addNeighbor(ts, tsid) return ts def disconnect(self, tsid): if ( self.neighbors.has_key(tsid) ): self.delNeighbor(tsid) def addNeighbor(self, ts, tsid): self.neighbors[tsid] = ts return ts def delNeighbor(self, tsid): del self.neighbors[tsid] def pack(self, data, cmd): return struct.pack(self.headerFormat, cmd) + data def unpack(self, packet): r = struct.unpack(self.headerFormat + str(len(packet)-struct.calcsize(self.headerFormat)) + "s", packet) return r def LinkConfig(self, mytsid, packet): self.tsid = mytsid lcparser = LinkConfiguration.LinkConfigParser() linkConfig = lcparser.parseLinkConfig(self.tsid, packet) mydstlist = linkConfig.getDstlist(linkConfig.label) for n in mydstlist: tsid = linkConfig.linklist[n].tsid if ( tsid and not self.neighbors.has_key(tsid) ): ts = self.connect(tsid) ts.Out(TUPLE_ID_LINKCONFIG, packet) ts.Out(TUPLE_ID_ROUTING, self.pack(self.tsid, ROUTING_COMMAND_CONNECT)) pass def RoutingConnect(self, data): print "connect" if ( not self.neighbors.has_key(data) ): ts = self.connect(data) ts.Out(TUPLE_ID_ROUTING, self.pack(self.tsid, ROUTING_COMMAND_CONNECT)) self.rt.register(data, 1, 16, data) upedxml = self.rt.getxml() # print "Gen XML ",upedxml # print "Neighbors ",self.neighbors for nts in self.neighbors.values(): nts.Out(TUPLE_ID_ROUTING, self.pack(upedxml, ROUTING_COMMAND_UPDATE_TABLE)) pass def RoutingDisconnect(self, data): print "disconnect" if ( self.neighbors.has_key(data) ): ts = self.neighbors[data] ts.Out(TUPLE_ID_ROUTING, self.pack(self.tsid, ROUTING_COMMAND_DISCONNECT)) self.disconnect(data) self.rt.deregister(data) upedxml = self.rt.getxml() for nts in self.neighbors.values(): nts.Out(TUPLE_ID_ROUTING, self.pack(upedxml, ROUTING_COMMAND_UPDATE_TABLE)) pass def RoutingTransfer(self, data): #print "transfer" # ReplyTuple is "DstTSID,TupleID,SrcTSID,DATA" # Src/DstTSID is "hostname:portnum" dsttsid, tid, srctsid, pdata = string.split(data,',',3) print "transfer tuple:" print "dsttsid=>",dsttsid, "tid=>",tid, "srctsid=>",srctsid, "data=>",pdata if ( dsttsid == self.rt.name ): self.linda.Out(int(tid), data) else: dstts = self.neighbors[self.rt.tslist[dsttsid].nexthop] dstts.Out(TUPLE_ID_ROUTING, self.pack(data, ROUTING_COMMAND_TRANSFER)) pass def RoutingTableUpdate(self, data): print "update" srcname = self.rt.getdstname(data) if ( self.rt.update(data, srcname) ): # Send Update Info to Neighbors upedxml = self.rt.getxml() for n in self.neighbors.values(): n.Out(TUPLE_ID_ROUTING, self.pack(upedxml, ROUTING_COMMAND_UPDATE_TABLE)) pass def run(self, mytsid): self.tsid = mytsid hostname, port = string.split(mytsid, ':', 1) self.linda = self.flinda.open(hostname, int(port)) if not self.linda: return self.rt = RoutingTable(mytsid) self.rt.register(self.rt.name, 0, 0, None) self.linda.getid() # get client id from Tuple Space (ldserv) linkConfigReply = self.linda.In(TUPLE_ID_LINKCONFIG) routingReply = self.linda.In(TUPLE_ID_ROUTING) self.flinda.sync() while (True): # Link Configuration rep = linkConfigReply.reply() if (rep): linkConfigReply = self.linda.In(TUPLE_ID_LINKCONFIG) # Link Configuration main self.LinkConfig(self.tsid, rep) # Routing Protocol rep = routingReply.reply() if (rep): routingReply = self.linda.In(TUPLE_ID_ROUTING) cmd , data = self.unpack(rep) # connect to other tuplespace if (cmd == ROUTING_COMMAND_CONNECT): # connect main self.RoutingConnect(data) # disconnect other tuplespace elif (cmd == ROUTING_COMMAND_DISCONNECT): # disconnect main self.RoutingDisconnect(data) # transfer tuple elif (cmd == ROUTING_COMMAND_TRANSFER): # transfer main self.RoutingTransfer(data) # update own routing table elif (cmd == ROUTING_COMMAND_UPDATE_TABLE): #routing table main self.RoutingTableUpdate(data) else: pass print self.rt.printxml() self.flinda.sync() # end while if __name__ == '__main__': import sys if (len(sys.argv) != 2) : print "Usage : %s <hostname:portnum>" % sys.argv[0] sys.exit(1) mytsid = sys.argv[1] routing = Routing() routing.run(mytsid)