Example #1
0
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);
}