class HashrouteSymmetric(BaseStrategy): """Hashroute with symmetric routing """ def __init__(self, topology, log_dir, scenario_id, params=None): ''' Constructor ''' super(HashrouteSymmetric, self).__init__(topology, log_dir, scenario_id) # map id of content to node with cache responsibility self.cache_assignment = self.assign_caches(topology, self.cache_size, replicas=1) self.stretch_logger = StretchLogger(path.join(log_dir, 'RESULTS_%s_STRETCH.txt' % scenario_id)) def handle_event(self, time, event): # get all required data receiver = event['receiver'] content = event['content'] log = event['log'] source = self.content_location[content] cache = self.cache_assignment[self.content_hash(content)] # handle (and log if required) actual request if log: self.log_transfer(time, receiver, cache, PACKET_TYPE_INTEREST, content) has_content = self.caches[cache].has_content(content) if has_content and log: self.cache_logger.log_cache_info(time, EVENT_CACHE_HIT, content, receiver, cache, source) self.log_transfer(time, cache, receiver, PACKET_TYPE_DATA, content) return else: if log: self.log_transfer(time, cache, source, PACKET_TYPE_INTEREST, content) self.cache_logger.log_cache_info(time, EVENT_SERVER_HIT, content, receiver, cache, source) self.log_transfer(time, source, cache, PACKET_TYPE_DATA, content) # pass via cache self.log_transfer(time, cache, receiver, PACKET_TYPE_DATA, content) optimal_path_len = len(self.shortest_path[source][receiver]) - 1 actual_path_len = len(self.shortest_path[source][cache]) + len(self.shortest_path[cache][receiver]) - 2 self.stretch_logger.log_stretch_info(time, receiver, source, content, optimal_path_len, actual_path_len) self.caches[cache].store(content) # insert content return def close(self): super(HashrouteSymmetric, self).close() self.stretch_logger.close()
class HashrouteHybridSymmMCast(BaseStrategy): """ Hashroute implementation with hybrid delivery of Data packets. In this implementation, the edge router receiving a DATA packet decides whether to deliver the packet using Multicast or asymmetric hashroute based on the total cost for delivering the Data to both cache and receiver in terms of hops. """ def __init__(self, topology, log_dir, scenario_id, params=None): ''' Constructor ''' super(HashrouteHybridSymmMCast, self).__init__(topology, log_dir, scenario_id) # map id of content to node with cache responsibility self.cache_assignment = self.assign_caches(topology, self.cache_size, replicas=1) self.stretch_logger = StretchLogger(path.join(log_dir, 'RESULTS_%s_STRETCH.txt' % scenario_id)) self.scenario_id = scenario_id self.symm_count = 0 self.mcast_count = 0 def handle_event(self, time, event): # get all required data receiver = event['receiver'] content = event['content'] log = event['log'] source = self.content_location[content] cache = self.cache_assignment[self.content_hash(content)] # handle (and log if required) actual request if log: self.log_transfer(time, receiver, cache, PACKET_TYPE_INTEREST, content) has_content = self.caches[cache].has_content(content) if has_content and log: self.cache_logger.log_cache_info(time, EVENT_CACHE_HIT, content, receiver, cache, source) self.log_transfer(time, cache, receiver, PACKET_TYPE_DATA, content) else: if log: self.log_transfer(time, cache, source, PACKET_TYPE_INTEREST, content) self.cache_logger.log_cache_info(time, EVENT_SERVER_HIT, content, receiver, cache, source) if cache in self.shortest_path[source][receiver]: self.caches[cache].store(content) # insert content if log: self.log_transfer(time, source, cache, PACKET_TYPE_DATA, content) # pass via cache self.log_transfer(time, cache, receiver, PACKET_TYPE_DATA, content) # pass via cache path_len = len(self.shortest_path[source][receiver]) self.stretch_logger.log_stretch_info(time, receiver, source, content, path_len, path_len) return else: #do multicast here cache_path = self.shortest_path[source][cache] recv_path = self.shortest_path[source][receiver] # find what is the node that has to fork the DATA packet for i in range(1, min([len(cache_path), len(recv_path)])): if cache_path[i] != recv_path[i]: fork_node = cache_path[i-1] break else: fork_node = cache optimal_path_len = len(self.shortest_path[source][receiver]) symmetric_path_len = len(self.shortest_path[source][cache]) + \ len(self.shortest_path[cache][receiver]) - 2 multicast_path_len = len(self.shortest_path[source][fork_node]) + \ len(self.shortest_path[fork_node][cache]) + \ len(self.shortest_path[fork_node][receiver]) - 3 # insert content in cache self.caches[cache].store(content) # decide if use symmetric or multicast depending on total costs if symmetric_path_len < multicast_path_len: # use symmetric delivery if log: self.symm_count += 1 self.log_transfer(time, source, cache, PACKET_TYPE_DATA, content) self.log_transfer(time, cache, receiver, PACKET_TYPE_DATA, content) self.stretch_logger.log_stretch_info(time, receiver, source, content, optimal_path_len, symmetric_path_len) else: # use multicast delivery if log: self.mcast_count += 1 self.log_transfer(time, source, fork_node, PACKET_TYPE_DATA, content) self.log_transfer(time, fork_node, receiver, PACKET_TYPE_DATA, content) self.log_transfer(time, fork_node, cache, PACKET_TYPE_DATA, content) self.stretch_logger.log_stretch_info(time, receiver, source, content, optimal_path_len, multicast_path_len) def close(self): super(HashrouteHybridSymmMCast, self).close() self.stretch_logger.close()
class HashrouteHybridStretch(BaseStrategy): """ Hashroute implementation with hybrid delivery of Data packets. In this strategy, if there is a cache miss, when DATA packets returns in the domain, the packet is multicasted, one copy being sent to the authoritative cache and the other to the receiver. If the cache is on the path from source to receiver, this strategy behaves as a normal asymmetric HashRoute """ def __init__(self, topology, log_dir, scenario_id, params=None): ''' Constructor ''' super(HashrouteHybridStretch, self).__init__(topology, log_dir, scenario_id) # map id of content to node with cache responsibility params = {'max_stretch': 0.2} self.cache_assignment = self.assign_caches(topology, self.cache_size, replicas=1) self.max_stretch = nx.diameter(topology) * params['max_stretch'] self.stretch_logger = StretchLogger(path.join(log_dir, 'RESULTS_%s_STRETCH.txt' % scenario_id)) def handle_event(self, time, event): # get all required data receiver = event['receiver'] content = event['content'] log = event['log'] source = self.content_location[content] cache = self.cache_assignment[self.content_hash(content)] # handle (and log if required) actual request if log: self.log_transfer(time, receiver, cache, PACKET_TYPE_INTEREST, content) has_content = self.caches[cache].has_content(content) if has_content and log: self.cache_logger.log_cache_info(time, EVENT_CACHE_HIT, content, receiver, cache, source) self.log_transfer(time, cache, receiver, PACKET_TYPE_DATA, content) else: if log: self.log_transfer(time, cache, source, PACKET_TYPE_INTEREST, content) self.cache_logger.log_cache_info(time, EVENT_SERVER_HIT, content, receiver, cache, source) if cache in self.shortest_path[source][receiver]: self.caches[cache].store(content) # insert content if log: self.log_transfer(time, source, cache, PACKET_TYPE_DATA, content) # pass via cache self.log_transfer(time, cache, receiver, PACKET_TYPE_DATA, content) # pass via cache path_len = len(self.shortest_path[source][receiver]) self.stretch_logger.log_stretch_info(time, receiver, source, content, path_len, path_len) return else: #do multicast here cache_path = self.shortest_path[source][cache] recv_path = self.shortest_path[source][receiver] # find what is the node that has to fork the DATA packet for i in range(1, min([len(cache_path), len(recv_path)])): if cache_path[i] != recv_path[i]: fork_node = cache_path[i-1] break else: fork_node = cache optimal_path_len = len(self.shortest_path[source][receiver]) - 1 actual_path_len = len(self.shortest_path[source][fork_node]) + \ len(self.shortest_path[fork_node][cache]) + \ len(self.shortest_path[fork_node][receiver]) - 3 # multicast to cache only if stretch is under threshold go_to_cache = ((actual_path_len - optimal_path_len) < self.max_stretch) if go_to_cache: self.caches[cache].store(content) if log: self.log_transfer(time, source, fork_node, PACKET_TYPE_DATA, content) self.log_transfer(time, fork_node, receiver, PACKET_TYPE_DATA, content) if go_to_cache: self.log_transfer(time, fork_node, cache, PACKET_TYPE_DATA, content) self.stretch_logger.log_stretch_info(time, receiver, source, content, optimal_path_len, actual_path_len) def close(self): super(HashrouteHybridStretch, self).close() self.stretch_logger.close()