CTEST(basement, insert_and_lookup) { int i; int ret; int R = 1000; char kbuf[KEY_SIZE]; char vbuf[VAL_SIZE]; struct basement_iter iter; struct basement *bsm = basement_new(); struct msg **msgs = xcalloc(R, sizeof(*msgs)); struct txnid_pair xidpair = { .child_xid = TXNID_NONE, .parent_xid = TXNID_NONE }; MSN msn = 0U; _random_key(vbuf, VAL_SIZE); for (i = 0; i < R; i++) { memset(kbuf, 0, KEY_SIZE); snprintf(kbuf, KEY_SIZE, "key-%d", i); struct msg k = {.data = kbuf, .size = KEY_SIZE}; struct msg v = {.data = vbuf, .size = VAL_SIZE}; msgs[i] = msgdup(&k); basement_put(bsm, msn++, MSG_INSERT, &k, &v, &xidpair ); } basement_iter_init(&iter, bsm); basement_iter_seektolast(&iter); ret = basement_iter_valid(&iter); ASSERT_EQUAL(1, ret); for (i = 0; i < R; i++) { basement_iter_seek(&iter, msgs[i]); ret = basement_iter_valid(&iter); ASSERT_EQUAL(1, ret); ret = msg_key_compare(msgs[i], &iter.key); ASSERT_EQUAL(0, ret); } /* do msg free */ for (i = 0; i < R; i++) { xfree(msgs[i]->data); xfree(msgs[i]); } xfree(msgs); basement_free(bsm); xcheck_all_free(); }
int _findlargest(struct basement **bsms, int bsms_size, struct cursor *cur, struct search *so) { int i; int ret; int end; struct basement_iter *largest = NULL; struct basement_iter iters[bsms_size]; /* seek each level */ for (i = (bsms_size - 1); i >= 0; i--) { struct basement *bsm; struct basement_iter *iter; bsm = bsms[i]; iter = &iters[i]; basement_iter_init(iter, bsm); if (so->key) { /* * since basement_iter_seek is >=so->key, * we should ensure that all sought iters positioned before so->key */ basement_iter_seek(iter, so->key); if (basement_iter_valid(iter)) basement_iter_prev(iter); else basement_iter_seektolast(iter); } else { basement_iter_seektolast(iter); } } for (i = (bsms_size - 1); i >= 0; i--) { struct basement_iter *iter = &iters[i]; if (basement_iter_valid(iter)) { if (largest == NULL) { largest = iter; } else if (so->key_compare_func(&iter->key, &largest->key) > 0) { largest = iter; } } } end = (basement_iter_valid(&iters[0]) == 0); if (end) { if (largest) { cur->valid = 1; cur->key = largest->key; cur->val = largest->val; } else cur->valid = 0; ret = CURSOR_EOF; } else { cur->valid = 1; cur->key = largest->key; cur->val = largest->val; ret = CURSOR_CONTINUE; } return ret; }
/* * apply parent's [leaf, right] messages to child node */ void _apply_msg_to_child(struct node *parent, int child_num, struct node *child, struct msg *left, struct msg *right) { int height; struct basement *bsm; struct basement_iter iter; nassert(child != NULL); nassert(parent->height > 0); height = child->height; if (height == 0) bsm = child->u.l.le->bsm; else bsm = child->u.n.parts[child_num].buffer; basement_iter_init(&iter, bsm); basement_iter_seek(&iter, left); while (basement_iter_valid_lessorequal(&iter, right)) { struct bt_cmd cmd = { .msn = iter.msn, .type = iter.type, .key = &iter.key, .val = &iter.val, .xidpair = iter.xidpair }; if (nessunlikely(height == 0)) leaf_put_cmd(child, &cmd); else nonleaf_put_cmd(child, &cmd); } } /* * apply msgs from ances to leaf basement which are between(include) left and right * REQUIRES: * 1) leaf write-lock * 2) ances all write-lock */ int leaf_apply_ancestors(struct node *leaf, struct ancestors *ances) { struct ancestors *ance; struct msg *left = NULL; struct msg *right = NULL; struct basement_iter iter; struct basement *bsm = leaf->u.l.le->bsm; basement_iter_init(&iter, bsm); basement_iter_seektofirst(&iter); if (basement_iter_valid(&iter)) left = msgdup(&iter.key); basement_iter_seektolast(&iter); if (basement_iter_valid(&iter)) right = msgdup(&iter.key); ance = ances; while (ance && ance->next) { /* apply [leaf, right] to leaf */ _apply_msg_to_child(ance->v, ance->childnum, ance->next->v, left, right); ance = ances->next; } msgfree(left); msgfree(right); return NESS_OK; }