summaryrefslogtreecommitdiff
path: root/storage/innobase/ut
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/ut')
-rw-r--r--storage/innobase/ut/ut0bh.cc159
-rw-r--r--storage/innobase/ut/ut0crc32.cc706
-rw-r--r--storage/innobase/ut/ut0dbg.cc83
-rw-r--r--storage/innobase/ut/ut0list.cc23
-rw-r--r--storage/innobase/ut/ut0mem.cc424
-rw-r--r--storage/innobase/ut/ut0new.cc227
-rw-r--r--storage/innobase/ut/ut0rbt.cc87
-rw-r--r--storage/innobase/ut/ut0rnd.cc7
-rw-r--r--storage/innobase/ut/ut0ut.cc477
-rw-r--r--storage/innobase/ut/ut0vec.cc4
-rw-r--r--storage/innobase/ut/ut0wqueue.cc35
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(
/*===============*/