コード例 #1
0
/********************************************************************//**
Fetches the next undo log record from the history list to purge. It must be
released with the corresponding release function.
@return copy of an undo log record or pointer to trx_purge_dummy_rec,
if the whole undo log can skipped in purge; NULL if none left */
UNIV_INTERN
trx_undo_rec_t*
trx_purge_fetch_next_rec(
    /*=====================*/
    roll_ptr_t*	roll_ptr,/*!< out: roll pointer to undo record */
    trx_undo_inf_t** cell,	/*!< out: storage cell for the record in the
				purge array */
    mem_heap_t*	heap)	/*!< in: memory heap where copied */
{
    trx_undo_rec_t*	undo_rec;


    if (purge_sys->state == TRX_STOP_PURGE) {
        trx_purge_truncate_if_arr_empty();

        return(NULL);
    } else if (!purge_sys->next_stored) {
        trx_purge_choose_next_log();

        if (!purge_sys->next_stored) {
            purge_sys->state = TRX_STOP_PURGE;

            trx_purge_truncate_if_arr_empty();

            if (srv_print_thread_releases) {
                fprintf(stderr,
                        "Purge: No logs left in the"
                        " history list; pages handled %lu\n",
                        (ulong) purge_sys->n_pages_handled);
            }

            return(NULL);
        }
    }

    if (purge_sys->n_pages_handled >= purge_sys->handle_limit) {

        purge_sys->state = TRX_STOP_PURGE;

        trx_purge_truncate_if_arr_empty();

        return(NULL);
    } else if (purge_sys->purge_trx_no >= purge_sys->view->low_limit_no) {
        purge_sys->state = TRX_STOP_PURGE;

        trx_purge_truncate_if_arr_empty();

        return(NULL);
    }

    /* fprintf(stderr, "Thread %lu purging trx %llu undo record %llu\n",
    os_thread_get_curr_id(),
    (ullint) purge_sys->purge_trx_no,
    (ullint) purge_sys->purge_undo_no); */


    *roll_ptr = trx_undo_build_roll_ptr(
                    FALSE, (purge_sys->rseg)->id, purge_sys->page_no,
                    purge_sys->offset);

    *cell = trx_purge_arr_store_info(
                purge_sys->purge_trx_no, purge_sys->purge_undo_no);

    ut_ad(purge_sys->purge_trx_no < purge_sys->view->low_limit_no);

    /* The following call will advance the stored values of purge_trx_no
    and purge_undo_no, therefore we had to store them first */

    undo_rec = trx_purge_get_next_rec(heap);

    return(undo_rec);
}
コード例 #2
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);
}
コード例 #3
0
trx_undo_rec_t*
trx_purge_fetch_next_rec(
/*=====================*/
				/* out: copy of an undo log record or
				pointer to the dummy undo log record
				&trx_purge_dummy_rec, if the whole undo log
				can skipped in purge; NULL if none left */
	dulint*		roll_ptr,/* out: roll pointer to undo record */
	trx_undo_inf_t** cell,	/* out: storage cell for the record in the
				purge array */
	mem_heap_t*	heap)	/* in: memory heap where copied */
{
	trx_undo_rec_t*	undo_rec;

	mutex_enter(&(purge_sys->mutex));

	if (purge_sys->state == TRX_STOP_PURGE) {
		trx_purge_truncate_if_arr_empty();

		mutex_exit(&(purge_sys->mutex));

		return(NULL);
	}

	if (!purge_sys->next_stored) {
		trx_purge_choose_next_log();

		if (!purge_sys->next_stored) {
			purge_sys->state = TRX_STOP_PURGE;

			trx_purge_truncate_if_arr_empty();

			if (srv_print_thread_releases) {
				fprintf(stderr,
					"Purge: No logs left in the"
					" history list; pages handled %lu\n",
					(ulong) purge_sys->n_pages_handled);
			}

			mutex_exit(&(purge_sys->mutex));

			return(NULL);
		}
	}

	if (purge_sys->n_pages_handled >= purge_sys->handle_limit) {

		purge_sys->state = TRX_STOP_PURGE;

		trx_purge_truncate_if_arr_empty();

		mutex_exit(&(purge_sys->mutex));

		return(NULL);
	}

	if (ut_dulint_cmp(purge_sys->purge_trx_no,
			  purge_sys->view->low_limit_no) >= 0) {
		purge_sys->state = TRX_STOP_PURGE;

		trx_purge_truncate_if_arr_empty();

		mutex_exit(&(purge_sys->mutex));

		return(NULL);
	}

	/*	fprintf(stderr, "Thread %lu purging trx %lu undo record %lu\n",
	os_thread_get_curr_id(),
	ut_dulint_get_low(purge_sys->purge_trx_no),
	ut_dulint_get_low(purge_sys->purge_undo_no)); */

	*roll_ptr = trx_undo_build_roll_ptr(FALSE, (purge_sys->rseg)->id,
					    purge_sys->page_no,
					    purge_sys->offset);

	*cell = trx_purge_arr_store_info(purge_sys->purge_trx_no,
					 purge_sys->purge_undo_no);

	ut_ad(ut_dulint_cmp(purge_sys->purge_trx_no,
			    (purge_sys->view)->low_limit_no) < 0);

	/* The following call will advance the stored values of purge_trx_no
	and purge_undo_no, therefore we had to store them first */

	undo_rec = trx_purge_get_next_rec(heap);

	mutex_exit(&(purge_sys->mutex));

	return(undo_rec);
}