Пример #1
0
/************************************************************************
Create an instance of a red black tree.
@return	an empty rb tree */
UNIV_INTERN
ib_rbt_t*
rbt_create(
/*=======*/
	size_t		sizeof_value,		/*!< in: sizeof data item */
	ib_rbt_compare	compare)		/*!< in: fn to compare items */
{
	ib_rbt_t*	tree;
	ib_rbt_node_t*	node;

	tree = (ib_rbt_t*) ut_malloc(sizeof(*tree));
	memset(tree, 0, sizeof(*tree));

	tree->sizeof_value = sizeof_value;

	/* Create the sentinel (NIL) node. */
	node = tree->nil = (ib_rbt_node_t*) ut_malloc(sizeof(*node));
	memset(node, 0, sizeof(*node));

	node->color = IB_RBT_BLACK;
	node->parent = node->left = node->right = node;

	/* Create the "fake" root, the real root node will be the
	left child of this node. */
	node = tree->root = (ib_rbt_node_t*) ut_malloc(sizeof(*node));
	memset(node, 0, sizeof(*node));

	node->color = IB_RBT_BLACK;
	node->parent = node->left = node->right = tree->nil;

	tree->compare = compare;

	return(tree);
}
Пример #2
0
byte*
os_awe_allocate_virtual_mem_window(
/*===============================*/
			/* out, own: allocated memory, or NULL if did not
			succeed */
	ulint	size)	/* in: virtual memory allocation size in bytes, must
			be < 2 GB */
{
#ifdef UNIV_SIMULATE_AWE
	ulint	i;

	os_awe_simulate_window = ut_align(ut_malloc(4096 + size), 4096);
	os_awe_simulate_window_size = size;

	os_awe_simulate_map = ut_malloc(sizeof(byte*) * (size / 4096));

	for (i = 0; i < (size / 4096); i++) {
		*(os_awe_simulate_map + i) = NULL;
	}

	return(os_awe_simulate_window);

#elif defined(__WIN2000__)
	byte*	ptr;

	if (size > (ulint)0x7FFFFFFFUL) {
		fprintf(stderr,
			"InnoDB: AWE: Cannot allocate %lu bytes"
			" of virtual memory\n", size);

		return(NULL);
	}

	ptr = VirtualAlloc(NULL, (SIZE_T)size, MEM_RESERVE | MEM_PHYSICAL,
			   PAGE_READWRITE);
	if (ptr == NULL) {
		fprintf(stderr,
			"InnoDB: AWE: Cannot allocate %lu bytes"
			" of virtual memory, error %lu\n",
			size, (ulint)GetLastError());

		return(NULL);
	}

	os_awe_window = ptr;
	os_awe_window_size = size;

	ut_total_allocated_memory += size;

	return(ptr);
#else
	UT_NOT_USED(size);

	return(NULL);
#endif
}
Пример #3
0
/**********************************************************************//**
Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
use this function because the allocation functions in mem0mem.h are the
recommended ones in InnoDB.

man realloc in Linux, 2004:

       realloc()  changes the size of the memory block pointed to
       by ptr to size bytes.  The contents will be  unchanged  to
       the minimum of the old and new sizes; newly allocated mem-
       ory will be uninitialized.  If ptr is NULL,  the	 call  is
       equivalent  to malloc(size); if size is equal to zero, the
       call is equivalent to free(ptr).	 Unless ptr is	NULL,  it
       must  have  been	 returned by an earlier call to malloc(),
       calloc() or realloc().

RETURN VALUE
       realloc() returns a pointer to the newly allocated memory,
       which is suitably aligned for any kind of variable and may
       be different from ptr, or NULL if the  request  fails.  If
       size  was equal to 0, either NULL or a pointer suitable to
       be passed to free() is returned.	 If realloc()  fails  the
       original	 block	is  left  untouched  - it is not freed or
       moved.
@return	own: pointer to new mem block or NULL */
UNIV_INTERN
void*
ut_realloc(
/*=======*/
	void*	ptr,	/*!< in: pointer to old block or NULL */
	ulint	size)	/*!< in: desired size */
{
	ut_mem_block_t* block;
	ulint		old_size;
	ulint		min_size;
	void*		new_ptr;

	if (UNIV_LIKELY(srv_use_sys_malloc)) {
		return(realloc(ptr, size));
	}

	if (ptr == NULL) {

		return(ut_malloc(size));
	}

	if (size == 0) {
		ut_free(ptr);

		return(NULL);
	}

	block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));

	ut_a(block->magic_n == UT_MEM_MAGIC_N);

	old_size = block->size - sizeof(ut_mem_block_t);

	if (size < old_size) {
		min_size = size;
	} else {
		min_size = old_size;
	}

	new_ptr = ut_malloc(size);

	if (new_ptr == NULL) {

		return(NULL);
	}

	/* Copy the old data from ptr */
	ut_memcpy(new_ptr, ptr, min_size);

	ut_free(ptr);

	return(new_ptr);
}
Пример #4
0
/*************************************************************//**
Creates a hash table with >= n array cells. The actual number of cells is
chosen to be a prime number slightly bigger than n.
@return	own: created table */
UNIV_INTERN
hash_table_t*
hash_create(
/*========*/
	ulint	n)	/*!< in: number of array cells */
{
	hash_cell_t*	array;
	ulint		prime;
	hash_table_t*	table;

	prime = ut_find_prime(n);

	table = mem_alloc(sizeof(hash_table_t));

	array = ut_malloc(sizeof(hash_cell_t) * prime);

	table->array = array;
	table->n_cells = prime;
#ifndef UNIV_HOTBACKUP
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
	table->adaptive = FALSE;
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
	table->n_mutexes = 0;
	table->mutexes = NULL;
	table->heaps = NULL;
#endif /* !UNIV_HOTBACKUP */
	table->heap = NULL;
	ut_d(table->magic_n = HASH_TABLE_MAGIC_N);

	/* Initialize the cell array */
	hash_table_clear(table);

	return(table);
}
Пример #5
0
struct client_queue*  client_create_shmqueue(unsigned long shm_addr, int shm_len){
	int i;
	struct client_queue *client_q = ut_malloc(sizeof(struct client_queue));
int desc_length;
	g_data_offset = 8*SHM_PAGE_SIZE;

