diff options
Diffstat (limited to 'storage/innobase/include/lock0priv.h')
-rw-r--r-- | storage/innobase/include/lock0priv.h | 203 |
1 files changed, 66 insertions, 137 deletions
diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h index f39692903fa..b0a5f7aaf3b 100644 --- a/storage/innobase/include/lock0priv.h +++ b/storage/innobase/include/lock0priv.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -64,49 +64,44 @@ operator<<(std::ostream& out, const lock_table_t& lock) return(lock.print(out)); } -/** Convert the member 'type_mode' into a human readable string. -@return human readable string */ -inline -std::string -ib_lock_t::type_mode_string() const -{ - std::ostringstream sout; - sout << type_string(); - sout << " | " << lock_mode_string(mode()); - - if (is_record_not_gap()) { - sout << " | LOCK_REC_NOT_GAP"; - } - - if (is_waiting()) { - sout << " | LOCK_WAIT"; - } - - if (is_gap()) { - sout << " | LOCK_GAP"; - } - - if (is_insert_intention()) { - sout << " | LOCK_INSERT_INTENTION"; - } - return(sout.str()); -} - inline std::ostream& ib_lock_t::print(std::ostream& out) const { - out << "[lock_t: type_mode=" << type_mode << "(" - << type_mode_string() << ")"; - - if (is_record_lock()) { - out << un_member.rec_lock; - } else { - out << un_member.tab_lock; - } - - out << "]"; - return(out); + static_assert(LOCK_MODE_MASK == 7, "compatibility"); + static_assert(LOCK_IS == 0, "compatibility"); + static_assert(LOCK_IX == 1, "compatibility"); + static_assert(LOCK_S == 2, "compatibility"); + static_assert(LOCK_X == 3, "compatibility"); + static_assert(LOCK_AUTO_INC == 4, "compatibility"); + static_assert(LOCK_NONE == 5, "compatibility"); + static_assert(LOCK_NONE_UNSET == 7, "compatibility"); + const char *const modes[8]= + { "IS", "IX", "S", "X", "AUTO_INC", "NONE", "?", "NONE_UNSET" }; + + out << "[lock_t: type_mode=" << type_mode << "(" << type_string() + << " | LOCK_" << modes[mode()]; + + if (is_record_not_gap()) + out << " | LOCK_REC_NOT_GAP"; + if (is_waiting()) + out << " | LOCK_WAIT"; + + if (is_gap()) + out << " | LOCK_GAP"; + + if (is_insert_intention()) + out << " | LOCK_INSERT_INTENTION"; + + out << ")"; + + if (is_table()) + out << un_member.tab_lock; + else + out << un_member.rec_lock; + + out << "]"; + return out; } inline @@ -120,24 +115,6 @@ operator<<(std::ostream& out, const ib_lock_t& lock) extern ibool lock_print_waits; #endif /* UNIV_DEBUG */ -/** Restricts the length of search we will do in the waits-for -graph of transactions */ -static const ulint LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK = 1000000; - -/** Restricts the search depth we will do in the waits-for graph of -transactions */ -static const ulint LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK = 200; - -/** When releasing transaction locks, this specifies how often we release -the lock mutex for a moment to give also others access to it */ -static const ulint LOCK_RELEASE_INTERVAL = 1000; - -/* Safety margin when creating a new record lock: this many extra records -can be inserted to the page without need to create a lock with a bigger -bitmap */ - -static const ulint LOCK_PAGE_BITMAP_MARGIN = 64; - /* An explicit record lock affects both the record and the gap before it. An implicit x-lock does not affect the gap, it only locks the index record from read or update. @@ -414,9 +391,6 @@ static const byte lock_strength_matrix[5][5] = { /* AI */ { FALSE, FALSE, FALSE, FALSE, TRUE} }; -/** Maximum depth of the DFS stack. */ -static const ulint MAX_STACK_SIZE = 4096; - #define PRDT_HEAPNO PAGE_HEAP_NO_INFIMUM /** Record locking request status */ enum lock_rec_req_status { @@ -434,15 +408,6 @@ static const ulint lock_types = UT_ARR_SIZE(lock_compatibility_matrix); #endif /* UNIV_DEBUG */ /*********************************************************************//** -Gets the type of a lock. -@return LOCK_TABLE or LOCK_REC */ -UNIV_INLINE -ulint -lock_get_type_low( -/*==============*/ - const lock_t* lock); /*!< in: lock */ - -/*********************************************************************//** Gets the previous record lock set on a record. @return previous lock on the same record, NULL if none exists */ const lock_t* @@ -452,14 +417,6 @@ lock_rec_get_prev( ulint heap_no);/*!< in: heap number of the record */ /*********************************************************************//** -Cancels a waiting lock request and releases possible other transactions -waiting behind it. */ -void -lock_cancel_waiting_and_release( -/*============================*/ - lock_t* lock); /*!< in/out: waiting lock request */ - -/*********************************************************************//** Checks if some transaction has an implicit x-lock on a record in a clustered index. @return transaction id of the transaction which has the x-lock, or 0 */ @@ -502,7 +459,7 @@ lock_rec_get_n_bits( /**********************************************************************//** Sets the nth bit of a record lock to TRUE. */ -UNIV_INLINE +inline void lock_rec_set_nth_bit( /*=================*/ @@ -515,7 +472,13 @@ lock_rec_set_nth_bit( @return previous value of the bit */ inline byte lock_rec_reset_nth_bit(lock_t* lock, ulint i) { - ut_ad(lock_get_type_low(lock) == LOCK_REC); + ut_ad(!lock->is_table()); +#ifdef SUX_LOCK_GENERIC + ut_ad(lock_sys.is_writer() || lock->trx->mutex_is_owner()); +#else + ut_ad(lock_sys.is_writer() || lock->trx->mutex_is_owner() + || (xtest() && !lock->trx->mutex_is_locked())); +#endif ut_ad(i < lock->un_member.rec_lock.n_bits); byte* b = reinterpret_cast<byte*>(&lock[1]) + (i >> 3); @@ -524,8 +487,9 @@ inline byte lock_rec_reset_nth_bit(lock_t* lock, ulint i) *b &= byte(~mask); if (bit != 0) { - ut_ad(lock->trx->lock.n_rec_locks > 0); - --lock->trx->lock.n_rec_locks; + ut_d(auto n=) + lock->trx->lock.n_rec_locks--; + ut_ad(n); } return(bit); @@ -560,25 +524,26 @@ lock_rec_get_next_const( ulint heap_no,/*!< in: heap number of the record */ const lock_t* lock); /*!< in: lock */ -/*********************************************************************//** -Gets the first explicit lock request on a record. -@return first lock, NULL if none exists */ -UNIV_INLINE -lock_t* -lock_rec_get_first( -/*===============*/ - hash_table_t* hash, /*!< in: hash chain the lock on */ - const buf_block_t* block, /*!< in: block containing the record */ - ulint heap_no);/*!< in: heap number of the record */ - -/*********************************************************************//** -Gets the mode of a lock. -@return mode */ -UNIV_INLINE -enum lock_mode -lock_get_mode( -/*==========*/ - const lock_t* lock); /*!< in: lock */ +/** Get the first explicit lock request on a record. +@param cell first lock hash table cell +@param id page identifier +@param heap_no record identifier in page +@return first lock +@retval nullptr if none exists */ +inline lock_t *lock_sys_t::get_first(const hash_cell_t &cell, page_id_t id, + ulint heap_no) +{ + lock_sys.assert_locked(cell); + + for (lock_t *lock= static_cast<lock_t*>(cell.node); lock; lock= lock->hash) + { + ut_ad(!lock->is_table()); + if (lock->un_member.rec_lock.page_id == id && + lock_rec_get_nth_bit(lock, heap_no)) + return lock; + } + return nullptr; +} /*********************************************************************//** Calculates if lock mode 1 is compatible with lock mode 2. @@ -601,15 +566,6 @@ lock_mode_stronger_or_eq( enum lock_mode mode2); /*!< in: lock mode */ /*********************************************************************//** -Gets the wait flag of a lock. -@return LOCK_WAIT if waiting, 0 if not */ -UNIV_INLINE -ulint -lock_get_wait( -/*==========*/ - const lock_t* lock); /*!< in: lock */ - -/*********************************************************************//** Checks if a transaction has the specified table lock, or stronger. This function should only be called by the thread that owns the transaction. @return lock or NULL */ @@ -621,33 +577,6 @@ lock_table_has( const dict_table_t* table, /*!< in: table */ enum lock_mode mode); /*!< in: lock mode */ -/** Set the wait status of a lock. -@param[in,out] lock lock that will be waited for -@param[in,out] trx transaction that will wait for the lock */ -inline void lock_set_lock_and_trx_wait(lock_t* lock, trx_t* trx) -{ - ut_ad(lock); - ut_ad(lock->trx == trx); - ut_ad(trx->lock.wait_lock == NULL); - ut_ad(lock_mutex_own()); - ut_ad(trx_mutex_own(trx)); - - trx->lock.wait_lock = lock; - lock->type_mode |= LOCK_WAIT; -} - -/** Reset the wait status of a lock. -@param[in,out] lock lock that was possibly being waited for */ -inline void lock_reset_lock_and_trx_wait(lock_t* lock) -{ - ut_ad(lock_get_wait(lock)); - ut_ad(lock_mutex_own()); - ut_ad(lock->trx->lock.wait_lock == NULL - || lock->trx->lock.wait_lock == lock); - lock->trx->lock.wait_lock = NULL; - lock->type_mode &= ~LOCK_WAIT; -} - #include "lock0priv.inl" #endif /* lock0priv_h */ |