2019-04-19 07:21:43 +08:00
|
|
|
# from operator import itemgetter
|
|
|
|
# import heapq
|
|
|
|
|
|
|
|
|
|
|
|
# class Node:
|
|
|
|
# def __init__(self, node_id, ip=None, port=None):
|
|
|
|
# self.id = node_id # pylint: disable=invalid-name
|
|
|
|
# self.ip = ip # pylint: disable=invalid-name
|
|
|
|
# self.port = port
|
|
|
|
# self.long_id = int(node_id.hex(), 16)
|
|
|
|
|
|
|
|
# def same_home_as(self, node):
|
|
|
|
# return self.ip == node.ip and self.port == node.port
|
|
|
|
|
|
|
|
# def distance_to(self, node):
|
|
|
|
# """
|
|
|
|
# Get the distance between this node and another.
|
|
|
|
# """
|
|
|
|
# return self.long_id ^ node.long_id
|
|
|
|
|
|
|
|
# def __iter__(self):
|
|
|
|
# """
|
|
|
|
# Enables use of Node as a tuple - i.e., tuple(node) works.
|
|
|
|
# """
|
|
|
|
# return iter([self.id, self.ip, self.port])
|
|
|
|
|
|
|
|
# def __repr__(self):
|
|
|
|
# return repr([self.long_id, self.ip, self.port])
|
|
|
|
|
|
|
|
# def __str__(self):
|
|
|
|
# return "%s:%s" % (self.ip, str(self.port))
|
|
|
|
|
|
|
|
|
|
|
|
# class NodeHeap:
|
|
|
|
# """
|
|
|
|
# A heap of nodes ordered by distance to a given node.
|
|
|
|
# """
|
|
|
|
# def __init__(self, node, maxsize):
|
|
|
|
# """
|
|
|
|
# Constructor.
|
|
|
|
|
|
|
|
# @param node: The node to measure all distnaces from.
|
|
|
|
# @param maxsize: The maximum size that this heap can grow to.
|
|
|
|
# """
|
|
|
|
# self.node = node
|
|
|
|
# self.heap = []
|
|
|
|
# self.contacted = set()
|
|
|
|
# self.maxsize = maxsize
|
|
|
|
|
|
|
|
# def remove(self, peers):
|
|
|
|
# """
|
|
|
|
# Remove a list of peer ids from this heap. Note that while this
|
|
|
|
# heap retains a constant visible size (based on the iterator), it's
|
|
|
|
# actual size may be quite a bit larger than what's exposed. Therefore,
|
|
|
|
# removal of nodes may not change the visible size as previously added
|
|
|
|
# nodes suddenly become visible.
|
|
|
|
# """
|
|
|
|
# peers = set(peers)
|
|
|
|
# if not peers:
|
|
|
|
# return
|
|
|
|
# nheap = []
|
|
|
|
# for distance, node in self.heap:
|
|
|
|
# if node.id not in peers:
|
|
|
|
# heapq.heappush(nheap, (distance, node))
|
|
|
|
# self.heap = nheap
|
|
|
|
|
|
|
|
# def get_node(self, node_id):
|
|
|
|
# for _, node in self.heap:
|
|
|
|
# if node.id == node_id:
|
|
|
|
# return node
|
|
|
|
# return None
|
|
|
|
|
|
|
|
# def have_contacted_all(self):
|
|
|
|
# return len(self.get_uncontacted()) == 0
|
|
|
|
|
|
|
|
# def get_ids(self):
|
|
|
|
# return [n.id for n in self]
|
|
|
|
|
|
|
|
# def mark_contacted(self, node):
|
|
|
|
# self.contacted.add(node.id)
|
|
|
|
|
|
|
|
# def popleft(self):
|
|
|
|
# return heapq.heappop(self.heap)[1] if self else None
|
|
|
|
|
|
|
|
# def push(self, nodes):
|
|
|
|
# """
|
|
|
|
# Push nodes onto heap.
|
|
|
|
|
|
|
|
# @param nodes: This can be a single item or a C{list}.
|
|
|
|
# """
|
|
|
|
# if not isinstance(nodes, list):
|
|
|
|
# nodes = [nodes]
|
|
|
|
|
|
|
|
# for node in nodes:
|
|
|
|
# if node not in self:
|
|
|
|
# distance = self.node.distance_to(node)
|
|
|
|
# heapq.heappush(self.heap, (distance, node))
|
|
|
|
|
|
|
|
# def __len__(self):
|
|
|
|
# return min(len(self.heap), self.maxsize)
|
|
|
|
|
|
|
|
# def __iter__(self):
|
|
|
|
# nodes = heapq.nsmallest(self.maxsize, self.heap)
|
|
|
|
# return iter(map(itemgetter(1), nodes))
|
|
|
|
|
|
|
|
# def __contains__(self, node):
|
|
|
|
# for _, other in self.heap:
|
|
|
|
# if node.id == other.id:
|
|
|
|
# return True
|
|
|
|
# return False
|
|
|
|
|
|
|
|
# def get_uncontacted(self):
|
|
|
|
# return [n for n in self if n.id not in self.contacted]
|