	client_q->recv_q.shm_queue = create_shmqueue(shm_addr,shm_len,&desc_length);
	client_q->recv_q.desc_head=0;
	client_q->recv_q.desc_list_length=0;
	client_q->recv_q.used_id=0;

	client_q->send_q.shm_queue = create_shmqueue(shm_addr+4*SHM_PAGE_SIZE,shm_len,&desc_length);
	client_q->send_q.desc_head=0;
	client_q->send_q.desc_list_length=desc_length;
	client_q->send_q.used_id=0;
	client_q->shm_start_addr = (unsigned char *)shm_addr;

	/* Fille the Recv queue with empty buffers */
	for (i = 0; i < MAX_BUF ; i++) {

		client_add_buf(client_q,i,RECV);
	}

	return client_q;
}
Пример #6
0
/************************************************************************
Generic insert of a value in the rb tree.
@return	inserted node */
UNIV_INTERN
const ib_rbt_node_t*
rbt_insert(
/*=======*/
	ib_rbt_t*	tree,			/*!< in: rb tree */
	const void*	key,			/*!< in: key for ordering */
	const void*	value)			/*!< in: value of key, this value
						is copied to the node */
{
	ib_rbt_node_t*	node;

	/* Create the node that will hold the value data. */
	node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree));

	memcpy(node->value, value, tree->sizeof_value);
	node->parent = node->left = node->right = tree->nil;

	/* Insert in the tree in the usual way. */
	rbt_tree_insert(tree, key, node);
	rbt_balance_tree(tree, node);

	++tree->n_nodes;

	return(node);
}
Пример #7
0
ibool
srv_parse_log_group_home_dirs(
/*==========================*/
					/* out: TRUE if ok, FALSE if parsing
					error */
	char*	str,			/* in: character string */
	char***	log_group_home_dirs)	/* out, own: log group home dirs */
{
	char*	input_str;
	char*	path;
	ulint	i	= 0;

	input_str = str;
	
	/* First calculate the number of directories and check syntax:
	path;path;... */

	while (*str != '\0') {
		path = str;

		while (*str != ';' && *str != '\0') {
			str++;
		}

		i++;

		if (*str == ';') {
			str++;
		} else if (*str != '\0') {

			return(FALSE);
		}
	}

	*log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*));

	/* Then store the actual values to our array */

	str = input_str;
	i = 0;

	while (*str != '\0') {
		path = str;

		while (*str != ';' && *str != '\0') {
			str++;
		}

		if (*str == ';') {
			*str = '\0';
			str++;
		}

		(*log_group_home_dirs)[i] = path;

		i++;
	}

	return(TRUE);
}
Пример #8
0
/***************************************************************//**
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);
}
Пример #9
0
/************************************************************************
Add a new node to the tree, useful for data that is pre-sorted.
@return	appended node */
UNIV_INTERN
const ib_rbt_node_t*
rbt_add_node(
/*=========*/
	ib_rbt_t*	tree,			/*!< in: rb tree */
	ib_rbt_bound_t*	parent,			/*!< in: bounds */
	const void*	value)			/*!< in: this value is copied
						to the node */
{
	ib_rbt_node_t*	node;

	/* Create the node that will hold the value data */
	node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree));

	memcpy(node->value, value, tree->sizeof_value);
	node->parent = node->left = node->right = tree->nil;

	/* If tree is empty */
	if (parent->last == NULL) {
		parent->last = tree->root;
	}

	/* Append the node, the hope here is that the caller knows
	what s/he is doing. */
	rbt_tree_add_child(tree, parent, node);
	rbt_balance_tree(tree, node);

	++tree->n_nodes;

#if	defined(IB_RBT_TESTING)
	ut_a(rbt_validate(tree));
