Commit e31cd1bd authored by Bradley C. Kuszmaul's avatar Bradley C. Kuszmaul

Some keyrange support. Addresess #764.

git-svn-id: file:///svn/tokudb@3846 c7de825b-a66e-492c-adef-691d508d4ae1
parent 21ccfb87
...@@ -71,7 +71,7 @@ OFILES += $(NEWBRT_HERE)/newbrt.o ...@@ -71,7 +71,7 @@ OFILES += $(NEWBRT_HERE)/newbrt.o
$(NEWBRT_HERE)/newbrt.o: CPPFLAGS += -I$(NEWBRT_HERE) $(NEWBRT_HERE)/newbrt.o: CPPFLAGS += -I$(NEWBRT_HERE)
$(NEWBRT_HERE)/newbrt.o: $(patsubst %,$(NEWBRT_HERE)/%.c,$(NEWBRT_FILES)) $(NEWBRT_HERE)/newbrt.o: $(patsubst %,$(NEWBRT_HERE)/%.c,$(NEWBRT_FILES))
$(CC) -combine $(CFLAGS) $(CPPFLAGS) $^ -c -o $@ cd $(NEWBRT_HERE);$(CC) -combine $(CFLAGS) $(CPPFLAGS) $(patsubst %,%.c,$(NEWBRT_FILES)) -c -o $@
$(NEWBRT_RBINS): $(NEWBRT_HERE)/newbrt.o $(NEWBRT_RBINS): $(NEWBRT_HERE)/newbrt.o
NEWBRT_NEED_HELPERS = test-inc-split test-del-inorder NEWBRT_NEED_HELPERS = test-inc-split test-del-inorder
...@@ -84,20 +84,21 @@ NEWBRT_CHECKS = \ ...@@ -84,20 +84,21 @@ NEWBRT_CHECKS = \
# This line intentially kept commented so I can have a \ on the previous line # This line intentially kept commented so I can have a \ on the previous line
newbrt.checkdir: $(patsubst %,$(NEWBRT_HERE)/%.check, $(NEWBRT_CHECKS)) newbrt.checkdir: $(patsubst %,$(NEWBRT_HERE)/%.check, $(NEWBRT_CHECKS))
newbrt.builddir: $(OFILES) $(NEWBRT_RBINS)
$(NEWBRT_HERE)/benchmarktest_256.check: $(NEWBRT_HERE)/benchmark-test $(NEWBRT_HERE)/benchmarktest_256.check: $(NEWBRT_HERE)/benchmark-test
cd $(NEWBRT_HERE)/; $(VGRIND) ./benchmark-test $(VERBVERBOSE) --valsize 256 --verify 1 cd $(NEWBRT_HERE); $(VGRIND) ./benchmark-test $(VERBVERBOSE) --valsize 256 --verify 1
#foo: #foo:
# echo $(NEWBRT_HERE)/benchmarktest_256.check # echo $(NEWBRT_HERE)/benchmarktest_256.check
$(NEWBRT_HERE)/test-assert.check: $(NEWBRT_HERE)/test-assert $(NEWBRT_HERE)/test-assert.check: $(NEWBRT_HERE)/test-assert
@# no arguments, should err @# no arguments, should err
$(VGRIND) $(NEWBRT_HERE)/test-assert > /dev/null 2>&1 ; test \($$?\) cd $(NEWBRT_HERE); $(VGRIND) ./test-assert > /dev/null 2>&1 ; test \($$?\)
@# one argument, not "ok" should err @# one argument, not "ok" should err
@echo Expect an abort message: @echo Expect an abort message:
($(VGRIND) $(NEWBRT_HERE)/test-assert notok) > test-assert.out 2>&1 ; test \($$?\) $(NEWBRT_HERE); ($(VGRIND) ./test-assert notok) > test-assert.out 2>&1 ; test \($$?\)
@fgrep failed test-assert.out > /dev/null @fgrep failed test-assert.out > /dev/null
@rm test-assert.out @rm test-assert.out
@# one argument, "ok" should not error @# one argument, "ok" should not error
$(DVGRIND) $(NEWBRT_HERE)/test-assert ok $(NEWBRT_HERE)/ $(VGRIND) ./test-assert ok
...@@ -2551,10 +2551,14 @@ static inline void brt_split_init(BRT_SPLIT *split) { ...@@ -2551,10 +2551,14 @@ static inline void brt_split_init(BRT_SPLIT *split) {
toku_init_dbt(&split->splitk); toku_init_dbt(&split->splitk);
} }
static int brt_search_node(BRT brt, BRTNODE node, brt_search_t *search, DBT *newkey, DBT *newval, BRT_SPLIT *split, TOKULOGGER logger); static int brt_search_node(BRT brt, BRTNODE node, brt_search_t *search, DBT *newkey, DBT *newval,
u_int64_t *est_left,
BRT_SPLIT *split, TOKULOGGER logger);
/* search in a node's child */ /* search in a node's child */
static int brt_search_child(BRT brt, BRTNODE node, int childnum, brt_search_t *search, DBT *newkey, DBT *newval, BRT_SPLIT *split, TOKULOGGER logger) { static int brt_search_child(BRT brt, BRTNODE node, int childnum, brt_search_t *search, DBT *newkey, DBT *newval,
u_int64_t *est_left, // estimate number of items to left.
BRT_SPLIT *split, TOKULOGGER logger) {
int r, rr; int r, rr;
/* if the child's buffer is not empty then try to empty it */ /* if the child's buffer is not empty then try to empty it */
...@@ -2572,7 +2576,7 @@ static int brt_search_child(BRT brt, BRTNODE node, int childnum, brt_search_t *s ...@@ -2572,7 +2576,7 @@ static int brt_search_child(BRT brt, BRTNODE node, int childnum, brt_search_t *s
for (;;) { for (;;) {
BRTNODE childnode = node_v; BRTNODE childnode = node_v;
BRT_SPLIT childsplit; brt_split_init(&childsplit); BRT_SPLIT childsplit; brt_split_init(&childsplit);
r = brt_search_node(brt, childnode, search, newkey, newval, &childsplit, logger); r = brt_search_node(brt, childnode, search, newkey, newval, est_left, &childsplit, logger);
if (childsplit.did_split) { if (childsplit.did_split) {
rr = handle_split_of_child(brt, node, childnum, childsplit.nodea, childsplit.nodeb, &childsplit.splitk, rr = handle_split_of_child(brt, node, childnum, childsplit.nodea, childsplit.nodeb, &childsplit.splitk,
&split->did_split, &split->nodea, &split->nodeb, &split->splitk, logger); &split->did_split, &split->nodea, &split->nodeb, &split->splitk, logger);
...@@ -2590,8 +2594,8 @@ static int brt_search_child(BRT brt, BRTNODE node, int childnum, brt_search_t *s ...@@ -2590,8 +2594,8 @@ static int brt_search_child(BRT brt, BRTNODE node, int childnum, brt_search_t *s
return r; return r;
} }
static int brt_search_nonleaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT *newkey, DBT *newval, BRT_SPLIT *split, TOKULOGGER logger) { static int brt_search_nonleaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT *newkey, DBT *newval, u_int64_t *est_left, BRT_SPLIT *split, TOKULOGGER logger) {
int r = DB_NOTFOUND; int r;
int c; int c;
/* binary search is overkill for a small array */ /* binary search is overkill for a small array */
...@@ -2608,16 +2612,37 @@ static int brt_search_nonleaf_node(BRT brt, BRTNODE node, brt_search_t *search, ...@@ -2608,16 +2612,37 @@ static int brt_search_nonleaf_node(BRT brt, BRTNODE node, brt_search_t *search,
if (search->compare(search, if (search->compare(search,
toku_fill_dbt(&pivotkey, kv_pair_key(pivot), kv_pair_keylen(pivot)), toku_fill_dbt(&pivotkey, kv_pair_key(pivot), kv_pair_keylen(pivot)),
brt->flags & TOKU_DB_DUPSORT ? toku_fill_dbt(&pivotval, kv_pair_val(pivot), kv_pair_vallen(pivot)): 0)) { brt->flags & TOKU_DB_DUPSORT ? toku_fill_dbt(&pivotval, kv_pair_val(pivot), kv_pair_vallen(pivot)): 0)) {
r = brt_search_child(brt, node, child[c], search, newkey, newval, split, logger); r = brt_search_child(brt, node, child[c], search, newkey, newval, est_left, split, logger);
if (r == 0 || r == EAGAIN) if (r == 0) {
break; if (est_left) {
int i;
for (i=0; i<c; i++)
*est_left += BNC_SUBTREE_LEAFENTRY_ESTIMATE(node, child[i]);
}
return r;
} else if (r == EAGAIN) {
return r;
}
} }
} }
/* check the first (left) or last (right) node if nothing has been found */ /* check the first (left) or last (right) node if nothing has been found */
if (r == DB_NOTFOUND && c == node->u.n.n_children-1) r = brt_search_child(brt, node, child[c], search, newkey, newval, est_left, split, logger);
r = brt_search_child(brt, node, child[c], search, newkey, newval, split, logger); if (r == 0) {
if (est_left) {
int i;
for (i=0; i+1<c; i++)
*est_left += BNC_SUBTREE_LEAFENTRY_ESTIMATE(node, child[i]);
}
return r;
} else if (r == DB_NOTFOUND) {
if (est_left) {
int i;
for (i=0; i<c; i++)
*est_left += BNC_SUBTREE_LEAFENTRY_ESTIMATE(node, child[i]);
}
return r;
}
return r; return r;
} }
...@@ -2666,7 +2691,7 @@ static int bessel_from_search_t (OMTVALUE lev, void *extra) { ...@@ -2666,7 +2691,7 @@ static int bessel_from_search_t (OMTVALUE lev, void *extra) {
LESWITCHCALL(leafval, pair_leafval_bessel, search); LESWITCHCALL(leafval, pair_leafval_bessel, search);
} }
static int brt_search_leaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT *newkey, DBT *newval) { static int brt_search_leaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT *newkey, DBT *newval, u_int64_t *est_left) {
// Now we have to convert from brt_search_t to the bessel function with a direction. What a pain... // Now we have to convert from brt_search_t to the bessel function with a direction. What a pain...
int direction; int direction;
switch (search->direction) { switch (search->direction) {
...@@ -2682,7 +2707,16 @@ static int brt_search_leaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT ...@@ -2682,7 +2707,16 @@ static int brt_search_leaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT
search, search,
direction, direction,
&datav, &idx); &datav, &idx);
if (r!=0) return r; if (r!=0) {
if (est_left) {
switch (search->direction) {
case BRT_SEARCH_LEFT: *est_left = toku_omt_size(node->u.l.buffer); return 0;
case BRT_SEARCH_RIGHT: *est_left = 0; return 0;
}
}
return r;
}
if (est_left) *est_left = idx;
LEAFENTRY le = datav; LEAFENTRY le = datav;
if (le_is_provdel(le)) { if (le_is_provdel(le)) {
...@@ -2723,14 +2757,16 @@ static int brt_search_leaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT ...@@ -2723,14 +2757,16 @@ static int brt_search_leaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT
return 0; return 0;
} }
static int brt_search_node(BRT brt, BRTNODE node, brt_search_t *search, DBT *newkey, DBT *newval, BRT_SPLIT *split, TOKULOGGER logger) { static int brt_search_node(BRT brt, BRTNODE node, brt_search_t *search, DBT *newkey, DBT *newval,
u_int64_t *est_left,
BRT_SPLIT *split, TOKULOGGER logger) {
if (node->height > 0) if (node->height > 0)
return brt_search_nonleaf_node(brt, node, search, newkey, newval, split, logger); return brt_search_nonleaf_node(brt, node, search, newkey, newval, est_left, split, logger);
else else
return brt_search_leaf_node(brt, node, search, newkey, newval); return brt_search_leaf_node(brt, node, search, newkey, newval, est_left);
} }
int toku_brt_search(BRT brt, brt_search_t *search, DBT *newkey, DBT *newval, TOKULOGGER logger) { int toku_brt_search(BRT brt, brt_search_t *search, DBT *newkey, DBT *newval, u_int64_t *est_left, TOKULOGGER logger) {
int r, rr; int r, rr;
rr = toku_read_and_pin_brt_header(brt->cf, &brt->h); rr = toku_read_and_pin_brt_header(brt->cf, &brt->h);
...@@ -2758,7 +2794,7 @@ int toku_brt_search(BRT brt, brt_search_t *search, DBT *newkey, DBT *newval, TOK ...@@ -2758,7 +2794,7 @@ int toku_brt_search(BRT brt, brt_search_t *search, DBT *newkey, DBT *newval, TOK
for (;;) { for (;;) {
BRT_SPLIT split; brt_split_init(&split); BRT_SPLIT split; brt_split_init(&split);
r = brt_search_node(brt, node, search, newkey, newval, &split, logger); r = brt_search_node(brt, node, search, newkey, newval, est_left, &split, logger);
if (split.did_split) { if (split.did_split) {
rr = brt_init_new_root(brt, split.nodea, split.nodeb, split.splitk, rootp, 0, &node); rr = brt_init_new_root(brt, split.nodea, split.nodeb, split.splitk, rootp, 0, &node);
...@@ -2894,7 +2930,7 @@ static int brt_cursor_current(BRT_CURSOR cursor, int op, DBT *outkey, DBT *outva ...@@ -2894,7 +2930,7 @@ static int brt_cursor_current(BRT_CURSOR cursor, int op, DBT *outkey, DBT *outva
DBT newval; toku_init_dbt(&newval); newval.flags = DB_DBT_MALLOC; DBT newval; toku_init_dbt(&newval); newval.flags = DB_DBT_MALLOC;
brt_search_t search; brt_search_init(&search, brt_cursor_compare_set, BRT_SEARCH_LEFT, &cursor->key, &cursor->val, cursor->brt); brt_search_t search; brt_search_init(&search, brt_cursor_compare_set, BRT_SEARCH_LEFT, &cursor->key, &cursor->val, cursor->brt);
r = toku_brt_search(cursor->brt, &search, &newkey, &newval, logger); r = toku_brt_search(cursor->brt, &search, &newkey, &newval, (u_int64_t*)0,logger);
if (r != 0 || compare_kv_xy(cursor->brt, &cursor->key, &cursor->val, &newkey, &newval) != 0) if (r != 0 || compare_kv_xy(cursor->brt, &cursor->key, &cursor->val, &newkey, &newval) != 0)
r = DB_KEYEMPTY; r = DB_KEYEMPTY;
dbt_cleanup(&newkey); dbt_cleanup(&newkey);
...@@ -2909,7 +2945,7 @@ static int brt_cursor_search(BRT_CURSOR cursor, brt_search_t *search, DBT *outke ...@@ -2909,7 +2945,7 @@ static int brt_cursor_search(BRT_CURSOR cursor, brt_search_t *search, DBT *outke
DBT newkey; toku_init_dbt(&newkey); newkey.flags = DB_DBT_MALLOC; DBT newkey; toku_init_dbt(&newkey); newkey.flags = DB_DBT_MALLOC;
DBT newval; toku_init_dbt(&newval); newval.flags = DB_DBT_MALLOC; DBT newval; toku_init_dbt(&newval); newval.flags = DB_DBT_MALLOC;
int r = toku_brt_search(cursor->brt, search, &newkey, &newval, logger); int r = toku_brt_search(cursor->brt, search, &newkey, &newval, (u_int64_t*)0, logger);
if (r == 0) { if (r == 0) {
brt_cursor_set_key_val(cursor, &newkey, &newval); brt_cursor_set_key_val(cursor, &newkey, &newval);
r = brt_cursor_copyout(cursor, outkey, outval); r = brt_cursor_copyout(cursor, outkey, outval);
...@@ -2924,7 +2960,7 @@ static int brt_cursor_search_eq_kv_xy(BRT_CURSOR cursor, brt_search_t *search, D ...@@ -2924,7 +2960,7 @@ static int brt_cursor_search_eq_kv_xy(BRT_CURSOR cursor, brt_search_t *search, D
DBT newkey; toku_init_dbt(&newkey); newkey.flags = DB_DBT_MALLOC; DBT newkey; toku_init_dbt(&newkey); newkey.flags = DB_DBT_MALLOC;
DBT newval; toku_init_dbt(&newval); newval.flags = DB_DBT_MALLOC; DBT newval; toku_init_dbt(&newval); newval.flags = DB_DBT_MALLOC;
int r = toku_brt_search(cursor->brt, search, &newkey, &newval, logger); int r = toku_brt_search(cursor->brt, search, &newkey, &newval, (u_int64_t*)0, logger);
if (r == 0) { if (r == 0) {
if (compare_kv_xy(cursor->brt, search->k, search->v, &newkey, &newval) == 0) { if (compare_kv_xy(cursor->brt, search->k, search->v, &newkey, &newval) == 0) {
brt_cursor_set_key_val(cursor, &newkey, &newval); brt_cursor_set_key_val(cursor, &newkey, &newval);
...@@ -2942,7 +2978,7 @@ static int brt_cursor_search_eq_k_x(BRT_CURSOR cursor, brt_search_t *search, DBT ...@@ -2942,7 +2978,7 @@ static int brt_cursor_search_eq_k_x(BRT_CURSOR cursor, brt_search_t *search, DBT
DBT newkey; toku_init_dbt(&newkey); newkey.flags = DB_DBT_MALLOC; DBT newkey; toku_init_dbt(&newkey); newkey.flags = DB_DBT_MALLOC;
DBT newval; toku_init_dbt(&newval); newval.flags = DB_DBT_MALLOC; DBT newval; toku_init_dbt(&newval); newval.flags = DB_DBT_MALLOC;
int r = toku_brt_search(cursor->brt, search, &newkey, &newval, logger); int r = toku_brt_search(cursor->brt, search, &newkey, &newval, (u_int64_t*)0, logger);
if (r == 0) { if (r == 0) {
if (compare_k_x(cursor->brt, search->k, &newkey) == 0) { if (compare_k_x(cursor->brt, search->k, &newkey) == 0) {
brt_cursor_set_key_val(cursor, &newkey, &newval); brt_cursor_set_key_val(cursor, &newkey, &newval);
......
...@@ -179,6 +179,7 @@ int toku_omt_find(OMT V, int (*h)(OMTVALUE, void*extra), void*extra, int directi ...@@ -179,6 +179,7 @@ int toku_omt_find(OMT V, int (*h)(OMTVALUE, void*extra), void*extra, int directi
/* Effect: /* Effect:
If direction >0 then find the smallest i such that h(V_i,extra)>0. If direction >0 then find the smallest i such that h(V_i,extra)>0.
If direction <0 then find the largest i such that h(V_i,extra)<0. If direction <0 then find the largest i such that h(V_i,extra)<0.
(Direction may not be equal to zero.)
If value!=NULL then store V_i in *value If value!=NULL then store V_i in *value
If index!=NULL then store i in *index. If index!=NULL then store i in *index.
Requires: The signum of h is monotically increasing. Requires: The signum of h is monotically increasing.
...@@ -188,7 +189,6 @@ int toku_omt_find(OMT V, int (*h)(OMTVALUE, void*extra), void*extra, int directi ...@@ -188,7 +189,6 @@ int toku_omt_find(OMT V, int (*h)(OMTVALUE, void*extra), void*extra, int directi
On nonzero return, *value and *index are unchanged. On nonzero return, *value and *index are unchanged.
Performance: time=O(\log N) Performance: time=O(\log N)
Rationale: Rationale:
The direction==0 is a strange case that should go away in the future.
Here's how to use the find function to find various things Here's how to use the find function to find various things
Cases for find: Cases for find:
find first value: ( h(v)=+1, direction=+1 ) find first value: ( h(v)=+1, direction=+1 )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment