class Simulator(object): """This is a Descrete Event Simulator *WARNING* Inside a simulated function, do not directly use `channel.send' of python stackless, because you'll mess with the schedule of the simulator. Use instead @microfunc(true/false), or Channel(True) (see lib/micro.py) *WARNING* """ def __init__(self): self.curtime = 0 self.queue = [] self.looping = False self.simchan = Channel() def ev_add(self, ev): ev.abs_time = self.curtime+ev.exec_time heappush(self.queue, ev) if self.curtime > 0 and not self.looping: self.simchan.sendq(1) def ev_exec(self): ev = heappop(self.queue) self.curtime = ev.abs_time ev.callf(*ev.callf_args) def loop(self): self.looping = True while self.queue != []: self.ev_exec() self.looping = False def _wake_up_wait(self, chan): chan.send(()) def wait(self, t): """Waits the specified number of time units""" chan = Channel() self.ev_add( SimEvent(t, self._wake_up_wait, (chan,)) ) chan.recv() @microfunc(True) def run(self): while 1: self.loop() self.simchan.recvq()
class Simulator(object): """This is a Descrete Event Simulator *WARNING* Inside a simulated function, do not directly use `channel.send' of python stackless, because you'll mess with the schedule of the simulator. Use instead @microfunc(true/false), or Channel(True) (see lib/micro.py) *WARNING* """ def __init__(self): self.curtime = 0 self.queue = [] self.looping = False self.simchan = Channel() def ev_add(self, ev): ev.abs_time = self.curtime + ev.exec_time heappush(self.queue, ev) if self.curtime > 0 and not self.looping: self.simchan.sendq(1) def ev_exec(self): ev = heappop(self.queue) self.curtime = ev.abs_time ev.callf(*ev.callf_args) def loop(self): self.looping = True while self.queue != []: self.ev_exec() self.looping = False def _wake_up_wait(self, chan): chan.send(()) def wait(self, t): """Waits the specified number of time units""" chan = Channel() self.ev_add(SimEvent(t, self._wake_up_wait, (chan, ))) chan.recv() @microfunc(True) def run(self): while 1: self.loop() self.simchan.recvq()
class Node(object): __slots__ = ['neighbours', 'recv_chan', 'accept_chan', 'sk_in', 'sk_out', 'ip'] def __init__(self, ip=None, neighs={}): self.change_ip(ip) # {Node: Link} self.neighbours = {} self.recv_chan = Channel() self.accept_chan = Channel() self.sk_in = {} # {sk: sk_chan} self.sk_out = {} # {sk: sk_chan} def change_ip(self, newip=None): self.ip=newip if self.ip == None: self.ip=randint(1, 2**32-1) def __hash__(self): return self.ip def neigh_add(self, n, link): self.neighbours[n]=link n.neighbours[self]=link # the links are symmetric def neigh_del(self, n): if n in self.neighbours: del self.neighbours[n] del n.neighbours[self] def neigh_del_all(self): for n in self.neighbours: self.neigh_del(n) def calc_time(self, d, sz): """Return the time necessary to send a packet of size `sz', from `self' to `d'""" return self.neighbours[d].rtt+float(sz)/self.neighbours[d].bw ## Non socket based def sendto(self, dst, msg): """dst: the destination neighbour msg: the packet itself. It must be a string! On error hell will be raised""" if not isinstance(msg, str): raise ESendMsg, ESendMsg.errstr if dst not in self.neighbours: raise ENotNeigh, ENotNeigh.errstr msglen = len(msg) ev = SimEvent(self.calc_time(dst, msglen), dst._sendto, (self, msg)) sim.cursim.ev_add(ev) return msglen def _sendto(self, sender, msg): """Send the msg to the recv channel""" self.recv_chan.sendq((sender, msg)) def sendtoall(self, msg): """Send the msg to all neighbours""" for n in self.neighbours: self.sendto(n, msg) def recvfrom(self): """Returns the (sender, msg) pair""" return self.recv_chan.recvq() ## Socket based def connect(self, dst): """Returns sk_chan, the Channel() of the new established socket""" if dst not in self.neighbours: raise ENotNeigh, ENotNeigh.errstr sk = randint(1, 2**32-1) self.sk_out[sk]=Channel() self.sk_in[sk]=Channel() dst.accept_chan.send((self, sk, self.sk_in[sk], self.sk_out[sk])) return sk def accept(self): """Returns (sk, src), where sk is the new established socket and `src' is the instance of the source node""" src, sk, sk_out, sk_in = self.accept_chan.recv() self.sk_out[sk]=sk_out self.sk_in[sk] =sk_in return sk, src def send(self, dst, sk, msg): if not isinstance(msg, str): raise ESendMsg, ESendMsg.errstr try: sk_chan = self.sk_out[sk] except KeyError: raise ESkt, ESkt.errstr msglen = len(msg) ev = SimEvent(self.calc_time(dst, msglen), dst._send, (sk_chan, msg)) sim.cursim.ev_add(ev) return msglen def _send(self, sk_chan, msg): sk_chan.sendq(msg) def recv(self, sk): try: sk_chan = self.sk_in[sk] except KeyError: raise ESkt, ESkt.errstr return sk_chan.recvq() def close(self, dst, sk): if sk in dst.sk_in: del dst.sk_in[sk] del dst.sk_out[sk] if sk in self.sk_in: del self.sk_in[sk] del self.sk_out[sk]
class Node(object): __slots__ = [ 'neighbours', 'recv_chan', 'accept_chan', 'sk_in', 'sk_out', 'ip' ] def __init__(self, ip=None, neighs={}): self.change_ip(ip) # {Node: Link} self.neighbours = {} self.recv_chan = Channel() self.accept_chan = Channel() self.sk_in = {} # {sk: sk_chan} self.sk_out = {} # {sk: sk_chan} def change_ip(self, newip=None): self.ip = newip if self.ip == None: self.ip = randint(1, 2**32 - 1) def __hash__(self): return self.ip def neigh_add(self, n, link): self.neighbours[n] = link n.neighbours[self] = link # the links are symmetric def neigh_del(self, n): if n in self.neighbours: del self.neighbours[n] del n.neighbours[self] def neigh_del_all(self): for n in self.neighbours: self.neigh_del(n) def calc_time(self, d, sz): """Return the time necessary to send a packet of size `sz', from `self' to `d'""" return self.neighbours[d].rtt + float(sz) / self.neighbours[d].bw ## Non socket based def sendto(self, dst, msg): """dst: the destination neighbour msg: the packet itself. It must be a string! On error hell will be raised""" if not isinstance(msg, str): raise ESendMsg, ESendMsg.errstr if dst not in self.neighbours: raise ENotNeigh, ENotNeigh.errstr msglen = len(msg) ev = SimEvent(self.calc_time(dst, msglen), dst._sendto, (self, msg)) sim.cursim.ev_add(ev) return msglen def _sendto(self, sender, msg): """Send the msg to the recv channel""" self.recv_chan.sendq((sender, msg)) def sendtoall(self, msg): """Send the msg to all neighbours""" for n in self.neighbours: self.sendto(n, msg) def recvfrom(self): """Returns the (sender, msg) pair""" return self.recv_chan.recvq() ## Socket based def connect(self, dst): """Returns sk_chan, the Channel() of the new established socket""" if dst not in self.neighbours: raise ENotNeigh, ENotNeigh.errstr sk = randint(1, 2**32 - 1) self.sk_out[sk] = Channel() self.sk_in[sk] = Channel() dst.accept_chan.send((self, sk, self.sk_in[sk], self.sk_out[sk])) return sk def accept(self): """Returns (sk, src), where sk is the new established socket and `src' is the instance of the source node""" src, sk, sk_out, sk_in = self.accept_chan.recv() self.sk_out[sk] = sk_out self.sk_in[sk] = sk_in return sk, src def send(self, dst, sk, msg): if not isinstance(msg, str): raise ESendMsg, ESendMsg.errstr try: sk_chan = self.sk_out[sk] except KeyError: raise ESkt, ESkt.errstr msglen = len(msg) ev = SimEvent(self.calc_time(dst, msglen), dst._send, (sk_chan, msg)) sim.cursim.ev_add(ev) return msglen def _send(self, sk_chan, msg): sk_chan.sendq(msg) def recv(self, sk): try: sk_chan = self.sk_in[sk] except KeyError: raise ESkt, ESkt.errstr return sk_chan.recvq() def close(self, dst, sk): if sk in dst.sk_in: del dst.sk_in[sk] del dst.sk_out[sk] if sk in self.sk_in: del self.sk_in[sk] del self.sk_out[sk]