From 0f3d1b0f07b4d55fc71f9b3e7d563f8bb7ef4d81 Mon Sep 17 00:00:00 2001 From: Yoni Fogel <yoni@tokutek.com> Date: Wed, 19 Mar 2008 17:23:08 +0000 Subject: [PATCH] Addresses #553 Lock tree manager keeps track of all the lock trees so we can loop through them. git-svn-id: file:///svn/tokudb@2949 c7de825b-a66e-492c-adef-691d508d4ae1 --- src/lock_tree/locktree.c | 36 +++++++++++++++++--- src/lock_tree/tests/test_00070_ltm.c | 49 ++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 src/lock_tree/tests/test_00070_ltm.c diff --git a/src/lock_tree/locktree.c b/src/lock_tree/locktree.c index 96d146c5b6..ce264f8d18 100644 --- a/src/lock_tree/locktree.c +++ b/src/lock_tree/locktree.c @@ -87,6 +87,16 @@ static inline int toku__lt_txn_cmp(const DB_TXN* a, const DB_TXN* b) { return a < b ? -1 : (a != b); } +static inline void toku_ltm_remove_lt(toku_ltm* mgr, toku_lock_tree* lt) { + assert(mgr && lt); + toku_lth_delete(mgr->lth, lt); +} + +static inline int toku_ltm_add_lt(toku_ltm* mgr, toku_lock_tree* lt) { + assert(mgr && lt); + return toku_lth_insert(mgr->lth, lt); +} + int toku__lt_point_cmp(const toku_point* x, const toku_point* y) { int partial_result; DBT point_1; @@ -162,6 +172,8 @@ cleanup: return r; } +static int toku_lt_close_without_ltm(toku_lock_tree* tree); + int toku_ltm_close(toku_ltm* mgr) { int r = ENOSYS; int first_error = 0; @@ -171,10 +183,9 @@ int toku_ltm_close(toku_ltm* mgr) { toku_lth_start_scan(mgr->lth); toku_lock_tree* lt; while ((lt = toku_lth_next(mgr->lth)) != NULL) { - r = toku_lt_close(lt); + r = toku_lt_close_without_ltm(lt); if (r!=0 && first_error==0) { first_error = r; } } - toku_lth_close(mgr->lth); mgr->free(mgr); r = first_error; @@ -1020,7 +1031,7 @@ int toku_lt_create(toku_lock_tree** ptree, DB* db, BOOL duplicates, tmp_tree->db = db; tmp_tree->duplicates = duplicates; tmp_tree->panic = panic; - tmp_tree->mgr = mgr; + tmp_tree->mgr = mgr; tmp_tree->compare_fun = compare_fun; tmp_tree->dup_compare = dup_compare; tmp_tree->malloc = user_malloc; @@ -1046,15 +1057,18 @@ int toku_lt_create(toku_lock_tree** ptree, DB* db, BOOL duplicates, tmp_tree->buflen = __toku_default_buflen; tmp_tree->buf = (toku_range*) user_malloc(tmp_tree->buflen * sizeof(toku_range)); + if (0) { died5: toku_free(tmp_tree->buf); goto died4; } if (!tmp_tree->buf) { r = errno; goto died4; } /* We have not failed lock escalation, so we allow escalation if we run out of locks. */ tmp_tree->lock_escalation_allowed = TRUE; + r = toku_ltm_add_lt(tmp_tree->mgr, tmp_tree); + if (r!=0) { goto died5; } *ptree = tmp_tree; return 0; } -int toku_lt_close(toku_lock_tree* tree) { +static int toku_lt_close_without_ltm(toku_lock_tree* tree) { if (!tree) return EINVAL; int r; int r2 = 0; @@ -1081,6 +1095,20 @@ int toku_lt_close(toku_lock_tree* tree) { return r2; } +int toku_lt_close(toku_lock_tree* tree) { + int r = ENOSYS; + int first_error = 0; + if (!tree) { r = EINVAL; goto cleanup; } + + toku_ltm_remove_lt(tree->mgr, tree); + r = toku_lt_close_without_ltm(tree); + if (r!=0 && first_error==0) { first_error = r; } + + r = first_error; +cleanup: + return r; +} + int toku_lt_acquire_read_lock(toku_lock_tree* tree, DB_TXN* txn, const DBT* key, const DBT* data) { return toku_lt_acquire_range_read_lock(tree, txn, key, data, key, data); diff --git a/src/lock_tree/tests/test_00070_ltm.c b/src/lock_tree/tests/test_00070_ltm.c new file mode 100644 index 0000000000..46de2f61e5 --- /dev/null +++ b/src/lock_tree/tests/test_00070_ltm.c @@ -0,0 +1,49 @@ +/* Test for a memory leak from just closing the lock tree manager (should close + all lock trees. */ + +#include "test.h" + +toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, DB_TXN* txn); +toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn); + +int r; +toku_lock_tree* lt = NULL; +toku_ltm* ltm = NULL; +DB* db = (DB*)1; +u_int32_t max_locks = 10; +BOOL duplicates = FALSE; +int nums[10000]; + +void setup_tree(BOOL dups) { + assert(!lt && !ltm); + r = toku_ltm_create(<m, max_locks, toku_malloc, toku_free, toku_realloc); + CKERR(r); + assert(ltm); + r = toku_lt_create(<, db, dups, dbpanic, ltm, intcmp, intcmp, + toku_malloc, toku_free, toku_realloc); + CKERR(r); + assert(lt); +} + +void close_ltm(void) { + assert(lt && ltm); + r = toku_ltm_close(ltm); + CKERR(r); + lt = NULL; + ltm = NULL; +} + +void run_test(BOOL dups) { + setup_tree(dups); + close_ltm(); +} + +int main(int argc, const char *argv[]) { + parse_args(argc, argv); + + + run_test(FALSE); + run_test(TRUE); + + return 0; +} -- 2.30.9