/***********************************************************************//**
Position the purge sys "iterator" on the undo record to use for purging. */
static
void
trx_purge_read_undo_rec(
    /*====================*/
    trx_purge_t*	purge_sys,		/*!< in/out: purge instance */
    ulint		zip_size)		/*!< in: block size or 0 */
{
    ulint		page_no;
    ulint		offset = 0;
    ib_uint64_t	undo_no = 0;

    purge_sys->hdr_offset = purge_sys->rseg->last_offset;
    page_no = purge_sys->hdr_page_no = purge_sys->rseg->last_page_no;

    if (purge_sys->rseg->last_del_marks) {
        mtr_t		mtr;
        trx_undo_rec_t*	undo_rec;

        mtr_start(&mtr);

        undo_rec = trx_undo_get_first_rec(
                       0 /* System space id */, zip_size,
                       purge_sys->hdr_page_no,
                       purge_sys->hdr_offset, RW_S_LATCH, &mtr);

        if (undo_rec != NULL) {
            offset = page_offset(undo_rec);
            undo_no = trx_undo_rec_get_undo_no(undo_rec);
            page_no = page_get_page_no(page_align(undo_rec));
        }

        mtr_commit(&mtr);
    }

    purge_sys->offset = offset;
    purge_sys->page_no = page_no;
    purge_sys->purge_undo_no = undo_no;

    purge_sys->next_stored = TRUE;
}
Beispiel #2
0
/***********************************************************************//**
Chooses the next undo log to purge and updates the info in purge_sys. This
function is used to initialize purge_sys when the next record to purge is
not known, and also to update the purge system info on the next record when
purge has handled the whole undo log for a transaction. */
static
void
trx_purge_choose_next_log(void)
/*===========================*/
{
	trx_undo_rec_t*	rec;
	trx_rseg_t*	rseg;
	trx_rseg_t*	min_rseg;
	trx_id_t	min_trx_no;
	ulint		space = 0;   /* remove warning (??? bug ???) */
	ulint		zip_size = 0;
	ulint		page_no = 0; /* remove warning (??? bug ???) */
	ulint		offset = 0;  /* remove warning (??? bug ???) */
	mtr_t		mtr;

	ut_ad(mutex_own(&(purge_sys->mutex)));
	ut_ad(purge_sys->next_stored == FALSE);

	rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);

	min_trx_no = ut_dulint_max;

	min_rseg = NULL;

	while (rseg) {
		mutex_enter(&(rseg->mutex));

		if (rseg->last_page_no != FIL_NULL) {

			if ((min_rseg == NULL)
			    || (ut_dulint_cmp(min_trx_no,
					      rseg->last_trx_no) > 0)) {

				min_rseg = rseg;
				min_trx_no = rseg->last_trx_no;
				space = rseg->space;
				zip_size = rseg->zip_size;
				ut_a(space == 0); /* We assume in purge of
						  externally stored fields
						  that space id == 0 */
				page_no = rseg->last_page_no;
				offset = rseg->last_offset;
			}
		}

		mutex_exit(&(rseg->mutex));

		rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
	}

	if (min_rseg == NULL) {

		return;
	}

	mtr_start(&mtr);

	if (!min_rseg->last_del_marks) {
		/* No need to purge this log */

		rec = &trx_purge_dummy_rec;
	} else {
		rec = trx_undo_get_first_rec(space, zip_size, page_no, offset,
					     RW_S_LATCH, &mtr);
		if (rec == NULL) {
			/* Undo log empty */

			rec = &trx_purge_dummy_rec;
		}
	}

	purge_sys->next_stored = TRUE;
	purge_sys->rseg = min_rseg;

	purge_sys->hdr_page_no = page_no;
	purge_sys->hdr_offset = offset;

	purge_sys->purge_trx_no = min_trx_no;

	if (rec == &trx_purge_dummy_rec) {

		purge_sys->purge_undo_no = ut_dulint_zero;
		purge_sys->page_no = page_no;
		purge_sys->offset = 0;
	} else {
		purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec);

		purge_sys->page_no = page_get_page_no(page_align(rec));
		purge_sys->offset = page_offset(rec);
	}

	mtr_commit(&mtr);
}