Exemple #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}))
Exemple #2
0
 def _update_stats(self, key, new_track=False, lost_peers=0, event=None, left=None) -> None:
     if not self.stats:
         return
     complete = '%s!complete' % key
     incomplete = '%s!incomplete' % key
     if new_track:
         mset(complete, '0', namespace='S')
         mset(incomplete, '0', namespace='S')
     elif lost_peers:
         decr(incomplete, lost_peers, namespace='S')
     elif event in ('stopped', 'started'):
         if left == '0':
             decr(complete, namespace='S')
         else:
             decr(incomplete, namespace='S')
     elif event in ('completed', ):
         decr(incomplete, namespace='S')
         incr(complete, namespace='S')
Exemple #3
0
 def _update_stats(self,
                   key,
                   new_track=False,
                   lost_peers=0,
                   event=None,
                   left=None) -> None:
     if not self.stats:
         return
     complete = '%s!complete' % key
     incomplete = '%s!incomplete' % key
     if new_track:
         mset(complete, '0', namespace='S')
         mset(incomplete, '0', namespace='S')
     elif lost_peers:
         decr(incomplete, lost_peers, namespace='S')
     elif event in ('stopped', 'started'):
         if left == '0':
             decr(complete, namespace='S')
         else:
             decr(incomplete, namespace='S')
     elif event in ('completed', ):
         decr(incomplete, namespace='S')
         incr(complete, namespace='S')
Exemple #4
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}))