コード例 #1
0
/***********************************************************************//**
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;
}
コード例 #2
0
ファイル: fut0lst.c プロジェクト: A-eolus/mysql
/********************************************************************//**
Prints info of a file-based list. */
UNIV_INTERN
void
flst_print(
/*=======*/
	const flst_base_node_t*	base,	/*!< in: pointer to base node of list */
	mtr_t*			mtr)	/*!< in: mtr */
{
	const buf_frame_t*	frame;
	ulint			len;

	ut_ad(base && mtr);
	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
	frame = page_align((byte*) base);

	len = flst_get_len(base, mtr);

	fprintf(stderr,
		"FILE-BASED LIST:\n"
		"Base node in space %lu page %lu byte offset %lu; len %lu\n",
		(ulong) page_get_space_id(frame),
		(ulong) page_get_page_no(frame),
		(ulong) page_offset(base), (ulong) len);
}
コード例 #3
0
/***********************************************************************//**
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);
}
コード例 #4
0
ファイル: btr0pcur.c プロジェクト: MPlatform/mariadb
/**************************************************************//**
The position of the cursor is stored by taking an initial segment of the
record the cursor is positioned on, before, or after, and copying it to the
cursor data structure, or just setting a flag if the cursor id before the
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
page where the cursor is positioned must not be empty if the index tree is
not totally empty! */
UNIV_INTERN
void
btr_pcur_store_position(
/*====================*/
	btr_pcur_t*	cursor, /*!< in: persistent cursor */
	mtr_t*		mtr)	/*!< in: mtr */
{
	page_cur_t*	page_cursor;
	buf_block_t*	block;
	rec_t*		rec;
	dict_index_t*	index;
	page_t*		page;
	ulint		offs;

	ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);

	block = btr_pcur_get_block(cursor);

	if (srv_pass_corrupt_table && !block) {
		return;
	}
	ut_a(block);

	index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));

	page_cursor = btr_pcur_get_page_cur(cursor);

	rec = page_cur_get_rec(page_cursor);
	page = page_align(rec);
	offs = page_offset(rec);

	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_S_FIX)
	      || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
	ut_a(cursor->latch_mode != BTR_NO_LATCHES);

	if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) {
		/* It must be an empty index tree; NOTE that in this case
		we do not store the modify_clock, but always do a search
		if we restore the cursor position */

		ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
		ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
		ut_ad(page_is_leaf(page));
		ut_ad(page_get_page_no(page) == index->page);

		cursor->old_stored = BTR_PCUR_OLD_STORED;

		if (page_rec_is_supremum_low(offs)) {

			cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
		} else {
			cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
		}

		return;
	}

	if (page_rec_is_supremum_low(offs)) {

		rec = page_rec_get_prev(rec);

		cursor->rel_pos = BTR_PCUR_AFTER;

	} else if (page_rec_is_infimum_low(offs)) {

		rec = page_rec_get_next(rec);

		cursor->rel_pos = BTR_PCUR_BEFORE;
	} else {
		cursor->rel_pos = BTR_PCUR_ON;
	}

	cursor->old_stored = BTR_PCUR_OLD_STORED;
	cursor->old_rec = dict_index_copy_rec_order_prefix(
		index, rec, &cursor->old_n_fields,
		&cursor->old_rec_buf, &cursor->buf_size);

	cursor->block_when_stored = block;
	cursor->modify_clock = buf_block_get_modify_clock(block);
}
コード例 #5
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);
}