def connect(self, address): asyncore.dispatcher.connect(self, address) # UDP sockets do not connect. if self.socket.type != SOCK_DGRAM and not self.connected: if not self.connectChannel: # Prefer the sender. Do not block when sending, given that # there is a tasklet known to be waiting, this will happen. self.connectChannel = Channel(prefer_sender=True) self.connectChannel.recv()
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 __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 sendto(self, sendData, sendAddress): waitChannel = None for idx, (data, address, channel, sentBytes) in enumerate(self.sendToBuffers): if address == sendAddress: self.sendToBuffers[idx] = (data + sendData, address, channel, sentBytes) waitChannel = channel break if waitChannel is None: waitChannel = Channel(micro_send=True) self.sendToBuffers.append((sendData, sendAddress, waitChannel, 0)) return waitChannel.recv()
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()
def __init__(self, sock): # This is worth doing. I was passing in an invalid socket which was # an instance of dispatcher and it was causing tasklet death. if not isinstance(sock, stdsocket.socket): raise StandardError("Invalid socket passed to dispatcher") asyncore.dispatcher.__init__(self, sock) # if self.socket.type == SOCK_DGRAM: # self.dgramRecvChannels = {} # self.dgramReadBuffers = {} #else: self.recvChannel = Channel(micro_send=True) self.readBufferString = '' self.readBufferList = [] self.sendBuffer = '' self.sendToBuffers = [] self.maxreceivebuf = 65536
def __init__(self, sock): # This is worth doing. I was passing in an invalid socket which was # an instance of dispatcher and it was causing tasklet death. if not isinstance(sock, stdsocket.socket): raise StandardError("Invalid socket passed to dispatcher") asyncore.dispatcher.__init__(self, sock) # if self.socket.type == SOCK_DGRAM: # self.dgramRecvChannels = {} # self.dgramReadBuffers = {} #else: self.recvChannel = Channel(micro_send=True) self.readBufferString = '' self.readBufferList = [] self.sendBuffer = '' self.sendToBuffers = [] self.maxreceivebuf=65536
micro(f, (8, 8)) mvoid() F1 = foo(1) F2 = foo(2) F1.void() F2.void() def xf(): print 'xf2', 1 c = Channel() csend(c, 1) micro(xf) crecv(c, 1) #print '---Atomic test---' def xf(): print 'xf4', 3 c = Channel(prefer_sender=False) crecv(c, 3) micro(xf) csend_atomic(c, 3)
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()
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]
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()
def __init__(self): self.curtime = 0 self.queue = [] self.looping = False self.simchan = Channel()
class dispatcher(asyncore.dispatcher): connectChannel = None acceptChannel = None recvChannel = None def __init__(self, sock): # This is worth doing. I was passing in an invalid socket which was # an instance of dispatcher and it was causing tasklet death. if not isinstance(sock, stdsocket.socket): raise StandardError("Invalid socket passed to dispatcher") asyncore.dispatcher.__init__(self, sock) # if self.socket.type == SOCK_DGRAM: # self.dgramRecvChannels = {} # self.dgramReadBuffers = {} #else: self.recvChannel = Channel(micro_send=True) self.readBufferString = '' self.readBufferList = [] self.sendBuffer = '' self.sendToBuffers = [] self.maxreceivebuf = 65536 def writable(self): if self.socket.type != SOCK_DGRAM and not self.connected: return True return len(self.sendBuffer) or len(self.sendToBuffers) def accept(self): if not self.acceptChannel: self.acceptChannel = Channel(micro_send=True) return self.acceptChannel.recv() def connect(self, address): asyncore.dispatcher.connect(self, address) # UDP sockets do not connect. if self.socket.type != SOCK_DGRAM and not self.connected: if not self.connectChannel: # Prefer the sender. Do not block when sending, given that # there is a tasklet known to be waiting, this will happen. self.connectChannel = Channel(prefer_sender=True) self.connectChannel.recv() def send(self, data): self.sendBuffer += data micro_block() return len(data) def sendall(self, data): # WARNING: this will busy wait until all data is sent # It should be possible to do away with the busy wait with # the use of a channel. self.sendBuffer += data while self.sendBuffer: micro_block() return len(data) def sendto(self, sendData, sendAddress): waitChannel = None for idx, (data, address, channel, sentBytes) in enumerate(self.sendToBuffers): if address == sendAddress: self.sendToBuffers[idx] = (data + sendData, address, channel, sentBytes) waitChannel = channel break if waitChannel is None: waitChannel = Channel(micro_send=True) self.sendToBuffers.append((sendData, sendAddress, waitChannel, 0)) return waitChannel.recv() # Read at most byteCount bytes. def recv(self, byteCount): self.maxreceivebuf = byteCount if len(self.readBufferString) < byteCount: # If our buffer is empty, we must block for more data we also # aggressively request more if it's available. if len(self.readBufferString ) == 0 or self.recvChannel.ch.balance > 0: self.readBufferString += self.recvChannel.recv() # Disabling this because I believe it is the onus of the application # to be aware of the need to run the scheduler to give other tasklets # leeway to run. # stackless.schedule() ret = self.readBufferString[:byteCount] self.readBufferString = self.readBufferString[byteCount:] return ret def recvfrom(self, byteCount): ret = "" address = None self.maxreceivebuf = byteCount return self.recvChannel.recv() def close(self): asyncore.dispatcher.close(self) self.connected = False self.accepting = False self.sendBuffer = '' # breaks the loop in sendall # Clear out all the channels with relevant errors. if self.acceptChannel is not None: while self.acceptChannel and self.acceptChannel.ch.balance < 0: self.acceptChannel.send_exception(error, 9, 'Bad file descriptor') if self.connectChannel is not None: while self.connectChannel and self.connectChannel.ch.balance < 0: self.connectChannel.send_exception(error, 10061, 'Connection refused') if self.recvChannel is not None: while self.recvChannel and self.recvChannel.ch.balance < 0: # The closing of a socket is indicted by receiving nothing. The # exception would have been sent if the server was killed, rather # than closed down gracefully. self.recvChannel.ch.send("") #self.recvChannel.send_exception(error, 10054, 'Connection reset by peer') # asyncore doesn't support this. Why not? def fileno(self): # XXX: self.socket.fileno() raises a Bad file descriptor error. # Therefore, we're using _fileno as a hack. This has to be # cleaned. # return self.socket.fileno() return self._fileno def handle_accept(self): if self.acceptChannel and self.acceptChannel.ch.balance < 0: currentSocket, clientAddress = asyncore.dispatcher.accept(self) currentSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # Give them the asyncore based socket, not the standard one. currentSocket = self.wrap_accept_socket(currentSocket) self.acceptChannel.send((currentSocket, clientAddress)) # Inform the blocked connect call that the connection has been made. def handle_connect(self): if self.socket.type != SOCK_DGRAM and self.connectChannel is not None: self.connectChannel.send(None) # Asyncore says its done but self.readBuffer may be non-empty # so can't close yet. Do nothing and let 'recv' trigger the close. def handle_close(self): pass # Some error, just close the channel and let that raise errors to # blocked calls. def handle_expt(self): self.close() def handle_read(self): try: if self.socket.type == SOCK_DGRAM: ret, address = self.socket.recvfrom(self.maxreceivebuf) self.recvChannel.send((ret, address)) else: ret = asyncore.dispatcher.recv(self, self.maxreceivebuf) # Not sure this is correct, but it seems to give the # right behaviour. Namely removing the socket from # asyncore. if not ret: self.close() self.recvChannel.send(ret) except stdsocket.error, err: # XXX Is this correct? # If there's a read error assume the connection is # broken and drop any pending output if self.sendBuffer: self.sendBuffer = "" # Why can't I pass the 'err' by itself? self.recvChannel.ch.send_exception(stdsocket.error, err)
def accept(self): if not self.acceptChannel: self.acceptChannel = Channel(micro_send=True) return self.acceptChannel.recv()
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 dispatcher(asyncore.dispatcher): connectChannel = None acceptChannel = None recvChannel = None def __init__(self, sock): # This is worth doing. I was passing in an invalid socket which was # an instance of dispatcher and it was causing tasklet death. if not isinstance(sock, stdsocket.socket): raise StandardError("Invalid socket passed to dispatcher") asyncore.dispatcher.__init__(self, sock) # if self.socket.type == SOCK_DGRAM: # self.dgramRecvChannels = {} # self.dgramReadBuffers = {} #else: self.recvChannel = Channel(micro_send=True) self.readBufferString = '' self.readBufferList = [] self.sendBuffer = '' self.sendToBuffers = [] self.maxreceivebuf=65536 def writable(self): if self.socket.type != SOCK_DGRAM and not self.connected: return True return len(self.sendBuffer) or len(self.sendToBuffers) def accept(self): if not self.acceptChannel: self.acceptChannel = Channel(micro_send=True) return self.acceptChannel.recv() def connect(self, address): asyncore.dispatcher.connect(self, address) # UDP sockets do not connect. if self.socket.type != SOCK_DGRAM and not self.connected: if not self.connectChannel: # Prefer the sender. Do not block when sending, given that # there is a tasklet known to be waiting, this will happen. self.connectChannel = Channel(prefer_sender=True) self.connectChannel.recv() def send(self, data): self.sendBuffer += data micro_block() return len(data) def sendall(self, data): # WARNING: this will busy wait until all data is sent # It should be possible to do away with the busy wait with # the use of a channel. self.sendBuffer += data while self.sendBuffer: micro_block() return len(data) def sendto(self, sendData, sendAddress): waitChannel = None for idx, (data, address, channel, sentBytes) in enumerate(self.sendToBuffers): if address == sendAddress: self.sendToBuffers[idx] = (data + sendData, address, channel, sentBytes) waitChannel = channel break if waitChannel is None: waitChannel = Channel(micro_send=True) self.sendToBuffers.append((sendData, sendAddress, waitChannel, 0)) return waitChannel.recv() # Read at most byteCount bytes. def recv(self, byteCount): self.maxreceivebuf=byteCount if len(self.readBufferString) < byteCount: # If our buffer is empty, we must block for more data we also # aggressively request more if it's available. if len(self.readBufferString) == 0 or self.recvChannel.ch.balance > 0: self.readBufferString += self.recvChannel.recv() # Disabling this because I believe it is the onus of the application # to be aware of the need to run the scheduler to give other tasklets # leeway to run. # stackless.schedule() ret = self.readBufferString[:byteCount] self.readBufferString = self.readBufferString[byteCount:] return ret def recvfrom(self, byteCount): ret = "" address = None self.maxreceivebuf=byteCount return self.recvChannel.recv() def close(self): asyncore.dispatcher.close(self) self.connected = False self.accepting = False self.sendBuffer = '' # breaks the loop in sendall # Clear out all the channels with relevant errors. if self.acceptChannel is not None: while self.acceptChannel and self.acceptChannel.ch.balance < 0: self.acceptChannel.send_exception(error, 9, 'Bad file descriptor') if self.connectChannel is not None: while self.connectChannel and self.connectChannel.ch.balance < 0: self.connectChannel.send_exception(error, 10061, 'Connection refused') if self.recvChannel is not None: while self.recvChannel and self.recvChannel.ch.balance < 0: # The closing of a socket is indicted by receiving nothing. The # exception would have been sent if the server was killed, rather # than closed down gracefully. self.recvChannel.ch.send("") #self.recvChannel.send_exception(error, 10054, 'Connection reset by peer') # asyncore doesn't support this. Why not? def fileno(self): # XXX: self.socket.fileno() raises a Bad file descriptor error. # Therefore, we're using _fileno as a hack. This has to be # cleaned. # return self.socket.fileno() return self._fileno def handle_accept(self): if self.acceptChannel and self.acceptChannel.ch.balance < 0: currentSocket, clientAddress = asyncore.dispatcher.accept(self) currentSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # Give them the asyncore based socket, not the standard one. currentSocket = self.wrap_accept_socket(currentSocket) self.acceptChannel.send((currentSocket, clientAddress)) # Inform the blocked connect call that the connection has been made. def handle_connect(self): if self.socket.type != SOCK_DGRAM and self.connectChannel is not None: self.connectChannel.send(None) # Asyncore says its done but self.readBuffer may be non-empty # so can't close yet. Do nothing and let 'recv' trigger the close. def handle_close(self): pass # Some error, just close the channel and let that raise errors to # blocked calls. def handle_expt(self): self.close() def handle_read(self): try: if self.socket.type == SOCK_DGRAM: ret, address = self.socket.recvfrom(self.maxreceivebuf) self.recvChannel.send((ret, address)) else: ret = asyncore.dispatcher.recv(self, self.maxreceivebuf) # Not sure this is correct, but it seems to give the # right behaviour. Namely removing the socket from # asyncore. if not ret: self.close() self.recvChannel.send(ret) except stdsocket.error, err: # XXX Is this correct? # If there's a read error assume the connection is # broken and drop any pending output if self.sendBuffer: self.sendBuffer = "" # Why can't I pass the 'err' by itself? self.recvChannel.ch.send_exception(stdsocket.error, err)
import sys sys.path.append('../../') import traceback import random from random import randint import pdb from ntk.sim.net import Net import ntk.sim.sim as sim import ntk.sim.wrap.xtime as xtime from ntk.lib.micro import micro, microfunc, allmicro_run, Channel ch = Channel() ch2 = Channel(True) ch3 = Channel() T = [] def myxtime(): t = xtime.time() T.append(t) return t @microfunc(True) def f(x): ch2.recv() print 'ch2'