#endif
	return(node);
}
Пример #10
0
sync_array_t*
sync_array_create(
/*==============*/
				/* out, own: created wait array */
	ulint	n_cells,	/* in: number of cells in the array
				to create */
	ulint	protection)	/* in: either SYNC_ARRAY_OS_MUTEX or
				SYNC_ARRAY_MUTEX: determines the type
				of mutex protecting the data structure */
{
	sync_array_t*	arr;
	sync_cell_t*	cell_array;
	sync_cell_t*	cell;
	ulint		i;

	ut_a(n_cells > 0);

	/* Allocate memory for the data structures */
	arr = ut_malloc(sizeof(sync_array_t));

	cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells);

	arr->n_cells = n_cells;
	arr->n_reserved = 0;
	arr->array = cell_array;
	arr->protection = protection;
	arr->sg_count = 0;
	arr->res_count = 0;

	/* Then create the mutex to protect the wait array complex */
	if (protection == SYNC_ARRAY_OS_MUTEX) {
		arr->os_mutex = os_mutex_create(NULL);
	} else if (protection == SYNC_ARRAY_MUTEX) {
		mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK);
	} else {
		ut_error;
	}

	for (i = 0; i < n_cells; i++) {
		cell = sync_array_get_nth_cell(arr, i);
	cell->wait_object = NULL;
		cell->waiting = FALSE;
		cell->signal_count = 0;
	}

	return(arr);
}
Пример #11
0
/*********************************************************//**
Creates an operating system mutex semaphore. Because these are slow, the
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
@return	the mutex handle */
UNIV_INTERN
os_mutex_t
os_mutex_create(
/*============*/
	const char*	name)	/*!< in: the name of the mutex, if NULL
				the mutex is created without a name */
{
#ifdef __WIN__
	HANDLE		mutex;
	os_mutex_t	mutex_str;

	mutex = CreateMutex(NULL,	/* No security attributes */
			    FALSE,		/* Initial state: no owner */
			    (LPCTSTR) name);
	ut_a(mutex);
#else
	os_fast_mutex_t*	mutex;
	os_mutex_t		mutex_str;

	UT_NOT_USED(name);

	mutex = ut_malloc(sizeof(os_fast_mutex_t));

	os_fast_mutex_init(mutex);
#endif
	mutex_str = ut_malloc(sizeof(os_mutex_str_t));

	mutex_str->handle = mutex;
	mutex_str->count = 0;
	mutex_str->event = os_event_create(NULL);

	if (UNIV_LIKELY(os_sync_mutex_inited)) {
		/* When creating os_sync_mutex itself we cannot reserve it */
		os_mutex_enter(os_sync_mutex);
	}

	UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);

	os_mutex_count++;

	if (UNIV_LIKELY(os_sync_mutex_inited)) {
		os_mutex_exit(os_sync_mutex);
	}

	return(mutex_str);
}
Пример #12
0
/********************************************************************//**
Creates a memory pool.
@return	memory pool */
UNIV_INTERN
mem_pool_t*
mem_pool_create(
/*============*/
	ulint	size)	/*!< in: pool size in bytes */
{
	mem_pool_t*	pool;
	mem_area_t*	area;
	ulint		i;
	ulint		used;

	pool = ut_malloc(sizeof(mem_pool_t));

	pool->buf = ut_malloc_low(size, TRUE);
	pool->size = size;

	mutex_create(&pool->mutex, SYNC_MEM_POOL);

	/* Initialize the free lists */

	for (i = 0; i < 64; i++) {

		UT_LIST_INIT(pool->free_list[i]);
	}

	used = 0;

	while (size - used >= MEM_AREA_MIN_SIZE) {

		i = ut_2_log(size - used);

		if (ut_2_exp(i) > size - used) {

			/* ut_2_log rounds upward */

			i--;
		}

		area = (mem_area_t*)(pool->buf + used);

		mem_area_set_size(area, ut_2_exp(i));
		mem_area_set_free(area, TRUE);
		UNIV_MEM_FREE(MEM_AREA_EXTRA_SIZE + (byte*) area,
			      ut_2_exp(i) - MEM_AREA_EXTRA_SIZE);

		UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area);

		used = used + ut_2_exp(i);
	}

	ut_ad(size >= used);

	pool->reserved = 0;

	return(pool);
}
Пример #13
0
/**********************************************************************//**
Creates a table memory object.
@return	own: table object */
UNIV_INTERN
dict_table_t*
dict_mem_table_create(
/*==================*/
	const char*	name,	/*!< in: table name */
	ulint		space,	/*!< in: space where the clustered index of
				the table is placed; this parameter is
				ignored if the table is made a member of
				a cluster */
	ulint		n_cols,	/*!< in: number of columns */
	ulint		flags)	/*!< in: table flags */
{
	dict_table_t*	table;
	mem_heap_t*	heap;

	ut_ad(name);
	ut_a(!(flags & (~0 << DICT_TF2_BITS)));

	heap = mem_heap_create(DICT_HEAP_SIZE);

	table = mem_heap_zalloc(heap, sizeof(dict_table_t));

	table->heap = heap;

	table->flags = (unsigned int) flags;
	table->name = ut_malloc(strlen(name) + 1);
	memcpy(table->name, name, strlen(name) + 1);
	table->space = (unsigned int) space;
	table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS);

	table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS)
				     * sizeof(dict_col_t));

#ifndef UNIV_HOTBACKUP
	table->autoinc_lock = mem_heap_alloc(heap, lock_get_size());

	mutex_create(autoinc_mutex_key,
		     &table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);

	table->autoinc = 0;

	/* The number of transactions that are either waiting on the
	AUTOINC lock or have been granted the lock. */
	table->n_waiting_or_granted_auto_inc_locks = 0;

	table->is_corrupt = FALSE;
#endif /* !UNIV_HOTBACKUP */

	ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
	return(table);
}
Пример #14
0
/*******************************************************************//**
Creates a synchronization wait array. It is protected by a mutex
which is automatically reserved when the functions operating on it
are called.
@return	own: created wait array */
UNIV_INTERN
sync_array_t*
sync_array_create(
/*==============*/
	ulint	n_cells,	/*!< in: number of cells in the array
				to create */
	ulint	protection)	/*!< in: either SYNC_ARRAY_OS_MUTEX or
				SYNC_ARRAY_MUTEX: determines the type
				of mutex protecting the data structure */
{
	ulint		sz;
	sync_array_t*	arr;

	ut_a(n_cells > 0);

	/* Allocate memory for the data structures */
	arr = ut_malloc(sizeof(sync_array_t));
	memset(arr, 0x0, sizeof(*arr));

	sz = sizeof(sync_cell_t) * n_cells;
	arr->array = ut_malloc(sz);
	memset(arr->array, 0x0, sz);

	arr->n_cells = n_cells;
	arr->protection = protection;

	/* Then create the mutex to protect the wait array complex */
	if (protection == SYNC_ARRAY_OS_MUTEX) {
		arr->os_mutex = os_mutex_create();
	} else if (protection == SYNC_ARRAY_MUTEX) {
		mutex_create(syn_arr_mutex_key,
			     &arr->mutex, SYNC_NO_ORDER_CHECK);
	} else {
		ut_error;
	}

	return(arr);
}
Пример #15
0
struct place * nc_create_place (void)
{
	struct place * p;
	
