예제 #1
0
    def __init__(self, db_connection, build_graphs=True):
        self.io = StupidIO()
        self.id_attributes = {'id':(STATIC_ATTRIBUTE, int), 'addr':(STATIC_ATTRIBUTE, str)}
        self.node_env = {}
        self.db_connection = db_connection
        self.build_graphs  = build_graphs

        self.id_only_view_spec = StatementParser.parse('''
        CREATE VIEW id_only
        AS SELECT node.id
        FROM parent
        FOREACH BUCKET
        ;
        ''')
예제 #2
0
    def run_circle_with_nodes(self, nodes):
        max_id = len(nodes) - 1
        n_count=6

        view_def = Template('''
        CREATE VIEW circle_neighbours
        AS SELECT node.id, node.addr
        RANKED lowest(n_count, min(abs(local.id - node.id),
                               $max_id - abs(local.id - node.id)))
        FROM db
        WITH local, n_count
        ;
        ''').substitute(max_id=max_id)

        # FIXME: twisted ...

        view_spec = StatementParser.parse(view_def)

        for node in nodes:
            node_env = self.node_env[node.addr]

            spec = ViewSpecification(view_spec,
                                     new_name='circle_neighbours_%010x' % node.id,
                                     new_parents=(node_env['db'].name,))
            view = NodeView(spec, node_env['vr'],
                            local=node, n_count=n_count)

            node_env['spec'] = spec
            node_env['view'] = view

        for node in nodes:
            node_env = self.node_env[node.addr]

            harvester = BidirectionalGossipHarvester(
                node_env['io'], node,
                node_env['db'], node_env['vr'], SQLNodeView,
                (node_env['spec'], node_env['view'])
                )

            node_env['harvester'] = harvester

        def is_correct(node):
            distances = sum( min(abs(nid - view_node.id), max_id - abs(nid - view_node.id))
                             for view_node in node._view )
            return distances <= (n_count ** 2) / 2 # FIXME ...

        def is_complete(node):
            return len(self.node_env[node.addr]['view']) < n_count

        self.run_harvesting(nodes)
예제 #3
0
    def run_chord_with_nodes(self, nodes):
        log_nodes = int(math.log(len(nodes), 2))
        max_id    = len(nodes) - 1
        n_count=6

        def chord_dist(n1, n2):
            dist = n2 - n1
            if dist < 0:
                dist += max_id + 1
            return dist

        sql_chord_dist = """
        CREATE FUNCTION %%s(integer, integer) RETURNS integer AS '
          SELECT CASE WHEN ($2-$1) < 0 THEN %s + ($2-$1) ELSE ($2-$1) END
        ' LANGUAGE SQL STRICT;
        """ % (max_id+1)

        for node_env in self.node_env.itervalues():
            node_db = node_env['db']
            node_db.create_function('dist', sql_chord_dist)

        func_def = {'dist' : chord_dist}

        view_def = Template('''
        CREATE VIEW circle_neighbours
        AS SELECT node.id, node.addr
        RANKED highest(i+1, dist(local.id, node.id))
        FROM db
        WITH local
        HAVING dist(local.id, node.id) in (2^i : 2^(i+1))
        FOREACH i IN (0:$log_nodes)
        ;
        ''').substitute(log_nodes=log_nodes)

        view_spec = StatementParser.parse(view_def)

        deferreds = []
        for node in nodes:
            node_env = self.node_env[node.addr]
            node_db  = node_env['db']
            view_reg = node_env['vr']
            spec = ViewSpecification(view_spec, func_def,
                                     new_name='circle_neighbours_%010x' % node.id,
                                     new_parents=(node_db.name,))
            node_env['spec'] = spec

            deferred = node_db.create_view(spec, view_reg)
            deferreds.append(deferred)

        def is_correct(node):
            node_env = self.node_env[node.addr]
            view = node_env['view']
            deferred = view.iterBuckets()

            nid = node.id
            def bucket_test(buckets):
                for (i,), bucket in buckets:
                    if len(bucket) == 0:
                        return False
                    id_range = xrange(2**i, 2**(i+1))
                    for neighbour in bucket:
                        if chord_dist(nid, neighbour.id) not in id_range:
                            return False
                return True

            deferred.addCallback(bucket_test)
            return deferred

        def is_complete(node):
            node_env = self.node_env[node.addr]
            view = node_env['view']
            deferred = view.iterBuckets()

            def bucket_test(buckets):
                bucket_count = 0
                for (i,), bucket in buckets:
                    bucket_count += 1
                    if len(bucket) < i:
                        return False
                return bucket_count > 0

            deferred.addCallback(bucket_test)
            return deferred

        deferred_list = defer.DeferredList(deferreds)
        deferred_list.addCallback(self._unpack_list)
        deferred_list.addCallback(self.build_harvesters, nodes, is_correct, is_complete)
        return deferred_list