예제 #1
0
/**********************************************************************
Adds a block to the LRU list end. */
UNIV_INLINE
void
buf_LRU_add_block_to_end_low(
/*=========================*/
	buf_block_t*	block)	/* in: control block */
{
	buf_block_t*	last_block;

	ut_ad(buf_pool);
	ut_ad(block);
	ut_ad(mutex_own(&(buf_pool->mutex)));

	ut_a(block->state == BUF_BLOCK_FILE_PAGE);

	block->old = TRUE;

	last_block = UT_LIST_GET_LAST(buf_pool->LRU);

	if (last_block) {
		block->LRU_position = last_block->LRU_position;
	} else {
		block->LRU_position = buf_pool_clock_tic();
	}

	ut_a(!block->in_LRU_list);
	UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block);
	block->in_LRU_list = TRUE;

	if (srv_use_awe && block->frame) {
		/* Add to the list of mapped pages */

		UT_LIST_ADD_LAST(awe_LRU_free_mapped,
				 buf_pool->awe_LRU_free_mapped, block);
	}

	if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {

		buf_pool->LRU_old_len++;
	}

	if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {

		ut_ad(buf_pool->LRU_old);

		/* Adjust the length of the old block list if necessary */

		buf_LRU_old_adjust_len();

	} else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {

		/* The LRU list is now long enough for LRU_old to become
		defined: init it */

		buf_LRU_old_init();
	}
}
예제 #2
0
파일: mem0dbg.c 프로젝트: AllenWeb/mariadb
/***************************************************************//**
Inserts a created memory heap to the hash table of current allocated
memory heaps. */
UNIV_INTERN
void
mem_hash_insert(
/*============*/
	mem_heap_t*	heap,	   /*!< in: the created heap */
	const char*	file_name, /*!< in: file name of creation */
	ulint		line)	   /*!< in: line where created */
{
	mem_hash_node_t*	new_node;
	ulint			cell_no	;

	ut_ad(mem_heap_check(heap));

	mutex_enter(&mem_hash_mutex);

	cell_no = ut_hash_ulint((ulint)heap, MEM_HASH_SIZE);

	/* Allocate a new node to the list */
	new_node = ut_malloc(sizeof(mem_hash_node_t));

	new_node->heap = heap;
	new_node->file_name = file_name;
	new_node->line = line;
	new_node->nth_heap = mem_n_created_heaps;

	/* Insert into lists */
	UT_LIST_ADD_FIRST(list, *mem_hash_get_nth_cell(cell_no), new_node);

	UT_LIST_ADD_LAST(all_list, mem_all_list_base, new_node);

	mem_n_created_heaps++;

	mutex_exit(&mem_hash_mutex);
}
예제 #3
0
파일: trx0trx.c 프로젝트: huahuaxu/MySQL5.1
/****************************************************************//**
Inserts the trx handle in the trx system trx list in the right position.
The list is sorted on the trx id so that the biggest id is at the list
start. This function is used at the database startup to insert incomplete
transactions to the list. */
static
void
trx_list_insert_ordered(
/*====================*/
	trx_t*	trx)	/*!< in: trx handle */
{
	trx_t*	trx2;

	ut_ad(mutex_own(&kernel_mutex));

	trx2 = UT_LIST_GET_FIRST(trx_sys->trx_list);

	while (trx2 != NULL) {
		if (ut_dulint_cmp(trx->id, trx2->id) >= 0) {

			ut_ad(ut_dulint_cmp(trx->id, trx2->id) == 1);
			break;
		}
		trx2 = UT_LIST_GET_NEXT(trx_list, trx2);
	}

	if (trx2 != NULL) {
		trx2 = UT_LIST_GET_PREV(trx_list, trx2);

		if (trx2 == NULL) {
			UT_LIST_ADD_FIRST(trx_list, trx_sys->trx_list, trx);
		} else {
			UT_LIST_INSERT_AFTER(trx_list, trx_sys->trx_list,
					     trx2, trx);
		}
	} else {
		UT_LIST_ADD_LAST(trx_list, trx_sys->trx_list, trx);
	}
}
예제 #4
0
파일: pars0sym.c 프로젝트: 0x00xw/mysql-2
/******************************************************************//**
Adds an identifier to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_id(
/*===========*/
	sym_tab_t*	sym_tab,	/*!< in: symbol table */
	byte*		name,		/*!< in: identifier name */
	ulint		len)		/*!< in: identifier length */
{
	sym_node_t*	node;

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = FALSE;
	node->indirection = NULL;

	node->name = mem_heap_strdupl(sym_tab->heap, (char*) name, len);
	node->name_len = len;

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	dfield_set_null(&node->common.val);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	node->sym_table = sym_tab;

	return(node);
}
예제 #5
0
파일: que0que.c 프로젝트: isleon/Jaxer
que_thr_t*
que_thr_create(
/*===========*/
				/* out, own: query thread node */
	que_fork_t*	parent,	/* in: parent node, i.e., a fork node */
	mem_heap_t*	heap)	/* in: memory heap where created */
{
	que_thr_t*	thr;
	
	ut_ad(parent && heap);
	
	thr = mem_heap_alloc(heap, sizeof(que_thr_t));

	thr->common.type = QUE_NODE_THR;
	thr->common.parent = parent;

	thr->magic_n = QUE_THR_MAGIC_N;

	thr->graph = parent->graph;

	thr->state = QUE_THR_COMMAND_WAIT;

	thr->is_active = FALSE;	

	thr->run_node = NULL;
	thr->resource = 0;
  thr->lock_state = QUE_THR_LOCK_NOLOCK;

	UT_LIST_ADD_LAST(thrs, parent->thrs, thr);

	return(thr);
}
예제 #6
0
파일: pars0sym.c 프로젝트: 0x00xw/mysql-2
/******************************************************************//**
Adds an SQL null literal to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_null_lit(
/*=================*/
	sym_tab_t*	sym_tab)	/*!< in: symbol table */
{
	sym_node_t*	node;

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = TRUE;
	node->token_type = SYM_LIT;

	node->indirection = NULL;

	dfield_get_type(&node->common.val)->mtype = DATA_ERROR;

	dfield_set_null(&node->common.val);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	node->sym_table = sym_tab;

	return(node);
}
예제 #7
0
파일: pars0sym.c 프로젝트: 0x00xw/mysql-2
/******************************************************************//**
Add a bound identifier to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_bound_id(
/*===========*/
	sym_tab_t*	sym_tab,	/*!< in: symbol table */
	const char*	name)		/*!< in: name of bound id */
{
	sym_node_t*		node;
	pars_bound_id_t*	bid;

	bid = pars_info_get_bound_id(sym_tab->info, name);
	ut_a(bid);

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = FALSE;
	node->indirection = NULL;

	node->name = mem_heap_strdup(sym_tab->heap, bid->id);
	node->name_len = strlen(node->name);

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	dfield_set_null(&node->common.val);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	node->sym_table = sym_tab;

	return(node);
}
예제 #8
0
파일: dyn0dyn.c 프로젝트: A-eolus/mysql
/************************************************************//**
Adds a new block to a dyn array.
@return	created block */
UNIV_INTERN
dyn_block_t*
dyn_array_add_block(
/*================*/
	dyn_array_t*	arr)	/*!< in: dyn array */
{
	mem_heap_t*	heap;
	dyn_block_t*	block;

	ut_ad(arr);
	ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);

	if (arr->heap == NULL) {
		UT_LIST_INIT(arr->base);
		UT_LIST_ADD_FIRST(list, arr->base, arr);

		arr->heap = mem_heap_create(sizeof(dyn_block_t));
	}

	block = dyn_array_get_last_block(arr);
	block->used = block->used | DYN_BLOCK_FULL_FLAG;

	heap = arr->heap;

	block = mem_heap_alloc(heap, sizeof(dyn_block_t));

	block->used = 0;

	UT_LIST_ADD_LAST(list, arr->base, block);

	return(block);
}
예제 #9
0
/***********************************************************************//**
Adds a query graph to the session's list of graphs. */
UNIV_INTERN
void
que_graph_publish(
/*==============*/
	que_t*	graph,	/*!< in: graph */
	sess_t*	sess)	/*!< in: session */
{
	ut_ad(mutex_own(&kernel_mutex));

	UT_LIST_ADD_LAST(graphs, sess->graphs, graph);
}
예제 #10
0
파일: que0que.c 프로젝트: isleon/Jaxer
void
que_graph_publish(
/*==============*/
	que_t*	graph,	/* in: graph */
	sess_t*	sess)	/* in: session */
{
#ifdef UNIV_SYNC_DEBUG
	ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */

	UT_LIST_ADD_LAST(graphs, sess->graphs, graph);
}
예제 #11
0
/**********************************************************************//**
Enqueues a task to server task queue and releases a worker thread, if there
is a suspended one. */
UNIV_INTERN
void
srv_que_task_enqueue_low(
/*=====================*/
	que_thr_t*	thr)	/*!< in: query thread */
{
	ut_ad(thr);
	ut_ad(mutex_own(&kernel_mutex));

	UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr);

	srv_release_threads(SRV_WORKER, 1);
}
예제 #12
0
/*******************************************************************//**
Creates a named savepoint. If the transaction is not yet started, starts it.
If there is already a savepoint of the same name, this call erases that old
savepoint and replaces it with a new. Savepoints are deleted in a transaction
commit or rollback.
@return	always DB_SUCCESS */
UNIV_INTERN
ulint
trx_savepoint_for_mysql(
/*====================*/
	trx_t*		trx,			/*!< in: transaction handle */
	const char*	savepoint_name,		/*!< in: savepoint name */
	ib_int64_t	binlog_cache_pos)	/*!< in: MySQL binlog cache
						position corresponding to this
						connection at the time of the
						savepoint */
{
	trx_named_savept_t*	savep;

	ut_a(trx);
	ut_a(savepoint_name);

	trx_start_if_not_started(trx);

	savep = UT_LIST_GET_FIRST(trx->trx_savepoints);

	while (savep != NULL) {
		if (0 == ut_strcmp(savep->name, savepoint_name)) {
			/* Found */
			break;
		}
		savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
	}

	if (savep) {
		/* There is a savepoint with the same name: free that */

		UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);

		mem_free(savep->name);
		mem_free(savep);
	}

	/* Create a new savepoint and add it as the last in the list */

	savep = mem_alloc(sizeof(trx_named_savept_t));

	savep->name = mem_strdup(savepoint_name);

	savep->savept = trx_savept_take(trx);

	savep->mysql_binlog_cache_pos = binlog_cache_pos;

	UT_LIST_ADD_LAST(trx_savepoints, trx->trx_savepoints, savep);

	return(DB_SUCCESS);
}
예제 #13
0
파일: pars0sym.c 프로젝트: 0x00xw/mysql-2
/******************************************************************//**
Adds a string literal to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_str_lit(
/*================*/
	sym_tab_t*	sym_tab,	/*!< in: symbol table */
	byte*		str,		/*!< in: string with no quotes around
					it */
	ulint		len)		/*!< in: string length */
{
	sym_node_t*	node;
	byte*		data;

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = TRUE;
	node->token_type = SYM_LIT;

	node->indirection = NULL;

	dtype_set(dfield_get_type(&node->common.val),
		  DATA_VARCHAR, DATA_ENGLISH, 0);

	if (len) {
		data = mem_heap_alloc(sym_tab->heap, len);
		ut_memcpy(data, str, len);
	} else {
		data = NULL;
	}

	dfield_set_data(&(node->common.val), data, len);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	node->sym_table = sym_tab;

	return(node);
}
예제 #14
0
파일: pars0sym.c 프로젝트: 0x00xw/mysql-2
/******************************************************************//**
Adds an integer literal to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_int_lit(
/*================*/
	sym_tab_t*	sym_tab,	/*!< in: symbol table */
	ulint		val)		/*!< in: integer value */
{
	sym_node_t*	node;
	byte*		data;

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = TRUE;
	node->token_type = SYM_LIT;

	node->indirection = NULL;

	dtype_set(dfield_get_type(&node->common.val), DATA_INT, 0, 4);

	data = mem_heap_alloc(sym_tab->heap, 4);
	mach_write_to_4(data, val);

	dfield_set_data(&(node->common.val), data, 4);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	node->sym_table = sym_tab;

	return(node);
}
예제 #15
0
파일: trx0trx.c 프로젝트: huahuaxu/MySQL5.1
/****************************************************************//**
Sends a signal to a trx object. */
UNIV_INTERN
void
trx_sig_send(
/*=========*/
	trx_t*		trx,		/*!< in: trx handle */
	ulint		type,		/*!< in: signal type */
	ulint		sender,		/*!< in: TRX_SIG_SELF or
					TRX_SIG_OTHER_SESS */
	que_thr_t*	receiver_thr,	/*!< in: query thread which wants the
					reply, or NULL; if type is
					TRX_SIG_END_WAIT, this must be NULL */
	trx_savept_t*	savept,		/*!< in: possible rollback savepoint, or
					NULL */
	que_thr_t**	next_thr)	/*!< in/out: next query thread to run;
					if the value which is passed in is
					a pointer to a NULL pointer, then the
					calling function can start running
					a new query thread; if the parameter
					is NULL, it is ignored */
{
	trx_sig_t*	sig;
	trx_t*		receiver_trx;

	ut_ad(trx);
	ut_ad(mutex_own(&kernel_mutex));

	if (!trx_sig_is_compatible(trx, type, sender)) {
		/* The signal is not compatible with the other signals in
		the queue: die */

		ut_error;
	}

	/* Queue the signal object */

	if (UT_LIST_GET_LEN(trx->signals) == 0) {

		/* The signal list is empty: the 'sig' slot must be unused
		(we improve performance a bit by avoiding mem_alloc) */
		sig = &(trx->sig);
	} else {
		/* It might be that the 'sig' slot is unused also in this
		case, but we choose the easy way of using mem_alloc */

		sig = mem_alloc(sizeof(trx_sig_t));
	}

	UT_LIST_ADD_LAST(signals, trx->signals, sig);

	sig->type = type;
	sig->sender = sender;
	sig->receiver = receiver_thr;

	if (savept) {
		sig->savept = *savept;
	}

	if (receiver_thr) {
		receiver_trx = thr_get_trx(receiver_thr);

		UT_LIST_ADD_LAST(reply_signals, receiver_trx->reply_signals,
				 sig);
	}

	if (trx->sess->state == SESS_ERROR) {

		trx_sig_reply_wait_to_suspended(trx);
	}

	if ((sender != TRX_SIG_SELF) || (type == TRX_SIG_BREAK_EXECUTION)) {
		ut_error;
	}

	/* If there were no other signals ahead in the queue, try to start
	handling of the signal */

	if (UT_LIST_GET_FIRST(trx->signals) == sig) {

		trx_sig_start_handle(trx, next_thr);
	}
}
예제 #16
0
/***************************************************************************
Creates and initializes a rollback segment object. The values for the
fields are read from the header. The object is inserted to the rseg
list of the trx system object and a pointer is inserted in the rseg
array in the trx system object.
@return	own: rollback segment object */
static
trx_rseg_t*
trx_rseg_mem_create(
/*================*/
	ulint	id,		/*!< in: rollback segment id */
	ulint	space,		/*!< in: space where the segment placed */
	ulint	zip_size,	/*!< in: compressed page size in bytes
				or 0 for uncompressed pages */
	ulint	page_no,	/*!< in: page number of the segment header */
	mtr_t*	mtr)		/*!< in: mtr */
{
	ulint		len;
	trx_rseg_t*	rseg;
	fil_addr_t	node_addr;
	trx_rsegf_t*	rseg_header;
	trx_ulogf_t*	undo_log_hdr;
	ulint		sum_of_undo_sizes;

	ut_ad(mutex_own(&kernel_mutex));

	rseg = mem_zalloc(sizeof(trx_rseg_t));

	rseg->id = id;
	rseg->space = space;
	rseg->zip_size = zip_size;
	rseg->page_no = page_no;

	mutex_create(rseg_mutex_key, &rseg->mutex, SYNC_RSEG);

	UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);

	trx_sys_set_nth_rseg(trx_sys, id, rseg);

	rseg_header = trx_rsegf_get_new(space, zip_size, page_no, mtr);

	rseg->max_size = mtr_read_ulint(rseg_header + TRX_RSEG_MAX_SIZE,
					MLOG_4BYTES, mtr);

	/* Initialize the undo log lists according to the rseg header */

	sum_of_undo_sizes = trx_undo_lists_init(rseg);

	rseg->curr_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
					 MLOG_4BYTES, mtr)
		+ 1 + sum_of_undo_sizes;

	len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
	if (len > 0) {
		trx_sys->rseg_history_len += len;

		node_addr = trx_purge_get_log_from_hist(
			flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
		rseg->last_page_no = node_addr.page;
		rseg->last_offset = node_addr.boffset;

		undo_log_hdr = trx_undo_page_get(rseg->space, rseg->zip_size,
						 node_addr.page,
						 mtr) + node_addr.boffset;

		rseg->last_trx_no = mtr_read_dulint(
			undo_log_hdr + TRX_UNDO_TRX_NO, mtr);
		rseg->last_del_marks = mtr_read_ulint(
			undo_log_hdr + TRX_UNDO_DEL_MARKS, MLOG_2BYTES, mtr);
	} else {
		rseg->last_page_no = FIL_NULL;
	}

	return(rseg);
}
예제 #17
0
read_view_t*
read_view_oldest_copy_or_open_new(
/*==============================*/
					/* out, own: read view struct */
	dulint		cr_trx_id,	/* in: trx_id of creating
					transaction, or (0, 0) used in purge*/
	mem_heap_t*	heap)		/* in: memory heap from which
					allocated */
{
	read_view_t*	old_view;
	read_view_t*	view_copy;
	ibool		needs_insert	= TRUE;
	ulint		insert_done	= 0;
	ulint		n;
	ulint		i;

	ut_ad(mutex_own(&kernel_mutex));

	old_view = UT_LIST_GET_LAST(trx_sys->view_list);

	if (old_view == NULL) {

		return(read_view_open_now(cr_trx_id, heap));
	}

	n = old_view->n_trx_ids;

	if (ut_dulint_cmp(old_view->creator_trx_id,
			  ut_dulint_create(0,0)) != 0) {
		n++;
	} else {
		needs_insert = FALSE;
	}

	view_copy = read_view_create_low(n, heap);

	/* Insert the id of the creator in the right place of the descending
	array of ids, if needs_insert is TRUE: */

	i = 0;
	while (i < n) {
		if (needs_insert
		    && (i >= old_view->n_trx_ids
			|| ut_dulint_cmp(old_view->creator_trx_id,
					 read_view_get_nth_trx_id(old_view, i))
			> 0)) {

			read_view_set_nth_trx_id(view_copy, i,
						 old_view->creator_trx_id);
			needs_insert = FALSE;
			insert_done = 1;
		} else {
			read_view_set_nth_trx_id(view_copy, i,
						 read_view_get_nth_trx_id(
							 old_view,
							 i - insert_done));
		}

		i++;
	}

	view_copy->creator_trx_id = cr_trx_id;

	view_copy->low_limit_no = old_view->low_limit_no;
	view_copy->low_limit_id = old_view->low_limit_id;


	if (n > 0) {
		/* The last active transaction has the smallest id: */
		view_copy->up_limit_id = read_view_get_nth_trx_id(
			view_copy, n - 1);
	} else {
		view_copy->up_limit_id = old_view->up_limit_id;
	}

	UT_LIST_ADD_LAST(view_list, trx_sys->view_list, view_copy);

	return(view_copy);
}
예제 #18
0
파일: pars0sym.c 프로젝트: 0x00xw/mysql-2
/******************************************************************//**
Add a bound literal to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_bound_lit(
/*==================*/
	sym_tab_t*	sym_tab,	/*!< in: symbol table */
	const char*	name,		/*!< in: name of bound literal */
	ulint*		lit_type)	/*!< out: type of literal (PARS_*_LIT) */
{
	sym_node_t*		node;
	pars_bound_lit_t*	blit;
	ulint			len = 0;

	blit = pars_info_get_bound_lit(sym_tab->info, name);
	ut_a(blit);

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = TRUE;
	node->token_type = SYM_LIT;

	node->indirection = NULL;

	switch (blit->type) {
	case DATA_FIXBINARY:
		len = blit->length;
		*lit_type = PARS_FIXBINARY_LIT;
		break;

	case DATA_BLOB:
		*lit_type = PARS_BLOB_LIT;
		break;

	case DATA_VARCHAR:
		*lit_type = PARS_STR_LIT;
		break;

	case DATA_CHAR:
		ut_a(blit->length > 0);

		len = blit->length;
		*lit_type = PARS_STR_LIT;
		break;

	case DATA_INT:
		ut_a(blit->length > 0);
		ut_a(blit->length <= 8);

		len = blit->length;
		*lit_type = PARS_INT_LIT;
		break;

	default:
		ut_error;
	}

	dtype_set(dfield_get_type(&node->common.val),
		  blit->type, blit->prtype, len);

	dfield_set_data(&(node->common.val), blit->address, blit->length);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	node->sym_table = sym_tab;

	return(node);
}
예제 #19
0
/***************************************************************//**
Creates a memory heap block where data can be allocated.
@return own: memory heap block, NULL if did not succeed (only possible
for MEM_HEAP_BTR_SEARCH type heaps) */
UNIV_INTERN
mem_block_t*
mem_heap_create_block(
/*==================*/
	mem_heap_t*	heap,	/*!< in: memory heap or NULL if first block
				should be created */
	ulint		n,	/*!< in: number of bytes needed for user data */
	ulint		type,	/*!< in: type of heap: MEM_HEAP_DYNAMIC or
				MEM_HEAP_BUFFER */
	const char*	file_name,/*!< in: file name where created */
	ulint		line)	/*!< in: line where created */
{
#ifndef UNIV_HOTBACKUP
	buf_block_t*	buf_block = NULL;
#endif /* !UNIV_HOTBACKUP */
	mem_block_t*	block;
	ulint		len;

	ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
	      || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));

	if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) {
		mem_analyze_corruption(heap);
	}

	/* In dynamic allocation, calculate the size: block header + data. */
	len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);