	p = ut_malloc (sizeof (struct place));
	ls_insert (&u.net.places, &p->nod);

	p->id = u.net.numpl++;
	al_init (&p->pre);
	al_init (&p->post);
	al_init (&p->cont);
	ls_init (&p->conds);
	p->m = 0;

	return p;
}
Пример #16
0
/**********************************************************************//**
Add a new node to the tree, useful for data that is pre-sorted.
@return	appended node */
UNIV_INTERN
const ib_rbt_node_t*
rbt_add_node(
/*=========*/
	ib_rbt_t*	tree,			/*!< in: rb tree */
	ib_rbt_bound_t*	parent,			/*!< in: bounds */
	const void*	value)			/*!< in: this value is copied
						to the node */
{
	ib_rbt_node_t*	node;

	/* Create the node that will hold the value data */
	node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree));

	memcpy(node->value, value, tree->sizeof_value);
	return(rbt_add_preallocated_node(tree, parent, node));
}
Пример #17
0
struct trans * nc_create_transition (void)
{
	struct trans * t;

	t = ut_malloc (sizeof (struct trans));
	ls_insert (&u.net.trans, &t->nod);

	t->id = ++u.net.numtr;
	al_init (&t->pre);
	al_init (&t->post);
	al_init (&t->cont);
	ls_init (&t->events);
	t->m = 0;
	t->parikhcnt1 = 0;
	t->parikhcnt2 = 0;

	return t;
}
Пример #18
0
void*
os_mem_alloc_nocache(
/*=================*/
			/* out: allocated memory */
	ulint	n)	/* in: number of bytes */
{
#ifdef __WIN__
	void*	ptr;

      	ptr = VirtualAlloc(NULL, n, MEM_COMMIT,
					PAGE_READWRITE | PAGE_NOCACHE);
	ut_a(ptr);

	return(ptr);
#else
	return(ut_malloc(n));
#endif
}
Пример #19
0
hash_table_t*
hash_create(
/*========*/
			/* out, own: created table */
	ulint	n)	/* in: number of array cells */
{
	hash_cell_t*	array;
	ulint		prime;
	hash_table_t*	table;
	ulint		i;
	hash_cell_t*	cell;
	
	prime = ut_find_prime(n);

	table = mem_alloc(sizeof(hash_table_t));

	array = ut_malloc(sizeof(hash_cell_t) * prime);
	
	table->array = array;
	table->n_cells = prime;
	table->n_mutexes = 0;
	table->mutexes = NULL;
	table->heaps = NULL;
	table->heap = NULL;
	table->magic_n = HASH_TABLE_MAGIC_N;
	
	/* Initialize the cell array */

	for (i = 0; i < prime; i++) {

		cell = hash_get_nth_cell(table, i);
		cell->node = NULL;
	}

	return(table);
}
Пример #20
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);
}
Пример #21
0
ibool
os_awe_allocate_physical_mem(
/*=========================*/
				/* out: TRUE if success */
	os_awe_t** page_info,	/* out, own: array of opaque data containing
				the info for allocated physical memory pages;
				each allocated 4 kB physical memory page has
				one slot of type os_awe_t in the array */
	ulint	  n_megabytes)	/* in: number of megabytes to allocate */
{
#ifdef UNIV_SIMULATE_AWE
	os_awe_simulate_page_info = ut_malloc
		(sizeof(os_awe_t) * n_megabytes
		 * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE));

	os_awe_simulate_mem
		= ut_align(ut_malloc(4096 + 1024 * 1024 * n_megabytes), 4096);
	os_awe_simulate_mem_size = n_megabytes * 1024 * 1024;

	*page_info = os_awe_simulate_page_info;

	return(TRUE);

