예제 #1
0
    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}))
예제 #2
0
 def test_zero(self):
     self.assertEqual(bencode(0), 'i0e')
예제 #3
0
 def test_compound_dict(self):
     self.assertEqual(bencode({'spam.mp3': {'author': 'Alice', 'length': 100000}}),
                      'd8:spam.mp3d6:author5:Alice6:lengthi100000eee')
예제 #4
0
 def test_empty_dict(self):
     self.assertEqual(bencode({}), 'de')
예제 #5
0
 def test_char_list(self):
     self.assertEqual(bencode([1, 2, 3]), 'li1ei2ei3ee')
예제 #6
0
 def test_int(self):
     self.assertEqual(bencode('1234567890'), '10:1234567890')
예제 #7
0
 def test_null_string(self):
     self.assertEqual(bencode(''), '0:')
예제 #8
0
 def test_negative(self):
     self.assertEqual(bencode(-10), 'i-10e')
예제 #9
0
 def test_char_list(self):
     self.assertEqual(bencode([1, 2, 3]), 'li1ei2ei3ee')
예제 #10
0
 def test_empty_list(self):
     self.assertEqual(bencode([]), 'le')
예제 #11
0
 def test_int(self):
     self.assertEqual(bencode('1234567890'), '10:1234567890')
예제 #12
0
 def test_string(self):
     self.assertEqual(bencode('abc'), '3:abc')
예제 #13
0
 def test_null_string(self):
     self.assertEqual(bencode(''), '0:')
예제 #14
0
 def test_long(self):
     self.assertEqual(bencode(12345678901234567890),
                      'i12345678901234567890e')
예제 #15
0
 def test_negative(self):
     self.assertEqual(bencode(-10), 'i-10e')
예제 #16
0
 def test_char(self):
     self.assertEqual(bencode(4), 'i4e')
예제 #17
0
 def test_zero(self):
     self.assertEqual(bencode(0), 'i0e')
예제 #18
0
 def test_list_list(self):
     self.assertEqual(bencode([['Alice', 'Bob'], [2, 3]]),
                      'll5:Alice3:Bobeli2ei3eee')
예제 #19
0
 def test_long(self):
     self.assertEqual(bencode(12345678901234567890), 'i12345678901234567890e')
예제 #20
0
 def test_empty_dict(self):
     self.assertEqual(bencode({}), 'de')
예제 #21
0
 def test_string(self):
     self.assertEqual(bencode('abc'), '3:abc')
예제 #22
0
 def test_dict(self):
     self.assertEqual(bencode({
         'age': 25,
         'eyes': 'blue'
     }), 'd3:agei25e4:eyes4:bluee')
예제 #23
0
 def test_empty_list(self):
     self.assertEqual(bencode([]), 'le')
예제 #24
0
 def test_compound_dict(self):
     self.assertEqual(
         bencode({'spam.mp3': {
             'author': 'Alice',
             'length': 100000
         }}), 'd8:spam.mp3d6:author5:Alice6:lengthi100000eee')
예제 #25
0
 def test_list_list(self):
     self.assertEqual(bencode([['Alice', 'Bob'], [2, 3]]), 'll5:Alice3:Bobeli2ei3eee')
예제 #26
0
 def test_raises_type_error(self):
     with self.assertRaises(TypeError):
         bencode({1: 'foo'})
예제 #27
0
 def test_dict(self):
     self.assertEqual(bencode({'age': 25, 'eyes': 'blue'}), 'd3:agei25e4:eyes4:bluee')
예제 #28
0
    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}))
예제 #29
0
 def test_raises_type_error(self):
     with self.assertRaises(TypeError):
         bencode({1: 'foo'})
예제 #30
0
 def test_char(self):
     self.assertEqual(bencode(4), 'i4e')