/**********************************************************//** Releases the mlocks and other objects stored in an mtr memo. They are released in the order opposite to which they were pushed to the memo. NOTE! It is essential that the x-rw-lock on a modified buffer page is not released before buf_page_note_modification is called for that page! Otherwise, some thread might race to modify it, and the flush list sort order on lsn would be destroyed. */ UNIV_INLINE void mtr_memo_pop_all( /*=============*/ mtr_t* mtr) /*!< in: mtr */ { mtr_memo_slot_t* slot; dyn_array_t* memo; ulint offset; ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in commit */ memo = &(mtr->memo); offset = dyn_array_get_data_size(memo); while (offset > 0) { offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); mtr_memo_slot_release(mtr, slot); } }
/**********************************************************//** Releases the latches stored in an mtr memo down to a savepoint. NOTE! The mtr must not have made changes to buffer pages after the savepoint, as these can be handled only by mtr_commit. */ UNIV_INTERN void mtr_rollback_to_savepoint( /*======================*/ mtr_t* mtr, /*!< in: mtr */ ulint savepoint) /*!< in: savepoint */ { mtr_memo_slot_t* slot; dyn_array_t* memo; ulint offset; ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); memo = &(mtr->memo); offset = dyn_array_get_data_size(memo); ut_ad(offset >= savepoint); while (offset > savepoint) { offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); ut_ad(slot->type != MTR_MEMO_MODIFY); mtr_memo_slot_release(mtr, slot); } }
/***************************************************//** Releases an object in the memo stack. */ UNIV_INTERN void mtr_memo_release( /*=============*/ mtr_t* mtr, /*!< in: mtr */ void* object, /*!< in: object */ ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */ { mtr_memo_slot_t* slot; dyn_array_t* memo; ulint offset; ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); memo = &(mtr->memo); offset = dyn_array_get_data_size(memo); while (offset > 0) { offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); if ((object == slot->object) && (type == slot->type)) { mtr_memo_slot_release(mtr, slot); break; } } }
/**********************************************************//** Releases the latches stored in an mtr memo down to a savepoint. NOTE! The mtr must not have made changes to buffer pages after the savepoint, as these can be handled only by mtr_commit. */ UNIV_INTERN void mtr_rollback_to_savepoint( /*======================*/ mtr_t* mtr, /*!< in: mtr */ ulint savepoint) /*!< in: savepoint */ { mtr_memo_slot_t* slot; dyn_array_t* memo; ulint offset; ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); memo = &(mtr->memo); offset = dyn_array_get_data_size(memo); ut_ad(offset >= savepoint); while (offset > savepoint) { offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); ut_ad(slot->type != MTR_MEMO_MODIFY); /* We do not call mtr_memo_slot_note_modification() because there MUST be no changes made to the buffer pages after the savepoint */ mtr_memo_slot_release(mtr, slot); } }
/**********************************************************//** Add the modified pages to the buffer flush list. They are released in the order opposite to which they were pushed to the memo. NOTE! It is essential that the x-rw-lock on a modified buffer page is not released before buf_page_note_modification is called for that page! Otherwise, some thread might race to modify it, and the flush list sort order on lsn would be destroyed. */ static void mtr_memo_note_modifications( /*========================*/ mtr_t* mtr) /*!< in: mtr */ { dyn_array_t* memo; ulint offset; ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in commit */ memo = &mtr->memo; offset = dyn_array_get_data_size(memo); while (offset > 0) { mtr_memo_slot_t* slot; offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); mtr_memo_slot_note_modification(mtr, slot); } }
UNIV_INLINE void mtr_memo_note_modification_all( /*===========================*/ mtr_t* mtr) /* in: mtr */ { mtr_memo_slot_t* slot; dyn_array_t* memo; ulint offset; ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in commit */ ut_ad(mtr->modifications); memo = &(mtr->memo); offset = dyn_array_get_data_size(memo); while (offset > 0) { offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); if (UNIV_LIKELY(slot->object != NULL) && slot->type == MTR_MEMO_PAGE_X_FIX) { buf_flush_note_modification( (buf_block_t*)slot->object, mtr); } } }
/***************************************************//** Releases an object in the memo stack. */ UNIV_INTERN void mtr_memo_release( /*=============*/ mtr_t* mtr, /*!< in: mtr */ void* object, /*!< in: object */ ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */ { mtr_memo_slot_t* slot; dyn_array_t* memo; ulint offset; ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); memo = &(mtr->memo); offset = dyn_array_get_data_size(memo); log_flush_order_mutex_enter(); while (offset > 0) { offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); if (object == slot->object && type == slot->type) { /* We cannot release a page that has been written to in the middle of a mini-transaction. */ ut_ad(!(mtr->modifications && slot->type == MTR_MEMO_PAGE_X_FIX)); mtr_memo_slot_release(mtr, slot); break; } } log_flush_order_mutex_exit(); }
/***************************************************//** Releases an object in the memo stack. */ UNIV_INTERN void mtr_memo_release( /*=============*/ mtr_t* mtr, /*!< in: mtr */ void* object, /*!< in: object */ ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */ { mtr_memo_slot_t* slot; dyn_array_t* memo; ulint offset; ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); memo = &(mtr->memo); offset = dyn_array_get_data_size(memo); while (offset > 0) { offset -= sizeof(mtr_memo_slot_t); slot = dyn_array_get_element(memo, offset); if ((object == slot->object) && (type == slot->type)) { if (mtr->modifications && UNIV_LIKELY(slot->object != NULL) && slot->type == MTR_MEMO_PAGE_X_FIX) { buf_flush_note_modification( (buf_block_t*)slot->object, mtr); } mtr_memo_slot_release(mtr, slot); break; } } }