Commit 619b9620 authored by John Esmet's avatar John Esmet Committed by Yoni Fogel

[t:5153] fix the error handling code for toku_ltm_get_lt() and better explain...

[t:5153] fix the error handling code for toku_ltm_get_lt() and better explain what the client contract is for the on_create and on_close callbacks.

the idea is you should only pass an on_create callback if there is also an on_close callback, and vice-versa. the on_create callback is called if
the lock tree is created and the on_close callback is called only if the on_create callback was actually called, either because of a user close
of the locktree or by an error path in toku_ltm_get_lt().

we never assume that either of these callbacks are non-null and we know both can be called at most once.


git-svn-id: file:///svn/toku/tokudb@45002 c7de825b-a66e-492c-adef-691d508d4ae1
parent 74b9b11d
......@@ -1353,6 +1353,13 @@ toku_ltm_get_lt(toku_ltm* mgr, toku_lock_tree** ptree, DICTIONARY_ID dict_id, DE
toku_lock_tree* tree = NULL;
bool added_to_ltm = FALSE;
bool added_to_idlth = FALSE;
// verify that the on_create and on_close callbacks are either
// mutually null or mutually non-null.
if ((on_close_callback == NULL) != (on_close_callback == NULL)) {
r = EINVAL;
goto out;
}
ltm_mutex_lock(mgr);
map = toku_idlth_find(mgr->idlth, dict_id);
......@@ -1370,11 +1377,15 @@ toku_ltm_get_lt(toku_ltm* mgr, toku_lock_tree** ptree, DICTIONARY_ID dict_id, DE
if (r != 0) {
goto cleanup;
}
// we just created the locktree, so call the callback if necessary
// we just created the locktree, so call the callback if necessary,
// and set the on_close callback. we checked above that these callbacks
// are either mutually null or non-null, so this is correct.
if (on_create_callback) {
on_create_callback(tree, on_create_extra);
} else {
assert(on_close_callback == NULL);
}
// set the on close callback
tree->on_close_callback = on_close_callback;
lt_set_dict_id(tree, dict_id);
......@@ -1406,22 +1417,24 @@ toku_ltm_get_lt(toku_ltm* mgr, toku_lock_tree** ptree, DICTIONARY_ID dict_id, DE
if (r == 0) {
mgr->STATUS_VALUE(LTM_LT_CREATE)++;
mgr->STATUS_VALUE(LTM_LT_NUM)++;
if (mgr->STATUS_VALUE(LTM_LT_NUM) > mgr->STATUS_VALUE(LTM_LT_NUM_MAX))
if (mgr->STATUS_VALUE(LTM_LT_NUM) > mgr->STATUS_VALUE(LTM_LT_NUM_MAX)) {
mgr->STATUS_VALUE(LTM_LT_NUM_MAX) = mgr->STATUS_VALUE(LTM_LT_NUM);
}
}
else {
if (tree != NULL) {
if (added_to_ltm)
if (added_to_ltm) {
ltm_remove_lt(mgr, tree);
if (added_to_idlth)
}
if (added_to_idlth) {
toku_idlth_delete(mgr->idlth, dict_id);
}
// if the on_create callback was called, then we will have set
// the on_close callback to something non-null, and it will
// be called in toku_lt_close(), as required.
toku_lt_close(tree);
}
mgr->STATUS_VALUE(LTM_LT_CREATE_FAIL)++;
// need to make sure the on close callback is called
// here, otherwise we might leak something from the
// on create callback.
on_close_callback(tree);
}
ltm_mutex_unlock(mgr);
return r;
......
......@@ -119,8 +119,12 @@ void
toku_lt_update_descriptor(toku_lock_tree* tree, DESCRIPTOR desc);
/**
Gets a lock tree for a given DB with id dict_id. If the locktree is created,
the on_create_callback will be called with a pointer to the new tree and extra.
Gets a lock tree for a given DB with id dict_id.
If an on_create callback is given, then an on_close callback must be given,
and vice-versa. The on_create callback is called if the locktree is actually
created by this call and the on_close callback is called when the locktree
eventually closes, by the user or by an error path in this call.
*/
int toku_ltm_get_lt(toku_ltm* mgr, toku_lock_tree** ptree, DICTIONARY_ID dict_id, DESCRIPTOR desc,
toku_dbt_cmp compare_fun, toku_lt_on_create_cb on_create_callback, void *on_create_extra,
......
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