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); } } }
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); } } }
/* 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); }
/* 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); }