Пример #1
0
/************************************************************************
Adds a node to an empty list. */
static
void
flst_add_to_empty(
    /*==============*/
    flst_base_node_t*	base,	/* in: pointer to base node of
					empty list */
    flst_node_t*		node,	/* in: node to add */
    mtr_t*			mtr)	/* in: mini-transaction handle */
{
    ulint		space;
    fil_addr_t	node_addr;
    ulint		len;

    ut_ad(mtr && base && node);
    ut_ad(base != node);
    ut_ad(mtr_memo_contains(mtr, buf_block_align(base),
                            MTR_MEMO_PAGE_X_FIX));
    ut_ad(mtr_memo_contains(mtr, buf_block_align(node),
                            MTR_MEMO_PAGE_X_FIX));
    len = flst_get_len(base, mtr);
    ut_a(len == 0);

    buf_ptr_get_fsp_addr(node, &space, &node_addr);

    /* Update first and last fields of base node */
    flst_write_addr(base + FLST_FIRST, node_addr, mtr);
    flst_write_addr(base + FLST_LAST, node_addr, mtr);

    /* Set prev and next fields of node to add */
    flst_write_addr(node + FLST_PREV, fil_addr_null, mtr);
    flst_write_addr(node + FLST_NEXT, fil_addr_null, mtr);

    /* Update len of base node */
    mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);
}
Пример #2
0
void
rec_set_nth_field_extern_bit(
/*=========================*/
	rec_t*	rec,	/* in: record */
	ulint	i,	/* in: ith field */
	ibool	val,	/* in: value to set */
	mtr_t*	mtr)	/* in: mtr holding an X-latch to the page where
			rec is, or NULL; in the NULL case we do not
			write to log about the change */
{
	ulint	info;

	ut_a(!rec_get_1byte_offs_flag(rec));
	ut_a(i < rec_get_n_fields(rec));
	
	info = rec_2_get_field_end_info(rec, i);

	if (val) {
		info = info | REC_2BYTE_EXTERN_MASK;
	} else {
		info = info & ~REC_2BYTE_EXTERN_MASK;
	}

	if (mtr) {
		mlog_write_ulint(rec - REC_N_EXTRA_BYTES - 2 * (i + 1), info,
							MLOG_2BYTES, mtr);
	} else {
		rec_2_set_field_end_info(rec, i, info);
	}
}
Пример #3
0
void
flst_cut_end(
    /*=========*/
    flst_base_node_t*	base,	/* in: pointer to base node of list */
    flst_node_t*		node2,	/* in: first node to remove */
    ulint			n_nodes,/* in: number of nodes to remove,
					must be >= 1 */
    mtr_t*			mtr)	/* in: mini-transaction handle */
{
    ulint		space;
    flst_node_t*	node1;
    fil_addr_t	node1_addr;
    fil_addr_t	node2_addr;
    ulint		len;

    ut_ad(mtr && node2 && base);
    ut_ad(mtr_memo_contains(mtr, buf_block_align(base),
                            MTR_MEMO_PAGE_X_FIX));
    ut_ad(mtr_memo_contains(mtr, buf_block_align(node2),
                            MTR_MEMO_PAGE_X_FIX));
    ut_ad(n_nodes > 0);

    buf_ptr_get_fsp_addr(node2, &space, &node2_addr);

    node1_addr = flst_get_prev_addr(node2, mtr);

    if (!fil_addr_is_null(node1_addr)) {

        /* Update next field of node1 */

        if (node1_addr.page == node2_addr.page) {

            node1 = buf_frame_align(node2) + node1_addr.boffset;
        } else {
            node1 = fut_get_ptr(space, node1_addr, RW_X_LATCH,
                                mtr);
        }

        flst_write_addr(node1 + FLST_NEXT, fil_addr_null, mtr);
    } else {
        /* node2 was first in list: update the field in base */
        flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr);
    }

    flst_write_addr(base + FLST_LAST, node1_addr, mtr);

    /* Update len of base node */
    len = flst_get_len(base, mtr);
    ut_ad(len >= n_nodes);

    mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr);
}
Пример #4
0
/********************************************************************//**
Inserts a node after another in a list. */
UNIV_INTERN
void
flst_insert_after(
/*==============*/
	flst_base_node_t*	base,	/*!< in: pointer to base node of list */
	flst_node_t*		node1,	/*!< in: node to insert after */
	flst_node_t*		node2,	/*!< in: node to add */
	mtr_t*			mtr)	/*!< in: mini-transaction handle */
{
	ulint		space;
	fil_addr_t	node1_addr;
	fil_addr_t	node2_addr;
	flst_node_t*	node3;
	fil_addr_t	node3_addr;
	ulint		len;

	ut_ad(mtr && node1 && node2 && base);
	ut_ad(base != node1);
	ut_ad(base != node2);
	ut_ad(node2 != node1);
	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
	ut_ad(mtr_memo_contains_page(mtr, node1, MTR_MEMO_PAGE_X_FIX));
	ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));

	buf_ptr_get_fsp_addr(node1, &space, &node1_addr);
	buf_ptr_get_fsp_addr(node2, &space, &node2_addr);

	node3_addr = flst_get_next_addr(node1, mtr);

	/* Set prev and next fields of node2 */
	flst_write_addr(node2 + FLST_PREV, node1_addr, mtr);
	flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr);

	if (!fil_addr_is_null(node3_addr)) {
		/* Update prev field of node3 */
		ulint	zip_size = fil_space_get_zip_size(space);

		node3 = fut_get_ptr(space, zip_size,
				    node3_addr, RW_X_LATCH, mtr);
		flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);
	} else {
		/* node1 was last in list: update last field in base */
		flst_write_addr(base + FLST_LAST, node2_addr, mtr);
	}

	/* Set next field of node1 */
	flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);

	/* Update len of base node */
	len = flst_get_len(base, mtr);
	mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);
}
Пример #5
0
void
flst_insert_before(
    /*===============*/
    flst_base_node_t*	base,	/* in: pointer to base node of list */
    flst_node_t*		node2,	/* in: node to insert */
    flst_node_t*		node3,	/* in: node to insert before */
    mtr_t*			mtr)	/* in: mini-transaction handle */
{
    ulint		space;
    flst_node_t*	node1;
    fil_addr_t	node1_addr;
    fil_addr_t	node2_addr;
    fil_addr_t	node3_addr;
    ulint		len;

    ut_ad(mtr && node2 && node3 && base);
    ut_ad(base != node2);
    ut_ad(base != node3);
    ut_ad(node2 != node3);
    ut_ad(mtr_memo_contains(mtr, buf_block_align(base),
                            MTR_MEMO_PAGE_X_FIX));
    ut_ad(mtr_memo_contains(mtr, buf_block_align(node2),
                            MTR_MEMO_PAGE_X_FIX));
    ut_ad(mtr_memo_contains(mtr, buf_block_align(node3),
                            MTR_MEMO_PAGE_X_FIX));

    buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
    buf_ptr_get_fsp_addr(node3, &space, &node3_addr);

    node1_addr = flst_get_prev_addr(node3, mtr);

    /* Set prev and next fields of node2 */
    flst_write_addr(node2 + FLST_PREV, node1_addr, mtr);
    flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr);

    if (!fil_addr_is_null(node1_addr)) {
        /* Update next field of node1 */
        node1 = fut_get_ptr(space, node1_addr, RW_X_LATCH, mtr);
        flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);
    } else {
        /* node3 was first in list: update first field in base */
        flst_write_addr(base + FLST_FIRST, node2_addr, mtr);
    }

    /* Set prev field of node3 */
    flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);

    /* Update len of base node */
    len = flst_get_len(base, mtr);
    mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);
}
Пример #6
0
/**********************************************************************//**
Returns a new table, index, or space id. */
UNIV_INTERN
void
dict_hdr_get_new_id(
/*================*/
	table_id_t*	table_id,	/*!< out: table id
					(not assigned if NULL) */
	index_id_t*	index_id,	/*!< out: index id
					(not assigned if NULL) */
	ulint*		space_id)	/*!< out: space id
					(not assigned if NULL) */
{
	dict_hdr_t*	dict_hdr;
	ib_id_t		id;
	mtr_t		mtr;

	mtr_start(&mtr);

	dict_hdr = dict_hdr_get(&mtr);

	if (table_id) {
		id = mach_read_from_8(dict_hdr + DICT_HDR_TABLE_ID);
		id++;
		mlog_write_ull(dict_hdr + DICT_HDR_TABLE_ID, id, &mtr);
		*table_id = id;
	}

	if (index_id) {
		id = mach_read_from_8(dict_hdr + DICT_HDR_INDEX_ID);
		id++;
		mlog_write_ull(dict_hdr + DICT_HDR_INDEX_ID, id, &mtr);
		*index_id = id;
	}

	if (space_id) {
		*space_id = mtr_read_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
					   MLOG_4BYTES, &mtr);
		if (fil_assign_new_space_id(space_id)) {
			mlog_write_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
					 *space_id, MLOG_4BYTES, &mtr);
		}
	}

	mtr_commit(&mtr);
}
Пример #7
0
void
flst_truncate_end(
    /*==============*/
    flst_base_node_t*	base,	/* in: pointer to base node of list */
    flst_node_t*		node2,	/* in: first node not to remove */
    ulint			n_nodes,/* in: number of nodes to remove */
    mtr_t*			mtr)	/* in: mini-transaction handle */
{
    fil_addr_t	node2_addr;
    ulint		len;
    ulint		space;

    ut_ad(mtr && node2 && base);
    ut_ad(mtr_memo_contains(mtr, buf_block_align(base),
                            MTR_MEMO_PAGE_X_FIX));
    ut_ad(mtr_memo_contains(mtr, buf_block_align(node2),
                            MTR_MEMO_PAGE_X_FIX));
    if (n_nodes == 0) {

        ut_ad(fil_addr_is_null(flst_get_next_addr(node2, mtr)));

        return;
    }

    buf_ptr_get_fsp_addr(node2, &space, &node2_addr);

    /* Update next field of node2 */
    flst_write_addr(node2 + FLST_NEXT, fil_addr_null, mtr);

    flst_write_addr(base + FLST_LAST, node2_addr, mtr);

    /* Update len of base node */
    len = flst_get_len(base, mtr);
    ut_ad(len >= n_nodes);

    mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr);
}
Пример #8
0
/**********************************************************************//**
Frees an undo log segment which is in the history list. Cuts the end of the
history list at the youngest undo log in this segment. */
static
void
trx_purge_free_segment(
    /*===================*/
    trx_rseg_t*	rseg,		/*!< in: rollback segment */
    fil_addr_t	hdr_addr,	/*!< in: the file address of log_hdr */
    ulint		n_removed_logs)	/*!< in: count of how many undo logs we
					will cut off from the end of the
					history list */
{
    page_t*		undo_page;
    trx_rsegf_t*	rseg_hdr;
    trx_ulogf_t*	log_hdr;
    trx_usegf_t*	seg_hdr;
    ibool		freed;
    ulint		seg_size;
    ulint		hist_size;
    ibool		marked		= FALSE;
    mtr_t		mtr;

    /*	fputs("Freeing an update undo log segment\n", stderr); */

loop:
    mtr_start(&mtr);
    mutex_enter(&(rseg->mutex));

    rseg_hdr = trx_rsegf_get(rseg->space, rseg->zip_size,
                             rseg->page_no, &mtr);

    undo_page = trx_undo_page_get(rseg->space, rseg->zip_size,
                                  hdr_addr.page, &mtr);
    seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
    log_hdr = undo_page + hdr_addr.boffset;

    /* Mark the last undo log totally purged, so that if the system
    crashes, the tail of the undo log will not get accessed again. The
    list of pages in the undo log tail gets inconsistent during the
    freeing of the segment, and therefore purge should not try to access
    them again. */

    if (!marked) {
        mlog_write_ulint(log_hdr + TRX_UNDO_DEL_MARKS, FALSE,
                         MLOG_2BYTES, &mtr);
        marked = TRUE;
    }

    freed = fseg_free_step_not_header(seg_hdr + TRX_UNDO_FSEG_HEADER,
                                      &mtr);
    if (!freed) {
        mutex_exit(&(rseg->mutex));
        mtr_commit(&mtr);

        goto loop;
    }

    /* The page list may now be inconsistent, but the length field
    stored in the list base node tells us how big it was before we
    started the freeing. */

    seg_size = flst_get_len(seg_hdr + TRX_UNDO_PAGE_LIST, &mtr);

    /* We may free the undo log segment header page; it must be freed
    within the same mtr as the undo log header is removed from the
    history list: otherwise, in case of a database crash, the segment
    could become inaccessible garbage in the file space. */

    flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY,
                 log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr);

    mutex_enter(&kernel_mutex);
    ut_ad(trx_sys->rseg_history_len >= n_removed_logs);
    trx_sys->rseg_history_len -= n_removed_logs;
    mutex_exit(&kernel_mutex);

    freed = FALSE;

    while (!freed) {
        /* Here we assume that a file segment with just the header
        page can be freed in a few steps, so that the buffer pool
        is not flooded with bufferfixed pages: see the note in
        fsp0fsp.c. */

        freed = fseg_free_step(seg_hdr + TRX_UNDO_FSEG_HEADER,
                               &mtr);
    }

    hist_size = mtr_read_ulint(rseg_hdr + TRX_RSEG_HISTORY_SIZE,
                               MLOG_4BYTES, &mtr);
    ut_ad(hist_size >= seg_size);

    mlog_write_ulint(rseg_hdr + TRX_RSEG_HISTORY_SIZE,
                     hist_size - seg_size, MLOG_4BYTES, &mtr);

    ut_ad(rseg->curr_size >= seg_size);

    rseg->curr_size -= seg_size;

    mutex_exit(&(rseg->mutex));

    mtr_commit(&mtr);
}
Пример #9
0
/********************************************************************//**
Adds the update undo log as the first log in the history list. Removes the
update undo log segment from the rseg slot if it is too big for reuse. */
UNIV_INTERN
void
trx_purge_add_update_undo_to_history(
    /*=================================*/
    trx_t*	trx,		/*!< in: transaction */
    page_t*	undo_page,	/*!< in: update undo log header page,
				x-latched */
    mtr_t*	mtr)		/*!< in: mtr */
{
    trx_undo_t*	undo;
    trx_rsegf_t*	rseg_header;
    trx_ulogf_t*	undo_header;

    undo = trx->update_undo;

    ut_ad(undo);

    ut_ad(mutex_own(&undo->rseg->mutex));

    rseg_header = trx_rsegf_get(
                      undo->rseg->space, undo->rseg->zip_size, undo->rseg->page_no,
                      mtr);

    undo_header = undo_page + undo->hdr_offset;
    /* Add the log as the first in the history list */

    if (undo->state != TRX_UNDO_CACHED) {
        ulint		hist_size;
#ifdef UNIV_DEBUG
        trx_usegf_t*	seg_header = undo_page + TRX_UNDO_SEG_HDR;
#endif /* UNIV_DEBUG */

        /* The undo log segment will not be reused */

        if (UNIV_UNLIKELY(undo->id >= TRX_RSEG_N_SLOTS)) {
            fprintf(stderr,
                    "InnoDB: Error: undo->id is %lu\n",
                    (ulong) undo->id);
            ut_error;
        }

        trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL, mtr);

        hist_size = mtr_read_ulint(
                        rseg_header + TRX_RSEG_HISTORY_SIZE, MLOG_4BYTES, mtr);

        ut_ad(undo->size == flst_get_len(
                  seg_header + TRX_UNDO_PAGE_LIST, mtr));

        mlog_write_ulint(
            rseg_header + TRX_RSEG_HISTORY_SIZE,
            hist_size + undo->size, MLOG_4BYTES, mtr);
    }

    flst_add_first(
        rseg_header + TRX_RSEG_HISTORY,
        undo_header + TRX_UNDO_HISTORY_NODE, mtr);

    /* Write the trx number to the undo log header */

    mlog_write_ull(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);

    /* Write information about delete markings to the undo log header */

    if (!undo->del_marks) {
        mlog_write_ulint(
            undo_header + TRX_UNDO_DEL_MARKS, FALSE,
            MLOG_2BYTES, mtr);
    }

    if (undo->rseg->last_page_no == FIL_NULL) {
        undo->rseg->last_trx_no = trx->no;
        undo->rseg->last_offset = undo->hdr_offset;
        undo->rseg->last_page_no = undo->hdr_page_no;
        undo->rseg->last_del_marks = undo->del_marks;

        /* FIXME: Add a bin heap validate function to check that
        the rseg exists. */
    }

    mutex_enter(&kernel_mutex);
    trx_sys->rseg_history_len++;
    mutex_exit(&kernel_mutex);