#elif defined(__WIN2000__)
	BOOL		bResult;
	os_awe_t	NumberOfPages;		/* Question: why does Windows
						use the name ULONG_PTR for
						a scalar integer type? Maybe
						because we may also refer to
						&NumberOfPages? */
	os_awe_t	NumberOfPagesInitial;
	SYSTEM_INFO	sSysInfo;
	int		PFNArraySize;

	if (n_megabytes > 64 * 1024) {

		fprintf(stderr,
			"InnoDB: AWE: Error: tried to allocate %lu MB.\n"
			"InnoDB: AWE cannot allocate more than"
			" 64 GB in any computer.\n", n_megabytes);

		return(FALSE);
	}

	GetSystemInfo(&sSysInfo);  /* fill the system information structure */

	if ((ulint)OS_AWE_X86_PAGE_SIZE != (ulint)sSysInfo.dwPageSize) {
		fprintf(stderr,
			"InnoDB: AWE: Error: this computer has a page size"
			" of %lu.\n"
			"InnoDB: Should be 4096 bytes for"
			" InnoDB AWE support to work.\n",
			(ulint)sSysInfo.dwPageSize);

		return(FALSE);
	}

	/* Calculate the number of pages of memory to request */

	NumberOfPages = n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE);

	/* Calculate the size of page_info for allocated physical pages */

	PFNArraySize = NumberOfPages * sizeof(os_awe_t);

	*page_info = (os_awe_t*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize);

	if (*page_info == NULL) {
		fprintf(stderr,
			"InnoDB: AWE: Failed to allocate page info"
			" array from process heap, error %lu\n",
			(ulint)GetLastError());

		return(FALSE);
	}

	ut_total_allocated_memory += PFNArraySize;

	/* Enable this process' privilege to lock pages to physical memory */

	if (!os_awe_enable_lock_pages_in_mem()) {

		return(FALSE);
	}

	/* Allocate the physical memory */

	NumberOfPagesInitial = NumberOfPages;

	os_awe_page_info = *page_info;
	os_awe_n_pages = (ulint)NumberOfPages;

	/* Compilation note: if the compiler complains the function is not
	defined, see the note at the start of this file */

	bResult = AllocateUserPhysicalPages(GetCurrentProcess(),
					    &NumberOfPages, *page_info);
	if (bResult != TRUE) {
		fprintf(stderr,
			"InnoDB: AWE: Cannot allocate physical pages,"
			" error %lu.\n",
			(ulint)GetLastError());

		return(FALSE);
	}

	if (NumberOfPagesInitial != NumberOfPages) {
		fprintf(stderr,
			"InnoDB: AWE: Error: allocated only %lu pages"
			" of %lu requested.\n"
			"InnoDB: Check that you have enough free RAM.\n"
			"InnoDB: In Windows XP Professional and"
			" 2000 Professional\n"
			"InnoDB: Windows PAE size is max 4 GB."
			" In 2000 and .NET\n"
			"InnoDB: Advanced Servers and 2000 Datacenter Server"
			" it is 32 GB,\n"
			"InnoDB: and in .NET Datacenter Server it is 64 GB.\n"
			"InnoDB: A Microsoft web page said that"
			" the processor must be an Intel\n"
			"InnoDB: processor.\n",
			(ulint)NumberOfPages,
			(ulint)NumberOfPagesInitial);

		return(FALSE);
	}

	fprintf(stderr,
		"InnoDB: Using Address Windowing Extensions (AWE);"
		" allocated %lu MB\n",
		n_megabytes);

	return(TRUE);
#else
	UT_NOT_USED(n_megabytes);
	UT_NOT_USED(page_info);

	return(FALSE);
#endif
}
Пример #22
0
/*********************************************************//**
Creates an event semaphore, i.e., a semaphore which may just have two
states: signaled and nonsignaled. The created event is manual reset: it
must be reset explicitly by calling sync_os_reset_event.
@return	the event handle */
UNIV_INTERN
os_event_t
os_event_create(
/*============*/
	const char*	name)	/*!< in: the name of the event, if NULL
				the event is created without a name */
{
#ifdef __WIN__
	os_event_t event;

	event = ut_malloc(sizeof(struct os_event_struct));

	event->handle = CreateEvent(NULL, /* No security attributes */
				    TRUE, /* Manual reset */
				    FALSE, /* Initial state nonsignaled */
				    (LPCTSTR) name);
	if (!event->handle) {
		fprintf(stderr,
			"InnoDB: Could not create a Windows event semaphore;"
			" Windows error %lu\n",
			(ulong) GetLastError());
	}
#else /* Unix */
	os_event_t	event;

	UT_NOT_USED(name);

	event = ut_malloc(sizeof(struct os_event_struct));

	os_fast_mutex_init(&(event->os_mutex));

	ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));

	event->is_set = FALSE;

	/* We return this value in os_event_reset(), which can then be
	be used to pass to the os_event_wait_low(). The value of zero
	is reserved in os_event_wait_low() for the case when the
	caller does not want to pass any signal_count value. To
	distinguish between the two cases we initialize signal_count
	to 1 here. */
	event->signal_count = 1;
