void nmb_to_msgpack(struct nmb *nmb, struct msgpack *packer) { struct mb_iter iter; mb_iter_init(&iter, nmb->pma); while (mb_iter_next(&iter)) { struct nmb_values values; nmb_get_values(&iter, &values); nmb_pack_values_to_msgpack(&values, packer); } }
/* * apply parent's (left, right] messages to child node */ void leaf_apply(struct node *leaf, struct nmb *msgbuf, struct msg *left, struct msg *right) { struct mb_iter iter; struct pma_coord coord_left; struct pma_coord coord_right; nmb_get_left_coord(msgbuf, left, &coord_left); nmb_get_right_coord(msgbuf, right, &coord_right); mb_iter_init(&iter, msgbuf->pma); while (mb_iter_on_range(&iter, &coord_left, &coord_right)) { struct nmb_values values; nmb_get_values(&iter, &values); struct bt_cmd cmd = { .msn = values.msn, .type = values.type, .key = &values.key, .val = &values.val, .xidpair = values.xidpair }; if (cmd.msn > leaf->msn) { leaf_put(leaf, &cmd); } } } int leaf_find_heaviest_idx(struct node *leaf) { int i; int idx = 0; uint32_t sz = 0; uint32_t maxsz = 0; for (i = 0; i < leaf->n_children; i++) { struct lmb *msgbuf = (struct lmb*)&leaf->parts[i].msgbuf; sz = lmb_memsize(msgbuf); if (sz > maxsz) { idx = i; maxsz = sz; } } return idx; }
void nmb_to_msgpack(void *p, void *n) { struct mb_iter iter; struct msgpack *packer = (struct msgpack*)p; struct nmb *nmb = (struct nmb*)n; mb_iter_init(&iter, nmb->pma); while (mb_iter_next(&iter)) { struct nmb_values values; nmb_get_values(&iter, &values); nmb_pack_values_to_msgpack(&values, packer); } }
int _search_leaf(struct cursor *cur, struct search *so, struct node *leaf) { int found; int ret = CURSOR_EOF; struct lmb *lmb; struct mb_iter iter; struct leafentry *le; struct pma_coord coord; /* 1) apply all msgs to leaf msgbuf */ //leaf_apply_ancestors(leaf, cur->ances); /* 2) init leaf iterator, TODO: which msgbuf to read */ lmb = leaf->parts[0].msgbuf; mb_iter_init(&iter, lmb->pma); /* 3) do search */ switch (so->gap) { case GAP_ZERO: found = lmb_find_zero(lmb, &cur->key, &le, &coord); if (found) { mb_iter_reset(&iter, &coord); if (mb_iter_valid(&iter)) { _cursor_get_values_from_leafentry(cur, iter.base); } } ret = CURSOR_EOF; break; case GAP_POSI: found = lmb_find_plus(lmb, &cur->key, &le, &coord); if (found) { mb_iter_reset(&iter, &coord); POSI_RETRY: if (mb_iter_valid(&iter)) { int got = _cursor_get_values_from_leafentry(cur, iter.base); if (!got) { mb_iter_next(&iter); goto POSI_RETRY; } else { ret = CURSOR_EOF; } } else { ret = CURSOR_CONTINUE; } } break; case GAP_NEGA: found = lmb_find_minus(lmb, &cur->key, &le, &coord); if (found) { mb_iter_reset(&iter, &coord); NEGA_RETRY: if (mb_iter_valid(&iter)) { int got = _cursor_get_values_from_leafentry(cur, iter.base); if (!got) { mb_iter_prev(&iter); goto NEGA_RETRY; } else { ret = CURSOR_EOF; } } else { ret = CURSOR_CONTINUE; } } break; } return ret; }
void _flush_buffer_to_child(struct tree *t, struct node *child, struct nmb *buf) { struct mb_iter iter; mb_iter_init(&iter, buf->pma); while (mb_iter_next(&iter)) { /* TODO(BohuTANG): check msn */ struct nmb_values nvalues; nmb_get_values(&iter, &nvalues); struct bt_cmd cmd = { .msn = nvalues.msn, .type = nvalues.type, .key = &nvalues.key, .val = &nvalues.val, .xidpair = nvalues.xidpair }; node_put_cmd(t, child, &cmd); } } void _flush_some_child(struct tree *t, struct node *parent); /* * PROCESS: * - check child reactivity * - if FISSIBLE: split child * - if FLUSHBLE: flush buffer from child * ENTER: * - parent is already locked * - child is already locked * EXIT: * - parent is unlocked * - no nodes are locked */ void _child_maybe_reactivity(struct tree *t, struct node *parent, struct node *child) { enum reactivity re = get_reactivity(t, child); switch (re) { case STABLE: cache_unpin(t->cf, child->cpair, make_cpair_attr(child)); cache_unpin(t->cf, parent->cpair, make_cpair_attr(parent)); break; case FISSIBLE: node_split_child(t, parent, child); cache_unpin(t->cf, child->cpair, make_cpair_attr(child)); cache_unpin(t->cf, parent->cpair, make_cpair_attr(parent)); break; case FLUSHBLE: cache_unpin(t->cf, parent->cpair, make_cpair_attr(parent)); _flush_some_child(t, child); break; } } /* * PROCESS: * - pick a heaviest child of parent * - flush from parent to child * - maybe split/flush child recursively * ENTER: * - parent is already locked * EXIT: * - parent is unlocked * - no nodes are locked */ void _flush_some_child(struct tree *t, struct node *parent) { int childnum; enum reactivity re; struct node *child; struct partition *part; struct nmb *buffer; struct timespec t1, t2; childnum = node_find_heaviest_idx(parent); nassert(childnum < parent->n_children); part = &parent->parts[childnum]; buffer = part->ptr.u.nonleaf->buffer; if (cache_get_and_pin(t->cf, part->child_nid, (void**)&child, L_WRITE) != NESS_OK) { __ERROR("cache get node error, nid [%" PRIu64 "]", part->child_nid); return; } ngettime(&t1); re = get_reactivity(t, child); if (re == STABLE) { node_set_dirty(parent); part->ptr.u.nonleaf->buffer = nmb_new(t->e); _flush_buffer_to_child(t, child, buffer); nmb_free(buffer); } ngettime(&t2); status_add(&t->e->status->tree_flush_child_costs, time_diff_ms(t1, t2)); status_increment(&t->e->status->tree_flush_child_nums); _child_maybe_reactivity(t, parent, child); }