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); } } }
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_cow_root_and_update_b( struct Oc_wu *wu_p, struct Oc_bpt_state *s_p, struct Oc_bpt_data *father_data_p, int size) { // Old disk-addr stored as data in father uint64 prev_addr = *((uint64*)father_data_p); Oc_bpt_node *node_p; int fs_refcnt; oc_bpt_trace_wu_lvl(2, OC_EV_BPT_COW_ROOT_AND_UPDATE, wu_p, "lba of root as appers in father (before update):%llu", prev_addr); oc_utl_assert(NULL != s_p->root_node_p); oc_utl_trk_crt_lock_write(wu_p, &s_p->lock); node_p = s_p->cfg_p->node_get_xl(wu_p, s_p->root_node_p->disk_addr); oc_utl_debugassert(node_p == s_p->root_node_p); fs_refcnt = s_p->cfg_p->fs_get_refcount( wu_p, s_p->root_node_p->disk_addr); s_p->cfg_p->node_mark_dirty(wu_p, s_p->root_node_p, (fs_refcnt > 1)); if (s_p->root_node_p->disk_addr != prev_addr) { uint64 new_addr = s_p->root_node_p->disk_addr; memcpy((char*)father_data_p, &new_addr, size); } oc_bpt_trace_wu_lvl(2, OC_EV_BPT_COW_ROOT_AND_UPDATE, wu_p, "lba of root as appers in father (AFTER update):%llu", *((uint64*)father_data_p)); oc_bpt_nd_release(wu_p, s_p, s_p->root_node_p);// Dalit: may not be needed oc_utl_trk_crt_unlock(wu_p, &s_p->lock); // Dalit: may not be needed }