diff options
Diffstat (limited to 'storage/innobase/lock/lock0lock.c')
-rw-r--r-- | storage/innobase/lock/lock0lock.c | 83 |
1 files changed, 67 insertions, 16 deletions
diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index c2ede22dccb..173d074cb82 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -3920,15 +3920,25 @@ lock_cancel_waiting_and_release( trx_end_lock_wait(lock->trx); } +/* True if a lock mode is S or X */ +#define IS_LOCK_S_OR_X(lock) \ + (lock_get_mode(lock) == LOCK_S \ + || lock_get_mode(lock) == LOCK_X) + + /************************************************************************* -Resets all record and table locks of a transaction on a table to be dropped. -No lock is allowed to be a wait lock. */ +Removes locks of a transaction on a table to be dropped. +If remove_also_table_sx_locks is TRUE then table-level S and X locks are +also removed in addition to other table-level and record-level locks. +No lock, that is going to be removed, is allowed to be a wait lock. */ static void -lock_reset_all_on_table_for_trx( -/*============================*/ - dict_table_t* table, /* in: table to be dropped */ - trx_t* trx) /* in: a transaction */ +lock_remove_all_on_table_for_trx( +/*=============================*/ + dict_table_t* table, /* in: table to be dropped */ + trx_t* trx, /* in: a transaction */ + ibool remove_also_table_sx_locks)/* in: also removes + table S and X locks */ { lock_t* lock; lock_t* prev_lock; @@ -3946,7 +3956,9 @@ lock_reset_all_on_table_for_trx( lock_rec_discard(lock); } else if (lock_get_type(lock) & LOCK_TABLE - && lock->un_member.tab_lock.table == table) { + && lock->un_member.tab_lock.table == table + && (remove_also_table_sx_locks + || !IS_LOCK_S_OR_X(lock))) { ut_a(!lock_get_wait(lock)); @@ -3958,26 +3970,65 @@ lock_reset_all_on_table_for_trx( } /************************************************************************* -Resets all locks, both table and record locks, on a table to be dropped. -No lock is allowed to be a wait lock. */ +Removes locks on a table to be dropped or truncated. +If remove_also_table_sx_locks is TRUE then table-level S and X locks are +also removed in addition to other table-level and record-level locks. +No lock, that is going to be removed, is allowed to be a wait lock. */ void -lock_reset_all_on_table( -/*====================*/ - dict_table_t* table) /* in: table to be dropped */ +lock_remove_all_on_table( +/*=====================*/ + dict_table_t* table, /* in: table to be dropped + or truncated */ + ibool remove_also_table_sx_locks)/* in: also removes + table S and X locks */ { lock_t* lock; + lock_t* prev_lock; mutex_enter(&kernel_mutex); lock = UT_LIST_GET_FIRST(table->locks); - while (lock) { - ut_a(!lock_get_wait(lock)); + while (lock != NULL) { - lock_reset_all_on_table_for_trx(table, lock->trx); + prev_lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, + lock); - lock = UT_LIST_GET_FIRST(table->locks); + /* If we should remove all locks (remove_also_table_sx_locks + is TRUE), or if the lock is not table-level S or X lock, + then check we are not going to remove a wait lock. */ + if (remove_also_table_sx_locks + || !(lock_get_type(lock) == LOCK_TABLE + && IS_LOCK_S_OR_X(lock))) { + + ut_a(!lock_get_wait(lock)); + } + + lock_remove_all_on_table_for_trx(table, lock->trx, + remove_also_table_sx_locks); + + if (prev_lock == NULL) { + if (lock == UT_LIST_GET_FIRST(table->locks)) { + /* lock was not removed, pick its successor */ + lock = UT_LIST_GET_NEXT( + un_member.tab_lock.locks, lock); + } else { + /* lock was removed, pick the first one */ + lock = UT_LIST_GET_FIRST(table->locks); + } + } else if (UT_LIST_GET_NEXT(un_member.tab_lock.locks, + prev_lock) != lock) { + /* If lock was removed by + lock_remove_all_on_table_for_trx() then pick the + successor of prev_lock ... */ + lock = UT_LIST_GET_NEXT( + un_member.tab_lock.locks, prev_lock); + } else { + /* ... otherwise pick the successor of lock. */ + lock = UT_LIST_GET_NEXT( + un_member.tab_lock.locks, lock); + } } mutex_exit(&kernel_mutex); |