mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
2c4fa340cc
Fixed bugs in my last changeset that made MySQL hard to compile. Added mutex around some data that could cause table cache corruptions when using OPTIMIZE TABLE / REPAIR TABLE or automatic repair of MyISAM tables. Added mutex around some data in the slave start/stop code that could cause THD linked list corruptions Extended my_chsize() to allow one to specify a filler character. Extend vio_blocking to return the old state (This made some usage of this function much simpler) Added testing for some functions that they caller have got the required mutexes before calling the function. Use setrlimit() to ensure that we can write core file if one specifies --core-file. Added --slave-compressed-protocol Made 2 the minimum length for ft_min_word_len Added variables foreign_key_checks & unique_checks. Less logging from replication code (if not started with --log-warnings) Changed that SHOW INNODB STATUS requre the SUPER privilege More DBUG statements and a lot of new code comments
347 lines
7.3 KiB
Text
347 lines
7.3 KiB
Text
/******************************************************
|
|
The dynamically allocated array
|
|
|
|
(c) 1996 Innobase Oy
|
|
|
|
Created 2/5/1996 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#define DYN_BLOCK_MAGIC_N 375767
|
|
#define DYN_BLOCK_FULL_FLAG 0x1000000
|
|
|
|
/****************************************************************
|
|
Adds a new block to a dyn array. */
|
|
|
|
dyn_block_t*
|
|
dyn_array_add_block(
|
|
/*================*/
|
|
/* out: created block */
|
|
dyn_array_t* arr); /* in: dyn array */
|
|
|
|
|
|
/****************************************************************
|
|
Gets the first block in a dyn array. */
|
|
UNIV_INLINE
|
|
dyn_block_t*
|
|
dyn_array_get_first_block(
|
|
/*======================*/
|
|
dyn_array_t* arr) /* in: dyn array */
|
|
{
|
|
return(arr);
|
|
}
|
|
|
|
/****************************************************************
|
|
Gets the last block in a dyn array. */
|
|
UNIV_INLINE
|
|
dyn_block_t*
|
|
dyn_array_get_last_block(
|
|
/*=====================*/
|
|
dyn_array_t* arr) /* in: dyn array */
|
|
{
|
|
if (arr->heap == NULL) {
|
|
|
|
return(arr);
|
|
}
|
|
|
|
return(UT_LIST_GET_LAST(arr->base));
|
|
}
|
|
|
|
/************************************************************************
|
|
Gets the next block in a dyn array. */
|
|
UNIV_INLINE
|
|
dyn_block_t*
|
|
dyn_array_get_next_block(
|
|
/*=====================*/
|
|
/* out: pointer to next, NULL if end of list */
|
|
dyn_array_t* arr, /* in: dyn array */
|
|
dyn_block_t* block) /* in: dyn array block */
|
|
{
|
|
ut_ad(arr && block);
|
|
|
|
if (arr->heap == NULL) {
|
|
ut_ad(arr == block);
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
return(UT_LIST_GET_NEXT(list, block));
|
|
}
|
|
|
|
/************************************************************************
|
|
Gets the number of used bytes in a dyn array block. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dyn_block_get_used(
|
|
/*===============*/
|
|
/* out: number of bytes used */
|
|
dyn_block_t* block) /* in: dyn array block */
|
|
{
|
|
ut_ad(block);
|
|
|
|
return((block->used) & ~DYN_BLOCK_FULL_FLAG);
|
|
}
|
|
|
|
/************************************************************************
|
|
Gets pointer to the start of data in a dyn array block. */
|
|
UNIV_INLINE
|
|
byte*
|
|
dyn_block_get_data(
|
|
/*===============*/
|
|
/* out: pointer to data */
|
|
dyn_block_t* block) /* in: dyn array block */
|
|
{
|
|
ut_ad(block);
|
|
|
|
return(block->data);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Initializes a dynamic array. */
|
|
UNIV_INLINE
|
|
dyn_array_t*
|
|
dyn_array_create(
|
|
/*=============*/
|
|
/* out: initialized dyn array */
|
|
dyn_array_t* arr) /* in: pointer to a memory buffer of
|
|
size sizeof(dyn_array_t) */
|
|
{
|
|
ut_ad(arr);
|
|
ut_ad(DYN_ARRAY_DATA_SIZE < DYN_BLOCK_FULL_FLAG);
|
|
|
|
arr->heap = NULL;
|
|
arr->used = 0;
|
|
|
|
#ifdef UNIV_DEBUG
|
|
arr->buf_end = 0;
|
|
arr->magic_n = DYN_BLOCK_MAGIC_N;
|
|
#endif
|
|
return(arr);
|
|
}
|
|
|
|
/****************************************************************
|
|
Frees a dynamic array. */
|
|
UNIV_INLINE
|
|
void
|
|
dyn_array_free(
|
|
/*===========*/
|
|
dyn_array_t* arr) /* in: dyn array */
|
|
{
|
|
if (arr->heap != NULL) {
|
|
mem_heap_free(arr->heap);
|
|
}
|
|
|
|
#ifdef UNIV_DEBUG
|
|
arr->magic_n = 0;
|
|
#endif
|
|
}
|
|
|
|
/*************************************************************************
|
|
Makes room on top of a dyn array and returns a pointer to the added element.
|
|
The caller must copy the element to the pointer returned. */
|
|
UNIV_INLINE
|
|
void*
|
|
dyn_array_push(
|
|
/*===========*/
|
|
/* out: pointer to the element */
|
|
dyn_array_t* arr, /* in: dynamic array */
|
|
ulint size) /* in: size in bytes of the element */
|
|
{
|
|
dyn_block_t* block;
|
|
ulint used;
|
|
|
|
ut_ad(arr);
|
|
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
|
ut_ad(size <= DYN_ARRAY_DATA_SIZE);
|
|
ut_ad(size);
|
|
|
|
block = arr;
|
|
used = block->used;
|
|
|
|
if (used + size > DYN_ARRAY_DATA_SIZE) {
|
|
/* Get the last array block */
|
|
|
|
block = dyn_array_get_last_block(arr);
|
|
used = block->used;
|
|
|
|
if (used + size > DYN_ARRAY_DATA_SIZE) {
|
|
block = dyn_array_add_block(arr);
|
|
used = block->used;
|
|
}
|
|
}
|
|
|
|
block->used = used + size;
|
|
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
|
|
|
|
return((block->data) + used);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Makes room on top of a dyn array and returns a pointer to a buffer in it.
|
|
After copying the elements, the caller must close the buffer using
|
|
dyn_array_close. */
|
|
UNIV_INLINE
|
|
byte*
|
|
dyn_array_open(
|
|
/*===========*/
|
|
/* out: pointer to the buffer */
|
|
dyn_array_t* arr, /* in: dynamic array */
|
|
ulint size) /* in: size in bytes of the buffer; MUST be
|
|
smaller than DYN_ARRAY_DATA_SIZE! */
|
|
{
|
|
dyn_block_t* block;
|
|
ulint used;
|
|
|
|
ut_ad(arr);
|
|
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
|
ut_ad(size <= DYN_ARRAY_DATA_SIZE);
|
|
ut_ad(size);
|
|
|
|
block = arr;
|
|
used = block->used;
|
|
|
|
if (used + size > DYN_ARRAY_DATA_SIZE) {
|
|
/* Get the last array block */
|
|
|
|
block = dyn_array_get_last_block(arr);
|
|
used = block->used;
|
|
|
|
if (used + size > DYN_ARRAY_DATA_SIZE) {
|
|
block = dyn_array_add_block(arr);
|
|
used = block->used;
|
|
ut_a(size <= DYN_ARRAY_DATA_SIZE);
|
|
}
|
|
}
|
|
|
|
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
|
|
#ifdef UNIV_DEBUG
|
|
ut_ad(arr->buf_end == 0);
|
|
|
|
arr->buf_end = used + size;
|
|
#endif
|
|
return((block->data) + used);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Closes the buffer returned by dyn_array_open. */
|
|
UNIV_INLINE
|
|
void
|
|
dyn_array_close(
|
|
/*============*/
|
|
dyn_array_t* arr, /* in: dynamic array */
|
|
byte* ptr) /* in: buffer space from ptr up was not used */
|
|
{
|
|
dyn_block_t* block;
|
|
|
|
ut_ad(arr);
|
|
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
|
|
|
block = dyn_array_get_last_block(arr);
|
|
|
|
ut_ad(arr->buf_end + block->data >= ptr);
|
|
|
|
block->used = ptr - block->data;
|
|
|
|
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
|
|
|
|
#ifdef UNIV_DEBUG
|
|
arr->buf_end = 0;
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************
|
|
Returns pointer to an element in dyn array. */
|
|
UNIV_INLINE
|
|
void*
|
|
dyn_array_get_element(
|
|
/*==================*/
|
|
/* out: pointer to element */
|
|
dyn_array_t* arr, /* in: dyn array */
|
|
ulint pos) /* in: position of element as bytes
|
|
from array start */
|
|
{
|
|
dyn_block_t* block;
|
|
ulint used;
|
|
|
|
ut_ad(arr);
|
|
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
|
|
|
/* Get the first array block */
|
|
block = dyn_array_get_first_block(arr);
|
|
|
|
if (arr->heap != NULL) {
|
|
used = dyn_block_get_used(block);
|
|
|
|
while (pos >= used) {
|
|
pos -= used;
|
|
block = UT_LIST_GET_NEXT(list, block);
|
|
ut_ad(block);
|
|
|
|
used = dyn_block_get_used(block);
|
|
}
|
|
}
|
|
|
|
ut_ad(block);
|
|
ut_ad(dyn_block_get_used(block) >= pos);
|
|
|
|
return(block->data + pos);
|
|
}
|
|
|
|
/****************************************************************
|
|
Returns the size of stored data in a dyn array. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dyn_array_get_data_size(
|
|
/*====================*/
|
|
/* out: data size in bytes */
|
|
dyn_array_t* arr) /* in: dyn array */
|
|
{
|
|
dyn_block_t* block;
|
|
ulint sum = 0;
|
|
|
|
ut_ad(arr);
|
|
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
|
|
|
if (arr->heap == NULL) {
|
|
|
|
return(arr->used);
|
|
}
|
|
|
|
/* Get the first array block */
|
|
block = dyn_array_get_first_block(arr);
|
|
|
|
while (block != NULL) {
|
|
sum += dyn_block_get_used(block);
|
|
block = dyn_array_get_next_block(arr, block);
|
|
}
|
|
|
|
return(sum);
|
|
}
|
|
|
|
/************************************************************
|
|
Pushes n bytes to a dyn array. */
|
|
UNIV_INLINE
|
|
void
|
|
dyn_push_string(
|
|
/*============*/
|
|
dyn_array_t* arr, /* in: dyn array */
|
|
byte* str, /* in: string to write */
|
|
ulint len) /* in: string length */
|
|
{
|
|
byte* ptr;
|
|
ulint n_copied;
|
|
|
|
while (len > 0) {
|
|
if (len > DYN_ARRAY_DATA_SIZE) {
|
|
n_copied = DYN_ARRAY_DATA_SIZE;
|
|
} else {
|
|
n_copied = len;
|
|
}
|
|
|
|
ptr = (byte*) dyn_array_push(arr, n_copied);
|
|
|
|
ut_memcpy(ptr, str, n_copied);
|
|
|
|
str += n_copied;
|
|
len -= n_copied;
|
|
}
|
|
}
|