def get(self, key: str): """ Memcached namespaces: - 'K' -> key: [peer_hash: str, ...] - 'P' -> peer_hash: (ip: str, port: int) - 'S' -> "%s!%s" % (key: str, param: str): int - 'D' -> Debug data This allows peer info to be shared and decay by itself, we will delete references to peers from the key namespace lazily. MAKE SURE YOU REFER TO doc/NTrack.rst FOR CONSISTENCY! :param key: :return: """ if len(key) > 128: pass # TODO Insanely long key, let them know peer_hash = self._peer_hash(self.request.remote_ip) event = self.get_argument('event', default=None) left = self.get_argument('left', default=None) if event == 'stopped': mdel(peer_hash, namespace='P') self._update_stats(key, event=event, left=left) self.write(bencode({'interval': self.interval, 'peers': []})) elif event == 'completed': self._update_stats(key, event=event, left=left) elif event == 'started': self._update_stats(key, event=event, left=left) peer_list = get(key, namespace='K') if peer_list: if peer_hash in peer_list: peer_list.remove(peer_hash) peers = get_multi(peer_list, namespace='P') lost_peers = [p_hash for p_hash, peer in zip(peer_list, peers) if peer is None] if lost_peers: for lost_peer in lost_peers: pass res = [encode_host_and_port(peer[0], peer[1]) for peer in peers] else: peer_list = res = [] self._update_stats(key, new_track=True) if not peer_hash in peer_list: mset(peer_hash, (self.request.remote_ip, self.port), namespace='P') peer_list.append(peer_hash) mset(key, peer_list, namespace='K') if self.stats: self.write(bencode({'interval': self.interval, 'peers': res, 'complete': get('%s!complete' % key, namespace='S') or 0, 'incomplete': get('%s!incomplete' % key, namespace='S') or 0})) else: self.write(bencode({'interval': self.interval, 'peers': res}))
def test_zero(self): self.assertEqual(bencode(0), 'i0e')
def test_compound_dict(self): self.assertEqual(bencode({'spam.mp3': {'author': 'Alice', 'length': 100000}}), 'd8:spam.mp3d6:author5:Alice6:lengthi100000eee')
def test_empty_dict(self): self.assertEqual(bencode({}), 'de')
def test_char_list(self): self.assertEqual(bencode([1, 2, 3]), 'li1ei2ei3ee')
def test_int(self): self.assertEqual(bencode('1234567890'), '10:1234567890')
def test_null_string(self): self.assertEqual(bencode(''), '0:')
def test_negative(self): self.assertEqual(bencode(-10), 'i-10e')
def test_empty_list(self): self.assertEqual(bencode([]), 'le')
def test_string(self): self.assertEqual(bencode('abc'), '3:abc')
def test_long(self): self.assertEqual(bencode(12345678901234567890), 'i12345678901234567890e')
def test_char(self): self.assertEqual(bencode(4), 'i4e')
def test_list_list(self): self.assertEqual(bencode([['Alice', 'Bob'], [2, 3]]), 'll5:Alice3:Bobeli2ei3eee')
def test_dict(self): self.assertEqual(bencode({ 'age': 25, 'eyes': 'blue' }), 'd3:agei25e4:eyes4:bluee')
def test_compound_dict(self): self.assertEqual( bencode({'spam.mp3': { 'author': 'Alice', 'length': 100000 }}), 'd8:spam.mp3d6:author5:Alice6:lengthi100000eee')
def test_raises_type_error(self): with self.assertRaises(TypeError): bencode({1: 'foo'})
def test_dict(self): self.assertEqual(bencode({'age': 25, 'eyes': 'blue'}), 'd3:agei25e4:eyes4:bluee')
def get(self, key: str): """ Memcached namespaces: - 'K' -> key: [peer_hash: str, ...] - 'P' -> peer_hash: (ip: str, port: int) - 'S' -> "%s!%s" % (key: str, param: str): int - 'D' -> Debug data This allows peer info to be shared and decay by itself, we will delete references to peers from the key namespace lazily. MAKE SURE YOU REFER TO doc/NTrack.rst FOR CONSISTENCY! :param key: :return: """ if len(key) > 128: pass # TODO Insanely long key, let them know peer_hash = self._peer_hash(self.request.remote_ip) event = self.get_argument('event', default=None) left = self.get_argument('left', default=None) if event == 'stopped': mdel(peer_hash, namespace='P') self._update_stats(key, event=event, left=left) self.write(bencode({'interval': self.interval, 'peers': []})) elif event == 'completed': self._update_stats(key, event=event, left=left) elif event == 'started': self._update_stats(key, event=event, left=left) peer_list = get(key, namespace='K') if peer_list: if peer_hash in peer_list: peer_list.remove(peer_hash) peers = get_multi(peer_list, namespace='P') lost_peers = [ p_hash for p_hash, peer in zip(peer_list, peers) if peer is None ] if lost_peers: for lost_peer in lost_peers: pass res = [encode_host_and_port(peer[0], peer[1]) for peer in peers] else: peer_list = res = [] self._update_stats(key, new_track=True) if not peer_hash in peer_list: mset(peer_hash, (self.request.remote_ip, self.port), namespace='P') peer_list.append(peer_hash) mset(key, peer_list, namespace='K') if self.stats: self.write( bencode({ 'interval': self.interval, 'peers': res, 'complete': get('%s!complete' % key, namespace='S') or 0, 'incomplete': get('%s!incomplete' % key, namespace='S') or 0 })) else: self.write(bencode({'interval': self.interval, 'peers': res}))