예제 #1
0
    def _get_kbucket_index(self, guid):
        """
        Return the index of the KBucket which is responsible for the
        given guid.

        Agrs:
            guid: The guid for which to find the appropriate KBucket index,
                as a string or unicode, in hexadecimal

        Returns:
            The index of the KBucket responsible for the given guid.

        Raises:
            BadGUIDError: The guid was no KBucket's responsibility; an
                invariant has been violated, or the guid is bad.
        """
        # Since the KBuckets have consecutive ID spaces,
        # we do a binary search.
        low, high = 0, len(self._buckets)
        num_guid = util.guid_to_num(guid)
        while low < high:
            mid = low + (high - low) // 2
            bucket = self._buckets[mid]
            if bucket.range_min > num_guid:
                high = mid
            elif bucket.range_max <= num_guid:
                low = mid + 1
            else:
                return mid
        raise util.BadGUIDError(
            "No KBucket responsible for guid {0}.".format(guid))
예제 #2
0
    def _get_kbucket_index(self, guid):
        """
        Return the index of the KBucket which is responsible for the
        given guid.

        Agrs:
            guid: The guid for which to find the appropriate KBucket index,
                as a string or unicode, in hexadecimal

        Returns:
            The index of the KBucket responsible for the given guid.

        Raises:
            BadGUIDError: The guid was no KBucket's responsibility; an
                invariant has been violated, or the guid is bad.
        """
        # Since the KBuckets have consecutive ID spaces,
        # we do a binary search.
        low, high = 0, len(self._buckets)
        num_guid = util.guid_to_num(guid)
        while low < high:
            mid = low + (high - low) // 2
            bucket = self._buckets[mid]
            if bucket.range_min > num_guid:
                high = mid
            elif bucket.range_max <= num_guid:
                low = mid + 1
            else:
                return mid
        raise util.BadGUIDError("No KBucket responsible for guid {0}.".format(guid))
예제 #3
0
    def test_guid_to_num(self):
        test_tuples = ((0, '0000000000000000000000000000000000000000'),
                       (42, '000000000000000000000000000000000000002a'),
                       (2**constants.BIT_NODE_ID_LEN - 1,
                        'ffffffffffffffffffffffffffffffffffffffff'),
                       (2**constants.BIT_NODE_ID_LEN - 1,
                        'ffffffffffffffffffffffffffffffffffffffffL'),
                       (2**constants.BIT_NODE_ID_LEN - 1,
                        '0xffffffffffffffffffffffffffffffffffffffffL'))

        for num, guid in test_tuples:
            self.assertEqual(util.guid_to_num(guid), num)
예제 #4
0
    def test_add_contact_max_recursion(self):
        # Add K + 1 contacts that are so close together and to
        # own_guid, that they force recursive bucket splits.
        base = util.guid_to_num(self.own_guid) + 1
        for i in range(constants.K + 1):
            self.rt.add_contact(
                self._make_contact_from_num(base + i)
            )

        # The actual number of KBuckets created is dependend upon K,
        # so this test will probably break if K changes. In such a case,
        # please update the test.
        self.assertEqual(len(self.rt), 157)
예제 #5
0
    def guid_in_range(self, guid):
        """
        Test whether the given guid is in the range of the ID space
        covered by this KBucket.

        Args:
            guid: The guid to test, as a string or unicode, in
                hexadecimal.

        Returns:
            True if `guid` is in this KBucket's range, False otherwise.
        """
        return self.range_min <= util.guid_to_num(guid) < self.range_max
예제 #6
0
    def test_guid_to_num(self):
        test_tuples = (
            (0, '0000000000000000000000000000000000000000'),
            (42, '000000000000000000000000000000000000002a'),
            (
                2**constants.BIT_NODE_ID_LEN - 1,
                'ffffffffffffffffffffffffffffffffffffffff'
            ),
            (
                2**constants.BIT_NODE_ID_LEN - 1,
                'ffffffffffffffffffffffffffffffffffffffffL'
            ),
            (
                2**constants.BIT_NODE_ID_LEN - 1,
                '0xffffffffffffffffffffffffffffffffffffffffL'
            )
        )

        for num, guid in test_tuples:
            self.assertEqual(util.guid_to_num(guid), num)
예제 #7
0
    def test_add_new_contact_and_cache(self):
        # Add K + 1 contacts to initial KBucket, to force a split.
        base = util.guid_to_num(self.own_guid) + 1
        for i in range(constants.K):
            self.rt.add_contact(
                self._make_contact_from_num(base + i)
            )
        self.rt.add_contact(self._make_contact_from_num(self.range_max - 1))

        # Create a guid that is at maximal distance from own_guid,
        # thus must be at a different bucket.
        self.assertEqual(len(self.rt), 2)
        max_base = (2**constants.BIT_NODE_ID_LEN - 1) ^ self.own_num_guid
        self.assertTrue(self.rt[0].guid_in_range(self.own_guid))
        self.assertTrue(self.rt[1].guid_in_range(util.num_to_guid(max_base)))

        # Add contacts to the other KBucket, until it is full.
        for i in range(constants.K):
            if len(self.rt[1]) == constants.K:
                break
            self.rt.add_contact(
                self._make_contact_from_num(max_base - i)
            )

        # Create and add a contact that is in the range of the other
        # KBucket.
        new_contact = self._make_contact_from_num(max_base - constants.K)
        self.rt.add_contact(new_contact)

        self.assertEqual(
            len(self.rt),
            2,
            'A KBucket not containing own_guid was split.'
        )

        # Assert the new contact was cached properly.
        self.assertNotIn(new_contact, self.rt[0])
        self.assertNotIn(new_contact, self.rt[1])
        self.assertEqual([], self.rt[0].get_cached_contacts())
        self.assertEqual([new_contact], self.rt[1].get_cached_contacts())