예제 #1
0
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()
예제 #2
0
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()
예제 #3
0
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]
예제 #4
0
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]