Example #1
0
static bool
delete_node(const void *key, bnode_t *bnode, piojo_btree_t *tree)
{
        bool found_p, deleted_p=FALSE;
        size_t i;
        bnode_t *next;
        iter_t iter;

        while (bnode != NULL){
                i = bin_search(key, tree, bnode, &found_p);
                if (found_p){
                        /* Key in leaf, shrink the leaf and finish. */
                        if (bnode->leaf_p){
                                free_entry(&bnode->kvs[i], tree, &deleted_p);
                                --bnode->ecnt;
                                for (; i < bnode->ecnt; ++i){
                                        copy_bentry(i + 1, bnode, i, bnode, tree);
                                }
                                return TRUE;
                        }

                        /* Key in internal node, move prev/next key up and delete it. */
                        iter.bnode = bnode;
                        if (bnode->children[i]->ecnt >= tree->cmin){
                                free_entry(&bnode->kvs[i], tree, &deleted_p);
                                iter.eidx = i;
                                search_max(&iter);
                                copy_bentry(iter.eidx, iter.bnode, i, bnode, tree);
                                key = entry_key(i, bnode, tree);
                                bnode = bnode->children[i];
                        }else if (bnode->children[i + 1]->ecnt >= tree->cmin){
                                free_entry(&bnode->kvs[i], tree, &deleted_p);
                                iter.eidx = i + 1;
                                search_min(&iter);
                                copy_bentry(iter.eidx, iter.bnode, i, bnode, tree);
                                key = entry_key(i, bnode, tree);
                                bnode = bnode->children[i + 1];
                        }else{
                                /* Both node children are key deficient, merge and try again. */
                                PIOJO_ASSERT(bnode->children[i]->ecnt == tree->cmin - 1);
                                PIOJO_ASSERT(bnode->children[i + 1]->ecnt == tree->cmin - 1);
                                next = bnode->children[i];
                                merge_bnodes(tree, i, next, bnode->children[i + 1], bnode);
                                bnode = next;
                        }
                }else if (! bnode->leaf_p){
                        /* Key not in internal node, rebalance and try again. */
                        next = bnode->children[i];
                        if (next->ecnt < tree->cmin){
                                PIOJO_ASSERT(next->ecnt == tree->cmin - 1);
                                next = rebalance_bnode(tree, i, next, bnode);
                        }
                        bnode = next;
                }else{
                        /* Key not in leaf. */
                        bnode = NULL;
                }
        }
        return FALSE;
}
Example #2
0
/**
 * Reads the previous key (order given by @a keycmp function).
 * @param[in] key
 * @param[in] tree
 * @param[out] data Entry value, can be @b NULL.
 * @return previous key or @b NULL if @a key is the first one.
 */
const void*
piojo_btree_prev(const void *key, const piojo_btree_t *tree, void **data)
{
        iter_t iter;
        PIOJO_ASSERT(tree);
        PIOJO_ASSERT(key);

        iter = search_node(key, tree);
        PIOJO_ASSERT(iter.bnode != NULL);

        if (! iter.bnode->leaf_p && iter.eidx < iter.bnode->ecnt + 1){
                iter.bnode = iter.bnode->children[iter.eidx];
                iter.eidx = iter.bnode->ecnt;
                search_max(&iter);
        }else if (iter.eidx > 0){
                --iter.eidx;
        }else{
                while (iter.bnode->parent != NULL){
                        iter.eidx = iter.bnode->pidx;
                        iter.bnode = iter.bnode->parent;
                        if (iter.eidx > 0){
                                --iter.eidx;
                                if (data != NULL){
                                        *data = entry_val(iter.eidx, iter.bnode, tree);
                                }
                                return entry_key(iter.eidx, iter.bnode, tree);
                        }
                }
                return NULL;
        }
        if (data != NULL){
                *data = entry_val(iter.eidx, iter.bnode, tree);
        }
        return entry_key(iter.eidx, iter.bnode, tree);
}
Example #3
0
static int
_mtbl_sorter_compare(const void *va, const void *vb)
{
	const struct entry *a = *((const struct entry **) va);
	const struct entry *b = *((const struct entry **) vb);

	return (bytes_compare(entry_key(a), a->len_key,
			      entry_key(b), b->len_key));
}
Example #4
0
static size_t
bin_search(const void *key, const piojo_btree_t *tree,
           bnode_t *bnode, bool *found_p)
{
        int cmpval;
        size_t mid, imin = 0, imax = bnode->ecnt - 1;

        *found_p = FALSE;
        if (bnode->ecnt > 0){
                while (imin <= imax){
                        mid = imin + ((imax - imin) / 2);
                        cmpval = tree->cmp_cb(key, entry_key(mid, bnode, tree));
                        if (cmpval == 0){
                                *found_p = TRUE;
                                imin = mid;
                                break;
                        }else if (cmpval > 0){
                                imin = mid + 1;
                        }else if (imin != mid){
                                imax = mid - 1;
                        }else{
                                break;
                        }
                }
        }
        return imin;
}
Example #5
0
/**
 * Deletes all entries in @a tree.
 * @param[out] tree Tree being cleared.
 */