#endif /* __WIN__ */

	/* The os_sync_mutex can be NULL because during startup an event
	can be created [ because it's embedded in the mutex/rwlock ] before
	this module has been initialized */
	if (os_sync_mutex != NULL) {
		os_mutex_enter(os_sync_mutex);
	}

	/* Put to the list of events */
	UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);

	os_event_count++;

	if (os_sync_mutex != NULL) {
		os_mutex_exit(os_sync_mutex);
	}

	return(event);
}
Пример #23
0
/********************************************************************//**
Allocates memory from a pool. NOTE: This low-level function should only be
used in mem0mem.*!
@return	own: allocated memory buffer */
UNIV_INTERN
void*
mem_area_alloc(
/*===========*/
	ulint*		psize,	/*!< in: requested size in bytes; for optimum
				space usage, the size should be a power of 2
				minus MEM_AREA_EXTRA_SIZE;
				out: allocated size in bytes (greater than
				or equal to the requested size) */
	mem_pool_t*	pool)	/*!< in: memory pool */
{
	mem_area_t*	area;
	ulint		size;
	ulint		n;
	ibool		ret;

	/* If we are using os allocator just make a simple call
	to malloc */
	if (UNIV_LIKELY(srv_use_sys_malloc)) {
		return(malloc(*psize));
	}

	size = *psize;
	n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE));

	mutex_enter(&(pool->mutex));
	mem_n_threads_inside++;

	ut_a(mem_n_threads_inside == 1);

	area = UT_LIST_GET_FIRST(pool->free_list[n]);

	if (area == NULL) {
		ret = mem_pool_fill_free_list(n, pool);

		if (ret == FALSE) {
			/* Out of memory in memory pool: we try to allocate
			from the operating system with the regular malloc: */

			mem_n_threads_inside--;
			mutex_exit(&(pool->mutex));

			return(ut_malloc(size));
		}

		area = UT_LIST_GET_FIRST(pool->free_list[n]);
	}

	if (!mem_area_get_free(area)) {
		fprintf(stderr,
			"InnoDB: Error: Removing element from mem pool"
			" free list %lu though the\n"
			"InnoDB: element is not marked free!\n",
			(ulong) n);

		mem_analyze_corruption(area);

		/* Try to analyze a strange assertion failure reported at
		[email protected] where the free bit IS 1 in the
		hex dump above */

		if (mem_area_get_free(area)) {
			fprintf(stderr,
				"InnoDB: Probably a race condition"
				" because now the area is marked free!\n");
		}

		ut_error;
	}

	if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) {
		fprintf(stderr,
			"InnoDB: Error: Removing element from mem pool"
			" free list %lu\n"
			"InnoDB: though the list length is 0!\n",
			(ulong) n);
		mem_analyze_corruption(area);

		ut_error;
	}

	ut_ad(mem_area_get_size(area) == ut_2_exp(n));

	mem_area_set_free(area, FALSE);

	UT_LIST_REMOVE(free_list, pool->free_list[n], area);

	pool->reserved += mem_area_get_size(area);

	mem_n_threads_inside--;
	mutex_exit(&(pool->mutex));

	ut_ad(mem_pool_validate(pool));

	*psize = ut_2_exp(n) - MEM_AREA_EXTRA_SIZE;
	UNIV_MEM_ALLOC(MEM_AREA_EXTRA_SIZE + (byte*)area, *psize);

	return((void*)(MEM_AREA_EXTRA_SIZE + ((byte*)area)));
}
Пример #24
0
/**********************************************************************
When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page
hash index entries belonging to that table. This function tries to
do that in batch. Note that this is a 'best effort' attempt and does
not guarantee that ALL hash entries will be removed. */
static
void
buf_LRU_drop_page_hash_for_tablespace(
/*==================================*/
	ulint	id)	/* in: space id */
{
	buf_block_t*	block;
	ulint*		page_arr;
	ulint		num_entries;

	page_arr = ut_malloc(sizeof(ulint)
			     * BUF_LRU_DROP_SEARCH_HASH_SIZE);
	mutex_enter(&buf_pool->mutex);

scan_again:
	num_entries = 0;
	block = UT_LIST_GET_LAST(buf_pool->LRU);

	while (block != NULL) {
		buf_block_t*	prev_block;

		mutex_enter(&block->mutex);
		prev_block = UT_LIST_GET_PREV(LRU, block);

		ut_a(block->state == BUF_BLOCK_FILE_PAGE);

		if (block->space != id
		    || block->buf_fix_count > 0
		    || block->io_fix != 0) {
			/* We leave the fixed pages as is in this scan.
			To be dealt with later in the final scan. */
			mutex_exit(&block->mutex);
			goto next_page;
		}

		ut_ad(block->space == id);
		if (block->is_hashed) {

			/* Store the offset(i.e.: page_no) in the array
			so that we can drop hash index in a batch
			later. */
			page_arr[num_entries] = block->offset;
			mutex_exit(&block->mutex);
			ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
			++num_entries;

			if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
				goto next_page;
			}
			/* Array full. We release the buf_pool->mutex to
			obey the latching order. */
			mutex_exit(&buf_pool->mutex);

			buf_LRU_drop_page_hash_batch(id, page_arr,
						     num_entries);
			num_entries = 0;
			mutex_enter(&buf_pool->mutex);
		} else {
			mutex_exit(&block->mutex);
		}

next_page:
		/* Note that we may have released the buf_pool->mutex
		above after reading the prev_block during processing
		of a page_hash_batch (i.e.: when the array was full).
		This means that prev_block can change in LRU list.
		This is OK because this function is a 'best effort'
		to drop as many search hash entries as possible and
		it does not guarantee that ALL such entries will be
		dropped. */
		block = prev_block;

		/* If, however, block has been removed from LRU list
		to the free list then we should restart the scan.
		block->state is protected by buf_pool->mutex. */
		if (block && block->state != BUF_BLOCK_FILE_PAGE) {
			ut_a(num_entries == 0);
			goto scan_again;
		}
	}

	mutex_exit(&buf_pool->mutex);

	/* Drop any remaining batch of search hashed pages. */
	buf_LRU_drop_page_hash_batch(id, page_arr, num_entries);
	ut_free(page_arr);
}
Пример #25
0
ibool
srv_parse_data_file_paths_and_sizes(
/*================================*/
					/* out: TRUE if ok, FALSE if parsing
					error */
	char*	str,			/* in: the data file path string */
	char***	data_file_names,	/* out, own: array of data file
					names */
	ulint**	data_file_sizes,	/* out, own: array of data file sizes
					in megabytes */
	ulint**	data_file_is_raw_partition,/* out, own: array of flags
					showing which data files are raw
					partitions */
	ulint*	n_data_files,		/* out: number of data files */
	ibool*	is_auto_extending,	/* out: TRUE if the last data file is
					auto-extending */
	ulint*	max_auto_extend_size)	/* out: max auto extend size for the
					last file if specified, 0 if not */
{
	char*	input_str;
	char*	endp;
	char*	path;
	ulint	size;
	ulint	i	= 0;

	*is_auto_extending = FALSE;
	*max_auto_extend_size = 0;

	input_str = str;
	
	/* First calculate the number of data files and check syntax:
	path:size[M | G];path:size[M | G]... . Note that a Windows path may
	contain a drive name and a ':'. */

	while (*str != '\0') {
		path = str;

		while ((*str != ':' && *str != '\0')
		       || (*str == ':'
			   && (*(str + 1) == '\\' || *(str + 1) == '/'))) {
			str++;
		}

		if (*str == '\0') {
			return(FALSE);
		}

		str++;

		size = strtoul(str, &endp, 10);

		str = endp;

		if (*str != 'M' && *str != 'G') {
			size = size / (1024 * 1024);
		} else if (*str == 'G') {
		        size = size * 1024;
			str++;
		} else {
		        str++;
		}

	        if (strlen(str) >= ut_strlen(":autoextend")
	            && 0 == ut_memcmp(str, (char*)":autoextend",
						ut_strlen(":autoextend"))) {

			str += ut_strlen(":autoextend");

	        	if (strlen(str) >= ut_strlen(":max:")
	            		&& 0 == ut_memcmp(str, (char*)":max:",
						ut_strlen(":max:"))) {

				str += ut_strlen(":max:");

				size = strtoul(str, &endp, 10);

				str = endp;

				if (*str != 'M' && *str != 'G') {
					size = size / (1024 * 1024);
				} else if (*str == 'G') {
		        		size = size * 1024;
					str++;
				} else {
		        		str++;
				}
			}

			if (*str != '\0') {

				return(FALSE);
			}
		}

	        if (strlen(str) >= 6
			   && *str == 'n'
			   && *(str + 1) == 'e' 
		           && *(str + 2) == 'w') {
		  	str += 3;
		}

	        if (strlen(str) >= 3
			   && *str == 'r'
			   && *(str + 1) == 'a' 
		           && *(str + 2) == 'w') {
		  	str += 3;
		}

		if (size == 0) {
			return(FALSE);
		}

		i++;

		if (*str == ';') {
			str++;
		} else if (*str != '\0') {

			return(FALSE);
		}
	}

	*data_file_names = (char**)ut_malloc(i * sizeof(void*));
	*data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint));
	*data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint));

	*n_data_files = i;

	/* Then store the actual values to our arrays */

	str = input_str;
	i = 0;

	while (*str != '\0') {
		path = str;

		/* Note that we must ignore the ':' in a Windows path */

		while ((*str != ':' && *str != '\0')
		       || (*str == ':'
			   && (*(str + 1) == '\\' || *(str + 1) == '/'))) {
			str++;
		}

		if (*str == ':') {
			/* Make path a null-terminated string */
			*str = '\0';
			str++;
		}

		size = strtoul(str, &endp, 10);

		str = endp;

		if ((*str != 'M') && (*str != 'G')) {
			size = size / (1024 * 1024);
		} else if (*str == 'G') {
		        size = size * 1024;
			str++;
		} else {
		        str++;
		}

		(*data_file_names)[i] = path;
		(*data_file_sizes)[i] = size;

	        if (strlen(str) >= ut_strlen(":autoextend")
	            && 0 == ut_memcmp(str, (char*)":autoextend",
						ut_strlen(":autoextend"))) {

			*is_auto_extending = TRUE;

			str += ut_strlen(":autoextend");

	        	if (strlen(str) >= ut_strlen(":max:")
	            		&& 0 == ut_memcmp(str, (char*)":max:",
						ut_strlen(":max:"))) {

				str += ut_strlen(":max:");

				size = strtoul(str, &endp, 10);

				str = endp;

				if (*str != 'M' && *str != 'G') {
					size = size / (1024 * 1024);
				} else if (*str == 'G') {
		        		size = size * 1024;
					str++;
				} else {
		        		str++;
				}

				*max_auto_extend_size = size;
			}

			if (*str != '\0') {

				return(FALSE);
			}
		}
		
		(*data_file_is_raw_partition)[i] = 0;

	        if (strlen(str) >= 6
			   && *str == 'n'
			   && *(str + 1) == 'e' 
		           && *(str + 2) == 'w') {
		  	str += 3;
		  	(*data_file_is_raw_partition)[i] = SRV_NEW_RAW;
		}

	        if (strlen(str) >= 3
			   && *str == 'r'
			   && *(str + 1) == 'a' 
		           && *(str + 2) == 'w') {
		 	str += 3;
		  
		  	if ((*data_file_is_raw_partition)[i] == 0) {
		    		(*data_file_is_raw_partition)[i] = SRV_OLD_RAW;
		  	}		  
		}

		i++;

		if (*str == ';') {
			str++;
		}
	}

	return(TRUE);
}
Пример #26
0
  mem_area_t *area,
  ibool free)
{
  area->size_and_free = (area->size_and_free & ~MEM_AREA_FREE) | free;
}

