#! /usr/bin/python # -*- coding: utf-8 -*- __author__ = 'Stefano Vissicchio ' # Copyright (C) 2013-2017 by # Stefano Vissicchio # All rights reserved. # BSD license. class Fed: def __init__(self): self._init_internal_structures() def _init_internal_structures(self): self.dup_entries = {} # map {router_with_dup_entries: set_of_dests_needing_dup_entries} self.updated_nodes = set() self.num_dup = 0 ### interface functions ### def get_dup_entries(self): return self.dup_entries def get_num_dup_entries(self): return self.num_dup def get_updated_nodes(self): return self.updated_nodes def add_duplication_steps(self,graph,nh_init,nh_final,non_migrated_nodes,unsafe_dests,alg_seq,map_unsafe_dests2nodes=None): self._init_internal_structures() new_seq = self._elaborate_node_seq(alg_seq) if map_unsafe_dests2nodes == None: map_unsafe_dests2nodes = {} for d in unsafe_dests: map_unsafe_dests2nodes[d] = set(non_migrated_nodes) if len(non_migrated_nodes) > 0: border_map = self._get_border_nodes(nh_init,nh_final,map_unsafe_dests2nodes) new_seq = self._add_prepare_match_tag(new_seq,border_map,map_unsafe_dests2nodes) new_seq.append(self._swap_tags(border_map)) new_seq.append(self._update_nodes(non_migrated_nodes)) new_seq.append(self._clean_borders(border_map)) return new_seq ### helper functions ### def _elaborate_node_seq(self,seq): new_seq = [] for elem in seq: new_elem = set() for n in elem: new_elem.add("upd_" + n) self.updated_nodes.add(n) new_seq.append(new_elem) return new_seq def _get_border_nodes(self,nh_init,nh_final,unsafe_dests): borders = {} for d in unsafe_dests: borders[d] = self._get_border_nodes_destination(nh_init[d]).union(self._get_border_nodes_destination(nh_final[d])) return borders def _get_border_nodes_destination(self,d_nh_fun): all_nodes = set() non_src_nodes = set() for k in d_nh_fun: all_nodes.add(k) non_src_nodes = non_src_nodes.union(d_nh_fun[k]) return all_nodes.difference(non_src_nodes) def _add_prepare_match_tag(self,new_seq,border_map,map_unsafe_dests2nodes): match_tag_ops = set() for d in border_map: for bnd in border_map[d]: match_tag_ops.add("tag_" + bnd + "_" + d + "_init") for nm in map_unsafe_dests2nodes[d]: match_tag_ops.add("duplicate_" + nm + "_" + d) self._add_dup_entry(nm,d) first_elem = new_seq.pop(0) new_seq.insert(0,first_elem.union(match_tag_ops)) return new_seq def _add_dup_entry(self,router,dest): if not self.dup_entries.has_key(router): self.dup_entries[router] = {} self.dup_entries[router][router + "_" + dest] = 1 self.num_dup += 1 def _swap_tags(self,border_map): swap_ops = set() for d in border_map: for bnd in border_map[d]: swap_ops.add("tag_" + bnd + "_" + d + "_fin") return swap_ops def _update_nodes(self,nodes): update_ops = set() for n in nodes: update_ops.add("upd_" + n) self.updated_nodes.add(n) return update_ops def _clean_borders(self,border_map): clean_ops = set() for d in border_map: for bnd in border_map[d]: clean_ops.add("no_tag_" + bnd) return clean_ops