diff options
Diffstat (limited to 'storage/innobase/ut')
-rw-r--r-- | storage/innobase/ut/ut0bh.cc | 159 | ||||
-rw-r--r-- | storage/innobase/ut/ut0crc32.cc | 706 | ||||
-rw-r--r-- | storage/innobase/ut/ut0dbg.cc | 83 | ||||
-rw-r--r-- | storage/innobase/ut/ut0list.cc | 23 | ||||
-rw-r--r-- | storage/innobase/ut/ut0mem.cc | 424 | ||||
-rw-r--r-- | storage/innobase/ut/ut0new.cc | 227 | ||||
-rw-r--r-- | storage/innobase/ut/ut0rbt.cc | 87 | ||||
-rw-r--r-- | storage/innobase/ut/ut0rnd.cc | 7 | ||||
-rw-r--r-- | storage/innobase/ut/ut0ut.cc | 477 | ||||
-rw-r--r-- | storage/innobase/ut/ut0vec.cc | 4 | ||||
-rw-r--r-- | storage/innobase/ut/ut0wqueue.cc | 35 |
11 files changed, 1138 insertions, 1094 deletions
diff --git a/storage/innobase/ut/ut0bh.cc b/storage/innobase/ut/ut0bh.cc deleted file mode 100644 index 1a3038a0d71..00000000000 --- a/storage/innobase/ut/ut0bh.cc +++ /dev/null @@ -1,159 +0,0 @@ -/***************************************************************************//** - -Copyright (c) 2010, 2011, Oracle and/or its affiliates. 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., -51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/******************************************************************//** -@file ut/ut0bh.cc -Binary min-heap implementation. - -Created 2010-05-28 by Sunny Bains -*******************************************************/ - -#include "ut0bh.h" -#include "ut0mem.h" - -#ifdef UNIV_NONINL -#include "ut0bh.ic" -#endif - -#include <string.h> - -/**********************************************************************//** -Create a binary heap. -@return a new binary heap */ -UNIV_INTERN -ib_bh_t* -ib_bh_create( -/*=========*/ - ib_bh_cmp_t compare, /*!< in: comparator */ - ulint sizeof_elem, /*!< in: size of one element */ - ulint max_elems) /*!< in: max elements allowed */ -{ - ulint sz; - ib_bh_t* ib_bh; - - sz = sizeof(*ib_bh) + (sizeof_elem * max_elems); - - ib_bh = (ib_bh_t*) ut_malloc(sz); - memset(ib_bh, 0x0, sz); - - ib_bh->compare = compare; - ib_bh->max_elems = max_elems; - ib_bh->sizeof_elem = sizeof_elem; - - return(ib_bh); -} - -/**********************************************************************//** -Free a binary heap. -@return a new binary heap */ -UNIV_INTERN -void -ib_bh_free( -/*=======*/ - ib_bh_t* ib_bh) /*!< in/own: instance */ -{ - ut_free(ib_bh); -} - -/**********************************************************************//** -Add an element to the binary heap. Note: The element is copied. -@return pointer to added element or NULL if full. */ -UNIV_INTERN -void* -ib_bh_push( -/*=======*/ - ib_bh_t* ib_bh, /*!< in/out: instance */ - const void* elem) /*!< in: element to add */ -{ - void* ptr; - - if (ib_bh_is_full(ib_bh)) { - return(NULL); - } else if (ib_bh_is_empty(ib_bh)) { - ++ib_bh->n_elems; - return(ib_bh_set(ib_bh, 0, elem)); - } else { - ulint i; - - i = ib_bh->n_elems; - - ++ib_bh->n_elems; - - for (ptr = ib_bh_get(ib_bh, i >> 1); - i > 0 && ib_bh->compare(ptr, elem) > 0; - i >>= 1, ptr = ib_bh_get(ib_bh, i >> 1)) { - - ib_bh_set(ib_bh, i, ptr); - } - - ptr = ib_bh_set(ib_bh, i, elem); - } - - return(ptr); -} - -/**********************************************************************//** -Remove the first element from the binary heap. */ -UNIV_INTERN -void -ib_bh_pop( -/*======*/ - ib_bh_t* ib_bh) /*!< in/out: instance */ -{ - byte* ptr; - byte* last; - ulint parent = 0; - - if (ib_bh_is_empty(ib_bh)) { - return; - } else if (ib_bh_size(ib_bh) == 1) { - --ib_bh->n_elems; - return; - } - - last = (byte*) ib_bh_last(ib_bh); - - /* Start from the child node */ - ptr = (byte*) ib_bh_get(ib_bh, 1); - - while (ptr < last) { - /* If the "right" child node is < "left" child node */ - if (ib_bh->compare(ptr + ib_bh->sizeof_elem, ptr) < 0) { - ptr += ib_bh->sizeof_elem; - } - - if (ib_bh->compare(last, ptr) <= 0) { - break; - } - - ib_bh_set(ib_bh, parent, ptr); - - parent = (ptr - (byte*) ib_bh_first(ib_bh)) - / ib_bh->sizeof_elem; - - if ((parent << 1) >= ib_bh_size(ib_bh)) { - break; - } - - ptr = (byte*) ib_bh_get(ib_bh, parent << 1); - } - - --ib_bh->n_elems; - - ib_bh_set(ib_bh, parent, last); -} diff --git a/storage/innobase/ut/ut0crc32.cc b/storage/innobase/ut/ut0crc32.cc index 8f3c699c24f..1e4cc7b8de4 100644 --- a/storage/innobase/ut/ut0crc32.cc +++ b/storage/innobase/ut/ut0crc32.cc @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (C) 2009, 2010 Facebook, Inc. All Rights Reserved. -Copyright (c) 2011, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2010 Facebook, Inc. All Rights Reserved. +Copyright (c) 2011, 2015, Oracle and/or its affiliates. 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 @@ -63,10 +63,9 @@ mysys/my_perf.c, contributed by Facebook under the following license. /* The below CRC32 implementation is based on the implementation included with * zlib with modifications to process 8 bytes at a time and using SSE 4.2 - * extentions when available. The polynomial constant has been changed to + * extensions when available. The polynomial constant has been changed to * match the one used by SSE 4.2 and does not return the same value as the - * version used by zlib. This implementation only supports 64-bit - * little-endian processors. The original zlib copyright notice follows. */ + * version used by zlib. The original zlib copyright notice follows. */ /* crc32.c -- compute the CRC-32 of a buf stream * Copyright (C) 1995-2005 Mark Adler @@ -79,27 +78,356 @@ mysys/my_perf.c, contributed by Facebook under the following license. * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ +// First include (the generated) my_config.h, to get correct platform defines. +#include "my_config.h" +#include <string.h> + #include "univ.i" #include "ut0crc32.h" -#if defined(__linux__) && defined(__powerpc__) -/* Used to detect at runtime if we have vpmsum instructions (PowerISA 2.07) */ -#include <sys/auxv.h> -#include <bits/hwcap.h> -#endif /* defined(__linux__) && defined(__powerpc__) */ +/** Pointer to CRC32 calculation function. */ +ut_crc32_func_t ut_crc32; -#include <string.h> +/** Pointer to CRC32 calculation function, which uses big-endian byte order +when converting byte strings to integers internally. */ +ut_crc32_func_t ut_crc32_legacy_big_endian; -ib_ut_crc32_t ut_crc32; +/** Pointer to CRC32-byte-by-byte calculation function (byte order agnostic, +but very slow). */ +ut_crc32_func_t ut_crc32_byte_by_byte; -/* Precalculated table used to generate the CRC32 if the CPU does not -have support for it */ -static ib_uint32_t ut_crc32_slice8_table[8][256]; -static ibool ut_crc32_slice8_table_initialized = FALSE; +/** Swap the byte order of an 8 byte integer. +@param[in] i 8-byte integer +@return 8-byte integer */ +inline +uint64_t +ut_crc32_swap_byteorder( + uint64_t i) +{ + return(i << 56 + | (i & 0x000000000000FF00ULL) << 40 + | (i & 0x0000000000FF0000ULL) << 24 + | (i & 0x00000000FF000000ULL) << 8 + | (i & 0x000000FF00000000ULL) >> 8 + | (i & 0x0000FF0000000000ULL) >> 24 + | (i & 0x00FF000000000000ULL) >> 40 + | i >> 56); +} + +/* CRC32 hardware implementation. */ /* Flag that tells whether the CPU supports CRC32 or not */ UNIV_INTERN bool ut_crc32_sse2_enabled = false; -UNIV_INTERN bool ut_crc32_power8_enabled = false; +UNIV_INTERN bool ut_crc32_power8_enabled = false; + +#if defined(__GNUC__) && defined(__x86_64__) +/********************************************************************//** +Fetches CPU info */ +static +void +ut_cpuid( +/*=====*/ + uint32_t vend[3], /*!< out: CPU vendor */ + uint32_t* model, /*!< out: CPU model */ + uint32_t* family, /*!< out: CPU family */ + uint32_t* stepping, /*!< out: CPU stepping */ + uint32_t* features_ecx, /*!< out: CPU features ecx */ + uint32_t* features_edx) /*!< out: CPU features edx */ +{ + uint32_t sig; + asm("cpuid" : "=b" (vend[0]), "=c" (vend[2]), "=d" (vend[1]) : "a" (0)); + asm("cpuid" : "=a" (sig), "=c" (*features_ecx), "=d" (*features_edx) + : "a" (1) + : "ebx"); + + *model = ((sig >> 4) & 0xF); + *family = ((sig >> 8) & 0xF); + *stepping = (sig & 0xF); + + if (memcmp(vend, "GenuineIntel", 12) == 0 + || (memcmp(vend, "AuthenticAMD", 12) == 0 && *family == 0xF)) { + + *model += (((sig >> 16) & 0xF) << 4); + *family += ((sig >> 20) & 0xFF); + } +} + +/** Calculate CRC32 over 8-bit data using a hardware/CPU instruction. +@param[in,out] crc crc32 checksum so far when this function is called, +when the function ends it will contain the new checksum +@param[in,out] data data to be checksummed, the pointer will be advanced +with 1 byte +@param[in,out] len remaining bytes, it will be decremented with 1 */ +inline +void +ut_crc32_8_hw( + uint32_t* crc, + const byte** data, + ulint* len) +{ + asm("crc32b %1, %0" + /* output operands */ + : "+r" (*crc) + /* input operands */ + : "rm" ((*data)[0])); + + (*data)++; + (*len)--; +} + +/** Calculate CRC32 over a 64-bit integer using a hardware/CPU instruction. +@param[in] crc crc32 checksum so far +@param[in] data data to be checksummed +@return resulting checksum of crc + crc(data) */ +inline +uint32_t +ut_crc32_64_low_hw( + uint32_t crc, + uint64_t data) +{ + uint64_t crc_64bit = crc; + + asm("crc32q %1, %0" + /* output operands */ + : "+r" (crc_64bit) + /* input operands */ + : "rm" (data)); + + return(static_cast<uint32_t>(crc_64bit)); +} + +/** Calculate CRC32 over 64-bit byte string using a hardware/CPU instruction. +@param[in,out] crc crc32 checksum so far when this function is called, +when the function ends it will contain the new checksum +@param[in,out] data data to be checksummed, the pointer will be advanced +with 8 bytes +@param[in,out] len remaining bytes, it will be decremented with 8 */ +inline +void +ut_crc32_64_hw( + uint32_t* crc, + const byte** data, + ulint* len) +{ + uint64_t data_int = *reinterpret_cast<const uint64_t*>(*data); + +#ifdef WORDS_BIGENDIAN + /* Currently we only support x86_64 (little endian) CPUs. In case + some big endian CPU supports a CRC32 instruction, then maybe we will + need a byte order swap here. */ +#error Dont know how to handle big endian CPUs + /* + data_int = ut_crc32_swap_byteorder(data_int); + */ +#endif /* WORDS_BIGENDIAN */ + + *crc = ut_crc32_64_low_hw(*crc, data_int); + + *data += 8; + *len -= 8; +} + +/** Calculate CRC32 over 64-bit byte string using a hardware/CPU instruction. +The byte string is converted to a 64-bit integer using big endian byte order. +@param[in,out] crc crc32 checksum so far when this function is called, +when the function ends it will contain the new checksum +@param[in,out] data data to be checksummed, the pointer will be advanced +with 8 bytes +@param[in,out] len remaining bytes, it will be decremented with 8 */ +inline +void +ut_crc32_64_legacy_big_endian_hw( + uint32_t* crc, + const byte** data, + ulint* len) +{ + uint64_t data_int = *reinterpret_cast<const uint64_t*>(*data); + +#ifndef WORDS_BIGENDIAN + data_int = ut_crc32_swap_byteorder(data_int); +#else + /* Currently we only support x86_64 (little endian) CPUs. In case + some big endian CPU supports a CRC32 instruction, then maybe we will + NOT need a byte order swap here. */ +#error Dont know how to handle big endian CPUs +#endif /* WORDS_BIGENDIAN */ + + *crc = ut_crc32_64_low_hw(*crc, data_int); + + *data += 8; + *len -= 8; +} + +/** Calculates CRC32 using hardware/CPU instructions. +@param[in] buf data over which to calculate CRC32 +@param[in] len data length +@return CRC-32C (polynomial 0x11EDC6F41) */ +uint32_t +ut_crc32_hw( + const byte* buf, + ulint len) +{ + uint32_t crc = 0xFFFFFFFFU; + + ut_a(ut_crc32_sse2_enabled); + + /* Calculate byte-by-byte up to an 8-byte aligned address. After + this consume the input 8-bytes at a time. */ + while (len > 0 && (reinterpret_cast<uintptr_t>(buf) & 7) != 0) { + ut_crc32_8_hw(&crc, &buf, &len); + } + + /* Perf testing + ./unittest/gunit/innodb/merge_innodb_tests-t --gtest_filter=ut0crc32.perf + on CPU "Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz" + with different N in "while (len >= N) {" shows: + N=16 + 2.867254 sec + 2.866860 sec + 2.867973 sec + + N=32 + 2.715725 sec + 2.713008 sec + 2.712520 sec + (5.36% speedup over N=16) + + N=64 + 2.634140 sec + 2.636558 sec + 2.636488 sec + (2.88% speedup over N=32) + + N=128 + 2.599534 sec + 2.599919 sec + 2.598035 sec + (1.39% speedup over N=64) + + N=256 + 2.576993 sec + 2.576748 sec + 2.575700 sec + (0.87% speedup over N=128) + + N=512 + 2.693928 sec + 2.691663 sec + 2.692142 sec + (4.51% slowdown over N=256) + */ + while (len >= 128) { + /* This call is repeated 16 times. 16 * 8 = 128. */ + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + ut_crc32_64_hw(&crc, &buf, &len); + } + + while (len >= 8) { + ut_crc32_64_hw(&crc, &buf, &len); + } + + while (len > 0) { + ut_crc32_8_hw(&crc, &buf, &len); + } + + return(~crc); +} + +/** Calculates CRC32 using hardware/CPU instructions. +This function uses big endian byte ordering when converting byte sequence to +integers. +@param[in] buf data over which to calculate CRC32 +@param[in] len data length +@return CRC-32C (polynomial 0x11EDC6F41) */ +uint32_t +ut_crc32_legacy_big_endian_hw( + const byte* buf, + ulint len) +{ + uint32_t crc = 0xFFFFFFFFU; + + ut_a(ut_crc32_sse2_enabled); + + /* Calculate byte-by-byte up to an 8-byte aligned address. After + this consume the input 8-bytes at a time. */ + while (len > 0 && (reinterpret_cast<uintptr_t>(buf) & 7) != 0) { + ut_crc32_8_hw(&crc, &buf, &len); + } + + while (len >= 128) { + /* This call is repeated 16 times. 16 * 8 = 128. */ + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + } + + while (len >= 8) { + ut_crc32_64_legacy_big_endian_hw(&crc, &buf, &len); + } + + while (len > 0) { + ut_crc32_8_hw(&crc, &buf, &len); + } + + return(~crc); +} + +/** Calculates CRC32 using hardware/CPU instructions. +This function processes one byte at a time (very slow) and thus it does +not depend on the byte order of the machine. +@param[in] buf data over which to calculate CRC32 +@param[in] len data length +@return CRC-32C (polynomial 0x11EDC6F41) */ +uint32_t +ut_crc32_byte_by_byte_hw( + const byte* buf, + ulint len) +{ + uint32_t crc = 0xFFFFFFFFU; + + ut_a(ut_crc32_sse2_enabled); + + while (len > 0) { + ut_crc32_8_hw(&crc, &buf, &len); + } + + return(~crc); +} +#endif /* defined(__GNUC__) && defined(__x86_64__) */ + +/* CRC32 software implementation. */ + +/* Precalculated table used to generate the CRC32 if the CPU does not +have support for it */ +static uint32_t ut_crc32_slice8_table[8][256]; +static bool ut_crc32_slice8_table_initialized = false; /********************************************************************//** Initializes the table that is used to generate the CRC32 if the CPU does @@ -110,10 +438,10 @@ ut_crc32_slice8_table_init() /*========================*/ { /* bit-reversed poly 0x1EDC6F41 (from SSE42 crc32 instruction) */ - static const ib_uint32_t poly = 0x82f63b78; - ib_uint32_t n; - ib_uint32_t k; - ib_uint32_t c; + static const uint32_t poly = 0x82f63b78; + uint32_t n; + uint32_t k; + uint32_t c; for (n = 0; n < 256; n++) { c = n; @@ -131,187 +459,243 @@ ut_crc32_slice8_table_init() } } - ut_crc32_slice8_table_initialized = TRUE; + ut_crc32_slice8_table_initialized = true; } -#if defined(__GNUC__) && defined(__x86_64__) -/********************************************************************//** -Fetches CPU info */ -static +/** Calculate CRC32 over 8-bit data using a software implementation. +@param[in,out] crc crc32 checksum so far when this function is called, +when the function ends it will contain the new checksum +@param[in,out] data data to be checksummed, the pointer will be advanced +with 1 byte +@param[in,out] len remaining bytes, it will be decremented with 1 */ +inline void -ut_cpuid( -/*=====*/ - ib_uint32_t vend[3], /*!< out: CPU vendor */ - ib_uint32_t* model, /*!< out: CPU model */ - ib_uint32_t* family, /*!< out: CPU family */ - ib_uint32_t* stepping, /*!< out: CPU stepping */ - ib_uint32_t* features_ecx, /*!< out: CPU features ecx */ - ib_uint32_t* features_edx) /*!< out: CPU features edx */ +ut_crc32_8_sw( + uint32_t* crc, + const byte** data, + ulint* len) { - ib_uint32_t sig; - asm("cpuid" : "=b" (vend[0]), "=c" (vend[2]), "=d" (vend[1]) : "a" (0)); - asm("cpuid" : "=a" (sig), "=c" (*features_ecx), "=d" (*features_edx) - : "a" (1) - : "ebx"); + const uint8_t i = (*crc ^ (*data)[0]) & 0xFF; - *model = ((sig >> 4) & 0xF); - *family = ((sig >> 8) & 0xF); - *stepping = (sig & 0xF); + *crc = (*crc >> 8) ^ ut_crc32_slice8_table[0][i]; - if (memcmp(vend, "GenuineIntel", 12) == 0 - || (memcmp(vend, "AuthenticAMD", 12) == 0 && *family == 0xF)) { + (*data)++; + (*len)--; +} - *model += (((sig >> 16) & 0xF) << 4); - *family += ((sig >> 20) & 0xFF); - } +/** Calculate CRC32 over a 64-bit integer using a software implementation. +@param[in] crc crc32 checksum so far +@param[in] data data to be checksummed +@return resulting checksum of crc + crc(data) */ +inline +uint32_t +ut_crc32_64_low_sw( + uint32_t crc, + uint64_t data) +{ + const uint64_t i = crc ^ data; + + return( + ut_crc32_slice8_table[7][(i ) & 0xFF] ^ + ut_crc32_slice8_table[6][(i >> 8) & 0xFF] ^ + ut_crc32_slice8_table[5][(i >> 16) & 0xFF] ^ + ut_crc32_slice8_table[4][(i >> 24) & 0xFF] ^ + ut_crc32_slice8_table[3][(i >> 32) & 0xFF] ^ + ut_crc32_slice8_table[2][(i >> 40) & 0xFF] ^ + ut_crc32_slice8_table[1][(i >> 48) & 0xFF] ^ + ut_crc32_slice8_table[0][(i >> 56)] + ); } -/* opcodes taken from objdump of "crc32b (%%rdx), %%rcx" -for RHEL4 support (GCC 3 doesn't support this instruction) */ -#define ut_crc32_sse42_byte \ - asm(".byte 0xf2, 0x48, 0x0f, 0x38, 0xf0, 0x0a" \ - : "=c"(crc) : "c"(crc), "d"(buf)); \ - len--, buf++ - -/* opcodes taken from objdump of "crc32q (%%rdx), %%rcx" -for RHEL4 support (GCC 3 doesn't support this instruction) */ -#define ut_crc32_sse42_quadword \ - asm(".byte 0xf2, 0x48, 0x0f, 0x38, 0xf1, 0x0a" \ - : "=c"(crc) : "c"(crc), "d"(buf)); \ - len -= 8, buf += 8 -#endif /* defined(__GNUC__) && defined(__x86_64__) */ +/** Calculate CRC32 over 64-bit byte string using a software implementation. +@param[in,out] crc crc32 checksum so far when this function is called, +when the function ends it will contain the new checksum +@param[in,out] data data to be checksummed, the pointer will be advanced +with 8 bytes +@param[in,out] len remaining bytes, it will be decremented with 8 */ +inline +void +ut_crc32_64_sw( + uint32_t* crc, + const byte** data, + ulint* len) +{ + uint64_t data_int = *reinterpret_cast<const uint64_t*>(*data); -#if defined(__powerpc__) -extern "C" { -unsigned int crc32_vpmsum(unsigned int crc, const unsigned char *p, unsigned long len); -}; -#endif /* __powerpc__ */ +#ifdef WORDS_BIGENDIAN + data_int = ut_crc32_swap_byteorder(data_int); +#endif /* WORDS_BIGENDIAN */ -UNIV_INLINE -ib_uint32_t -ut_crc32_power8( -/*===========*/ - const byte* buf, /*!< in: data over which to calculate CRC32 */ - ulint len) /*!< in: data length */ + *crc = ut_crc32_64_low_sw(*crc, data_int); + + *data += 8; + *len -= 8; +} + +/** Calculate CRC32 over 64-bit byte string using a software implementation. +The byte string is converted to a 64-bit integer using big endian byte order. +@param[in,out] crc crc32 checksum so far when this function is called, +when the function ends it will contain the new checksum +@param[in,out] data data to be checksummed, the pointer will be advanced +with 8 bytes +@param[in,out] len remaining bytes, it will be decremented with 8 */ +inline +void +ut_crc32_64_legacy_big_endian_sw( + uint32_t* crc, + const byte** data, + ulint* len) { -#if defined(__powerpc__) && !defined(WORDS_BIGENDIAN) - return crc32_vpmsum(0, buf, len); -#else - ut_error; - /* silence compiler warning about unused parameters */ - return((ib_uint32_t) buf[len]); -#endif /* __powerpc__ */ + uint64_t data_int = *reinterpret_cast<const uint64_t*>(*data); + +#ifndef WORDS_BIGENDIAN + data_int = ut_crc32_swap_byteorder(data_int); +#endif /* WORDS_BIGENDIAN */ + + *crc = ut_crc32_64_low_sw(*crc, data_int); + + *data += 8; + *len -= 8; } -/********************************************************************//** -Calculates CRC32 using CPU instructions. +/** Calculates CRC32 in software, without using CPU instructions. +@param[in] buf data over which to calculate CRC32 +@param[in] len data length @return CRC-32C (polynomial 0x11EDC6F41) */ -UNIV_INLINE -ib_uint32_t -ut_crc32_sse42( -/*===========*/ - const byte* buf, /*!< in: data over which to calculate CRC32 */ - ulint len) /*!< in: data length */ +uint32_t +ut_crc32_sw( + const byte* buf, + ulint len) { -#if defined(__GNUC__) && defined(__x86_64__) - ib_uint64_t crc = (ib_uint32_t) (-1); + uint32_t crc = 0xFFFFFFFFU; - ut_a(ut_crc32_sse2_enabled); + ut_a(ut_crc32_slice8_table_initialized); - while (len && ((ulint) buf & 7)) { - ut_crc32_sse42_byte; + /* Calculate byte-by-byte up to an 8-byte aligned address. After + this consume the input 8-bytes at a time. */ + while (len > 0 && (reinterpret_cast<uintptr_t>(buf) & 7) != 0) { + ut_crc32_8_sw(&crc, &buf, &len); } - while (len >= 32) { - ut_crc32_sse42_quadword; - ut_crc32_sse42_quadword; - ut_crc32_sse42_quadword; - ut_crc32_sse42_quadword; + while (len >= 128) { + /* This call is repeated 16 times. 16 * 8 = 128. */ + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); + ut_crc32_64_sw(&crc, &buf, &len); } while (len >= 8) { - ut_crc32_sse42_quadword; + ut_crc32_64_sw(&crc, &buf, &len); } - while (len) { - ut_crc32_sse42_byte; + while (len > 0) { + ut_crc32_8_sw(&crc, &buf, &len); } - return((ib_uint32_t) ((~crc) & 0xFFFFFFFF)); -#else - ut_error; - /* silence compiler warning about unused parameters */ - return((ib_uint32_t) buf[len]); -#endif /* defined(__GNUC__) && defined(__x86_64__) */ + return(~crc); } -#define ut_crc32_slice8_byte \ - crc = (crc >> 8) ^ ut_crc32_slice8_table[0][(crc ^ *buf++) & 0xFF]; \ - len-- - -#define ut_crc32_slice8_quadword \ - crc ^= *(ib_uint64_t*) buf; \ - crc = ut_crc32_slice8_table[7][(crc ) & 0xFF] ^ \ - ut_crc32_slice8_table[6][(crc >> 8) & 0xFF] ^ \ - ut_crc32_slice8_table[5][(crc >> 16) & 0xFF] ^ \ - ut_crc32_slice8_table[4][(crc >> 24) & 0xFF] ^ \ - ut_crc32_slice8_table[3][(crc >> 32) & 0xFF] ^ \ - ut_crc32_slice8_table[2][(crc >> 40) & 0xFF] ^ \ - ut_crc32_slice8_table[1][(crc >> 48) & 0xFF] ^ \ - ut_crc32_slice8_table[0][(crc >> 56)]; \ - len -= 8, buf += 8 - -/********************************************************************//** -Calculates CRC32 manually. +/** Calculates CRC32 in software, without using CPU instructions. +This function uses big endian byte ordering when converting byte sequence to +integers. +@param[in] buf data over which to calculate CRC32 +@param[in] len data length @return CRC-32C (polynomial 0x11EDC6F41) */ -UNIV_INLINE -ib_uint32_t -ut_crc32_slice8( -/*============*/ - const byte* buf, /*!< in: data over which to calculate CRC32 */ - ulint len) /*!< in: data length */ +uint32_t +ut_crc32_legacy_big_endian_sw( + const byte* buf, + ulint len) { - ib_uint64_t crc = (ib_uint32_t) (-1); + uint32_t crc = 0xFFFFFFFFU; ut_a(ut_crc32_slice8_table_initialized); - while (len && ((ulint) buf & 7)) { - ut_crc32_slice8_byte; + /* Calculate byte-by-byte up to an 8-byte aligned address. After + this consume the input 8-bytes at a time. */ + while (len > 0 && (reinterpret_cast<uintptr_t>(buf) & 7) != 0) { + ut_crc32_8_sw(&crc, &buf, &len); } - while (len >= 32) { - ut_crc32_slice8_quadword; - ut_crc32_slice8_quadword; - ut_crc32_slice8_quadword; - ut_crc32_slice8_quadword; + while (len >= 128) { + /* This call is repeated 16 times. 16 * 8 = 128. */ + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); } while (len >= 8) { - ut_crc32_slice8_quadword; + ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); } - while (len) { - ut_crc32_slice8_byte; + while (len > 0) { + ut_crc32_8_sw(&crc, &buf, &len); } - return((ib_uint32_t) ((~crc) & 0xFFFFFFFF)); + return(~crc); +} + +/** Calculates CRC32 in software, without using CPU instructions. +This function processes one byte at a time (very slow) and thus it does +not depend on the byte order of the machine. +@param[in] buf data over which to calculate CRC32 +@param[in] len data length +@return CRC-32C (polynomial 0x11EDC6F41) */ +uint32_t +ut_crc32_byte_by_byte_sw( + const byte* buf, + ulint len) +{ + uint32_t crc = 0xFFFFFFFFU; + + ut_a(ut_crc32_slice8_table_initialized); + + while (len > 0) { + ut_crc32_8_sw(&crc, &buf, &len); + } + + return(~crc); } /********************************************************************//** -Initializes the data structures used by ut_crc32(). Does not do any +Initializes the data structures used by ut_crc32*(). Does not do any allocations, would not hurt if called twice, but would be pointless. */ -UNIV_INTERN void ut_crc32_init() /*===========*/ { #if defined(__GNUC__) && defined(__x86_64__) - ib_uint32_t vend[3]; - ib_uint32_t model; - ib_uint32_t family; - ib_uint32_t stepping; - ib_uint32_t features_ecx; - ib_uint32_t features_edx; + uint32_t vend[3]; + uint32_t model; + uint32_t family; + uint32_t stepping; + uint32_t features_ecx; + uint32_t features_edx; ut_cpuid(vend, &model, &family, &stepping, &features_ecx, &features_edx); @@ -336,20 +720,18 @@ ut_crc32_init() ut_crc32_sse2_enabled = (features_ecx >> 20) & 1; #endif /* UNIV_DEBUG_VALGRIND */ -#endif /* defined(__GNUC__) && defined(__x86_64__) */ + if (ut_crc32_sse2_enabled) { + ut_crc32 = ut_crc32_hw; + ut_crc32_legacy_big_endian = ut_crc32_legacy_big_endian_hw; + ut_crc32_byte_by_byte = ut_crc32_byte_by_byte_hw; + } -#if defined(__linux__) && defined(__powerpc__) && defined(AT_HWCAP2) \ - && !defined(WORDS_BIGENDIAN) - if (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07) - ut_crc32_power8_enabled = true; -#endif /* defined(__linux__) && defined(__powerpc__) */ +#endif /* defined(__GNUC__) && defined(__x86_64__) */ - if (ut_crc32_sse2_enabled) { - ut_crc32 = ut_crc32_sse42; - } else if (ut_crc32_power8_enabled) { - ut_crc32 = ut_crc32_power8; - } else { + if (!ut_crc32_sse2_enabled) { ut_crc32_slice8_table_init(); - ut_crc32 = ut_crc32_slice8; + ut_crc32 = ut_crc32_sw; + ut_crc32_legacy_big_endian = ut_crc32_legacy_big_endian_sw; + ut_crc32_byte_by_byte = ut_crc32_byte_by_byte_sw; } } diff --git a/storage/innobase/ut/ut0dbg.cc b/storage/innobase/ut/ut0dbg.cc index a1cad144da4..673c8d9150d 100644 --- a/storage/innobase/ut/ut0dbg.cc +++ b/storage/innobase/ut/ut0dbg.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2014, Oracle and/or its affiliates. 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 @@ -23,21 +23,12 @@ Debug utilities for Innobase. Created 1/30/1994 Heikki Tuuri **********************************************************************/ -#include "univ.i" -#include "ut0dbg.h" -#ifndef UNIV_HOTBACKUP -# include "ha_prototypes.h" -#endif /* !UNIV_HOTBACKUP */ +#include "ha_prototypes.h" -#if defined(__GNUC__) && (__GNUC__ > 2) -#else -/** This is used to eliminate compiler warnings */ -UNIV_INTERN ulint ut_dbg_zero = 0; -#endif +#include "ut0dbg.h" /*************************************************************//** Report a failed assertion. */ -UNIV_INTERN void ut_dbg_assertion_failed( /*====================*/ @@ -70,70 +61,8 @@ ut_dbg_assertion_failed( "InnoDB: corruption in the InnoDB tablespace. Please refer to\n" "InnoDB: " REFMAN "forcing-innodb-recovery.html\n" "InnoDB: about forcing recovery.\n", stderr); -} - -#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); + fflush(stderr); + fflush(stdout); + abort(); } - -/*******************************************************************//** -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/innobase/ut/ut0list.cc b/storage/innobase/ut/ut0list.cc index f906061d185..f62cbf8232b 100644 --- a/storage/innobase/ut/ut0list.cc +++ b/storage/innobase/ut/ut0list.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2006, 2014, Oracle and/or its affiliates. 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 @@ -30,15 +30,14 @@ Created 4/26/2006 Osku Salerma /****************************************************************//** Create a new list. -@return list */ -UNIV_INTERN +@return list */ ib_list_t* ib_list_create(void) /*=================*/ { ib_list_t* list; - list = static_cast<ib_list_t*>(mem_alloc(sizeof(*list))); + list = static_cast<ib_list_t*>(ut_malloc_nokey(sizeof(*list))); list->first = NULL; list->last = NULL; @@ -50,8 +49,7 @@ ib_list_create(void) /****************************************************************//** 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 +@return list */ ib_list_t* ib_list_create_heap( /*================*/ @@ -70,7 +68,6 @@ ib_list_create_heap( /****************************************************************//** Free a list. */ -UNIV_INTERN void ib_list_free( /*=========*/ @@ -82,13 +79,12 @@ ib_list_free( 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); + ut_free(list); } /****************************************************************//** Add the data to the start of the list. -@return new list node */ -UNIV_INTERN +@return new list node */ ib_list_node_t* ib_list_add_first( /*==============*/ @@ -101,8 +97,7 @@ ib_list_add_first( /****************************************************************//** Add the data to the end of the list. -@return new list node */ -UNIV_INTERN +@return new list node */ ib_list_node_t* ib_list_add_last( /*=============*/ @@ -115,8 +110,7 @@ ib_list_add_last( /****************************************************************//** Add the data after the indicated node. -@return new list node */ -UNIV_INTERN +@return new list node */ ib_list_node_t* ib_list_add_after( /*==============*/ @@ -172,7 +166,6 @@ ib_list_add_after( /****************************************************************//** Remove the node from the list. */ -UNIV_INTERN void ib_list_remove( /*===========*/ diff --git a/storage/innobase/ut/ut0mem.cc b/storage/innobase/ut/ut0mem.cc index 2bb5d9ce332..0ad251be157 100644 --- a/storage/innobase/ut/ut0mem.cc +++ b/storage/innobase/ut/ut0mem.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2014, Oracle and/or its affiliates. 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 @@ -32,337 +32,14 @@ Created 5/11/1994 Heikki Tuuri #ifndef UNIV_HOTBACKUP # include "os0thread.h" # include "srv0srv.h" - -#include <stdlib.h> - -/** 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; - -#ifdef UNIV_PFS_MUTEX -/* Key to register server_mutex with performance schema */ -UNIV_INTERN mysql_pfs_key_t ut_list_mutex_key; -#endif - -/** Dynamically allocated memory block */ -struct ut_mem_block_t{ - 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_t::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_key, &ut_list_mutex); - UT_LIST_INIT(ut_mem_block_list); - ut_mem_block_list_inited = TRUE; -} -#endif /* !UNIV_HOTBACKUP */ - -/**********************************************************************//** -Allocates memory. -@return own: allocated memory */ -UNIV_INTERN -void* -ut_malloc_low( -/*==========*/ - ulint n, /*!< in: number of bytes to allocate */ - 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); - - 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 */ - 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); - } - } - - 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); - - return(ret); -#endif /* !UNIV_HOTBACKUP */ -} - -/**********************************************************************//** -Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is -a nop. */ -UNIV_INTERN -void -ut_free( -/*====*/ - void* ptr) /*!< in, own: memory block, can be NULL */ -{ -#ifndef UNIV_HOTBACKUP - ut_mem_block_t* block; - - if (ptr == NULL) { - return; - } else 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.cc. 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); - } - - ut_mem_block_list_inited = FALSE; -} +# include <stdlib.h> #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 +@return strlen(src) */ ulint ut_strlcpy( /*=======*/ @@ -385,8 +62,7 @@ ut_strlcpy( /**********************************************************************//** 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 +@return strlen(src) */ ulint ut_strlcpy_rev( /*===========*/ @@ -409,8 +85,7 @@ ut_strlcpy_rev( /**********************************************************************//** 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 +@return the number of times s2 occurs in s1 */ ulint ut_strcount( /*========*/ @@ -442,12 +117,11 @@ ut_strcount( /******************************************************************** Concatenate 3 strings.*/ - char* ut_str3cat( /*=======*/ /* out, own: concatenated string, must be - freed with mem_free() */ + freed with ut_free() */ const char* s1, /* in: string 1 */ const char* s2, /* in: string 2 */ const char* s3) /* in: string 3 */ @@ -457,7 +131,7 @@ ut_str3cat( ulint s2_len = strlen(s2); ulint s3_len = strlen(s3); - s = static_cast<char*>(mem_alloc(s1_len + s2_len + s3_len + 1)); + s = static_cast<char*>(ut_malloc_nokey(s1_len + s2_len + s3_len + 1)); memcpy(s, s1, s1_len); memcpy(s + s1_len, s2, s2_len); @@ -470,8 +144,7 @@ ut_str3cat( /**********************************************************************//** 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 +@return own: modified string, must be freed with ut_free() */ char* ut_strreplace( /*==========*/ @@ -497,7 +170,7 @@ ut_strreplace( } new_str = static_cast<char*>( - mem_alloc(str_len + count * len_delta + 1)); + ut_malloc_nokey(str_len + count * len_delta + 1)); ptr = new_str; @@ -527,83 +200,4 @@ ut_strreplace( 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/innobase/ut/ut0new.cc b/storage/innobase/ut/ut0new.cc new file mode 100644 index 00000000000..ed725819b8a --- /dev/null +++ b/storage/innobase/ut/ut0new.cc @@ -0,0 +1,227 @@ +/***************************************************************************** + +Copyright (c) 2014, 2015, Oracle and/or its affiliates. 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., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/**************************************************//** +@file ut/ut0new.cc +Instrumented memory allocator. + +Created May 26, 2014 Vasil Dimov +*******************************************************/ + +#include "univ.i" + +#include "ut0new.h" + +/** Maximum number of retries to allocate memory. */ +const size_t alloc_max_retries = 60; + +/** Keys for registering allocations with performance schema. +Keep this list alphabetically sorted. */ +PSI_memory_key mem_key_ahi; +PSI_memory_key mem_key_buf_buf_pool; +PSI_memory_key mem_key_dict_stats_bg_recalc_pool_t; +PSI_memory_key mem_key_dict_stats_index_map_t; +PSI_memory_key mem_key_dict_stats_n_diff_on_level; +PSI_memory_key mem_key_other; +PSI_memory_key mem_key_row_log_buf; +PSI_memory_key mem_key_row_merge_sort; +PSI_memory_key mem_key_std; +PSI_memory_key mem_key_trx_sys_t_rw_trx_ids; +PSI_memory_key mem_key_partitioning; + +#ifdef UNIV_PFS_MEMORY + +/** Auxiliary array of performance schema 'PSI_memory_info'. +Each allocation appears in +performance_schema.memory_summary_global_by_event_name (and alike) in the form +of e.g. 'memory/innodb/NAME' where the last component NAME is picked from +the list below: +1. If key is specified, then the respective name is used +2. Without a specified key, allocations from inside std::* containers use + mem_key_std +3. Without a specified key, allocations from outside std::* pick up the key + based on the file name, and if file name is not found in the predefined list + (in ut_new_boot()) then mem_key_other is used. +Keep this list alphabetically sorted. */ +static PSI_memory_info pfs_info[] = { + {&mem_key_ahi, "adaptive hash index", 0}, + {&mem_key_buf_buf_pool, "buf_buf_pool", 0}, + {&mem_key_dict_stats_bg_recalc_pool_t, "dict_stats_bg_recalc_pool_t", 0}, + {&mem_key_dict_stats_index_map_t, "dict_stats_index_map_t", 0}, + {&mem_key_dict_stats_n_diff_on_level, "dict_stats_n_diff_on_level", 0}, + {&mem_key_other, "other", 0}, + {&mem_key_row_log_buf, "row_log_buf", 0}, + {&mem_key_row_merge_sort, "row_merge_sort", 0}, + {&mem_key_std, "std", 0}, + {&mem_key_trx_sys_t_rw_trx_ids, "trx_sys_t::rw_trx_ids", 0}, + {&mem_key_partitioning, "partitioning", 0}, +}; + +/** Map used for default performance schema keys, based on file name of the +caller. The key is the file name of the caller and the value is a pointer +to a PSI_memory_key variable to be passed to performance schema methods. +We use ut_strcmp_functor because by default std::map will compare the pointers +themselves (cont char*) and not do strcmp(). */ +typedef std::map<const char*, PSI_memory_key*, ut_strcmp_functor> + mem_keys_auto_t; + +/** Map of filename/pfskey, used for tracing allocations that have not +provided a manually created pfs key. This map is only ever modified (bulk +insert) at startup in a single-threaded environment by ut_new_boot(). +Later it is only read (only std::map::find() is called) from multithreaded +environment, thus it is not protected by any latch. */ +static mem_keys_auto_t mem_keys_auto; + +#endif /* UNIV_PFS_MEMORY */ + +/** Setup the internal objects needed for UT_NEW() to operate. +This must be called before the first call to UT_NEW(). */ +void +ut_new_boot() +{ +#ifdef UNIV_PFS_MEMORY + static const char* auto_event_names[] = { + /* Keep this list alphabetically sorted. */ + "api0api", + "btr0btr", + "btr0bulk", + "btr0cur", + "btr0pcur", + "btr0sea", + "buf0buf", + "buf0dblwr", + "buf0dump", + "buf0flu", + "buf0lru", + "dict0dict", + "dict0mem", + "dict0stats", + "dict0stats_bg", + "eval0eval", + "fil0fil", + "fsp0file", + "fsp0space", + "fsp0sysspace", + "fts0ast", + "fts0config", + "fts0fts", + "fts0opt", + "fts0pars", + "fts0que", + "fts0sql", + "gis0sea", + "ha0ha", + "ha_innodb", + "handler0alter", + "hash0hash", + "i_s", + "ibuf0ibuf", + "lexyy", + "lock0lock", + "log0log", + "log0recv", + "mem0mem", + "os0event", + "os0file", + "page0cur", + "page0zip", + "pars0lex", + "read0read", + "rem0rec", + "row0ftsort", + "row0import", + "row0log", + "row0merge", + "row0mysql", + "row0sel", + "row0trunc", + "srv0conc", + "srv0srv", + "srv0start", + "sync0arr", + "sync0debug", + "sync0rw", + "sync0types", + "trx0i_s", + "trx0purge", + "trx0roll", + "trx0rseg", + "trx0sys", + "trx0trx", + "trx0undo", + "usr0sess", + "ut0list", + "ut0mem", + "ut0mutex", + "ut0pool", + "ut0rbt", + "ut0wqueue", + }; + static const size_t n_auto = UT_ARR_SIZE(auto_event_names); + static PSI_memory_key auto_event_keys[n_auto]; + static PSI_memory_info pfs_info_auto[n_auto]; + + for (size_t i = 0; i < n_auto; i++) { + + const std::pair<mem_keys_auto_t::iterator, bool> ret + __attribute__((unused)) + = mem_keys_auto.insert( + mem_keys_auto_t::value_type(auto_event_names[i], + &auto_event_keys[i])); + + /* ret.second is true if new element has been inserted */ + ut_a(ret.second); + + /* e.g. "btr0btr" */ + pfs_info_auto[i].m_name = auto_event_names[i]; + + /* a pointer to the pfs key */ + pfs_info_auto[i].m_key = &auto_event_keys[i]; + + pfs_info_auto[i].m_flags = 0; + } + + PSI_MEMORY_CALL(register_memory)("innodb", + pfs_info, + UT_ARR_SIZE(pfs_info)); + PSI_MEMORY_CALL(register_memory)("innodb", + pfs_info_auto, + n_auto); +#endif /* UNIV_PFS_MEMORY */ +} + +#ifdef UNIV_PFS_MEMORY + +/** Retrieve a memory key (registered with PFS), given a portion of the file +name of the caller. +@param[in] file portion of the filename - basename without an extension +@return registered memory key or PSI_NOT_INSTRUMENTED if not found */ +PSI_memory_key +ut_new_get_key_by_file( + const char* file) +{ + mem_keys_auto_t::const_iterator el = mem_keys_auto.find(file); + + if (el != mem_keys_auto.end()) { + return(*(el->second)); + } + + return(PSI_NOT_INSTRUMENTED); +} + +#endif /* UNIV_PFS_MEMORY */ diff --git a/storage/innobase/ut/ut0rbt.cc b/storage/innobase/ut/ut0rbt.cc index e93844af600..8345c2c7593 100644 --- a/storage/innobase/ut/ut0rbt.cc +++ b/storage/innobase/ut/ut0rbt.cc @@ -1,6 +1,6 @@ /***************************************************************************//** -Copyright (c) 2007, 2010, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2014, Oracle and/or its affiliates. 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 @@ -23,6 +23,9 @@ Red-Black tree implementation Created 2007-03-20 Sunny Bains ***********************************************************************/ +#include "univ.i" + +#include "ut0new.h" #include "ut0rbt.h" /**********************************************************************//** @@ -71,7 +74,7 @@ rbt_print_subtree( /**********************************************************************//** Verify that the keys are in order. -@return TRUE of OK. FALSE if not ordered */ +@return TRUE of OK. FALSE if not ordered */ static ibool rbt_check_ordering( @@ -110,7 +113,7 @@ rbt_check_ordering( /**********************************************************************//** Check that every path from the root to the leaves has the same count. Count is expressed in the number of black nodes. -@return 0 on failure else black height of the subtree */ +@return 0 on failure else black height of the subtree */ static ibool rbt_count_black_nodes( @@ -388,7 +391,7 @@ rbt_balance_tree( /**********************************************************************//** Find the given node's successor. -@return successor node or NULL if no successor */ +@return successor node or NULL if no successor */ static ib_rbt_node_t* rbt_find_successor( @@ -428,7 +431,7 @@ rbt_find_successor( /**********************************************************************//** Find the given node's precedecessor. -@return predecessor node or NULL if no predecesor */ +@return predecessor node or NULL if no predecesor */ static ib_rbt_node_t* rbt_find_predecessor( @@ -519,7 +522,7 @@ rbt_replace_node( /**********************************************************************//** Detach node from the tree replacing it with one of it's children. -@return the child node that now occupies the position of the detached node */ +@return the child node that now occupies the position of the detached node */ static ib_rbt_node_t* rbt_detach_node( @@ -562,7 +565,7 @@ rbt_detach_node( /**********************************************************************//** Rebalance the right sub-tree after deletion. -@return node to rebalance if more rebalancing required else NULL */ +@return node to rebalance if more rebalancing required else NULL */ static ib_rbt_node_t* rbt_balance_right( @@ -622,7 +625,7 @@ rbt_balance_right( /**********************************************************************//** Rebalance the left sub-tree after deletion. -@return node to rebalance if more rebalancing required else NULL */ +@return node to rebalance if more rebalancing required else NULL */ static ib_rbt_node_t* rbt_balance_left( @@ -751,7 +754,6 @@ rbt_free_node( /**********************************************************************//** Free all the nodes and free the tree. */ -UNIV_INTERN void rbt_free( /*=====*/ @@ -765,8 +767,7 @@ rbt_free( /**********************************************************************//** Create an instance of a red black tree, whose comparison function takes an argument -@return an empty rb tree */ -UNIV_INTERN +@return an empty rb tree */ ib_rbt_t* rbt_create_arg_cmp( /*===============*/ @@ -788,8 +789,7 @@ rbt_create_arg_cmp( /**********************************************************************//** Create an instance of a red black tree. -@return an empty rb tree */ -UNIV_INTERN +@return an empty rb tree */ ib_rbt_t* rbt_create( /*=======*/ @@ -799,22 +799,19 @@ rbt_create( ib_rbt_t* tree; ib_rbt_node_t* node; - tree = (ib_rbt_t*) ut_malloc(sizeof(*tree)); - memset(tree, 0, sizeof(*tree)); + tree = (ib_rbt_t*) ut_zalloc_nokey(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 = tree->nil = (ib_rbt_node_t*) ut_zalloc_nokey(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 = tree->root = (ib_rbt_node_t*) ut_zalloc_nokey(sizeof(*node)); node->color = IB_RBT_BLACK; node->parent = node->left = node->right = tree->nil; @@ -826,8 +823,7 @@ rbt_create( /**********************************************************************//** Generic insert of a value in the rb tree. -@return inserted node */ -UNIV_INTERN +@return inserted node */ const ib_rbt_node_t* rbt_insert( /*=======*/ @@ -839,7 +835,7 @@ rbt_insert( ib_rbt_node_t* node; /* Create the node that will hold the value data. */ - node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree)); + node = (ib_rbt_node_t*) ut_malloc_nokey(SIZEOF_NODE(tree)); memcpy(node->value, value, tree->sizeof_value); node->parent = node->left = node->right = tree->nil; @@ -855,8 +851,7 @@ rbt_insert( /**********************************************************************//** Add a new node to the tree, useful for data that is pre-sorted. -@return appended node */ -UNIV_INTERN +@return appended node */ const ib_rbt_node_t* rbt_add_node( /*=========*/ @@ -868,7 +863,7 @@ rbt_add_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)); + node = (ib_rbt_node_t*) ut_malloc_nokey(SIZEOF_NODE(tree)); memcpy(node->value, value, tree->sizeof_value); node->parent = node->left = node->right = tree->nil; @@ -893,8 +888,7 @@ rbt_add_node( /**********************************************************************//** Find a matching node in the rb tree. -@return NULL if not found else the node where key was found */ -UNIV_INTERN +@return NULL if not found else the node where key was found */ const ib_rbt_node_t* rbt_lookup( /*=======*/ @@ -928,8 +922,7 @@ rbt_lookup( /**********************************************************************//** Delete a node indentified by key. -@return TRUE if success FALSE if not found */ -UNIV_INTERN +@return TRUE if success FALSE if not found */ ibool rbt_delete( /*=======*/ @@ -952,8 +945,7 @@ rbt_delete( /**********************************************************************//** Remove a node from the rb tree, the node is not free'd, that is the callers responsibility. -@return deleted node but without the const */ -UNIV_INTERN +@return deleted node but without the const */ ib_rbt_node_t* rbt_remove_node( /*============*/ @@ -975,8 +967,7 @@ rbt_remove_node( /**********************************************************************//** Find the node that has the lowest key that is >= key. -@return node satisfying the lower bound constraint or NULL */ -UNIV_INTERN +@return node satisfying the lower bound constraint or NULL */ const ib_rbt_node_t* rbt_lower_bound( /*============*/ @@ -1016,8 +1007,7 @@ rbt_lower_bound( /**********************************************************************//** Find the node that has the greatest key that is <= key. -@return node satisfying the upper bound constraint or NULL */ -UNIV_INTERN +@return node satisfying the upper bound constraint or NULL */ const ib_rbt_node_t* rbt_upper_bound( /*============*/ @@ -1057,8 +1047,7 @@ rbt_upper_bound( /**********************************************************************//** Find the node that has the greatest key that is <= key. -@return value of result */ -UNIV_INTERN +@return value of result */ int rbt_search( /*=======*/ @@ -1098,8 +1087,7 @@ rbt_search( /**********************************************************************//** Find the node that has the greatest key that is <= key. But use the supplied comparison function. -@return value of result */ -UNIV_INTERN +@return value of result */ int rbt_search_cmp( /*===========*/ @@ -1143,7 +1131,6 @@ rbt_search_cmp( /**********************************************************************//** Return the left most node in the tree. */ -UNIV_INTERN const ib_rbt_node_t* rbt_first( /*======*/ @@ -1163,8 +1150,7 @@ rbt_first( /**********************************************************************//** Return the right most node in the tree. -@return the rightmost node or NULL */ -UNIV_INTERN +@return the rightmost node or NULL */ const ib_rbt_node_t* rbt_last( /*=====*/ @@ -1183,8 +1169,7 @@ rbt_last( /**********************************************************************//** Return the next node. -@return node next from current */ -UNIV_INTERN +@return node next from current */ const ib_rbt_node_t* rbt_next( /*=====*/ @@ -1196,8 +1181,7 @@ rbt_next( /**********************************************************************//** Return the previous node. -@return node prev from current */ -UNIV_INTERN +@return node prev from current */ const ib_rbt_node_t* rbt_prev( /*=====*/ @@ -1209,7 +1193,6 @@ rbt_prev( /**********************************************************************//** Reset the tree. Delete all the nodes. */ -UNIV_INTERN void rbt_clear( /*======*/ @@ -1223,8 +1206,7 @@ rbt_clear( /**********************************************************************//** Merge the node from dst into src. Return the number of nodes merged. -@return no. of recs merged */ -UNIV_INTERN +@return no. of recs merged */ ulint rbt_merge_uniq( /*===========*/ @@ -1254,8 +1236,7 @@ rbt_merge_uniq( Merge the node from dst into src. Return the number of nodes merged. Delete the nodes from src after copying node to dst. As a side effect the duplicates will be left untouched in the src. -@return no. of recs merged */ -UNIV_INTERN +@return no. of recs merged */ ulint rbt_merge_uniq_destructive( /*=======================*/ @@ -1301,8 +1282,7 @@ rbt_merge_uniq_destructive( /**********************************************************************//** Check that every path from the root to the leaves has the same count and the tree nodes are in order. -@return TRUE if OK FALSE otherwise */ -UNIV_INTERN +@return TRUE if OK FALSE otherwise */ ibool rbt_validate( /*=========*/ @@ -1317,7 +1297,6 @@ rbt_validate( /**********************************************************************//** Iterate over the tree in depth first order. */ -UNIV_INTERN void rbt_print( /*======*/ diff --git a/storage/innobase/ut/ut0rnd.cc b/storage/innobase/ut/ut0rnd.cc index 3b4d7381181..2ff6248b0b4 100644 --- a/storage/innobase/ut/ut0rnd.cc +++ b/storage/innobase/ut/ut0rnd.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2014, Oracle and/or its affiliates. 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 @@ -37,13 +37,12 @@ Created 5/11/1994 Heikki Tuuri /*@}*/ /** Seed value of ut_rnd_gen_ulint(). */ -UNIV_INTERN ulint ut_rnd_ulint_counter = 65654363; +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 +@return prime */ ulint ut_find_prime( /*==========*/ diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index bde40220db3..ac71c3280a6 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2015, Oracle and/or its affiliates. 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 @@ -23,39 +23,45 @@ Various utilities for Innobase. Created 5/11/1994 Heikki Tuuri ********************************************************************/ -#include "ut0ut.h" +#include "ha_prototypes.h" + +#if HAVE_SYS_TIME_H +#include <sys/time.h> +#endif #ifndef UNIV_INNOCHECKSUM -#include "ut0sort.h" -#include "os0thread.h" /* thread-ID */ +#ifndef UNIV_HOTBACKUP +# include <mysql_com.h> +#endif /* !UNIV_HOTBACKUP */ + +#include "os0thread.h" +#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 */ + # include <string> -#endif /* UNIV_HOTBACKUP */ +#include "log.h" -#ifdef __WIN__ +/** A constant to prevent the compiler from optimizing ut_delay() away. */ +ibool ut_always_false = FALSE; +#ifdef _WIN32 /*****************************************************************//** 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) +#define WIN_TO_UNIX_DELTA_USEC 11644473600000000LL /*****************************************************************//** This is the Windows version of gettimeofday(2). -@return 0 if all OK else -1 */ +@return 0 if all OK else -1 */ static int ut_gettimeofday( @@ -64,7 +70,7 @@ ut_gettimeofday( void* tz) /*!< in: not used */ { FILETIME ft; - ib_int64_t tm; + int64_t tm; if (!tv) { errno = EINVAL; @@ -73,7 +79,7 @@ ut_gettimeofday( GetSystemTimeAsFileTime(&ft); - tm = (ib_int64_t) ft.dwHighDateTime << 32; + tm = (int64_t) ft.dwHighDateTime << 32; tm |= ft.dwLowDateTime; ut_a(tm >= 0); /* If tm wraps over to negative, the quotient / 10 @@ -99,8 +105,7 @@ reimplement this function. */ /**********************************************************//** 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 +@return system time */ ib_time_t ut_time(void) /*=========*/ @@ -114,8 +119,7 @@ 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 +@return 0 on success, -1 otherwise */ int ut_usectime( /*========*/ @@ -133,9 +137,8 @@ ut_usectime( if (ret == -1) { errno_gettimeofday = errno; - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: gettimeofday(): %s\n", - strerror(errno_gettimeofday)); + ib::error() << "gettimeofday(): " + << strerror(errno_gettimeofday); os_thread_sleep(100000); /* 0.1 sec */ errno = errno_gettimeofday; } else { @@ -155,19 +158,18 @@ ut_usectime( 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 +@return us since epoch */ +uintmax_t ut_time_us( /*=======*/ - ullint* tloc) /*!< out: us since epoch, if non-NULL */ + uintmax_t* tloc) /*!< out: us since epoch, if non-NULL */ { struct timeval tv; - ullint us; + uintmax_t us; ut_gettimeofday(&tv, NULL); - us = (ullint) tv.tv_sec * 1000000 + tv.tv_usec; + us = static_cast<uintmax_t>(tv.tv_sec) * 1000000 + tv.tv_usec; if (tloc != NULL) { *tloc = us; @@ -180,8 +182,7 @@ ut_time_us( Returns the number of milliseconds since some epoch. The value may wrap around. It should only be used for heuristic purposes. -@return ms since epoch */ -UNIV_INTERN +@return ms since epoch */ ulint ut_time_ms(void) /*============*/ @@ -196,8 +197,7 @@ ut_time_ms(void) /**********************************************************//** Returns the difference of two times in seconds. -@return time2 - time1 expressed in seconds */ -UNIV_INTERN +@return time2 - time1 expressed in seconds */ double ut_difftime( /*========*/ @@ -211,7 +211,6 @@ ut_difftime( /**********************************************************//** Prints a timestamp to a file. */ -UNIV_INTERN void ut_print_timestamp( /*===============*/ @@ -221,14 +220,14 @@ ut_print_timestamp( #ifndef UNIV_INNOCHECKSUM thread_id = os_thread_pf(os_thread_get_curr_id()); -#endif +#endif /* !UNIV_INNOCHECKSUM */ -#ifdef __WIN__ +#ifdef _WIN32 SYSTEMTIME cal_tm; GetLocalTime(&cal_tm); - fprintf(file, "%d-%02d-%02d %02d:%02d:%02d %lx", + fprintf(file, "%d-%02d-%02d %02d:%02d:%02d %#lx", (int) cal_tm.wYear, (int) cal_tm.wMonth, (int) cal_tm.wDay, @@ -240,16 +239,11 @@ ut_print_timestamp( struct tm* cal_tm_ptr; time_t tm; -#ifdef HAVE_LOCALTIME_R struct tm cal_tm; time(&tm); localtime_r(&tm, &cal_tm); cal_tm_ptr = &cal_tm; -#else - time(&tm); - cal_tm_ptr = localtime(&tm); -#endif - fprintf(file, "%d-%02d-%02d %02d:%02d:%02d %lx", + fprintf(file, "%d-%02d-%02d %02d:%02d:%02d %#lx", cal_tm_ptr->tm_year + 1900, cal_tm_ptr->tm_mon + 1, cal_tm_ptr->tm_mday, @@ -264,13 +258,12 @@ ut_print_timestamp( /**********************************************************//** 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__ +#ifdef _WIN32 SYSTEMTIME cal_tm; GetLocalTime(&cal_tm); @@ -286,15 +279,10 @@ ut_sprintf_timestamp( struct tm* cal_tm_ptr; time_t tm; -#ifdef HAVE_LOCALTIME_R struct tm cal_tm; time(&tm); localtime_r(&tm, &cal_tm); cal_tm_ptr = &cal_tm; -#else - time(&tm); - 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, @@ -309,13 +297,12 @@ ut_sprintf_timestamp( /**********************************************************//** 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__ +#ifdef _WIN32 SYSTEMTIME cal_tm; GetLocalTime(&cal_tm); @@ -331,15 +318,10 @@ ut_sprintf_timestamp_without_extra_chars( struct tm* cal_tm_ptr; time_t tm; -#ifdef HAVE_LOCALTIME_R struct tm cal_tm; time(&tm); localtime_r(&tm, &cal_tm); cal_tm_ptr = &cal_tm; -#else - time(&tm); - 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, @@ -352,7 +334,6 @@ ut_sprintf_timestamp_without_extra_chars( /**********************************************************//** Returns current year, month, day. */ -UNIV_INTERN void ut_get_year_month_day( /*==================*/ @@ -360,7 +341,7 @@ ut_get_year_month_day( ulint* month, /*!< out: month */ ulint* day) /*!< out: day */ { -#ifdef __WIN__ +#ifdef _WIN32 SYSTEMTIME cal_tm; GetLocalTime(&cal_tm); @@ -372,28 +353,22 @@ ut_get_year_month_day( struct tm* cal_tm_ptr; time_t tm; -#ifdef HAVE_LOCALTIME_R struct tm cal_tm; time(&tm); localtime_r(&tm, &cal_tm); cal_tm_ptr = &cal_tm; -#else - time(&tm); - 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 +#else /* 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 +@return dummy value */ void ut_delay( /*=====*/ @@ -403,18 +378,20 @@ ut_delay( UT_LOW_PRIORITY_CPU(); + for (i = 0; i < delay * 50; i++) { UT_RELAX_CPU(); UT_COMPILER_BARRIER(); } UT_RESUME_PRIORITY_CPU(); + UT_RESUME_PRIORITY_CPU(); + } -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_HOTBACKUP */ /*************************************************************//** Prints the contents of a memory buffer in hex and ascii. */ -UNIV_INTERN void ut_print_buf( /*=========*/ @@ -445,25 +422,59 @@ ut_print_buf( putc(';', file); } -/**********************************************************************//** -Sort function for ulint arrays. */ -UNIV_INTERN +/*************************************************************//** +Prints the contents of a memory buffer in hex. */ void -ut_ulint_sort( -/*==========*/ - ulint* arr, /*!< in/out: array to sort */ - ulint* aux_arr, /*!< in/out: aux array to use in sort */ - ulint low, /*!< in: lower bound */ - ulint high) /*!< in: upper bound */ +ut_print_buf_hex( +/*=============*/ + std::ostream& o, /*!< in/out: output stream */ + const void* buf, /*!< in: memory buffer */ + ulint len) /*!< in: length of the buffer */ +{ + const byte* data; + ulint i; + + static const char hexdigit[16] = { + '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' + }; + + UNIV_MEM_ASSERT_RW(buf, len); + + o << "(0x"; + + for (data = static_cast<const byte*>(buf), i = 0; i < len; i++) { + byte b = *data++; + o << hexdigit[(int) b >> 16] << hexdigit[b & 15]; + } + + o << ")"; +} + +/*************************************************************//** +Prints the contents of a memory buffer in hex and ascii. */ +void +ut_print_buf( +/*=========*/ + std::ostream& o, /*!< in/out: output stream */ + const void* buf, /*!< in: memory buffer */ + ulint len) /*!< in: length of the buffer */ { - UT_SORT_FUNCTION_BODY(ut_ulint_sort, arr, aux_arr, low, high, - ut_ulint_cmp); + const byte* data; + ulint i; + + UNIV_MEM_ASSERT_RW(buf, len); + + for (data = static_cast<const byte*>(buf), i = 0; i < len; i++) { + int c = static_cast<int>(*data++); + o << (isprint(c) ? static_cast<char>(c) : ' '); + } + + ut_print_buf_hex(o, buf, len); } /*************************************************************//** Calculates fast the number rounded up to the nearest power of 2. -@return first power of 2 which is >= n */ -UNIV_INTERN +@return first power of 2 which is >= n */ ulint ut_2_power_up( /*==========*/ @@ -482,65 +493,19 @@ ut_2_power_up( 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 */ - const 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. +/** Get 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 */ - const 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 */ +as in SQL database_name.identifier. + @param [in] trx transaction (NULL=no quotes). + @param [in] name table name. + @retval String quoted as an SQL identifier. +*/ +std::string +ut_get_name( + const trx_t* trx, + const char* name) { /* 2 * NAME_LEN for database and table name, and some slack for the #mysql50# prefix and quotes */ @@ -548,11 +513,10 @@ ut_print_namel( 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); + name, strlen(name), + trx ? trx->mysql_thd : NULL); + buf[bufend - buf] = '\0'; + return(std::string(buf, 0, bufend - buf)); } /**********************************************************************//** @@ -560,47 +524,41 @@ 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 -std::string -ut_get_name( -/*=========*/ - const trx_t* trx, /*!< in: transaction (NULL=no quotes) */ - ibool table_id,/*!< in: TRUE=print a table name, - FALSE=print other identifier */ +void +ut_print_name( +/*==========*/ + FILE* f, /*!< in: output stream */ + const trx_t* trx, /*!< in: transaction */ const char* name) /*!< in: name to print */ { /* 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; - ulint namelen = strlen(name); bufend = innobase_convert_name(buf, sizeof buf, - name, namelen, - trx ? trx->mysql_thd : NULL, - table_id); - buf[bufend-buf]='\0'; - std::string str(buf); - return str; + name, strlen(name), + trx ? trx->mysql_thd : NULL); + + if (fwrite(buf, 1, bufend - buf, f) != (size_t) (bufend - buf)) { + perror("fwrite"); + } } -/**********************************************************************//** -Formats a table or index name, quoted as an SQL identifier. If the name -contains a slash '/', the result will contain two identifiers separated by -a period (.), as in SQL database_name.identifier. +/** Format a table name, quoted as an SQL identifier. +If the name contains a slash '/', the result will contain two +identifiers separated by a period (.), as in SQL +database_name.table_name. +@see table_name_t +@param[in] name table or index name +@param[out] formatted formatted result, will be NUL-terminated +@param[in] formatted_size size of the buffer in bytes @return pointer to 'formatted' */ -UNIV_INTERN char* ut_format_name( -/*===========*/ - const char* name, /*!< in: table or index name, must be - '\0'-terminated */ - ibool is_table, /*!< in: if TRUE then 'name' is a table - name */ - char* formatted, /*!< out: formatted result, will be - '\0'-terminated */ - ulint formatted_size) /*!< out: no more than this number of - bytes will be written to 'formatted' */ + const char* name, + char* formatted, + ulint formatted_size) { switch (formatted_size) { case 1: @@ -613,7 +571,7 @@ ut_format_name( char* end; end = innobase_convert_name(formatted, formatted_size, - name, strlen(name), NULL, is_table); + name, strlen(name), NULL); /* If the space in 'formatted' was completely used, then sacrifice the last character in order to write '\0' at the end. */ @@ -630,7 +588,6 @@ ut_format_name( /**********************************************************************//** Catenate files. */ -UNIV_INTERN void ut_copy_file( /*=========*/ @@ -646,7 +603,9 @@ ut_copy_file( ? (size_t) len : sizeof buf; size_t size = fread(buf, 1, maxs, src); - fwrite(buf, 1, size, dest); + if (fwrite(buf, 1, size, dest) != size) { + perror("fwrite"); + } len -= (long) size; if (size < maxs) { break; @@ -655,7 +614,7 @@ ut_copy_file( } #endif /* !UNIV_HOTBACKUP */ -#ifdef __WIN__ +#ifdef _WIN32 # include <stdarg.h> /**********************************************************************//** A substitute for vsnprintf(3), formatted output conversion into @@ -664,7 +623,6 @@ characters that would have been printed if the buffer was unlimited because VC's _vsnprintf() returns -1 in this case and we would need to call _vscprintf() in addition to estimate that but we would need another copy of "ap" for that and VC does not provide va_copy(). */ -UNIV_INTERN void ut_vsnprintf( /*=========*/ @@ -682,7 +640,6 @@ 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( /*========*/ @@ -714,17 +671,43 @@ ut_snprintf( return(res); } -#endif /* __WIN__ */ +#endif /* _WIN32 */ -/*************************************************************//** -Convert an error number to a human readable text message. The -returned string is static and should not be freed or modified. -@return string, describing the error */ +/**********************************************************************//** +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 +std::string +ut_get_name( +/*=========*/ + const 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 */ +{ + /* 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; + ulint namelen = strlen(name); + + bufend = innobase_convert_name(buf, sizeof buf, + name, namelen, + trx ? trx->mysql_thd : NULL); + buf[bufend-buf]='\0'; + std::string str(buf); + return str; +} + +/** Convert an error number to a human readable text message. +The returned string is static and should not be freed or modified. +@param[in] num InnoDB internal error number +@return string, describing the error */ const char* ut_strerr( -/*======*/ - dberr_t num) /*!< in: error number */ + dberr_t num) { switch (num) { case DB_SUCCESS: @@ -783,6 +766,8 @@ ut_strerr( return("Tablespace already exists"); case DB_TABLESPACE_DELETED: return("Tablespace deleted or being deleted"); + case DB_TABLESPACE_TRUNCATED: + return("Tablespace was truncated"); case DB_TABLESPACE_NOT_FOUND: return("Tablespace not found"); case DB_LOCK_TABLE_FULL: @@ -835,20 +820,40 @@ ut_strerr( return("not found"); case DB_ONLINE_LOG_TOO_BIG: return("Log size exceeded during online index creation"); - case DB_DICT_CHANGED: - return("Table dictionary has changed"); case DB_IDENTIFIER_TOO_LONG: return("Identifier name is too long"); case DB_FTS_EXCEED_RESULT_CACHE_LIMIT: return("FTS query exceeds result cache limit"); - case DB_TEMP_FILE_WRITE_FAILURE: + case DB_TEMP_FILE_WRITE_FAIL: return("Temp file write failure"); + case DB_CANT_CREATE_GEOMETRY_OBJECT: + return("Can't create specificed geometry data object"); + case DB_CANNOT_OPEN_FILE: + return("Cannot open a file"); + case DB_TABLE_CORRUPT: + return("Table is corrupted"); case DB_FTS_TOO_MANY_WORDS_IN_PHRASE: return("Too many words in a FTS phrase or proximity search"); - case DB_TOO_BIG_FOR_REDO: - return("BLOB record length is greater than 10%% of redo log"); + case DB_IO_DECOMPRESS_FAIL: + return("Page decompress failed after reading from disk"); case DB_DECRYPTION_FAILED: return("Table is encrypted but decrypt failed."); + case DB_IO_NO_PUNCH_HOLE: + return("No punch hole support"); + case DB_IO_NO_PUNCH_HOLE_FS: + return("Punch hole not supported by the file system"); + case DB_IO_NO_PUNCH_HOLE_TABLESPACE: + return("Punch hole not supported by the tablespace"); + case DB_IO_PARTIAL_FAILED: + return("Partial IO failed"); + case DB_FORCED_ABORT: + return("Transaction aborted by another higher priority " + "transaction"); + case DB_WRONG_FILE_NAME: + return("Invalid Filename"); + + case DB_COMPUTE_VALUE_FAILED: + return("Compute generated column failed"); /* do not add default: in order to produce a warning if new code is added to the enum but not added here */ @@ -862,4 +867,96 @@ ut_strerr( /* NOT REACHED */ return("Unknown error"); } + +#ifdef UNIV_PFS_MEMORY + +/** Extract the basename of a file without its extension. +For example, extract "foo0bar" out of "/path/to/foo0bar.cc". +@param[in] file file path, e.g. "/path/to/foo0bar.cc" +@param[out] base result, e.g. "foo0bar" +@param[in] base_size size of the output buffer 'base', if there +is not enough space, then the result will be truncated, but always +'\0'-terminated +@return number of characters that would have been printed if the size +were unlimited (not including the final ‘\0’) */ +size_t +ut_basename_noext( + const char* file, + char* base, + size_t base_size) +{ + /* Assuming 'file' contains something like the following, + extract the file name without the extenstion out of it by + setting 'beg' and 'len'. + ...mysql-trunk/storage/innobase/dict/dict0dict.cc:302 + ^-- beg, len=9 + */ + + const char* beg = strrchr(file, OS_PATH_SEPARATOR); + + if (beg == NULL) { + beg = file; + } else { + beg++; + } + + size_t len = strlen(beg); + + const char* end = strrchr(beg, '.'); + + if (end != NULL) { + len = end - beg; + } + + const size_t copy_len = std::min(len, base_size - 1); + + memcpy(base, beg, copy_len); + + base[copy_len] = '\0'; + + return(len); +} + +#endif /* UNIV_PFS_MEMORY */ + +namespace ib { + +info::~info() +{ + sql_print_information("InnoDB: %s", m_oss.str().c_str()); +} + +warn::~warn() +{ + sql_print_warning("InnoDB: %s", m_oss.str().c_str()); +} + +error::~error() +{ + sql_print_error("InnoDB: %s", m_oss.str().c_str()); +} + +fatal::~fatal() +{ + sql_print_error("[FATAL] InnoDB: %s", m_oss.str().c_str()); + ut_error; +} + +error_or_warn::~error_or_warn() +{ + if (m_error) { + sql_print_error("InnoDB: %s", m_oss.str().c_str()); + } else { + sql_print_warning("InnoDB: %s", m_oss.str().c_str()); + } +} + +fatal_or_error::~fatal_or_error() +{ + sql_print_error("InnoDB: %s", m_oss.str().c_str()); + ut_a(!m_fatal); +} + +} // namespace ib + #endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/ut/ut0vec.cc b/storage/innobase/ut/ut0vec.cc index 5842d9f1c0e..f4a893967c7 100644 --- a/storage/innobase/ut/ut0vec.cc +++ b/storage/innobase/ut/ut0vec.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2006, 2014, Oracle and/or its affiliates. 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 @@ -31,7 +31,6 @@ Created 4/6/2006 Osku Salerma /******************************************************************** Create a new vector with the given initial size. */ -UNIV_INTERN ib_vector_t* ib_vector_create( /*=============*/ @@ -61,7 +60,6 @@ ib_vector_create( /******************************************************************** Resize the vector, currently the vector can only grow and we expand the number of elements it can hold by 2 times. */ -UNIV_INTERN void ib_vector_resize( /*=============*/ diff --git a/storage/innobase/ut/ut0wqueue.cc b/storage/innobase/ut/ut0wqueue.cc index 1607e535a94..3df32d92a9b 100644 --- a/storage/innobase/ut/ut0wqueue.cc +++ b/storage/innobase/ut/ut0wqueue.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2006, 2015, Oracle and/or its affiliates. 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 @@ -16,6 +16,8 @@ this program; if not, write to the Free Software Foundation, Inc., *****************************************************************************/ +#include "ut0list.h" +#include "mem0mem.h" #include "ut0wqueue.h" /*******************************************************************//** @@ -25,29 +27,36 @@ A work queue Created 4/26/2006 Osku Salerma ************************************************************************/ +/* Work queue. */ +struct ib_wqueue_t { + ib_mutex_t mutex; /*!< mutex protecting everything */ + ib_list_t* items; /*!< work item list */ + os_event_t event; /*!< event we use to signal additions to list */ +}; + /****************************************************************//** Create a new work queue. -@return work queue */ -UNIV_INTERN +@return work queue */ ib_wqueue_t* ib_wqueue_create(void) /*===================*/ { - ib_wqueue_t* wq = static_cast<ib_wqueue_t*>(mem_alloc(sizeof(*wq))); + ib_wqueue_t* wq = static_cast<ib_wqueue_t*>( + ut_malloc_nokey(sizeof(*wq))); /* Function ib_wqueue_create() has not been used anywhere, not necessary to instrument this mutex */ - mutex_create(PFS_NOT_INSTRUMENTED, &wq->mutex, SYNC_WORK_QUEUE); + + mutex_create(LATCH_ID_WORK_QUEUE, &wq->mutex); wq->items = ib_list_create(); - wq->event = os_event_create(); + wq->event = os_event_create(0); return(wq); } /****************************************************************//** Free a work queue. */ -UNIV_INTERN void ib_wqueue_free( /*===========*/ @@ -55,14 +64,13 @@ ib_wqueue_free( { mutex_free(&wq->mutex); ib_list_free(wq->items); - os_event_free(wq->event); + os_event_destroy(wq->event); - mem_free(wq); + ut_free(wq); } /****************************************************************//** Add a work item to the queue. */ -UNIV_INTERN void ib_wqueue_add( /*==========*/ @@ -81,8 +89,7 @@ ib_wqueue_add( /****************************************************************//** Wait for a work item to appear in the queue. -@return work item */ -UNIV_INTERN +@return work item */ void* ib_wqueue_wait( /*===========*/ @@ -120,7 +127,6 @@ ib_wqueue_wait( /******************************************************************** Wait for a work item to appear in the queue for specified time. */ - void* ib_wqueue_timedwait( /*================*/ @@ -132,7 +138,7 @@ ib_wqueue_timedwait( for (;;) { ulint error; - ib_int64_t sig_count; + int64_t sig_count; mutex_enter(&wq->mutex); @@ -195,7 +201,6 @@ ib_wqueue_nowait( /******************************************************************** Check if queue is empty. */ - ibool ib_wqueue_is_empty( /*===============*/ |