/* search in a node's child */ int _search_child(struct cursor *cur, struct search *so, struct node *n, int childnum) { int ret; NID child_nid; int child_to_search; struct node *child; nassert(n->height > 0); ancestors_append(cur, n->parts[childnum].msgbuf); child_nid = n->parts[childnum].child_nid; if (!cache_get_and_pin(cur->tree->cf, child_nid, (void**)&child, L_READ)) { __ERROR("cache get node error, nid [%" PRIu64 "]", child_nid); return NESS_ERR; } child_to_search = _search_in_which_child(so, child); ret = _search_node(cur, so, child, child_to_search); /* unpin */ cache_unpin(cur->tree->cf, child->cpair); return ret; }
/* * |key44, key88| * / \ * |key10, key20| |key90| * / | \ \ * |basement0| |basement1| |basement2| |basement3| * * (a tree with height 2) * * cursor search is very similar to depth-first-search algorithm. * for cursor_seektofirst operation, the root-to-leaf path is: * key44 -> key10 -> basement0 * and do the inner sliding along with the basement. * if we get the end of one leaf, CURSOR_EOF will be returned to upper on, * and we also set search->pivot_bound = key10, for the next time, * the root-to-leaf path(restart with a jump) will be: * key44 -> key10 -> basement1 */ void _tree_search(struct cursor *cur, struct search *so) { int r; NID root_nid; int child_to_search; struct tree *t; struct node *root; struct cache_operations *c_op = cur->tree->cache->c_op; t = cur->tree; try_again: root_nid = t->hdr->root_nid; if (c_op->cache_get_and_pin(t->cache, root_nid, &root, L_READ) < 0) { __ERROR("cache get root node error, nid [%" PRIu64 "]", root_nid); return; } child_to_search = _search_in_which_child(so, root); r = _search_node(cur, so, root, child_to_search); /* unpin */ c_op->cache_unpin_readonly(t->cache, root); switch (r) { case CURSOR_CONTINUE: break; case CURSOR_TRY_AGAIN: goto try_again; break; case CURSOR_EOF: break; default: break; } }
/* search in a node's child */ int _search_child(struct cursor *cur, struct search *so, struct node *n, int childnum) { int ret; int child_to_search; NID child_nid; struct node *child; struct cache_operations *c_op = cur->tree->cache->c_op; nassert(n->height > 0); /* add basement to ances */ ancestors_append(cur, n->u.n.parts[childnum].buffer); child_nid = n->u.n.parts[childnum].child_nid; if (c_op->cache_get_and_pin(cur->tree->cache, child_nid, &child, L_READ) < 0) { __ERROR("cache get node error, nid [%" PRIu64 "]", child_nid); return NESS_ERR; } child_to_search = _search_in_which_child(so, child); ret = _search_node(cur, so, child, child_to_search); /* unpin */ c_op->cache_unpin_readonly(cur->tree->cache, child); return ret; }
/* * |key44, key88| * / \ * |key10, key20| |key90| * / | \ \ * |msgbuf0| |msgbuf1| |msgbuf2| |msgbuf3| * * (a tree with height 2) * * cursor search is very similar to depth-first-search algorithm. * for cursor_seektofirst operation, the root-to-leaf path is: * key44 -> key10 -> msgbuf0 * and do the inner sliding along with the msgbuf. * if we get the end of one leaf, CURSOR_EOF will be returned to upper on, * and we also set search->pivot_bound = key10, for the next time, * the root-to-leaf path(restart with a jump) will be: * key44 -> key10 -> msgbuf1 */ void _tree_search(struct cursor * cur, struct search * so) { int r; NID root_nid; int child_to_search; struct buftree *t; struct node *root; t = cur->tree; TRY_AGAIN: root_nid = t->hdr->root_nid; if (!cache_get_and_pin(t->cf, root_nid, (void**)&root, L_READ)) { __ERROR("cache get root node error, nid [%" PRIu64 "]", root_nid); return; } child_to_search = _search_in_which_child(so, root); r = _search_node(cur, so, root, child_to_search); /* unpin */ cache_unpin(t->cf, root->cpair); switch (r) { case CURSOR_CONTINUE: /* got the end of leaf */ goto TRY_AGAIN; break; case CURSOR_TRY_AGAIN: /* got the end of node */ goto TRY_AGAIN; break; case CURSOR_EOF: break; default: break; } }