/* We are going to test whether create and close properly check their input. */ #include "test.h" int r; toku_lock_tree* lt = NULL; toku_ltm* ltm = NULL; DB* db = (DB*)1; TXNID txn = (TXNID)1; enum { MAX_LT_LOCKS = 1000 }; uint32_t max_locks = MAX_LT_LOCKS; uint64_t max_lock_memory = MAX_LT_LOCKS*64; bool duplicates = false; int nums[100]; DBT _keys_left[2]; DBT _keys_right[2]; DBT _datas_left[2]; DBT _datas_right[2]; DBT* keys_left[2] ; DBT* keys_right[2] ; DBT* datas_left[2] ; DBT* datas_right[2] ; toku_point qleft, qright; toku_interval query; toku_range* buf; unsigned buflen; unsigned numfound; static void init_query(void) { init_point(&qleft, lt); init_point(&qright, lt); qleft.key_payload = (void *) toku_lt_neg_infinity; qright.key_payload = (void *) toku_lt_infinity; memset(&query,0,sizeof(query)); query.left = &qleft; query.right = &qright; } static DB *fake_db = (DB *) 1; static void setup_tree(void) { assert(!lt && !ltm); r = toku_ltm_create(<m, max_locks, max_lock_memory, dbpanic); CKERR(r); assert(ltm); r = toku_ltm_get_lt(ltm, <, (DICTIONARY_ID){1}, fake_db, dbcmp); CKERR(r); assert(lt); init_query(); } static void close_tree(void) { r = toku_lt_unlock_txn(lt, txn); CKERR(r); assert(lt && ltm); toku_lt_remove_db_ref(lt, fake_db); r = toku_ltm_close(ltm); CKERR(r); lt = NULL; ltm = NULL; } typedef enum { null = -1, infinite = -2, neg_infinite = -3 } lt_infty; static DBT* set_to_infty(DBT *dbt, int value) { if (value == infinite) return (DBT*)toku_lt_infinity; if (value == neg_infinite) return (DBT*)toku_lt_neg_infinity; if (value == null) return dbt_init(dbt, NULL, 0); assert(value >= 0); return dbt_init(dbt, &nums[value], sizeof(nums[0])); } static void lt_insert(int key_l, int key_r) { DBT _key_left; DBT _key_right; DBT* key_left = &_key_left; DBT* key_right = &_key_right; key_left = set_to_infty(key_left, key_l); key_right = set_to_infty(key_right, key_r); assert(key_left); assert(key_right); r = toku_lt_acquire_range_read_lock(lt, db, txn, key_left, key_right); CKERR(r); toku_lt_verify(lt, db); } static void setup_payload_len(void** payload, uint32_t* len, int val) { assert(payload && len); DBT temp; *payload = set_to_infty(&temp, val); if (val < 0) { *len = 0; } else { *len = sizeof(nums[0]); *payload = temp.data; } } static void lt_find(toku_range_tree* rt, unsigned k, int key_l, int key_r, TXNID find_txn) { r = toku_rt_find(rt, &query, 0, &buf, &buflen, &numfound); CKERR(r); assert(numfound==k); toku_point left, right; init_point(&left, lt); setup_payload_len(&left.key_payload, &left.key_len, key_l); init_point(&right, lt); setup_payload_len(&right.key_payload, &right.key_len, key_r); unsigned i; for (i = 0; i < numfound; i++) { if (toku_lt_point_cmp(buf[i].ends.left, &left ) == 0 && toku_lt_point_cmp(buf[i].ends.right, &right) == 0 && buf[i].data == find_txn) { goto cleanup; } } assert(false); //Crash since we didn't find it. cleanup: return; } static void insert_1(int key_l, int key_r, const void* kl, const void* kr) { DBT _key_left; DBT _key_right; DBT* key_left = &_key_left; DBT* key_right = &_key_right; dbt_init (key_left, &nums[key_l], sizeof(nums[key_l])); dbt_init (key_right, &nums[key_r], sizeof(nums[key_r])); if (kl) key_left = (DBT*)kl; if (kr) key_right = (DBT*)kr; setup_tree(); r = toku_lt_acquire_range_read_lock(lt, db, txn, key_left, key_right); CKERR(r); close_tree(); setup_tree(); r = toku_lt_acquire_read_lock(lt, db, txn, key_left); CKERR(r); close_tree(); } static void runtest(void) { const DBT* choices[3]; choices[0] = toku_lt_neg_infinity; choices[1] = NULL; choices[2] = toku_lt_infinity; for (int i = 0; i < 9; i++) { int a = i / 3; int b = i % 3; if (a > b) continue; insert_1(3, 3, choices[a], choices[b]); } toku_range_tree *rt; /* ************************************** */ setup_tree(); /////BUG HERE MAYBE NOT CONSOLIDATING. /* [3, 7] and [4, 5] */ lt_insert(3, 7); lt_insert(4, 5); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 1, 3, 7, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 1, 3, 7, txn); #endif close_tree(); /* ************************************** */ setup_tree(); /* [3, 7)] and [4, 5] */ lt_insert(4, 5); lt_insert(3, 7); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 1, 3, 7, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 1, 3, 7, txn); #endif rt = NULL; close_tree(); /* ************************************** */ setup_tree(); lt_insert(3, 3); lt_insert(4, 4); lt_insert(3, 3); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 2, 3, 3, txn); lt_find(rt, 2, 4, 4, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 2, 3, 3, txn); lt_find(rt, 2, 4, 4, txn); #endif rt = NULL; close_tree(); /* ************************************** */ setup_tree(); for (int i = 0; i < 20; i += 2) { lt_insert(i, i + 1); } rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); for (int i = 0; i < 20; i += 2) { lt_find(rt, 10, i, i + 1, txn); } #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); for (int i = 0; i < 20; i += 2) { lt_find(rt, 10, i, i + 1, txn); } #endif lt_insert(0, 20); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find( rt, 1, 0, 20, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find( rt, 1, 0, 20, txn); #endif rt = NULL; close_tree(); /* ************************************** */ setup_tree(); lt_insert(0, 1); lt_insert(1, 2); lt_insert(4, 5); lt_insert(3, 4); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 2, 0, 2, txn); lt_find(rt, 2, 3, 5, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 2, 0, 2, txn); lt_find(rt, 2, 3, 5, txn); #endif lt_insert(2, 3); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 1, 0, 5, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 1, 0, 5, txn); #endif rt = NULL; close_tree(); /* ************************************** */ setup_tree(); lt_insert(1, 3); lt_insert(4, 6); lt_insert(2, 5); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 1, 1, 6, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 1, 1, 6, txn); #endif close_tree(); setup_tree(); lt_insert(neg_infinite, 3); lt_insert( 4, 5); lt_insert( 6, 8); lt_insert( 2, 7); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 1, neg_infinite, 8, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 1, neg_infinite, 8, txn); #endif close_tree(); setup_tree(); lt_insert(1, 2); lt_insert(3, infinite); lt_insert(2, 3); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 1, 1, infinite, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 1, 1, infinite, txn); #endif close_tree(); setup_tree(); lt_insert(1, 2); lt_insert(3, 4); lt_insert(5, 6); lt_insert(2, 5); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 1, 1, 6, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 1, 1, 6, txn); #endif close_tree(); setup_tree(); lt_insert(1, 2); lt_insert(3, 5); lt_insert(2, 4); rt = toku_lt_ifexist_selfread(lt, txn); assert(rt); lt_find(rt, 1, 1, 5, txn); #if TOKU_LT_USE_MAINREAD && !defined(TOKU_RT_NOOVERLAPS) rt = lt->mainread; assert(rt); lt_find(rt, 1, 1, 5, txn); #endif close_tree(); setup_tree(); lt_insert(1, 1); lt_insert(1, 2); lt_insert(1, 3); close_tree(); } static void init_test(void) { for (unsigned i = 0; i < sizeof(nums)/sizeof(nums[0]); i++) nums[i] = i; buflen = 64; buf = (toku_range*) toku_malloc(buflen*sizeof(toku_range)); assert(buf); } static void close_test(void) { toku_free(buf); } int main(int argc, const char *argv[]) { parse_args(argc, argv); init_test(); runtest(); close_test(); return 0; }