示例#1
0
文件: node.c 项目: OpenDZ/libbus1
/**
 * b1_node_implement() - implement interface on node
 * @node:               node to operate on
 * @interface:          interface to implement
 *
 * Extend @node to support the interface given as @interface. From then on, the
 * node will dispatch incoming method calls on this interface.
 *
 * This fails, if the given interface is already implemented by @node.
 *
 * Return: 0 on success, negative error code on failure.
 */
_c_public_ int b1_node_implement(B1Node *node, B1Interface *interface) {
        B1Implementation *implementation;
        CRBNode **slot, *p;

        assert(node);
        assert(interface);

        if (node->live || node->slot)
                return -EBUSY;

        slot = c_rbtree_find_slot(&node->implementations, implementations_compare, interface->name, &p);
        if (!slot)
                return -ENOTUNIQ;

        implementation = calloc(1, sizeof(*implementation));
        if (!implementation)
                return -ENOMEM;

        c_rbnode_init(&implementation->rb);
        implementation->interface = b1_interface_ref(interface);
        interface->implemented = true;

        c_rbtree_add(&node->implementations, p, slot, &implementation->rb);
        return 0;
}
示例#2
0
static void test_parent_start(TestContext *ctx) {
        size_t i;

        /*
         * Generate a tree with @n_nodes entries. We store the entries in
         * @ctx->node_mem, generate a randomized access-map in @ctx->nodes
         * (i.e., an array of pointers to entries in @ctx->node_mem, but in
         * random order), and a temporary cache for free use in the parent.
         *
         * All this is stored in a MAP_SHARED memory region so it is equivalent
         * in child and parent.
         */

        ctx->n_nodes = 32;
        ctx->mapsize = sizeof(CRBTree);
        ctx->mapsize += ctx->n_nodes * sizeof(TestNode);
        ctx->mapsize += ctx->n_nodes * sizeof(CRBNode*);
        ctx->mapsize += ctx->n_nodes * sizeof(CRBNode*);

        ctx->map = mmap(NULL, ctx->mapsize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
        c_assert(ctx->map != MAP_FAILED);

        ctx->tree = (void *)ctx->map;
        ctx->node_mem = (void *)(ctx->tree + 1);
        ctx->nodes = (void *)(ctx->node_mem + ctx->n_nodes);
        ctx->cache = (void *)(ctx->nodes + ctx->n_nodes);

        for (i = 0; i < ctx->n_nodes; ++i) {
                ctx->nodes[i] = &ctx->node_mem[i].rb;
                c_rbnode_init(ctx->nodes[i]);
        }

        shuffle(ctx->nodes, ctx->n_nodes);
}
示例#3
0
/* verify that all API calls are exported */
static void test_api(void) {
        CRBTree t = {};
        CRBNode n = C_RBNODE_INIT(n);

        assert(!c_rbnode_is_linked(&n));

        /* init, is_linked, add, remove, remove_init */

        c_rbtree_add(&t, NULL, &t.root, &n);
        assert(c_rbnode_is_linked(&n));

        c_rbtree_remove_init(&t, &n);
        assert(!c_rbnode_is_linked(&n));

        c_rbtree_add(&t, NULL, &t.root, &n);
        assert(c_rbnode_is_linked(&n));

        c_rbtree_remove(&t, &n);
        assert(c_rbnode_is_linked(&n)); /* @n wasn't touched */

        c_rbnode_init(&n);
        assert(!c_rbnode_is_linked(&n));

        /* first, last, leftmost, rightmost, next, prev */

        assert(!c_rbtree_first(&t));
        assert(!c_rbtree_last(&t));
        assert(&n == c_rbnode_leftmost(&n));
        assert(&n == c_rbnode_rightmost(&n));
        assert(!c_rbnode_next(&n));
        assert(!c_rbnode_prev(&n));
}
示例#4
0
/* run tests against the c_rbtree_find*() helpers */
static void test_map(void) {
        CRBNode **slot, *p;
        CRBTree t = {};
        Node *nodes[2048];
        unsigned long i;

        /* allocate and initialize all nodes */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
                nodes[i] = malloc(sizeof(*nodes[i]));
                assert(nodes[i]);
                nodes[i]->key = i;
                c_rbnode_init(&nodes[i]->rb);
        }

        /* shuffle nodes */
        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));

        /* add all nodes, and verify that each node is linked */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
                assert(!c_rbnode_is_linked(&nodes[i]->rb));
                assert(!c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb));

                slot = c_rbtree_find_slot(&t, compare, (void *)nodes[i]->key, &p);
                assert(slot);
                c_rbtree_add(&t, p, slot, &nodes[i]->rb);

                assert(c_rbnode_is_linked(&nodes[i]->rb));
                assert(nodes[i] == c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb));
        }

        /* shuffle nodes again */
        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));

        /* remove all nodes (in different order) */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
                assert(c_rbnode_is_linked(&nodes[i]->rb));
                assert(nodes[i] == c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb));

                c_rbtree_remove_init(&t, &nodes[i]->rb);

                assert(!c_rbnode_is_linked(&nodes[i]->rb));
                assert(!c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb));
        }

        /* free nodes again */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i)
                free(nodes[i]);
}
示例#5
0
文件: node.c 项目: OpenDZ/libbus1
int b1_handle_new(B1Peer *peer, uint64_t id, B1Handle **handlep) {
        _c_cleanup_(b1_handle_unrefp) B1Handle *handle = NULL;

        assert(peer);
        assert(handlep);

        handle = calloc(1, sizeof(*handle));
        if (!handle)
                return -ENOMEM;

        handle->n_ref = 1;
        handle->holder = b1_peer_ref(peer);
        handle->id = id;
        handle->marked = false;
        c_rbnode_init(&handle->rb);

        *handlep = handle;
        handle = NULL;
        return 0;
}
示例#6
0
文件: node.c 项目: eworm-de/libbus1
static int b1_handle_new(B1Peer *peer, B1Handle **handlep) {
        _c_cleanup_(b1_handle_unrefp) B1Handle *handle = NULL;

        assert(peer);
        assert(handlep);

        handle = calloc(1, sizeof(*handle));
        if (!handle)
                return -ENOMEM;

        handle->ref = (CRef)C_REF_INIT;
        handle->holder = b1_peer_ref(peer);
        handle->id = BUS1_HANDLE_INVALID;
        handle->marked = false;
        handle->live = false;
        c_rbnode_init(&handle->rb);

        *handlep = handle;
        handle = NULL;
        return 0;
}
示例#7
0
文件: node.c 项目: eworm-de/libbus1
/**
 * b1_node_new() - create a new node for a peer
 * @peer:               the owning peer
 * @nodep:              pointer to the new node object
 *
 * Return: 0 on success, and a negative error code on failure.
 */
