Newer
Older
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.buffer = Buffer(self.env, capacity=buffer_size)
if router is None:
router = routers['direct']
self.router = router(self)
self.start(self.env)
def route_packet(self, packet):
'''
Applies the routing heuristic to packet and queues packet for
transfer if requested
Returns:
True - if the packet should be deleted from the buffer
False - otherwise
'''
# check if packet has expired
if packet.expired(self.env.now):
return True
# ask the router what to do
targets, reason, delete = self.router(packet)
# check if there are targets to send to
if targets is None:
return False
# 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))
return delete
def route_packets(self):
'''
Applies the routing heuristic to all packets in the buffer and
queues transfers if requested. Additionally, removes packets
from the buffer if the packet has exipred or if the router
requests the packet to be removed.
'''
for packet in self.buffer:
delete = self.route_packet(packet)
if delete:
packets_to_delete.append(packet)
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
success.append(target)
self.router.on_send_success(target, packet)
else:
self.router.on_send_failure(target, packet)
packet.send(self, success, reason=reason)
if failed:
delete = self.route_packet(packet)
if delete:
self.buffer.remove(packet)
def send(self, target, packet):
'''
Instantly sends a packet to a target if they are connected.
Returns:
True - if successful
False - otherwise
'''
if self.connected_to(target):
return target.recv(packet)
else:
return False
'''
Tells the node to recieve a packet.
Returns:
True - if the node was able to recieved the packet.
False - otherwise, triggered by buffer being full.
'''
if packet.destination == self:
packet.recv()
@property
def community(self):
return self.network.community[self]
def connected_to(self, other):
return self.network[self][other]['state']
@property
def links(self):
'''
Returns a list of connected links.
'''
met: data
for met, data in self.network[self].items()
}
def __repr__(self):
return 'Node(id={})'.format(self.id)