mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 19:41:47 +01:00
fixes #6205 handle the case where a transaction has not yet noted a locktree during the escalation callback
git-svn-id: file:///svn/toku/tokudb@54261 c7de825b-a66e-492c-adef-691d508d4ae1
This commit is contained in:
parent
a85f32968c
commit
4334b8fb0c
1 changed files with 23 additions and 17 deletions
|
@ -86,8 +86,8 @@ void toku_db_txn_escalate_callback(TXNID txnid, const toku::locktree *lt, const
|
||||||
//
|
//
|
||||||
// If we did find the transaction, then it has not yet been removed
|
// If we did find the transaction, then it has not yet been removed
|
||||||
// from the manager and therefore has not yet released its locks.
|
// from the manager and therefore has not yet released its locks.
|
||||||
// We must be able to find and replace the range buffer associated
|
// We must try to replace the range buffer associated with this locktree,
|
||||||
// with this locktree. This is impotant, otherwise it can grow out of
|
// if it exists. This is impotant, otherwise it can grow out of
|
||||||
// control (ticket 5961).
|
// control (ticket 5961).
|
||||||
|
|
||||||
if (ttxn != nullptr) {
|
if (ttxn != nullptr) {
|
||||||
|
@ -103,25 +103,31 @@ void toku_db_txn_escalate_callback(TXNID txnid, const toku::locktree *lt, const
|
||||||
// will not need to take the txn mutex, so the deadlock is avoided.
|
// will not need to take the txn mutex, so the deadlock is avoided.
|
||||||
toku_mutex_lock(&db_txn_struct_i(txn)->txn_mutex);
|
toku_mutex_lock(&db_txn_struct_i(txn)->txn_mutex);
|
||||||
|
|
||||||
// We should be able to find this locktree. It was just escalated, and we had locks.
|
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
txn_lt_key_ranges ranges;
|
txn_lt_key_ranges ranges;
|
||||||
toku::omt<txn_lt_key_ranges> *map = &db_txn_struct_i(txn)->lt_map;
|
toku::omt<txn_lt_key_ranges> *map = &db_txn_struct_i(txn)->lt_map;
|
||||||
int r = map->find_zero<const toku::locktree *, find_key_ranges_by_lt>(lt, &ranges, &idx);
|
int r = map->find_zero<const toku::locktree *, find_key_ranges_by_lt>(lt, &ranges, &idx);
|
||||||
invariant_zero(r);
|
if (r == 0) {
|
||||||
|
// Destroy the old range buffer, create a new one, and insert the new ranges.
|
||||||
// Destroy the old range buffer, create a new one, and insert the new ranges.
|
//
|
||||||
//
|
// We could theoretically steal the memory from the caller instead of copying
|
||||||
// We could theoretically steal the memory from the caller instead of copying
|
// it, but it's simpler to have a callback API that doesn't transfer memory ownership.
|
||||||
// it, but it's simpler to have a callback API that doesn't transfer memory ownership.
|
ranges.buffer->destroy();
|
||||||
ranges.buffer->destroy();
|
ranges.buffer->create();
|
||||||
ranges.buffer->create();
|
toku::range_buffer::iterator iter;
|
||||||
toku::range_buffer::iterator iter;
|
toku::range_buffer::iterator::record rec;
|
||||||
toku::range_buffer::iterator::record rec;
|
iter.create(&buffer);
|
||||||
iter.create(&buffer);
|
while (iter.current(&rec)) {
|
||||||
while (iter.current(&rec)) {
|
ranges.buffer->append(rec.get_left_key(), rec.get_right_key());
|
||||||
ranges.buffer->append(rec.get_left_key(), rec.get_right_key());
|
iter.next();
|
||||||
iter.next();
|
}
|
||||||
|
} else {
|
||||||
|
// In rare cases, we may not find the associated locktree, because we are
|
||||||
|
// racing with the transaction trying to add this locktree to the lt map
|
||||||
|
// after acquiring its first lock. The escalated lock set must be the single
|
||||||
|
// lock that this txnid just acquired. Do nothing here and let the txn
|
||||||
|
// take care of adding this locktree and range to its lt map as usual.
|
||||||
|
invariant(buffer.get_num_ranges() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
toku_mutex_unlock(&db_txn_struct_i(txn)->txn_mutex);
|
toku_mutex_unlock(&db_txn_struct_i(txn)->txn_mutex);
|
||||||
|
|
Loading…
Add table
Reference in a new issue