Commit e4604aac authored by Yoni Fogel's avatar Yoni Fogel

Closes #553

Lock escalation causes all lock trees (all dbs in an environment)
to escalate their locks.
This is useful, since we can have one lock tree/db holding 99% of the locks
and then we run out of locks on a different lock tree.

git-svn-id: file:///svn/tokudb@2952 c7de825b-a66e-492c-adef-691d508d4ae1
parent 52d8a95c
...@@ -1316,15 +1316,15 @@ static inline int toku__escalate_reads_from_border_range(toku_lock_tree* tree, ...@@ -1316,15 +1316,15 @@ static inline int toku__escalate_reads_from_border_range(toku_lock_tree* tree,
* Replaces all writes that overlap with range * Replaces all writes that overlap with range
* Deletes all reads dominated by range * Deletes all reads dominated by range
*/ */
static int toku__do_escalation(toku_lock_tree* tree, BOOL* locks_available) { static int toku__lt_do_escalation(toku_lock_tree* tree) {
int r = ENOSYS; int r = ENOSYS;
if (!tree || !locks_available) { r = EINVAL; goto cleanup; } if (!tree) { r = EINVAL; goto cleanup; }
if (!tree->lock_escalation_allowed) { r = EDOM; goto cleanup; } if (!tree->lock_escalation_allowed) { r = 0; goto cleanup; }
toku_range_tree* border = tree->borderwrite; toku_range_tree* border = tree->borderwrite;
assert(border); assert(border);
toku_range border_range; toku_range border_range;
BOOL found = FALSE; BOOL found = FALSE;
BOOL trivial = FALSE; BOOL trivial = FALSE;
toku_rt_start_scan(border); toku_rt_start_scan(border);
while ((r = toku_rt_next(border, &border_range, &found)) == 0 && found) { while ((r = toku_rt_next(border, &border_range, &found)) == 0 && found) {
...@@ -1341,14 +1341,25 @@ static int toku__do_escalation(toku_lock_tree* tree, BOOL* locks_available) { ...@@ -1341,14 +1341,25 @@ static int toku__do_escalation(toku_lock_tree* tree, BOOL* locks_available) {
if (r!=0) { r = toku__lt_panic(tree, r); goto cleanup; } if (r!=0) { r = toku__lt_panic(tree, r); goto cleanup; }
} }
r = 0; r = 0;
*locks_available = toku__mgr_lock_test_incr(tree->mgr, 0);
/* Escalation is allowed if 1/10th of the locks (or more) are free. */
cleanup: cleanup:
if (r!=0) { return r;
if (tree && locks_available) { }
*locks_available = FALSE;
} /* TODO: Different error code for escalation failed vs not even happened. */
static int toku__ltm_do_escalation(toku_ltm* mgr, BOOL* locks_available) {
assert(mgr && locks_available);
int r = ENOSYS;
toku_lock_tree* lt = NULL;
toku_lth_start_scan(mgr->lth);
while ((lt = toku_lth_next(mgr->lth)) != NULL) {
r = toku__lt_do_escalation(lt);
if (r!=0) { goto cleanup; }
} }
*locks_available = toku__mgr_lock_test_incr(mgr, 0);
r = 0;
cleanup:
return r; return r;
} }
...@@ -1363,9 +1374,9 @@ int toku_lt_acquire_range_read_lock(toku_lock_tree* tree, DB_TXN* txn, ...@@ -1363,9 +1374,9 @@ int toku_lt_acquire_range_read_lock(toku_lock_tree* tree, DB_TXN* txn,
&out_of_locks); &out_of_locks);
if (r != 0) { goto cleanup; } if (r != 0) { goto cleanup; }
if (out_of_locks && tree->lock_escalation_allowed) { if (out_of_locks) {
BOOL locks_available = FALSE; BOOL locks_available = FALSE;
r = toku__do_escalation(tree, &locks_available); r = toku__ltm_do_escalation(tree->mgr, &locks_available);
if (r != 0) { goto cleanup; } if (r != 0) { goto cleanup; }
if (!locks_available) { if (!locks_available) {
...@@ -1479,9 +1490,9 @@ int toku_lt_acquire_write_lock(toku_lock_tree* tree, DB_TXN* txn, ...@@ -1479,9 +1490,9 @@ int toku_lt_acquire_write_lock(toku_lock_tree* tree, DB_TXN* txn,
&out_of_locks); &out_of_locks);
if (r != 0) { goto cleanup; } if (r != 0) { goto cleanup; }
if (out_of_locks && tree->lock_escalation_allowed) { if (out_of_locks) {
BOOL locks_available = FALSE; BOOL locks_available = FALSE;
r = toku__do_escalation(tree, &locks_available); r = toku__ltm_do_escalation(tree->mgr, &locks_available);
if (r != 0) { goto cleanup; } if (r != 0) { goto cleanup; }
if (!locks_available) { if (!locks_available) {
...@@ -1545,9 +1556,9 @@ int toku_lt_acquire_range_write_lock(toku_lock_tree* tree, DB_TXN* txn, ...@@ -1545,9 +1556,9 @@ int toku_lt_acquire_range_write_lock(toku_lock_tree* tree, DB_TXN* txn,
&out_of_locks); &out_of_locks);
if (r != 0) { goto cleanup; } if (r != 0) { goto cleanup; }
if (out_of_locks && tree->lock_escalation_allowed) { if (out_of_locks) {
BOOL locks_available = FALSE; BOOL locks_available = FALSE;
r = toku__do_escalation(tree, &locks_available); r = toku__ltm_do_escalation(tree->mgr, &locks_available);
if (r != 0) { goto cleanup; } if (r != 0) { goto cleanup; }
if (!locks_available) { if (!locks_available) {
......
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