mem_pool_t*
mem_pool_create(
  ulint size)
{
  mem_pool_t* pool;
  mem_area_t* area;
  ulint i;
  ulint used;
  pool = ut_maloc(sizeof(mem_pool_t));
  pool_buf = ut_malloc(size);
  pool_size = size;
  
  mutex_create(&(pool->mutex));
  mutex_set_level(&(pool->mutex), SYNC_MEM_POOL);
  
  for(i = 0; i < 64; i++) {
    UT_LIST_INIT(pool->free_list[i]);
  }
  used = 0;
  while(size - used >= MEM_AREA_MIN_SIZE) {
    i = ut_2_log(size - used);
    if (ut_2_exp(i) > size - used) {
      i--;
    }
    
Пример #27
0
mem_pool_t*
mem_pool_create(
/*============*/
			/* out: memory pool */
	ulint	size)	/* in: pool size in bytes */
{
	mem_pool_t*	pool;
	mem_area_t*	area;
	ulint		i;
	ulint		used;

	ut_a(size > 10000);

	pool = ut_malloc(sizeof(mem_pool_t));

	/* We do not set the memory to zero (FALSE) in the pool,
	but only when allocated at a higher level in mem0mem.c.
	This is to avoid masking useful Purify warnings. */

	pool->buf = ut_malloc_low(size, FALSE, TRUE);
	pool->size = size;

	mutex_create(&pool->mutex, SYNC_MEM_POOL);

	/* Initialize the free lists */

	for (i = 0; i < 64; i++) {

		UT_LIST_INIT(pool->free_list[i]);
	}

	used = 0;

	while (size - used >= MEM_AREA_MIN_SIZE) {

		i = ut_2_log(size - used);

		if (ut_2_exp(i) > size - used) {

			/* ut_2_log rounds upward */

			i--;
		}

		area = (mem_area_t*)(pool->buf + used);

		mem_area_set_size(area, ut_2_exp(i));
		mem_area_set_free(area, TRUE);
		UNIV_MEM_FREE(MEM_AREA_EXTRA_SIZE + (byte*) area,
			      ut_2_exp(i) - MEM_AREA_EXTRA_SIZE);

		UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area);

		used = used + ut_2_exp(i);
	}

	ut_ad(size >= used);

	pool->reserved = 0;

	return(pool);
}
Пример #28
0
ibool
srv_parse_data_file_paths_and_sizes(
/*================================*/
					/* out: TRUE if ok, FALSE if parsing
					error */
	char*	str,			/* in: the data file path string */
	char***	data_file_names,	/* out, own: array of data file
					names */
	ulint**	data_file_sizes,	/* out, own: array of data file sizes
					in megabytes */
	ulint**	data_file_is_raw_partition,/* out, own: array of flags
					showing which data files are raw
					partitions */
	ulint*	n_data_files,		/* out: number of data files */
	ibool*	is_auto_extending,	/* out: TRUE if the last data file is
					auto-extending */
	ulint*	max_auto_extend_size)	/* out: max auto extend size for the
					last file if specified, 0 if not */
{
	char*	input_str;
	char*	path;
	ulint	size;
	ulint	i	= 0;

	*is_auto_extending = FALSE;
	*max_auto_extend_size = 0;

	input_str = str;

	/* First calculate the number of data files and check syntax:
	path:size[M | G];path:size[M | G]... . Note that a Windows path may
	contain a drive name and a ':'. */

	while (*str != '\0') {
		path = str;

		while ((*str != ':' && *str != '\0')
		       || (*str == ':'
			   && (*(str + 1) == '\\' || *(str + 1) == '/'
			       || *(str + 1) == ':'))) {
			str++;
		}

		if (*str == '\0') {
			return(FALSE);
		}

		str++;

		str = srv_parse_megabytes(str, &size);

		if (0 == strncmp(str, ":autoextend",
				 (sizeof ":autoextend") - 1)) {

			str += (sizeof ":autoextend") - 1;

			if (0 == strncmp(str, ":max:",
					 (sizeof ":max:") - 1)) {

				str += (sizeof ":max:") - 1;

				str = srv_parse_megabytes(str, &size);
			}

			if (*str != '\0') {

				return(FALSE);
			}
		}

		if (strlen(str) >= 6
		    && *str == 'n'
		    && *(str + 1) == 'e'
		    && *(str + 2) == 'w') {
			str += 3;
		}

		if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
			str += 3;
		}

		if (size == 0) {
			return(FALSE);
		}

		i++;

		if (*str == ';') {
			str++;
		} else if (*str != '\0') {

			return(FALSE);
		}
	}

	if (i == 0) {
		/* If innodb_data_file_path was defined it must contain
		at least one data file definition */

		return(FALSE);
	}

	*data_file_names = (char**)ut_malloc(i * sizeof(void*));
	*data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint));
	*data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint));

	*n_data_files = i;

	/* Then store the actual values to our arrays */

	str = input_str;
	i = 0;

	while (*str != '\0') {
		path = str;

		/* Note that we must step over the ':' in a Windows path;
		a Windows path normally looks like C:\ibdata\ibdata1:1G, but
		a Windows raw partition may have a specification like
		\\.\C::1Gnewraw or \\.\PHYSICALDRIVE2:1Gnewraw */

		while ((*str != ':' && *str != '\0')
		       || (*str == ':'
			   && (*(str + 1) == '\\' || *(str + 1) == '/'
			       || *(str + 1) == ':'))) {
			str++;
		}

		if (*str == ':') {
			/* Make path a null-terminated string */
			*str = '\0';
			str++;
		}

		str = srv_parse_megabytes(str, &size);

		(*data_file_names)[i] = path;
		(*data_file_sizes)[i] = size;

		if (0 == strncmp(str, ":autoextend",
				 (sizeof ":autoextend") - 1)) {

			*is_auto_extending = TRUE;

			str += (sizeof ":autoextend") - 1;

			if (0 == strncmp(str, ":max:",
					 (sizeof ":max:") - 1)) {

				str += (sizeof ":max:") - 1;

				str = srv_parse_megabytes(
					str, max_auto_extend_size);
			}

			if (*str != '\0') {

				return(FALSE);
			}
		}

		(*data_file_is_raw_partition)[i] = 0;

		if (strlen(str) >= 6
		    && *str == 'n'
		    && *(str + 1) == 'e'
		    && *(str + 2) == 'w') {
			str += 3;
			(*data_file_is_raw_partition)[i] = SRV_NEW_RAW;
		}

		if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
			str += 3;

			if ((*data_file_is_raw_partition)[i] == 0) {
				(*data_file_is_raw_partition)[i] = SRV_OLD_RAW;
			}
		}

		i++;

		if (*str == ';') {
			str++;
		}
	}

	return(TRUE);
}