trx_undo_rec_t* trx_undo_get_next_rec( /*==================*/ /* out: undo log record, the page s-latched, NULL if none */ trx_undo_rec_t* rec, /* in: undo record */ ulint page_no,/* in: undo log header page number */ ulint offset, /* in: undo log header offset on page */ mtr_t* mtr) /* in: mtr */ { trx_undo_rec_t* next_rec; next_rec = trx_undo_page_get_next_rec(rec, page_no, offset); if (next_rec) { return(next_rec); } return(trx_undo_get_next_rec_from_next_page(buf_frame_align(rec), page_no, offset, RW_S_LATCH, mtr)); }
/***********************************************************************//** Gets the next record to purge and updates the info in the purge system. @return copy of an undo log record or pointer to the dummy undo log record */ static trx_undo_rec_t* trx_purge_get_next_rec( /*===================*/ mem_heap_t* heap) /*!< in: memory heap where copied */ { trx_undo_rec_t* rec; trx_undo_rec_t* rec_copy; trx_undo_rec_t* rec2; trx_undo_rec_t* next_rec; page_t* undo_page; page_t* page; ulint offset; ulint page_no; ulint space; ulint zip_size; ulint type; ulint cmpl_info; mtr_t mtr; ut_ad(purge_sys->next_stored); space = purge_sys->rseg->space; zip_size = purge_sys->rseg->zip_size; page_no = purge_sys->page_no; offset = purge_sys->offset; if (offset == 0) { /* It is the dummy undo log record, which means that there is no need to purge this undo log */ trx_purge_rseg_get_next_history_log(purge_sys->rseg); /* Look for the next undo log and record to purge */ trx_purge_choose_next_log(); return(&trx_purge_dummy_rec); } mtr_start(&mtr); undo_page = trx_undo_page_get_s_latched(space, zip_size, page_no, &mtr); rec = undo_page + offset; rec2 = rec; for (;;) { /* Try first to find the next record which requires a purge operation from the same page of the same undo log */ next_rec = trx_undo_page_get_next_rec( rec2, purge_sys->hdr_page_no, purge_sys->hdr_offset); if (next_rec == NULL) { rec2 = trx_undo_get_next_rec( rec2, purge_sys->hdr_page_no, purge_sys->hdr_offset, &mtr); break; } rec2 = next_rec; type = trx_undo_rec_get_type(rec2); if (type == TRX_UNDO_DEL_MARK_REC) { break; } cmpl_info = trx_undo_rec_get_cmpl_info(rec2); if (trx_undo_rec_get_extern_storage(rec2)) { break; } if ((type == TRX_UNDO_UPD_EXIST_REC) && !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { break; } } if (rec2 == NULL) { mtr_commit(&mtr); trx_purge_rseg_get_next_history_log(purge_sys->rseg); /* Look for the next undo log and record to purge */ trx_purge_choose_next_log(); mtr_start(&mtr); undo_page = trx_undo_page_get_s_latched(space, zip_size, page_no, &mtr); rec = undo_page + offset; } else { page = page_align(rec2); purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec2); purge_sys->page_no = page_get_page_no(page); purge_sys->offset = rec2 - page; if (undo_page != page) { /* We advance to a new page of the undo log: */ purge_sys->n_pages_handled++; } } rec_copy = trx_undo_rec_copy(rec, heap); mtr_commit(&mtr); return(rec_copy); }