Пример #1
0
static bool lookup_b(
    struct Oc_wu *wu_p,
    struct Oc_bpt_state *s_p,
    struct Oc_bpt_key *key_p,
    struct Oc_bpt_data *data_po)
{
    Oc_bpt_node *father_p, *child_p;
    uint64 addr;
    bool rc;
    int idx;
    
    oc_bpt_nd_get_for_read(wu_p, s_p, s_p->root_node_p->disk_addr);

    // 1. base case, this is the root node and the root is a leaf
    if (oc_bpt_nd_is_leaf(s_p, s_p->root_node_p))
    {
        rc = lookup_in_leaf(wu_p, s_p, s_p->root_node_p, key_p, data_po);
        oc_bpt_nd_release(wu_p, s_p, s_p->root_node_p);
        return rc;
    }
        
    // 2. this is the root, and it isn't a leaf node:
    //    look for the correct child and get it
    addr = oc_bpt_nd_index_lookup_key(wu_p, s_p, s_p->root_node_p, key_p,
                                      NULL, &idx);
    if (0 == addr) {
        oc_bpt_nd_release(wu_p, s_p, s_p->root_node_p);
        return FALSE;
    }
    child_p = oc_bpt_nd_get_for_read(wu_p, s_p, addr);
    father_p = s_p->root_node_p;
    
    // 3. regular case: child, with a father, both are locked for read.
    //    if the child is a leaf node, then do a local lookup.
    //    else, release the father, get the child's son. 
    while (1) {

        if (oc_bpt_nd_is_leaf(s_p, child_p)) {
            rc = lookup_in_leaf(wu_p, s_p, child_p, key_p, data_po);
            oc_bpt_nd_release(wu_p, s_p, father_p);
            oc_bpt_nd_release(wu_p, s_p, child_p);
            return rc;
        }
        else {
            // release the father
            oc_bpt_nd_release(wu_p, s_p, father_p);

            // switch places between father and son.
            father_p = child_p;
            
            addr = oc_bpt_nd_index_lookup_key(wu_p, s_p, father_p, key_p,
                                              NULL, &idx);
            if (0 == addr) {
                oc_bpt_nd_release(wu_p, s_p, father_p);                
                return FALSE;
            }
            child_p = oc_bpt_nd_get_for_read(wu_p, s_p, addr);
        }
    }
}
Пример #2
0
void oc_bpt_utl_iter_b(
    struct Oc_wu *wu_p,
    struct Oc_bpt_state *s_p,
    void (*iter_f)(struct Oc_wu *, Oc_bpt_node*),
    Oc_bpt_node *node_p)
{
    iter_f(wu_p, node_p);

    if (!oc_bpt_nd_is_leaf(s_p, node_p)) {
        // An index node, recurse through its children
        int i;
        int num_entries = oc_bpt_nd_num_entries(s_p, node_p);
        Oc_bpt_node *child_node_p;
        struct Oc_bpt_key *dummy_key_p;
        uint64 child_addr;
        
        for (i=0; i< num_entries; i++) {
            oc_bpt_nd_index_get_kth(s_p, node_p, i,
                                    &dummy_key_p,
                                    &child_addr);
            child_node_p = oc_bpt_nd_get_for_read(wu_p, s_p, child_addr);
            oc_bpt_utl_iter_b(wu_p, s_p, iter_f, child_node_p);
            oc_bpt_nd_release(wu_p, s_p, child_node_p);
        }
    }
}
Пример #3
0
/* Delete a sub-tree rooted at [addr].
 * 
 * Recursive decent through the tree. Remove the leaves and perform
 * the user-defined "data_release" function for all data. Deallocate all
 * internal nodes. 
 */
void oc_bpt_utl_delete_subtree_b(
    struct Oc_wu *wu_p,
    struct Oc_bpt_state *s_p,
    Oc_bpt_node *node_p)
{
    int fs_refcnt = s_p->cfg_p->fs_get_refcount(wu_p, node_p->disk_addr);

    oc_utl_debugassert(fs_refcnt > 0);

    if (1 == fs_refcnt) {
        /* If this node is referenced from a single snapshot only, 
         * Then recurse down and then delete it on the way back up.
         */
        if (!oc_bpt_nd_is_leaf(s_p, node_p)) {
            // An index node, recurse through its children
            int i;
            int num_entries = oc_bpt_nd_num_entries(s_p, node_p);
            Oc_bpt_node *child_node_p;
            struct Oc_bpt_key *dummy_key_p;
            uint64 child_addr;
            
            for (i=0; i< num_entries; i++) {
                oc_bpt_nd_index_get_kth(s_p, node_p, i,
                                        &dummy_key_p,
                                        &child_addr);
                child_node_p = oc_bpt_nd_get_for_read(wu_p, s_p, child_addr);
                oc_bpt_utl_delete_subtree_b(wu_p, s_p, child_node_p);
            }
        }
    }
    
    // reduce the ref-count on this node
    oc_bpt_nd_delete(wu_p, s_p, node_p);
}
Пример #4
0
/* Delete all the key-value pairs in the tree. 
 * Leave the root node empty but do not delete it. 
 */
void oc_bpt_utl_delete_all_b(
    struct Oc_wu *wu_p,
    struct Oc_bpt_state *s_p)
{
    int num_entries = oc_bpt_nd_num_entries(s_p, s_p->root_node_p);

    if (!oc_bpt_nd_is_leaf(s_p, s_p->root_node_p)) {
        // This is a full fledged tree. Remove all the sub-trees. 
        int i;
        Oc_bpt_node *child_node_p;
        struct Oc_bpt_key *dummy_key_p;
        uint64 child_addr;
        
        for (i=0; i< num_entries; i++) {
            oc_bpt_nd_index_get_kth(s_p, s_p->root_node_p, i,
                                    &dummy_key_p,
                                    &child_addr);
            child_node_p = oc_bpt_nd_get_for_read(wu_p, s_p, child_addr);
            oc_bpt_utl_delete_subtree_b(wu_p, s_p, child_node_p);
        }
    }

    // Remove all the entries from the root node
    oc_bpt_nd_remove_range(wu_p, s_p,
                           s_p->root_node_p,
                           0, num_entries - 1);
}