//	if (!(trx_sys->rseg_history_len % srv_purge_batch_size)) { /*should wake up always*/
    /* Inform the purge thread that there is work to do. */
    srv_wake_purge_thread_if_not_active();
//	}
}
Пример #10
0
/****************************************************************//**
Creates a rollback segment header. This function is called only when
a new rollback segment is created in the database.
@return	page number of the created segment, FIL_NULL if fail */
UNIV_INTERN
ulint
trx_rseg_header_create(
/*===================*/
	ulint	space,		/*!< in: space id */
	ulint	zip_size,	/*!< in: compressed page size in bytes
				or 0 for uncompressed pages */
	ulint	max_size,	/*!< in: max size in pages */
	ulint	rseg_slot_no,	/*!< in: rseg id == slot number in trx sys */
	mtr_t*	mtr)		/*!< in: mtr */
{
	ulint		page_no;
	trx_rsegf_t*	rsegf;
	trx_sysf_t*	sys_header;
	ulint		i;
	buf_block_t*	block;

	ut_ad(mtr);
	ut_ad(mutex_own(&kernel_mutex));
	ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
				MTR_MEMO_X_LOCK));

	/* Allocate a new file segment for the rollback segment */
	block = fseg_create(space, 0,
			    TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);

	if (block == NULL) {
		/* No space left */

		return(FIL_NULL);
	}

	buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);

	page_no = buf_block_get_page_no(block);

	/* Get the rollback segment file page */
	rsegf = trx_rsegf_get_new(space, zip_size, page_no, mtr);

	/* Initialize max size field */
	mlog_write_ulint(rsegf + TRX_RSEG_MAX_SIZE, max_size,
			 MLOG_4BYTES, mtr);

	/* Initialize the history list */

	mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr);
	flst_init(rsegf + TRX_RSEG_HISTORY, mtr);

	/* Reset the undo log slots */
	for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {

		trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
	}

	/* Add the rollback segment info to the free slot in
	the trx system header */

	sys_header = trx_sysf_get(mtr);

	trx_sysf_rseg_set_space(sys_header, rseg_slot_no, space, mtr);
	trx_sysf_rseg_set_page_no(sys_header, rseg_slot_no, page_no, mtr);

	return(page_no);
}
Пример #11
0
/********************************************************************//**
Adds the update undo log as the first log in the history list. Removes the
update undo log segment from the rseg slot if it is too big for reuse. */
UNIV_INTERN
void
trx_purge_add_update_undo_to_history(
/*=================================*/
	trx_t*	trx,		/*!< in: transaction */
	page_t*	undo_page,	/*!< in: update undo log header page,
				x-latched */
	mtr_t*	mtr)		/*!< in: mtr */
{
	trx_undo_t*	undo;
	trx_rseg_t*	rseg;
	trx_rsegf_t*	rseg_header;
#ifdef UNIV_DEBUG
	trx_usegf_t*	seg_header;
#endif /* UNIV_DEBUG */
	trx_ulogf_t*	undo_header;
	ulint		hist_size;

	undo = trx->update_undo;

	ut_ad(undo);

	rseg = undo->rseg;

	ut_ad(mutex_own(&(rseg->mutex)));

	rseg_header = trx_rsegf_get(rseg->space, rseg->zip_size,
				    rseg->page_no, mtr);

	undo_header = undo_page + undo->hdr_offset;
#ifdef UNIV_DEBUG
	seg_header  = undo_page + TRX_UNDO_SEG_HDR;
#endif /* UNIV_DEBUG */

	if (undo->state != TRX_UNDO_CACHED) {
		/* The undo log segment will not be reused */

		if (undo->id >= TRX_RSEG_N_SLOTS) {
			fprintf(stderr,
				"InnoDB: Error: undo->id is %lu\n",
				(ulong) undo->id);
			ut_error;
		}

		trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL, mtr);

		hist_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
					   MLOG_4BYTES, mtr);
		ut_ad(undo->size == flst_get_len(
			      seg_header + TRX_UNDO_PAGE_LIST, mtr));

		mlog_write_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
				 hist_size + undo->size, MLOG_4BYTES, mtr);
	}

	/* Add the log as the first in the history list */
	flst_add_first(rseg_header + TRX_RSEG_HISTORY,
		       undo_header + TRX_UNDO_HISTORY_NODE, mtr);
	mutex_enter(&kernel_mutex);
	trx_sys->rseg_history_len++;
	mutex_exit(&kernel_mutex);

	/* Write the trx number to the undo log header */
	mlog_write_dulint(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);
	/* Write information about delete markings to the undo log header */

	if (!undo->del_marks) {
		mlog_write_ulint(undo_header + TRX_UNDO_DEL_MARKS, FALSE,
				 MLOG_2BYTES, mtr);
	}

	if (rseg->last_page_no == FIL_NULL) {

		rseg->last_page_no = undo->hdr_page_no;
		rseg->last_offset = undo->hdr_offset;
		rseg->last_trx_no = trx->no;
		rseg->last_del_marks = undo->del_marks;
	}
}
Пример #12
0
/*****************************************************************//**
Creates the file page for the dictionary header. This function is
called only at the database creation.
@return	TRUE if succeed */
static
ibool
dict_hdr_create(
/*============*/
	mtr_t*	mtr)	/*!< in: mtr */
{
	buf_block_t*	block;
	dict_hdr_t*	dict_header;
	ulint		root_page_no;

	ut_ad(mtr);

	/* Create the dictionary header file block in a new, allocated file
	segment in the system tablespace */
	block = fseg_create(DICT_HDR_SPACE, 0,
			    DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);

	ut_a(DICT_HDR_PAGE_NO == buf_block_get_page_no(block));

	dict_header = dict_hdr_get(mtr);

	/* Start counting row, table, index, and tree ids from
	DICT_HDR_FIRST_ID */
	mlog_write_dulint(dict_header + DICT_HDR_ROW_ID,
			  ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);

	mlog_write_dulint(dict_header + DICT_HDR_TABLE_ID,
			  ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);

	mlog_write_dulint(dict_header + DICT_HDR_INDEX_ID,
			  ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);

	/* Obsolete, but we must initialize it to 0 anyway. */
	mlog_write_dulint(dict_header + DICT_HDR_MIX_ID,
			  ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);

	/* Create the B-tree roots for the clustered indexes of the basic
	system tables */

	/*--------------------------*/
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
				  DICT_HDR_SPACE, 0, DICT_TABLES_ID,
				  dict_ind_redundant, mtr);
	if (root_page_no == FIL_NULL) {

		return(FALSE);
	}

	mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
			 MLOG_4BYTES, mtr);
	/*--------------------------*/
	root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE, 0,
				  DICT_TABLE_IDS_ID,
				  dict_ind_redundant, mtr);
	if (root_page_no == FIL_NULL) {

		return(FALSE);
	}

	mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
			 MLOG_4BYTES, mtr);
	/*--------------------------*/
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
				  DICT_HDR_SPACE, 0, DICT_COLUMNS_ID,
				  dict_ind_redundant, mtr);
	if (root_page_no == FIL_NULL) {

		return(FALSE);
	}

	mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
			 MLOG_4BYTES, mtr);
	/*--------------------------*/
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
				  DICT_HDR_SPACE, 0, DICT_INDEXES_ID,
				  dict_ind_redundant, mtr);
	if (root_page_no == FIL_NULL) {

		return(FALSE);
	}

	mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
			 MLOG_4BYTES, mtr);
	/*--------------------------*/
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
				  DICT_HDR_SPACE, 0, DICT_FIELDS_ID,
				  dict_ind_redundant, mtr);
	if (root_page_no == FIL_NULL) {

		return(FALSE);
	}

	mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
			 MLOG_4BYTES, mtr);
	/*--------------------------*/

	return(TRUE);
}
Пример #13
0
void
flst_remove(
    /*========*/
    flst_base_node_t*	base,	/* in: pointer to base node of list */
    flst_node_t*		node2,	/* in: node to remove */
    mtr_t*			mtr)	/* in: mini-transaction handle */
{
    ulint		space;
    flst_node_t*	node1;
    fil_addr_t	node1_addr;
    fil_addr_t	node2_addr;
    flst_node_t*	node3;
    fil_addr_t	node3_addr;
    ulint		len;

    ut_ad(mtr && node2 && base);
    ut_ad(mtr_memo_contains(mtr, buf_block_align(base),
                            MTR_MEMO_PAGE_X_FIX));
    ut_ad(mtr_memo_contains(mtr, buf_block_align(node2),
                            MTR_MEMO_PAGE_X_FIX));

    buf_ptr_get_fsp_addr(node2, &space, &node2_addr);

    node1_addr = flst_get_prev_addr(node2, mtr);
    node3_addr = flst_get_next_addr(node2, mtr);

    if (!fil_addr_is_null(node1_addr)) {

        /* Update next field of node1 */

        if (node1_addr.page == node2_addr.page) {

            node1 = buf_frame_align(node2) + node1_addr.boffset;
        } else {
            node1 = fut_get_ptr(space, node1_addr, RW_X_LATCH,
                                mtr);
        }

        ut_ad(node1 != node2);

        flst_write_addr(node1 + FLST_NEXT, node3_addr, mtr);
    } else {
        /* node2 was first in list: update first field in base */
        flst_write_addr(base + FLST_FIRST, node3_addr, mtr);
    }

    if (!fil_addr_is_null(node3_addr)) {
        /* Update prev field of node3 */

        if (node3_addr.page == node2_addr.page) {

            node3 = buf_frame_align(node2) + node3_addr.boffset;
        } else {
            node3 = fut_get_ptr(space, node3_addr, RW_X_LATCH,
                                mtr);
        }

        ut_ad(node2 != node3);

        flst_write_addr(node3 + FLST_PREV, node1_addr, mtr);
    } else {
        /* node2 was last in list: update last field in base */
        flst_write_addr(base + FLST_LAST, node1_addr, mtr);
    }

    /* Update len of base node */
    len = flst_get_len(base, mtr);
    ut_ad(len > 0);

    mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr);
}
Пример #14
0
ulint
trx_rseg_header_create(
/*===================*/
				/* out: page number of the created segment,
				FIL_NULL if fail */
	ulint	space,		/* in: space id */
	ulint	max_size,	/* in: max size in pages */
	ulint*	slot_no,	/* out: rseg id == slot number in trx sys */
	mtr_t*	mtr)		/* in: mtr */
{
	ulint		page_no;
	trx_rsegf_t*	rsegf;
	trx_sysf_t*	sys_header;
	ulint		i;
	page_t*		page;
	
	ut_ad(mtr);
#ifdef UNIV_SYNC_DEBUG
	ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
	ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space),
							MTR_MEMO_X_LOCK));
	sys_header = trx_sysf_get(mtr);

	*slot_no = trx_sysf_rseg_find_free(mtr);

	if (*slot_no == ULINT_UNDEFINED) {

		return(FIL_NULL);
	}

	/* Allocate a new file segment for the rollback segment */
	page = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);

	if (page == NULL) {
		/* No space left */

		return(FIL_NULL);
	}

#ifdef UNIV_SYNC_DEBUG
	buf_page_dbg_add_level(page, SYNC_RSEG_HEADER_NEW);
#endif /* UNIV_SYNC_DEBUG */

	page_no = buf_frame_get_page_no(page);

	/* Get the rollback segment file page */
	rsegf = trx_rsegf_get_new(space, page_no, mtr);
					    
	/* Initialize max size field */
	mlog_write_ulint(rsegf + TRX_RSEG_MAX_SIZE, max_size, MLOG_4BYTES, mtr);
	
	/* Initialize the history list */

	mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr);
	flst_init(rsegf + TRX_RSEG_HISTORY, mtr);

	/* Reset the undo log slots */
	for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {

		trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
	}

	/* Add the rollback segment info to the free slot in the trx system
	header */

	trx_sysf_rseg_set_space(sys_header, *slot_no, space, mtr);	
	trx_sysf_rseg_set_page_no(sys_header, *slot_no, page_no, mtr);

	return(page_no);
}