diff options
author | Satya B <satya.bn@sun.com> | 2009-05-27 15:15:59 +0530 |
---|---|---|
committer | Satya B <satya.bn@sun.com> | 2009-05-27 15:15:59 +0530 |
commit | 3945d5e5549187a18c64a112899f90a7f6a320d6 (patch) | |
tree | 1857c73fc15e12543e009c30aeac2d2463f284fb /storage/innodb_plugin/ut | |
parent | 74a495cc81e5cebd56b99acf090b9d5436866b7e (diff) | |
download | mariadb-git-3945d5e5549187a18c64a112899f90a7f6a320d6.tar.gz |
Adding innodb_plugin-1.0.4 as storage/innodb_plugin.
Diffstat (limited to 'storage/innodb_plugin/ut')
-rw-r--r-- | storage/innodb_plugin/ut/ut0auxconf_atomic_pthread_t_gcc.c | 43 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0auxconf_atomic_pthread_t_solaris.c | 34 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0auxconf_have_solaris_atomics.c | 39 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0auxconf_sizeof_pthread_t.c | 35 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0byte.c | 55 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0dbg.c | 187 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0list.c | 194 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0mem.c | 706 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0rnd.c | 97 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0ut.c | 598 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0vec.c | 79 | ||||
-rw-r--r-- | storage/innodb_plugin/ut/ut0wqueue.c | 118 |
12 files changed, 2185 insertions, 0 deletions
diff --git a/storage/innodb_plugin/ut/ut0auxconf_atomic_pthread_t_gcc.c b/storage/innodb_plugin/ut/ut0auxconf_atomic_pthread_t_gcc.c new file mode 100644 index 00000000000..30de5aa6f17 --- /dev/null +++ b/storage/innodb_plugin/ut/ut0auxconf_atomic_pthread_t_gcc.c @@ -0,0 +1,43 @@ +/***************************************************************************** + +Copyright (c) 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/***************************************************************************** +If this program compiles, then pthread_t objects can be used as arguments +to GCC atomic builtin functions. + +Created March 5, 2009 Vasil Dimov +*****************************************************************************/ + +#include <pthread.h> +#include <string.h> + +int +main(int argc, char** argv) +{ + pthread_t x1; + pthread_t x2; + pthread_t x3; + + memset(&x1, 0x0, sizeof(x1)); + memset(&x2, 0x0, sizeof(x2)); + memset(&x3, 0x0, sizeof(x3)); + + __sync_bool_compare_and_swap(&x1, x2, x3); + + return(0); +} diff --git a/storage/innodb_plugin/ut/ut0auxconf_atomic_pthread_t_solaris.c b/storage/innodb_plugin/ut/ut0auxconf_atomic_pthread_t_solaris.c new file mode 100644 index 00000000000..a18a537d1d4 --- /dev/null +++ b/storage/innodb_plugin/ut/ut0auxconf_atomic_pthread_t_solaris.c @@ -0,0 +1,34 @@ +/***************************************************************************** + +Copyright (c) 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/***************************************************************************** +If this program compiles, then pthread_t objects can be used as arguments +to Solaris libc atomic functions. + +Created April 18, 2009 Vasil Dimov +*****************************************************************************/ + +#include <pthread.h> + +int +main(int argc, char** argv) +{ + pthread_t x = 0; + + return(0); +} diff --git a/storage/innodb_plugin/ut/ut0auxconf_have_solaris_atomics.c b/storage/innodb_plugin/ut/ut0auxconf_have_solaris_atomics.c new file mode 100644 index 00000000000..7eb704edd4b --- /dev/null +++ b/storage/innodb_plugin/ut/ut0auxconf_have_solaris_atomics.c @@ -0,0 +1,39 @@ +/***************************************************************************** + +Copyright (c) 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/***************************************************************************** +If this program compiles, then Solaris libc atomic funcions are available. + +Created April 18, 2009 Vasil Dimov +*****************************************************************************/ +#include <atomic.h> + +int +main(int argc, char** argv) +{ + ulong_t ulong = 0; + uint32_t uint32 = 0; + uint64_t uint64 = 0; + + atomic_cas_ulong(&ulong, 0, 1); + atomic_cas_32(&uint32, 0, 1); + atomic_cas_64(&uint64, 0, 1); + atomic_add_long(&ulong, 0); + + return(0); +} diff --git a/storage/innodb_plugin/ut/ut0auxconf_sizeof_pthread_t.c b/storage/innodb_plugin/ut/ut0auxconf_sizeof_pthread_t.c new file mode 100644 index 00000000000..96add4526ef --- /dev/null +++ b/storage/innodb_plugin/ut/ut0auxconf_sizeof_pthread_t.c @@ -0,0 +1,35 @@ +/***************************************************************************** + +Copyright (c) 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/***************************************************************************** +This program should compile and when run, print a single line like: +#define SIZEOF_PTHREAD_T %d + +Created April 18, 2009 Vasil Dimov +*****************************************************************************/ + +#include <stdio.h> +#include <pthread.h> + +int +main(int argc, char** argv) +{ + printf("#define SIZEOF_PTHREAD_T %d\n", (int) sizeof(pthread_t)); + + return(0); +} diff --git a/storage/innodb_plugin/ut/ut0byte.c b/storage/innodb_plugin/ut/ut0byte.c new file mode 100644 index 00000000000..4e093f72ce2 --- /dev/null +++ b/storage/innodb_plugin/ut/ut0byte.c @@ -0,0 +1,55 @@ +/***************************************************************************** + +Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/***************************************************************//** +@file ut/ut0byte.c +Byte utilities + +Created 5/11/1994 Heikki Tuuri +********************************************************************/ + +#include "ut0byte.h" + +#ifdef UNIV_NONINL +#include "ut0byte.ic" +#endif + +/** Zero value for a dulint */ +UNIV_INTERN const dulint ut_dulint_zero = {0, 0}; + +/** Maximum value for a dulint */ +UNIV_INTERN const dulint ut_dulint_max = {0xFFFFFFFFUL, 0xFFFFFFFFUL}; + +#ifdef notdefined /* unused code */ +#include "ut0sort.h" + +/************************************************************//** +Sort function for dulint arrays. */ +UNIV_INTERN +void +ut_dulint_sort( +/*===========*/ + dulint* arr, /*!< in/out: array to be sorted */ + dulint* aux_arr,/*!< in/out: auxiliary array (same size as arr) */ + ulint low, /*!< in: low bound of sort interval, inclusive */ + ulint high) /*!< in: high bound of sort interval, noninclusive */ +{ + UT_SORT_FUNCTION_BODY(ut_dulint_sort, arr, aux_arr, low, high, + ut_dulint_cmp); +} +#endif /* notdefined */ diff --git a/storage/innodb_plugin/ut/ut0dbg.c b/storage/innodb_plugin/ut/ut0dbg.c new file mode 100644 index 00000000000..4484e6c36de --- /dev/null +++ b/storage/innodb_plugin/ut/ut0dbg.c @@ -0,0 +1,187 @@ +/***************************************************************************** + +Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/*****************************************************************//** +@file ut/ut0dbg.c +Debug utilities for Innobase. + +Created 1/30/1994 Heikki Tuuri +**********************************************************************/ + +#include "univ.i" +#include "ut0dbg.h" + +#if defined(__GNUC__) && (__GNUC__ > 2) +#else +/** This is used to eliminate compiler warnings */ +UNIV_INTERN ulint ut_dbg_zero = 0; +#endif + +#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) +/** If this is set to TRUE by ut_dbg_assertion_failed(), all threads +will stop at the next ut_a() or ut_ad(). */ +UNIV_INTERN ibool ut_dbg_stop_threads = FALSE; +#endif +#ifdef __NETWARE__ +/** Flag for ignoring further assertion failures. This is set to TRUE +when on NetWare there happens an InnoDB assertion failure or other +fatal error condition that requires an immediate shutdown. */ +UNIV_INTERN ibool panic_shutdown = FALSE; +#elif !defined(UT_DBG_USE_ABORT) +/** A null pointer that will be dereferenced to trigger a memory trap */ +UNIV_INTERN ulint* ut_dbg_null_ptr = NULL; +#endif + +/*************************************************************//** +Report a failed assertion. */ +UNIV_INTERN +void +ut_dbg_assertion_failed( +/*====================*/ + const char* expr, /*!< in: the failed assertion (optional) */ + const char* file, /*!< in: source file containing the assertion */ + ulint line) /*!< in: line number of the assertion */ +{ + ut_print_timestamp(stderr); +#ifdef UNIV_HOTBACKUP + fprintf(stderr, " InnoDB: Assertion failure in file %s line %lu\n", + file, line); +#else /* UNIV_HOTBACKUP */ + fprintf(stderr, + " InnoDB: Assertion failure in thread %lu" + " in file %s line %lu\n", + os_thread_pf(os_thread_get_curr_id()), file, line); +#endif /* UNIV_HOTBACKUP */ + if (expr) { + fprintf(stderr, + "InnoDB: Failing assertion: %s\n", expr); + } + + fputs("InnoDB: We intentionally generate a memory trap.\n" + "InnoDB: Submit a detailed bug report" + " to http://bugs.mysql.com.\n" + "InnoDB: If you get repeated assertion failures" + " or crashes, even\n" + "InnoDB: immediately after the mysqld startup, there may be\n" + "InnoDB: corruption in the InnoDB tablespace. Please refer to\n" + "InnoDB: " REFMAN "forcing-recovery.html\n" + "InnoDB: about forcing recovery.\n", stderr); +#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) + ut_dbg_stop_threads = TRUE; +#endif +} + +#ifdef __NETWARE__ +/*************************************************************//** +Shut down MySQL/InnoDB after assertion failure. */ +UNIV_INTERN +void +ut_dbg_panic(void) +/*==============*/ +{ + if (!panic_shutdown) { + panic_shutdown = TRUE; + innobase_shutdown_for_mysql(); + } + exit(1); +} +#else /* __NETWARE__ */ +# if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) +/*************************************************************//** +Stop a thread after assertion failure. */ +UNIV_INTERN +void +ut_dbg_stop_thread( +/*===============*/ + const char* file, + ulint line) +{ +#ifndef UNIV_HOTBACKUP + fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n", + os_thread_pf(os_thread_get_curr_id()), file, line); + os_thread_sleep(1000000000); +#endif /* !UNIV_HOTBACKUP */ +} +# endif +#endif /* __NETWARE__ */ + +#ifdef UNIV_COMPILE_TEST_FUNCS + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> + +#include <unistd.h> + +#ifndef timersub +#define timersub(a, b, r) \ + do { \ + (r)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (r)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((r)->tv_usec < 0) { \ + (r)->tv_sec--; \ + (r)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* timersub */ + +/*******************************************************************//** +Resets a speedo (records the current time in it). */ +UNIV_INTERN +void +speedo_reset( +/*=========*/ + speedo_t* speedo) /*!< out: speedo */ +{ + gettimeofday(&speedo->tv, NULL); + + getrusage(RUSAGE_SELF, &speedo->ru); +} + +/*******************************************************************//** +Shows the time elapsed and usage statistics since the last reset of a +speedo. */ +UNIV_INTERN +void +speedo_show( +/*========*/ + const speedo_t* speedo) /*!< in: speedo */ +{ + struct rusage ru_now; + struct timeval tv_now; + struct timeval tv_diff; + + getrusage(RUSAGE_SELF, &ru_now); + + gettimeofday(&tv_now, NULL); + +#define PRINT_TIMEVAL(prefix, tvp) \ + fprintf(stderr, "%s% 5ld.%06ld sec\n", \ + prefix, (tvp)->tv_sec, (tvp)->tv_usec) + + timersub(&tv_now, &speedo->tv, &tv_diff); + PRINT_TIMEVAL("real", &tv_diff); + + timersub(&ru_now.ru_utime, &speedo->ru.ru_utime, &tv_diff); + PRINT_TIMEVAL("user", &tv_diff); + + timersub(&ru_now.ru_stime, &speedo->ru.ru_stime, &tv_diff); + PRINT_TIMEVAL("sys ", &tv_diff); +} + +#endif /* UNIV_COMPILE_TEST_FUNCS */ diff --git a/storage/innodb_plugin/ut/ut0list.c b/storage/innodb_plugin/ut/ut0list.c new file mode 100644 index 00000000000..895a575c535 --- /dev/null +++ b/storage/innodb_plugin/ut/ut0list.c @@ -0,0 +1,194 @@ +/***************************************************************************** + +Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/*******************************************************************//** +@file ut/ut0list.c +A double-linked list + +Created 4/26/2006 Osku Salerma +************************************************************************/ + +#include "ut0list.h" +#ifdef UNIV_NONINL +#include "ut0list.ic" +#endif + +/****************************************************************//** +Create a new list. +@return list */ +UNIV_INTERN +ib_list_t* +ib_list_create(void) +/*=================*/ +{ + ib_list_t* list = mem_alloc(sizeof(ib_list_t)); + + list->first = NULL; + list->last = NULL; + list->is_heap_list = FALSE; + + return(list); +} + +/****************************************************************//** +Create a new list using the given heap. ib_list_free MUST NOT BE CALLED for +lists created with this function. +@return list */ +UNIV_INTERN +ib_list_t* +ib_list_create_heap( +/*================*/ + mem_heap_t* heap) /*!< in: memory heap to use */ +{ + ib_list_t* list = mem_heap_alloc(heap, sizeof(ib_list_t)); + + list->first = NULL; + list->last = NULL; + list->is_heap_list = TRUE; + + return(list); +} + +/****************************************************************//** +Free a list. */ +UNIV_INTERN +void +ib_list_free( +/*=========*/ + ib_list_t* list) /*!< in: list */ +{ + ut_a(!list->is_heap_list); + + /* We don't check that the list is empty because it's entirely valid + to e.g. have all the nodes allocated from a single heap that is then + freed after the list itself is freed. */ + + mem_free(list); +} + +/****************************************************************//** +Add the data to the start of the list. +@return new list node */ +UNIV_INTERN +ib_list_node_t* +ib_list_add_first( +/*==============*/ + ib_list_t* list, /*!< in: list */ + void* data, /*!< in: data */ + mem_heap_t* heap) /*!< in: memory heap to use */ +{ + return(ib_list_add_after(list, ib_list_get_first(list), data, heap)); +} + +/****************************************************************//** +Add the data to the end of the list. +@return new list node */ +UNIV_INTERN +ib_list_node_t* +ib_list_add_last( +/*=============*/ + ib_list_t* list, /*!< in: list */ + void* data, /*!< in: data */ + mem_heap_t* heap) /*!< in: memory heap to use */ +{ + return(ib_list_add_after(list, ib_list_get_last(list), data, heap)); +} + +/****************************************************************//** +Add the data after the indicated node. +@return new list node */ +UNIV_INTERN +ib_list_node_t* +ib_list_add_after( +/*==============*/ + ib_list_t* list, /*!< in: list */ + ib_list_node_t* prev_node, /*!< in: node preceding new node (can + be NULL) */ + void* data, /*!< in: data */ + mem_heap_t* heap) /*!< in: memory heap to use */ +{ + ib_list_node_t* node = mem_heap_alloc(heap, sizeof(ib_list_node_t)); + + node->data = data; + + if (!list->first) { + /* Empty list. */ + + ut_a(!prev_node); + + node->prev = NULL; + node->next = NULL; + + list->first = node; + list->last = node; + } else if (!prev_node) { + /* Start of list. */ + + node->prev = NULL; + node->next = list->first; + + list->first->prev = node; + + list->first = node; + } else { + /* Middle or end of list. */ + + node->prev = prev_node; + node->next = prev_node->next; + + prev_node->next = node; + + if (node->next) { + node->next->prev = node; + } else { + list->last = node; + } + } + + return(node); +} + +/****************************************************************//** +Remove the node from the list. */ +UNIV_INTERN +void +ib_list_remove( +/*===========*/ + ib_list_t* list, /*!< in: list */ + ib_list_node_t* node) /*!< in: node to remove */ +{ + if (node->prev) { + node->prev->next = node->next; + } else { + /* First item in list. */ + + ut_ad(list->first == node); + + list->first = node->next; + } + + if (node->next) { + node->next->prev = node->prev; + } else { + /* Last item in list. */ + + ut_ad(list->last == node); + + list->last = node->prev; + } +} diff --git a/storage/innodb_plugin/ut/ut0mem.c b/storage/innodb_plugin/ut/ut0mem.c new file mode 100644 index 00000000000..7ed43d32fe0 --- /dev/null +++ b/storage/innodb_plugin/ut/ut0mem.c @@ -0,0 +1,706 @@ +/***************************************************************************** + +Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/********************************************************************//** +@file ut/ut0mem.c +Memory primitives + +Created 5/11/1994 Heikki Tuuri +*************************************************************************/ + +#include "ut0mem.h" + +#ifdef UNIV_NONINL +#include "ut0mem.ic" +#endif + +#ifndef UNIV_HOTBACKUP +# include "os0thread.h" +# include "srv0srv.h" + +#include <stdlib.h> + +/** This struct is placed first in every allocated memory block */ +typedef struct ut_mem_block_struct ut_mem_block_t; + +/** The total amount of memory currently allocated from the operating +system with os_mem_alloc_large() or malloc(). Does not count malloc() +if srv_use_sys_malloc is set. Protected by ut_list_mutex. */ +UNIV_INTERN ulint ut_total_allocated_memory = 0; + +/** Mutex protecting ut_total_allocated_memory and ut_mem_block_list */ +UNIV_INTERN os_fast_mutex_t ut_list_mutex; + +/** Dynamically allocated memory block */ +struct ut_mem_block_struct{ + UT_LIST_NODE_T(ut_mem_block_t) mem_block_list; + /*!< mem block list node */ + ulint size; /*!< size of allocated memory */ + ulint magic_n;/*!< magic number (UT_MEM_MAGIC_N) */ +}; + +/** The value of ut_mem_block_struct::magic_n. Used in detecting +memory corruption. */ +#define UT_MEM_MAGIC_N 1601650166 + +/** List of all memory blocks allocated from the operating system +with malloc. Protected by ut_list_mutex. */ +static UT_LIST_BASE_NODE_T(ut_mem_block_t) ut_mem_block_list; + +/** Flag: has ut_mem_block_list been initialized? */ +static ibool ut_mem_block_list_inited = FALSE; + +/** A dummy pointer for generating a null pointer exception in +ut_malloc_low() */ +static ulint* ut_mem_null_ptr = NULL; + +/**********************************************************************//** +Initializes the mem block list at database startup. */ +UNIV_INTERN +void +ut_mem_init(void) +/*=============*/ +{ + ut_a(!ut_mem_block_list_inited); + os_fast_mutex_init(&ut_list_mutex); + UT_LIST_INIT(ut_mem_block_list); + ut_mem_block_list_inited = TRUE; +} +#endif /* !UNIV_HOTBACKUP */ + +/**********************************************************************//** +Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is +defined and set_to_zero is TRUE. +@return own: allocated memory */ +UNIV_INTERN +void* +ut_malloc_low( +/*==========*/ + ulint n, /*!< in: number of bytes to allocate */ + ibool set_to_zero, /*!< in: TRUE if allocated memory should be + set to zero if UNIV_SET_MEM_TO_ZERO is + defined */ + ibool assert_on_error)/*!< in: if TRUE, we crash mysqld if the + memory cannot be allocated */ +{ +#ifndef UNIV_HOTBACKUP + ulint retry_count; + void* ret; + + if (UNIV_LIKELY(srv_use_sys_malloc)) { + ret = malloc(n); + ut_a(ret || !assert_on_error); + +#ifdef UNIV_SET_MEM_TO_ZERO + if (set_to_zero) { + memset(ret, '\0', n); + UNIV_MEM_ALLOC(ret, n); + } +#endif + return(ret); + } + + ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */ + ut_a(ut_mem_block_list_inited); + + retry_count = 0; +retry: + os_fast_mutex_lock(&ut_list_mutex); + + ret = malloc(n + sizeof(ut_mem_block_t)); + + if (ret == NULL && retry_count < 60) { + if (retry_count == 0) { + ut_print_timestamp(stderr); + + fprintf(stderr, + " InnoDB: Error: cannot allocate" + " %lu bytes of\n" + "InnoDB: memory with malloc!" + " Total allocated memory\n" + "InnoDB: by InnoDB %lu bytes." + " Operating system errno: %lu\n" + "InnoDB: Check if you should" + " increase the swap file or\n" + "InnoDB: ulimits of your operating system.\n" + "InnoDB: On FreeBSD check you" + " have compiled the OS with\n" + "InnoDB: a big enough maximum process size.\n" + "InnoDB: Note that in most 32-bit" + " computers the process\n" + "InnoDB: memory space is limited" + " to 2 GB or 4 GB.\n" + "InnoDB: We keep retrying" + " the allocation for 60 seconds...\n", + (ulong) n, (ulong) ut_total_allocated_memory, +#ifdef __WIN__ + (ulong) GetLastError() +#else + (ulong) errno +#endif + ); + } + + os_fast_mutex_unlock(&ut_list_mutex); + + /* Sleep for a second and retry the allocation; maybe this is + just a temporary shortage of memory */ + + os_thread_sleep(1000000); + + retry_count++; + + goto retry; + } + + if (ret == NULL) { + /* Flush stderr to make more probable that the error + message gets in the error file before we generate a seg + fault */ + + fflush(stderr); + + os_fast_mutex_unlock(&ut_list_mutex); + + /* Make an intentional seg fault so that we get a stack + trace */ + /* Intentional segfault on NetWare causes an abend. Avoid this + by graceful exit handling in ut_a(). */ +#if (!defined __NETWARE__) + if (assert_on_error) { + ut_print_timestamp(stderr); + + fprintf(stderr, + " InnoDB: We now intentionally" + " generate a seg fault so that\n" + "InnoDB: on Linux we get a stack trace.\n"); + + if (*ut_mem_null_ptr) ut_mem_null_ptr = 0; + } else { + return(NULL); + } +#else + ut_a(0); +#endif + } + + if (set_to_zero) { +#ifdef UNIV_SET_MEM_TO_ZERO + memset(ret, '\0', n + sizeof(ut_mem_block_t)); +#endif + } + + UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t)); + + ((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t); + ((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N; + + ut_total_allocated_memory += n + sizeof(ut_mem_block_t); + + UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list, + ((ut_mem_block_t*)ret)); + os_fast_mutex_unlock(&ut_list_mutex); + + return((void*)((byte*)ret + sizeof(ut_mem_block_t))); +#else /* !UNIV_HOTBACKUP */ + void* ret = malloc(n); + ut_a(ret || !assert_on_error); + +# ifdef UNIV_SET_MEM_TO_ZERO + if (set_to_zero) { + memset(ret, '\0', n); + } +# endif + return(ret); +#endif /* !UNIV_HOTBACKUP */ +} + +/**********************************************************************//** +Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is +defined. +@return own: allocated memory */ +UNIV_INTERN +void* +ut_malloc( +/*======*/ + ulint n) /*!< in: number of bytes to allocate */ +{ +#ifndef UNIV_HOTBACKUP + return(ut_malloc_low(n, TRUE, TRUE)); +#else /* !UNIV_HOTBACKUP */ + return(malloc(n)); +#endif /* !UNIV_HOTBACKUP */ +} + +#ifndef UNIV_HOTBACKUP +/**********************************************************************//** +Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs +out. It cannot be used if we want to return an error message. Prints to +stderr a message if fails. +@return TRUE if succeeded */ +UNIV_INTERN +ibool +ut_test_malloc( +/*===========*/ + ulint n) /*!< in: try to allocate this many bytes */ +{ + void* ret; + + ret = malloc(n); + + if (ret == NULL) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Error: cannot allocate" + " %lu bytes of memory for\n" + "InnoDB: a BLOB with malloc! Total allocated memory\n" + "InnoDB: by InnoDB %lu bytes." + " Operating system errno: %d\n" + "InnoDB: Check if you should increase" + " the swap file or\n" + "InnoDB: ulimits of your operating system.\n" + "InnoDB: On FreeBSD check you have" + " compiled the OS with\n" + "InnoDB: a big enough maximum process size.\n", + (ulong) n, + (ulong) ut_total_allocated_memory, + (int) errno); + return(FALSE); + } + + free(ret); + + return(TRUE); +} +#endif /* !UNIV_HOTBACKUP */ + +/**********************************************************************//** +Frees a memory block allocated with ut_malloc. */ +UNIV_INTERN +void +ut_free( +/*====*/ + void* ptr) /*!< in, own: memory block */ +{ +#ifndef UNIV_HOTBACKUP + ut_mem_block_t* block; + + if (UNIV_LIKELY(srv_use_sys_malloc)) { + free(ptr); + return; + } + + block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t)); + + os_fast_mutex_lock(&ut_list_mutex); + + ut_a(block->magic_n == UT_MEM_MAGIC_N); + ut_a(ut_total_allocated_memory >= block->size); + + ut_total_allocated_memory -= block->size; + + UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block); + free(block); + + os_fast_mutex_unlock(&ut_list_mutex); +#else /* !UNIV_HOTBACKUP */ + free(ptr); +#endif /* !UNIV_HOTBACKUP */ +} + +#ifndef UNIV_HOTBACKUP +/**********************************************************************//** +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); +} + +/**********************************************************************//** +Frees in shutdown all allocated memory not freed yet. */ +UNIV_INTERN +void +ut_free_all_mem(void) +/*=================*/ +{ + ut_mem_block_t* block; + + ut_a(ut_mem_block_list_inited); + ut_mem_block_list_inited = FALSE; + os_fast_mutex_free(&ut_list_mutex); + + while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) { + + ut_a(block->magic_n == UT_MEM_MAGIC_N); + ut_a(ut_total_allocated_memory >= block->size); + + ut_total_allocated_memory -= block->size; + + UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block); + free(block); + } + + if (ut_total_allocated_memory != 0) { + fprintf(stderr, + "InnoDB: Warning: after shutdown" + " total allocated memory is %lu\n", + (ulong) ut_total_allocated_memory); + } +} +#endif /* !UNIV_HOTBACKUP */ + +/**********************************************************************//** +Copies up to size - 1 characters from the NUL-terminated string src to +dst, NUL-terminating the result. Returns strlen(src), so truncation +occurred if the return value >= size. +@return strlen(src) */ +UNIV_INTERN +ulint +ut_strlcpy( +/*=======*/ + char* dst, /*!< in: destination buffer */ + const char* src, /*!< in: source buffer */ + ulint size) /*!< in: size of destination buffer */ +{ + ulint src_size = strlen(src); + + if (size != 0) { + ulint n = ut_min(src_size, size - 1); + + memcpy(dst, src, n); + dst[n] = '\0'; + } + + return(src_size); +} + +/**********************************************************************//** +Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last +(size - 1) bytes of src, not the first. +@return strlen(src) */ +UNIV_INTERN +ulint +ut_strlcpy_rev( +/*===========*/ + char* dst, /*!< in: destination buffer */ + const char* src, /*!< in: source buffer */ + ulint size) /*!< in: size of destination buffer */ +{ + ulint src_size = strlen(src); + + if (size != 0) { + ulint n = ut_min(src_size, size - 1); + + memcpy(dst, src + src_size - n, n + 1); + } + + return(src_size); +} + +/**********************************************************************//** +Make a quoted copy of a NUL-terminated string. Leading and trailing +quotes will not be included; only embedded quotes will be escaped. +See also ut_strlenq() and ut_memcpyq(). +@return pointer to end of dest */ +UNIV_INTERN +char* +ut_strcpyq( +/*=======*/ + char* dest, /*!< in: output buffer */ + char q, /*!< in: the quote character */ + const char* src) /*!< in: null-terminated string */ +{ + while (*src) { + if ((*dest++ = *src++) == q) { + *dest++ = q; + } + } + + return(dest); +} + +/**********************************************************************//** +Make a quoted copy of a fixed-length string. Leading and trailing +quotes will not be included; only embedded quotes will be escaped. +See also ut_strlenq() and ut_strcpyq(). +@return pointer to end of dest */ +UNIV_INTERN +char* +ut_memcpyq( +/*=======*/ + char* dest, /*!< in: output buffer */ + char q, /*!< in: the quote character */ + const char* src, /*!< in: string to be quoted */ + ulint len) /*!< in: length of src */ +{ + const char* srcend = src + len; + + while (src < srcend) { + if ((*dest++ = *src++) == q) { + *dest++ = q; + } + } + + return(dest); +} + +#ifndef UNIV_HOTBACKUP +/**********************************************************************//** +Return the number of times s2 occurs in s1. Overlapping instances of s2 +are only counted once. +@return the number of times s2 occurs in s1 */ +UNIV_INTERN +ulint +ut_strcount( +/*========*/ + const char* s1, /*!< in: string to search in */ + const char* s2) /*!< in: string to search for */ +{ + ulint count = 0; + ulint len = strlen(s2); + + if (len == 0) { + + return(0); + } + + for (;;) { + s1 = strstr(s1, s2); + + if (!s1) { + + break; + } + + count++; + s1 += len; + } + + return(count); +} + +/**********************************************************************//** +Replace every occurrence of s1 in str with s2. Overlapping instances of s1 +are only replaced once. +@return own: modified string, must be freed with mem_free() */ +UNIV_INTERN +char* +ut_strreplace( +/*==========*/ + const char* str, /*!< in: string to operate on */ + const char* s1, /*!< in: string to replace */ + const char* s2) /*!< in: string to replace s1 with */ +{ + char* new_str; + char* ptr; + const char* str_end; + ulint str_len = strlen(str); + ulint s1_len = strlen(s1); + ulint s2_len = strlen(s2); + ulint count = 0; + int len_delta = (int)s2_len - (int)s1_len; + + str_end = str + str_len; + + if (len_delta <= 0) { + len_delta = 0; + } else { + count = ut_strcount(str, s1); + } + + new_str = mem_alloc(str_len + count * len_delta + 1); + ptr = new_str; + + while (str) { + const char* next = strstr(str, s1); + + if (!next) { + next = str_end; + } + + memcpy(ptr, str, next - str); + ptr += next - str; + + if (next == str_end) { + + break; + } + + memcpy(ptr, s2, s2_len); + ptr += s2_len; + + str = next + s1_len; + } + + *ptr = '\0'; + + return(new_str); +} + +#ifdef UNIV_COMPILE_TEST_FUNCS + +void +test_ut_str_sql_format() +{ + char buf[128]; + ulint ret; + +#define CALL_AND_TEST(str, str_len, buf, buf_size, ret_expected, buf_expected)\ + do {\ + ibool ok = TRUE;\ + memset(buf, 'x', 10);\ + buf[10] = '\0';\ + fprintf(stderr, "TESTING \"%s\", %lu, %lu\n",\ + str, (ulint) str_len, (ulint) buf_size);\ + ret = ut_str_sql_format(str, str_len, buf, buf_size);\ + if (ret != ret_expected) {\ + fprintf(stderr, "expected ret %lu, got %lu\n",\ + (ulint) ret_expected, ret);\ + ok = FALSE;\ + }\ + if (strcmp((char*) buf, buf_expected) != 0) {\ + fprintf(stderr, "expected buf \"%s\", got \"%s\"\n",\ + buf_expected, buf);\ + ok = FALSE;\ + }\ + if (ok) {\ + fprintf(stderr, "OK: %lu, \"%s\"\n\n",\ + (ulint) ret, buf);\ + } else {\ + return;\ + }\ + } while (0) + + CALL_AND_TEST("abcd", 4, buf, 0, 0, "xxxxxxxxxx"); + + CALL_AND_TEST("abcd", 4, buf, 1, 1, ""); + + CALL_AND_TEST("abcd", 4, buf, 2, 1, ""); + + CALL_AND_TEST("abcd", 0, buf, 3, 3, "''"); + CALL_AND_TEST("abcd", 1, buf, 3, 1, ""); + CALL_AND_TEST("abcd", 2, buf, 3, 1, ""); + CALL_AND_TEST("abcd", 3, buf, 3, 1, ""); + CALL_AND_TEST("abcd", 4, buf, 3, 1, ""); + + CALL_AND_TEST("abcd", 0, buf, 4, 3, "''"); + CALL_AND_TEST("abcd", 1, buf, 4, 4, "'a'"); + CALL_AND_TEST("abcd", 2, buf, 4, 4, "'a'"); + CALL_AND_TEST("abcd", 3, buf, 4, 4, "'a'"); + CALL_AND_TEST("abcd", 4, buf, 4, 4, "'a'"); + CALL_AND_TEST("abcde", 5, buf, 4, 4, "'a'"); + CALL_AND_TEST("'", 1, buf, 4, 3, "''"); + CALL_AND_TEST("''", 2, buf, 4, 3, "''"); + CALL_AND_TEST("a'", 2, buf, 4, 4, "'a'"); + CALL_AND_TEST("'a", 2, buf, 4, 3, "''"); + CALL_AND_TEST("ab", 2, buf, 4, 4, "'a'"); + + CALL_AND_TEST("abcdef", 0, buf, 5, 3, "''"); + CALL_AND_TEST("abcdef", 1, buf, 5, 4, "'a'"); + CALL_AND_TEST("abcdef", 2, buf, 5, 5, "'ab'"); + CALL_AND_TEST("abcdef", 3, buf, 5, 5, "'ab'"); + CALL_AND_TEST("abcdef", 4, buf, 5, 5, "'ab'"); + CALL_AND_TEST("abcdef", 5, buf, 5, 5, "'ab'"); + CALL_AND_TEST("abcdef", 6, buf, 5, 5, "'ab'"); + CALL_AND_TEST("'", 1, buf, 5, 5, "''''"); + CALL_AND_TEST("''", 2, buf, 5, 5, "''''"); + CALL_AND_TEST("a'", 2, buf, 5, 4, "'a'"); + CALL_AND_TEST("'a", 2, buf, 5, 5, "''''"); + CALL_AND_TEST("ab", 2, buf, 5, 5, "'ab'"); + CALL_AND_TEST("abc", 3, buf, 5, 5, "'ab'"); + + CALL_AND_TEST("ab", 2, buf, 6, 5, "'ab'"); + + CALL_AND_TEST("a'b'c", 5, buf, 32, 10, "'a''b''c'"); + CALL_AND_TEST("a'b'c'", 6, buf, 32, 12, "'a''b''c'''"); +} + +#endif /* UNIV_COMPILE_TEST_FUNCS */ +#endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innodb_plugin/ut/ut0rnd.c b/storage/innodb_plugin/ut/ut0rnd.c new file mode 100644 index 00000000000..cefd0990ecc --- /dev/null +++ b/storage/innodb_plugin/ut/ut0rnd.c @@ -0,0 +1,97 @@ +/***************************************************************************** + +Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/***************************************************************//** +@file ut/ut0rnd.c +Random numbers and hashing + +Created 5/11/1994 Heikki Tuuri +********************************************************************/ + +#include "ut0rnd.h" + +#ifdef UNIV_NONINL +#include "ut0rnd.ic" +#endif + +/** These random numbers are used in ut_find_prime */ +/*@{*/ +#define UT_RANDOM_1 1.0412321 +#define UT_RANDOM_2 1.1131347 +#define UT_RANDOM_3 1.0132677 +/*@}*/ + +/** Seed value of ut_rnd_gen_ulint(). */ +UNIV_INTERN ulint ut_rnd_ulint_counter = 65654363; + +/***********************************************************//** +Looks for a prime number slightly greater than the given argument. +The prime is chosen so that it is not near any power of 2. +@return prime */ +UNIV_INTERN +ulint +ut_find_prime( +/*==========*/ + ulint n) /*!< in: positive number > 100 */ +{ + ulint pow2; + ulint i; + + n += 100; + + pow2 = 1; + while (pow2 * 2 < n) { + pow2 = 2 * pow2; + } + + if ((double)n < 1.05 * (double)pow2) { + n = (ulint) ((double)n * UT_RANDOM_1); + } + + pow2 = 2 * pow2; + + if ((double)n > 0.95 * (double)pow2) { + n = (ulint) ((double)n * UT_RANDOM_2); + } + + if (n > pow2 - 20) { + n += 30; + } + + /* Now we have n far enough from powers of 2. To make + n more random (especially, if it was not near + a power of 2), we then multiply it by a random number. */ + + n = (ulint) ((double)n * UT_RANDOM_3); + + for (;; n++) { + i = 2; + while (i * i <= n) { + if (n % i == 0) { + goto next_n; + } + i++; + } + + /* Found a prime */ + break; +next_n: ; + } + + return(n); +} diff --git a/storage/innodb_plugin/ut/ut0ut.c b/storage/innodb_plugin/ut/ut0ut.c new file mode 100644 index 00000000000..c0ea362bee3 --- /dev/null +++ b/storage/innodb_plugin/ut/ut0ut.c @@ -0,0 +1,598 @@ +/***************************************************************************** + +Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/***************************************************************//** +@file ut/ut0ut.c +Various utilities for Innobase. + +Created 5/11/1994 Heikki Tuuri +********************************************************************/ + +#include "ut0ut.h" + +#ifdef UNIV_NONINL +#include "ut0ut.ic" +#endif + +#include <stdarg.h> +#include <string.h> +#include <ctype.h> + +#ifndef UNIV_HOTBACKUP +# include "trx0trx.h" +# include "ha_prototypes.h" +# include "mysql_com.h" /* NAME_LEN */ +#endif /* UNIV_HOTBACKUP */ + +/** A constant to prevent the compiler from optimizing ut_delay() away. */ +UNIV_INTERN ibool ut_always_false = FALSE; + +#ifdef __WIN__ +/*****************************************************************//** +NOTE: The Windows epoch starts from 1601/01/01 whereas the Unix +epoch starts from 1970/1/1. For selection of constant see: +http://support.microsoft.com/kb/167296/ */ +#define WIN_TO_UNIX_DELTA_USEC ((ib_int64_t) 11644473600000000ULL) + + +/*****************************************************************//** +This is the Windows version of gettimeofday(2). +@return 0 if all OK else -1 */ +static +int +ut_gettimeofday( +/*============*/ + struct timeval* tv, /*!< out: Values are relative to Unix epoch */ + void* tz) /*!< in: not used */ +{ + FILETIME ft; + ib_int64_t tm; + + if (!tv) { + errno = EINVAL; + return(-1); + } + + GetSystemTimeAsFileTime(&ft); + + tm = (ib_int64_t) ft.dwHighDateTime << 32; + tm |= ft.dwLowDateTime; + + ut_a(tm >= 0); /* If tm wraps over to negative, the quotient / 10 + does not work */ + + tm /= 10; /* Convert from 100 nsec periods to usec */ + + /* If we don't convert to the Unix epoch the value for + struct timeval::tv_sec will overflow.*/ + tm -= WIN_TO_UNIX_DELTA_USEC; + + tv->tv_sec = (long) (tm / 1000000L); + tv->tv_usec = (long) (tm % 1000000L); + + return(0); +} +#else +/** An alias for gettimeofday(2). On Microsoft Windows, we have to +reimplement this function. */ +#define ut_gettimeofday gettimeofday +#endif + +/********************************************************//** +Gets the high 32 bits in a ulint. That is makes a shift >> 32, +but since there seem to be compiler bugs in both gcc and Visual C++, +we do this by a special conversion. +@return a >> 32 */ +UNIV_INTERN +ulint +ut_get_high32( +/*==========*/ + ulint a) /*!< in: ulint */ +{ + ib_int64_t i; + + i = (ib_int64_t)a; + + i = i >> 32; + + return((ulint)i); +} + +/**********************************************************//** +Returns system time. We do not specify the format of the time returned: +the only way to manipulate it is to use the function ut_difftime. +@return system time */ +UNIV_INTERN +ib_time_t +ut_time(void) +/*=========*/ +{ + return(time(NULL)); +} + +/**********************************************************//** +Returns system time. +Upon successful completion, the value 0 is returned; otherwise the +value -1 is returned and the global variable errno is set to indicate the +error. +@return 0 on success, -1 otherwise */ +UNIV_INTERN +int +ut_usectime( +/*========*/ + ulint* sec, /*!< out: seconds since the Epoch */ + ulint* ms) /*!< out: microseconds since the Epoch+*sec */ +{ + struct timeval tv; + int ret; + int errno_gettimeofday; + int i; + + for (i = 0; i < 10; i++) { + + ret = ut_gettimeofday(&tv, NULL); + + if (ret == -1) { + errno_gettimeofday = errno; + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: gettimeofday(): %s\n", + strerror(errno_gettimeofday)); + os_thread_sleep(100000); /* 0.1 sec */ + errno = errno_gettimeofday; + } else { + break; + } + } + + if (ret != -1) { + *sec = (ulint) tv.tv_sec; + *ms = (ulint) tv.tv_usec; + } + + return(ret); +} + +/**********************************************************//** +Returns the number of microseconds since epoch. Similar to +time(3), the return value is also stored in *tloc, provided +that tloc is non-NULL. +@return us since epoch */ +UNIV_INTERN +ullint +ut_time_us( +/*=======*/ + ullint* tloc) /*!< out: us since epoch, if non-NULL */ +{ + struct timeval tv; + ullint us; + + ut_gettimeofday(&tv, NULL); + + us = (ullint) tv.tv_sec * 1000000 + tv.tv_usec; + + if (tloc != NULL) { + *tloc = us; + } + + return(us); +} + +/**********************************************************//** +Returns the difference of two times in seconds. +@return time2 - time1 expressed in seconds */ +UNIV_INTERN +double +ut_difftime( +/*========*/ + ib_time_t time2, /*!< in: time */ + ib_time_t time1) /*!< in: time */ +{ + return(difftime(time2, time1)); +} + +/**********************************************************//** +Prints a timestamp to a file. */ +UNIV_INTERN +void +ut_print_timestamp( +/*===============*/ + FILE* file) /*!< in: file where to print */ +{ +#ifdef __WIN__ + SYSTEMTIME cal_tm; + + GetLocalTime(&cal_tm); + + fprintf(file,"%02d%02d%02d %2d:%02d:%02d", + (int)cal_tm.wYear % 100, + (int)cal_tm.wMonth, + (int)cal_tm.wDay, + (int)cal_tm.wHour, + (int)cal_tm.wMinute, + (int)cal_tm.wSecond); +#else + struct tm cal_tm; + struct tm* cal_tm_ptr; + time_t tm; + + time(&tm); + +#ifdef HAVE_LOCALTIME_R + localtime_r(&tm, &cal_tm); + cal_tm_ptr = &cal_tm; +#else + cal_tm_ptr = localtime(&tm); +#endif + fprintf(file,"%02d%02d%02d %2d:%02d:%02d", + cal_tm_ptr->tm_year % 100, + cal_tm_ptr->tm_mon + 1, + cal_tm_ptr->tm_mday, + cal_tm_ptr->tm_hour, + cal_tm_ptr->tm_min, + cal_tm_ptr->tm_sec); +#endif +} + +/**********************************************************//** +Sprintfs a timestamp to a buffer, 13..14 chars plus terminating NUL. */ +UNIV_INTERN +void +ut_sprintf_timestamp( +/*=================*/ + char* buf) /*!< in: buffer where to sprintf */ +{ +#ifdef __WIN__ + SYSTEMTIME cal_tm; + + GetLocalTime(&cal_tm); + + sprintf(buf, "%02d%02d%02d %2d:%02d:%02d", + (int)cal_tm.wYear % 100, + (int)cal_tm.wMonth, + (int)cal_tm.wDay, + (int)cal_tm.wHour, + (int)cal_tm.wMinute, + (int)cal_tm.wSecond); +#else + struct tm cal_tm; + struct tm* cal_tm_ptr; + time_t tm; + + time(&tm); + +#ifdef HAVE_LOCALTIME_R + localtime_r(&tm, &cal_tm); + cal_tm_ptr = &cal_tm; +#else + cal_tm_ptr = localtime(&tm); +#endif + sprintf(buf, "%02d%02d%02d %2d:%02d:%02d", + cal_tm_ptr->tm_year % 100, + cal_tm_ptr->tm_mon + 1, + cal_tm_ptr->tm_mday, + cal_tm_ptr->tm_hour, + cal_tm_ptr->tm_min, + cal_tm_ptr->tm_sec); +#endif +} + +#ifdef UNIV_HOTBACKUP +/**********************************************************//** +Sprintfs a timestamp to a buffer with no spaces and with ':' characters +replaced by '_'. */ +UNIV_INTERN +void +ut_sprintf_timestamp_without_extra_chars( +/*=====================================*/ + char* buf) /*!< in: buffer where to sprintf */ +{ +#ifdef __WIN__ + SYSTEMTIME cal_tm; + + GetLocalTime(&cal_tm); + + sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d", + (int)cal_tm.wYear % 100, + (int)cal_tm.wMonth, + (int)cal_tm.wDay, + (int)cal_tm.wHour, + (int)cal_tm.wMinute, + (int)cal_tm.wSecond); +#else + struct tm cal_tm; + struct tm* cal_tm_ptr; + time_t tm; + + time(&tm); + +#ifdef HAVE_LOCALTIME_R + localtime_r(&tm, &cal_tm); + cal_tm_ptr = &cal_tm; +#else + cal_tm_ptr = localtime(&tm); +#endif + sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d", + cal_tm_ptr->tm_year % 100, + cal_tm_ptr->tm_mon + 1, + cal_tm_ptr->tm_mday, + cal_tm_ptr->tm_hour, + cal_tm_ptr->tm_min, + cal_tm_ptr->tm_sec); +#endif +} + +/**********************************************************//** +Returns current year, month, day. */ +UNIV_INTERN +void +ut_get_year_month_day( +/*==================*/ + ulint* year, /*!< out: current year */ + ulint* month, /*!< out: month */ + ulint* day) /*!< out: day */ +{ +#ifdef __WIN__ + SYSTEMTIME cal_tm; + + GetLocalTime(&cal_tm); + + *year = (ulint)cal_tm.wYear; + *month = (ulint)cal_tm.wMonth; + *day = (ulint)cal_tm.wDay; +#else + struct tm cal_tm; + struct tm* cal_tm_ptr; + time_t tm; + + time(&tm); + +#ifdef HAVE_LOCALTIME_R + localtime_r(&tm, &cal_tm); + cal_tm_ptr = &cal_tm; +#else + cal_tm_ptr = localtime(&tm); +#endif + *year = (ulint)cal_tm_ptr->tm_year + 1900; + *month = (ulint)cal_tm_ptr->tm_mon + 1; + *day = (ulint)cal_tm_ptr->tm_mday; +#endif +} +#endif /* UNIV_HOTBACKUP */ + +#ifndef UNIV_HOTBACKUP +/*************************************************************//** +Runs an idle loop on CPU. The argument gives the desired delay +in microseconds on 100 MHz Pentium + Visual C++. +@return dummy value */ +UNIV_INTERN +ulint +ut_delay( +/*=====*/ + ulint delay) /*!< in: delay in microseconds on 100 MHz Pentium */ +{ + ulint i, j; + + j = 0; + + for (i = 0; i < delay * 50; i++) { + j += i; + } + + if (ut_always_false) { + ut_always_false = (ibool) j; + } + + return(j); +} +#endif /* !UNIV_HOTBACKUP */ + +/*************************************************************//** +Prints the contents of a memory buffer in hex and ascii. */ +UNIV_INTERN +void +ut_print_buf( +/*=========*/ + FILE* file, /*!< in: file where to print */ + const void* buf, /*!< in: memory buffer */ + ulint len) /*!< in: length of the buffer */ +{ + const byte* data; + ulint i; + + UNIV_MEM_ASSERT_RW(buf, len); + + fprintf(file, " len %lu; hex ", len); + + for (data = (const byte*)buf, i = 0; i < len; i++) { + fprintf(file, "%02lx", (ulong)*data++); + } + + fputs("; asc ", file); + + data = (const byte*)buf; + + for (i = 0; i < len; i++) { + int c = (int) *data++; + putc(isprint(c) ? c : ' ', file); + } + + putc(';', file); +} + +/*************************************************************//** +Calculates fast the number rounded up to the nearest power of 2. +@return first power of 2 which is >= n */ +UNIV_INTERN +ulint +ut_2_power_up( +/*==========*/ + ulint n) /*!< in: number != 0 */ +{ + ulint res; + + res = 1; + + ut_ad(n > 0); + + while (res < n) { + res = res * 2; + } + + return(res); +} + +/**********************************************************************//** +Outputs a NUL-terminated file name, quoted with apostrophes. */ +UNIV_INTERN +void +ut_print_filename( +/*==============*/ + FILE* f, /*!< in: output stream */ + const char* name) /*!< in: name to print */ +{ + putc('\'', f); + for (;;) { + int c = *name++; + switch (c) { + case 0: + goto done; + case '\'': + putc(c, f); + /* fall through */ + default: + putc(c, f); + } + } +done: + putc('\'', f); +} +#ifndef UNIV_HOTBACKUP +/**********************************************************************//** +Outputs a fixed-length string, quoted as an SQL identifier. +If the string contains a slash '/', the string will be +output as two identifiers separated by a period (.), +as in SQL database_name.identifier. */ +UNIV_INTERN +void +ut_print_name( +/*==========*/ + FILE* f, /*!< in: output stream */ + trx_t* trx, /*!< in: transaction */ + ibool table_id,/*!< in: TRUE=print a table name, + FALSE=print other identifier */ + const char* name) /*!< in: name to print */ +{ + ut_print_namel(f, trx, table_id, name, strlen(name)); +} + +/**********************************************************************//** +Outputs a fixed-length string, quoted as an SQL identifier. +If the string contains a slash '/', the string will be +output as two identifiers separated by a period (.), +as in SQL database_name.identifier. */ +UNIV_INTERN +void +ut_print_namel( +/*===========*/ + FILE* f, /*!< in: output stream */ + trx_t* trx, /*!< in: transaction (NULL=no quotes) */ + ibool table_id,/*!< in: TRUE=print a table name, + FALSE=print other identifier */ + const char* name, /*!< in: name to print */ + ulint namelen)/*!< in: length of name */ +{ + /* 2 * NAME_LEN for database and table name, + and some slack for the #mysql50# prefix and quotes */ + char buf[3 * NAME_LEN]; + const char* bufend; + + bufend = innobase_convert_name(buf, sizeof buf, + name, namelen, + trx ? trx->mysql_thd : NULL, + table_id); + + fwrite(buf, 1, bufend - buf, f); +} + +/**********************************************************************//** +Catenate files. */ +UNIV_INTERN +void +ut_copy_file( +/*=========*/ + FILE* dest, /*!< in: output file */ + FILE* src) /*!< in: input file to be appended to output */ +{ + long len = ftell(src); + char buf[4096]; + + rewind(src); + do { + size_t maxs = len < (long) sizeof buf + ? (size_t) len + : sizeof buf; + size_t size = fread(buf, 1, maxs, src); + fwrite(buf, 1, size, dest); + len -= (long) size; + if (size < maxs) { + break; + } + } while (len > 0); +} +#endif /* !UNIV_HOTBACKUP */ + +#ifdef __WIN__ +# include <stdarg.h> +/**********************************************************************//** +A substitute for snprintf(3), formatted output conversion into +a limited buffer. +@return number of characters that would have been printed if the size +were unlimited, not including the terminating '\0'. */ +UNIV_INTERN +int +ut_snprintf( +/*========*/ + char* str, /*!< out: string */ + size_t size, /*!< in: str size */ + const char* fmt, /*!< in: format */ + ...) /*!< in: format values */ +{ + int res; + va_list ap1; + va_list ap2; + + va_start(ap1, fmt); + va_start(ap2, fmt); + + res = _vscprintf(fmt, ap1); + ut_a(res != -1); + + if (size > 0) { + _vsnprintf(str, size, fmt, ap2); + + if ((size_t) res >= size) { + str[size - 1] = '\0'; + } + } + + va_end(ap1); + va_end(ap2); + + return(res); +} +#endif /* __WIN__ */ diff --git a/storage/innodb_plugin/ut/ut0vec.c b/storage/innodb_plugin/ut/ut0vec.c new file mode 100644 index 00000000000..45f2bc9771f --- /dev/null +++ b/storage/innodb_plugin/ut/ut0vec.c @@ -0,0 +1,79 @@ +/***************************************************************************** + +Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/*******************************************************************//** +@file ut/ut0vec.c +A vector of pointers to data items + +Created 4/6/2006 Osku Salerma +************************************************************************/ + +#include "ut0vec.h" +#ifdef UNIV_NONINL +#include "ut0vec.ic" +#endif +#include <string.h> + +/****************************************************************//** +Create a new vector with the given initial size. +@return vector */ +UNIV_INTERN +ib_vector_t* +ib_vector_create( +/*=============*/ + mem_heap_t* heap, /*!< in: heap */ + ulint size) /*!< in: initial size */ +{ + ib_vector_t* vec; + + ut_a(size > 0); + + vec = mem_heap_alloc(heap, sizeof(*vec)); + + vec->heap = heap; + vec->data = mem_heap_alloc(heap, sizeof(void*) * size); + vec->used = 0; + vec->total = size; + + return(vec); +} + +/****************************************************************//** +Push a new element to the vector, increasing its size if necessary. */ +UNIV_INTERN +void +ib_vector_push( +/*===========*/ + ib_vector_t* vec, /*!< in: vector */ + void* elem) /*!< in: data element */ +{ + if (vec->used >= vec->total) { + void** new_data; + ulint new_total = vec->total * 2; + + new_data = mem_heap_alloc(vec->heap, + sizeof(void*) * new_total); + memcpy(new_data, vec->data, sizeof(void*) * vec->total); + + vec->data = new_data; + vec->total = new_total; + } + + vec->data[vec->used] = elem; + vec->used++; +} diff --git a/storage/innodb_plugin/ut/ut0wqueue.c b/storage/innodb_plugin/ut/ut0wqueue.c new file mode 100644 index 00000000000..5220d1e17f4 --- /dev/null +++ b/storage/innodb_plugin/ut/ut0wqueue.c @@ -0,0 +1,118 @@ +/***************************************************************************** + +Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "ut0wqueue.h" + +/*******************************************************************//** +@file ut/ut0wqueue.c +A work queue + +Created 4/26/2006 Osku Salerma +************************************************************************/ + +/****************************************************************//** +Create a new work queue. +@return work queue */ +UNIV_INTERN +ib_wqueue_t* +ib_wqueue_create(void) +/*===================*/ +{ + ib_wqueue_t* wq = mem_alloc(sizeof(ib_wqueue_t)); + + mutex_create(&wq->mutex, SYNC_WORK_QUEUE); + + wq->items = ib_list_create(); + wq->event = os_event_create(NULL); + + return(wq); +} + +/****************************************************************//** +Free a work queue. */ +UNIV_INTERN +void +ib_wqueue_free( +/*===========*/ + ib_wqueue_t* wq) /*!< in: work queue */ +{ + ut_a(!ib_list_get_first(wq->items)); + + mutex_free(&wq->mutex); + ib_list_free(wq->items); + os_event_free(wq->event); + + mem_free(wq); +} + +/****************************************************************//** +Add a work item to the queue. */ +UNIV_INTERN +void +ib_wqueue_add( +/*==========*/ + ib_wqueue_t* wq, /*!< in: work queue */ + void* item, /*!< in: work item */ + mem_heap_t* heap) /*!< in: memory heap to use for allocating the + list node */ +{ + mutex_enter(&wq->mutex); + + ib_list_add_last(wq->items, item, heap); + os_event_set(wq->event); + + mutex_exit(&wq->mutex); +} + +/****************************************************************//** +Wait for a work item to appear in the queue. +@return work item */ +UNIV_INTERN +void* +ib_wqueue_wait( +/*===========*/ + ib_wqueue_t* wq) /*!< in: work queue */ +{ + ib_list_node_t* node; + + for (;;) { + os_event_wait(wq->event); + + mutex_enter(&wq->mutex); + + node = ib_list_get_first(wq->items); + + if (node) { + ib_list_remove(wq->items, node); + + if (!ib_list_get_first(wq->items)) { + /* We must reset the event when the list + gets emptied. */ + os_event_reset(wq->event); + } + + break; + } + + mutex_exit(&wq->mutex); + } + + mutex_exit(&wq->mutex); + + return(node->data); +} |