void
piojo_btree_clear(piojo_btree_t *tree)
{
        void *key;
        PIOJO_ASSERT(tree);

        key = tree->allocator.alloc_cb(tree->eksize);
        PIOJO_ASSERT(key);
        while (tree->ecount > 0){
                memcpy(key, entry_key(0, tree->root, tree), tree->eksize);
                delete_node(key, tree->root, tree);
                --tree->ecount;
        }
        tree->allocator.free_cb(key);
}
Example #6
0
/* Similar to search_node() but split bnodes before traversing them. */
static iter_t
insert_node(const void *key, const void *data, piojo_btree_t *tree)
{
        int cmpval;
        bool found_p;
        size_t idx=0, j;
        iter_t iter;
        bnode_t *bnode;

        if (tree->root->ecnt == tree->cmax - 1){
                split_root(tree);
        }
        bnode = tree->root;
        iter.bnode = NULL;
        while (bnode->ecnt > 0){
                idx = bin_search(key, tree, bnode, &found_p);
                if (found_p){
                        iter.bnode = bnode;
                        iter.eidx = idx;
                        return iter;
                }else if (bnode->leaf_p){
                        break;
                }
                if (bnode->children[idx]->ecnt == tree->cmax - 1){
                        split_bnode(tree, idx, bnode->children[idx], bnode);
                        cmpval = tree->cmp_cb(key, entry_key(idx, bnode, tree));
                        if (cmpval == 0){
                                iter.bnode = bnode;
                                iter.eidx = idx;
                                return iter;
                        }else if (cmpval > 0){
                                ++idx;
                        }
                }
                bnode = bnode->children[idx];
        }

        PIOJO_ASSERT(bnode->ecnt < tree->cmax - 1);
        for (j = bnode->ecnt; j > idx; --j){
                copy_bentry(j - 1, bnode, j, bnode, tree);
        }

        init_entry(key, data, idx, bnode, tree);
        ++bnode->ecnt;

        return iter;
}
Example #7
0
static void
init_entry(const void *key, const void *data, uint8_t eidx,
           const bnode_t *bnode, const piojo_btree_t *tree)
{
        bool null_p = TRUE;
        piojo_alloc_if ator = tree->allocator;

        if (data == NULL){
                data = &null_p;
        }

        memcpy(entry_key(eidx, bnode, tree), key, tree->eksize);

        bnode->kvs[eidx].value = ator.alloc_cb(tree->evsize);
        PIOJO_ASSERT(bnode->kvs[eidx].value);
        memcpy(entry_val(eidx, bnode, tree), data, tree->evsize);
}
Example #8
0
/**
 * Reads the last key in @a tree (order given by @a keycmp function).
 * @param[in] tree
 * @param[out] data Entry value, can be @b NULL.
 * @return last key or @b NULL if @a tree is empty.
 */
const void*
piojo_btree_last(const piojo_btree_t *tree, void **data)
{
        iter_t iter;
        PIOJO_ASSERT(tree);

        if (tree->ecount > 0){
                iter.tree = tree;
                iter.eidx = tree->root->ecnt;
                iter.bnode = tree->root;
                search_max(&iter);
                if (data != NULL){
                        *data = entry_val(iter.eidx, iter.bnode, tree);
                }
                return entry_key(iter.eidx, iter.bnode, tree);
        }
        return NULL;
}