_c_public_ int b1_node_new(B1Peer *peer, B1Node **nodep) {
        _c_cleanup_(b1_node_freep) B1Node *node = NULL;
        int r;

        node = calloc(1, sizeof(*node));
        if (!node)
                return -ENOMEM;

        node->id = BUS1_HANDLE_INVALID;
        node->owner = b1_peer_ref(peer);
        c_rbnode_init(&node->rb_nodes);

        r = b1_handle_new(peer, &node->handle);
        if (r < 0)
                return r;

        node->handle->node = node;

        *nodep = node;
        node = NULL;
        return 0;
}
示例#8
0
/* run some pseudo-random tests on the tree */
static void test_shuffle(void) {
        CRBNode *nodes[256];
        CRBTree t = {};
        unsigned int i, j;
        size_t n;

        /* allocate and initialize all nodes */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
                nodes[i] = malloc(sizeof(*nodes[i]));
                assert(nodes[i]);
                c_rbnode_init(nodes[i]);
        }

        /* shuffle nodes and validate *empty* tree */
        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
        n = validate(&t);
        assert(n == 0);

        /* add all nodes and validate after each insertion */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
                insert(&t, nodes[i]);
                n = validate(&t);
                assert(n == i + 1);
        }

        /* shuffle nodes again */
        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));

        /* remove all nodes (in different order) and validate on each round */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
                c_rbtree_remove(&t, nodes[i]);
                n = validate(&t);
                assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1);
                c_rbnode_init(nodes[i]);
        }

        /* shuffle nodes and validate *empty* tree again */
        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
        n = validate(&t);
        assert(n == 0);

        /* add all nodes again */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
                insert(&t, nodes[i]);
                n = validate(&t);
                assert(n == i + 1);
        }

        /* 4 times, remove half of the nodes and add them again */
        for (j = 0; j < 4; ++j) {
                /* shuffle nodes again */
                shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));

                /* remove half of the nodes */
                for (i = 0; i < sizeof(nodes) / sizeof(*nodes) / 2; ++i) {
                        c_rbtree_remove(&t, nodes[i]);
                        n = validate(&t);
                        assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1);
                        c_rbnode_init(nodes[i]);
                }

                /* shuffle the removed half */
                shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes) / 2);

                /* add the removed half again */
                for (i = 0; i < sizeof(nodes) / sizeof(*nodes) / 2; ++i) {
                        insert(&t, nodes[i]);
                        n = validate(&t);
                        assert(n == sizeof(nodes) / sizeof(*nodes) / 2 + i + 1);
                }
        }

        /* shuffle nodes again */
        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));

        /* remove all */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
                c_rbtree_remove(&t, nodes[i]);
                n = validate(&t);
                assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1);
                c_rbnode_init(nodes[i]);
        }

        /* free nodes again */
        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i)
                free(nodes[i]);
}