#ifndef UNIV_HOTBACKUP
	if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {

		ut_ad(type == MEM_HEAP_DYNAMIC || n <= MEM_MAX_ALLOC_IN_BUF);

		block = mem_area_alloc(&len, mem_comm_pool);
	} else {
		len = UNIV_PAGE_SIZE;

		if ((type & MEM_HEAP_BTR_SEARCH) && heap) {
			/* We cannot allocate the block from the
			buffer pool, but must get the free block from
			the heap header free block field */

			buf_block = heap->free_block;
			heap->free_block = NULL;

			if (UNIV_UNLIKELY(!buf_block)) {

				return(NULL);
			}
		} else {
			buf_block = buf_block_alloc(NULL, 0);
		}

		block = (mem_block_t*) buf_block->frame;
	}

	ut_ad(block);
	block->buf_block = buf_block;
	block->free_block = NULL;
#else /* !UNIV_HOTBACKUP */
	len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);
	block = ut_malloc(len);
	ut_ad(block);
#endif /* !UNIV_HOTBACKUP */

	block->magic_n = MEM_BLOCK_MAGIC_N;
	ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name));
	block->line = line;

#ifdef MEM_PERIODIC_CHECK
	mem_pool_mutex_enter();

	if (!mem_block_list_inited) {
		mem_block_list_inited = TRUE;
		UT_LIST_INIT(mem_block_list);
	}

	UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block);

	mem_pool_mutex_exit();
