def percentages(self): """ Returns parts of DHT ring each node and each node backend occupies (in percents)\n print routes.percentages() """ perc = {} for group in self.groups(): routes = self.filter_by_group(group) perc[group] = {} for i, r in enumerate(routes[1:]): prev = routes[i] amount = int(str(r.id), 16) - int(str(prev.id), 16) if prev.address not in perc[group]: perc[group][prev.address] = {prev.backend_id: amount} elif prev.backend_id not in perc[group][prev.address]: perc[group][prev.address][prev.backend_id] = amount else: perc[group][prev.address][prev.backend_id] += amount max = int(str(Id([255] * 64, 0)), 16) for group in perc: sum = 0 for address in perc[group]: address_sum = 0 for backend in perc[group][address]: sum += perc[group][address][backend] address_sum += perc[group][address][backend] perc[group][address][ backend] = perc[group][address][backend] * 100.0 / max perc[group][address]['total'] = address_sum * 100.0 / max assert (sum == max) return perc
def percentages(self): """ Returns parts of DHT ring each node occupies (in percents) """ perc = {} for g in self.groups(): routes = self.filter_by_group_id(g) prev = None perc[g] = {} for r in routes: if prev: amount = int(str(r.key), 16) - int(str(prev.key), 16) if prev.address not in perc[g]: perc[g][prev.address] = amount else: perc[g][prev.address] += amount prev = r max = int(str(Id([255] * 64, 0)), 16) for g in perc: sum = 0 for p in perc[g]: sum += perc[g][p] perc[g][p] = perc[g][p] * 100.0 / max assert(sum == max) return perc
def from_routes(cls, routes): """ Create RouteList from elliptics route table. It slightly mangles route list by explicitly inserting start and end of hash-ring and also merging adj. routes for the same into one. """ routes_dict = dict() # splits all routes between groups for r in routes: if r.id.group_id in routes_dict: routes_dict[r.id.group_id].append( Route(r.id, r.address, r.backend_id)) else: routes_dict[r.id.group_id] = [ Route(r.id, r.address, r.backend_id) ] # merges adj. ids for same address smallest_id = [0] * 64 biggest_id = [255] * 64 merged_routes = [] for group in routes_dict: # sorts routes inside one group group_routes = sorted(routes_dict[group], key=lambda route: route.id) last = (group_routes[-1].address, group_routes[-1].backend_id) # Insert implicit first route if needed if group_routes[0].id.id != smallest_id: route = Route(Id(smallest_id, group), *last) group_routes.insert(0, route) # Insert implicit last route if needed if group_routes[-1].id.id != biggest_id: route = Route(Id(biggest_id, group), *last) group_routes.append(route) # Extend route list merged_routes.extend(group_routes) # Sort results by key merged_routes.sort(key=lambda route: route.id) # Return RouteList from sorted and merged routes return cls(merged_routes)
def from_routes(cls, routes): """ Create RouteList from elliptics route table. It slightly mangles route list by explicitly inserting start and end of hash-ring and also merging adj. routes for the same into one. """ sorted_routes = [] # First pass - sort keys and construct addresses from text routes for key, str_address in sorted(routes, key=lambda route: route[0].id): address = Address.from_host_port(str_address, key.group_id) sorted_routes.append(Route(key, address)) # Merge adj. keys for same address merged_routes = [] for group in cls(sorted_routes).groups(): group_routes = cls(sorted_routes).filter_by_group_id(group) last_address = group_routes[-1].address merged_group = [] # Insert implicit first route group_routes.insert(0, Route(Id([0]*64, group), last_address)) # For each Route in list left only first one for each route for _, g in groupby(group_routes, attrgetter('address')): merged_group.append(list(g)[0]) assert(all(r1.address != r2.address for r1, r2 in izip(merged_group, merged_group[1:]))) assert(all(r1.key < r2.key for r1, r2 in izip(merged_group, merged_group[1:]))) # Insert implicit last route merged_group.append(Route(Id([255]*64, group), last_address)) # Extend route list merged_routes.extend(merged_group) # Sort results by key merged_routes.sort(key=itemgetter(0)) # Return RouteList from sorted and merged routes return cls(merged_routes)
def from_routes(cls, routes): """ Create RouteList from elliptics route table. It slightly mangles route list by explicitly inserting start and end of hash-ring and also merging adj. routes for the same into one. """ sorted_routes = [] # First pass - sort ids and construct addresses from text routes for route in sorted(routes, key=lambda route: route.id): sorted_routes.append(Route(route.id, route.address, route.backend_id)) # Merge adj. ids for same address smallest_id = [0] * 64 biggest_id = [255] * 64 merged_routes = [] for group in cls(sorted_routes).groups(): group_routes = cls(sorted_routes).filter_by_group(group).routes last = (group_routes[-1].address, group_routes[-1].backend_id) # Insert implicit first route if needed if group_routes[0].id.id != smallest_id: route = Route(Id(smallest_id, group), *last) group_routes.insert(0, route) # Insert implicit last route if needed if group_routes[-1].id.id != biggest_id: route = Route(Id(biggest_id, group), *last) group_routes.append(route) # Extend route list merged_routes.extend(group_routes) # Sort results by key merged_routes.sort(key=itemgetter(0)) # Return RouteList from sorted and merged routes return cls(merged_routes)
def get_address_ranges(self, address): """ Returns key ranges which belong to specified address """ ranges = [] group_id = self.get_address_group_id(address) key = None for route in self.filter_by_group_id(group_id): if route.address == address: if not key is None: key = route.key elif key: ranges.append((key, route.key)) key = None if key: ranges.append((key, Id([255]*64, group_id))) return ranges
def get_address_backend_ranges(self, address, backend_id): """ Returns id ranges which belong to specified @backend_id at @address\n ranges = routes.get_address_backend_ranges( Address.from_host_port_family('host.com:1025:2', 0)) """ ranges = [] group = self.get_address_backend_group(address, backend_id) id = None for route in self.filter_by_groups([group]): if (route.address, route.backend_id) == (address, backend_id): if id is None: id = route.id elif id: ranges.append((id, route.id)) id = None if id: ranges.append((id, Id([255] * 64, id.group_id))) return ranges
def get_address_ranges(self, address): """ Returns id ranges which belong to specified @address\n ranges = routes.get_address_ranges( Address.from_host_port_family('host.com:1025:2')) """ ranges = [] groups = self.get_address_groups(address) id = None for route in self.filter_by_groups(groups): if route.address == address: if id is None: id = route.id elif id: ranges.append((id, route.id)) id = None if id: ranges.append((id, Id([255] * 64, id.group_id))) return ranges
def get_address_ranges(self, address): """ Returns key ranges which belong to specified address\n ranges = routes.get_address_ranges( Address.from_host_port_family('host.com:1025:2')) """ ranges = [] group_id = self.get_address_group_id(address) key = None for route in self.filter_by_group_id(group_id): if route.address == address: if key is None: key = route.key elif key: ranges.append((key, route.key)) key = None if key: ranges.append((key, Id([255] * 64, group_id))) return ranges