Skip to content
Snippets Groups Projects
node.py 3.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Jarrod Pas's avatar
    Jarrod Pas committed
    from collections import Iterable
    
    
    from simpy import Store
    
    
    Jarrod Pas's avatar
    Jarrod Pas committed
    from .buffer import Buffer
    from .core import TickProcess
    
    def NodeFactory(router, **kwargs):
        def factory(network, nid):
            return Node(network, nid, router=router, **kwargs)
        return factory
    
    
    class Node(TickProcess):
        ''''''
        def __init__(self, network, nid,
                     buffer_size=None, tick_time=1, router=None):
            ''''''
            super().__init__(tick_time)
            self.env = network.env
            self.network = network
            self.id = nid
    
    
            self.bandwidth = float('inf')
    
    
    Jarrod Pas's avatar
    Jarrod Pas committed
            self.buffer = Buffer(self.env, capacity=buffer_size)
    
            if router is None:
                router = routers['direct']
            self.router = router(self)
    
            self.start(self.env)
    
    
            self.transfer_queue = Store(self.env)
    
    
    Jarrod Pas's avatar
    Jarrod Pas committed
        def route_packets(self):
            packets_to_delete = []
    
            for packet in self.buffer:
                # remove expired packets from buffer
                if packet.expired(self.env.now):
                    packets_to_delete.append(packet)
                    continue
    
                # ask the router what to do
                targets, reason, delete = self.router(packet)
    
                # check if there are targets to send to
                if targets is None:
                    continue
    
                # allow for targets to be iterable or single item
                if not isinstance(targets, Iterable):
                    targets = [targets]
    
    
                # add the packet to the transfer queue
                self.transfer_queue.put((packet, targets, reason))
                #self.send(targets, packet, reason)
    
    Jarrod Pas's avatar
    Jarrod Pas committed
    
                # if the router requested deletion from the buffer do it
                if delete:
                    packets_to_delete.append(packet)
    
    
    Jarrod Pas's avatar
    Jarrod Pas committed
            for packet in packets_to_delete:
                self.buffer.remove(packet)
    
        def process(self, **kwargs):
            ''''''
            while True:
    
                packet, targets, reason = yield self.transfer_queue.get()
    
                # simulate transfer delay of packet
                delay = packet.size / self.bandwidth
                yield self.env.timeout(delay)
    
                success = []
                # simulates broadcast
                for target in targets:
                    # try sending packet
                    if self.network.send_link(self, target, packet):
                        success.append(target)
                        self.router.on_send_success(target, packet)
                    else:
                        self.router.on_send_failure(target, packet)
    
                packet.send(self, success, reason=reason)
    
    
    Jarrod Pas's avatar
    Jarrod Pas committed
        def recv(self, packet):
            if packet.destination == self:
                packet.recv()
            else:
                self.buffer.add(packet)
    
        @property
        def community(self):
            return self.network.community[self]
    
    
        def connected_to(self, other):
            return self.network[self][other]['state']
    
    
    Jarrod Pas's avatar
    Jarrod Pas committed
        @property
        def links(self):
            '''
            Returns a list of connected links.
            '''
    
            return {
    
    Jarrod Pas's avatar
    Jarrod Pas committed
                met: data
                for met, data in self.network[self].items()
    
                if self.connected_to(met)
    
    Jarrod Pas's avatar
    Jarrod Pas committed
            }
    
        def __repr__(self):
            return 'Node(id={})'.format(self.id)