#endif
	mem_block_set_len(block, len);
	mem_block_set_type(block, type);
	mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
	mem_block_set_start(block, MEM_BLOCK_HEADER_SIZE);

	if (UNIV_UNLIKELY(heap == NULL)) {
		/* This is the first block of the heap. The field
		total_size should be initialized here */
		block->total_size = len;
	} else {
		/* Not the first allocation for the heap. This block's
		total_length field should be set to undefined. */
		ut_d(block->total_size = ULINT_UNDEFINED);
		UNIV_MEM_INVALID(&block->total_size,
				 sizeof block->total_size);

		heap->total_size += len;
	}

	ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len);

	return(block);
}
예제 #20
0
파일: mem0mem.c 프로젝트: isleon/Jaxer
mem_block_t*
mem_heap_create_block(
/*==================*/
				/* out, own: memory heap block,
				NULL if did not succeed */
	mem_heap_t*	heap,	/* in: memory heap or NULL if first block
				should be created */
	ulint		n,	/* in: number of bytes needed for user data, or
				if init_block is not NULL, its size in bytes */
	void*		init_block, /* in: init block in fast create,
				type must be MEM_HEAP_DYNAMIC */
	ulint		type,	/* in: type of heap: MEM_HEAP_DYNAMIC or
				MEM_HEAP_BUFFER */
	const char*	file_name,/* in: file name where created */
	ulint		line)	/* in: line where created */
{
	mem_block_t*	block;
	ulint		len;
	
	ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
		|| (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));

	if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) {
		mem_analyze_corruption((byte*)heap);
	}

	/* In dynamic allocation, calculate the size: block header + data. */

	if (init_block != NULL) {
		ut_ad(type == MEM_HEAP_DYNAMIC);
		ut_ad(n > MEM_BLOCK_START_SIZE + MEM_BLOCK_HEADER_SIZE);
		len = n;
		block = init_block;

	} else if (type == MEM_HEAP_DYNAMIC) {

		len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);
		block = mem_area_alloc(len, mem_comm_pool);
	} else {
		ut_ad(n <= MEM_MAX_ALLOC_IN_BUF);

		len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);

		if (len < UNIV_PAGE_SIZE / 2) {

			block = mem_area_alloc(len, mem_comm_pool);
		} else {
			len = UNIV_PAGE_SIZE;

			if ((type & MEM_HEAP_BTR_SEARCH) && heap) {
				/* We cannot allocate the block from the
				buffer pool, but must get the free block from
				the heap header free block field */

				block = (mem_block_t*)heap->free_block;
				heap->free_block = NULL;
			} else {
				block = (mem_block_t*)buf_frame_alloc();
			}
		}
	}

	if (block == NULL) {

		return(NULL);
	}

	block->magic_n = MEM_BLOCK_MAGIC_N;
	ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name));
	block->line = line;

#ifdef MEM_PERIODIC_CHECK	
	mem_pool_mutex_enter();

	if (!mem_block_list_inited) {
		mem_block_list_inited = TRUE;
		UT_LIST_INIT(mem_block_list);
	}
	
	UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block);

	mem_pool_mutex_exit();
#endif
	mem_block_set_len(block, len);
	mem_block_set_type(block, type);
	mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
	mem_block_set_start(block, MEM_BLOCK_HEADER_SIZE);

	block->free_block = NULL;
	block->init_block = (init_block != NULL);

	ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len);

	return(block);
}