diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:24:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:24:36 +0000 |
commit | 06eaf7232e9a920468c0f8d74dcf2fe8b555501c (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /include | |
parent | Initial commit. (diff) | |
download | mariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.tar.xz mariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include')
190 files changed, 41293 insertions, 0 deletions
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 00000000..a82d1143 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,125 @@ +# Copyright (c) 2006, 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 St, Fifth Floor, Boston, MA 02110-1335 USA + +SET(HEADERS_GEN_CONFIGURE + mysql_version.h + my_config.h + mysqld_ername.h + mysqld_error.h + sql_state.h +) + +SET(HEADERS + mysql.h + mysql_com.h + mysql_com_server.h + mariadb_capi_rename.h + pack.h + my_byteorder.h + byte_order_generic.h + byte_order_generic_x86.h + byte_order_generic_x86_64.h + little_endian.h + big_endian.h + mysql_time.h + ma_dyncol.h + my_list.h + my_alloc.h + my_alloca.h + typelib.h + my_dbug.h + m_string.h + my_sys.h + my_xml.h + mysql_embed.h + my_decimal_limits.h + my_pthread.h + decimal.h + errmsg.h + my_global.h + my_net.h + my_getopt.h + sslopt-longopts.h + my_dir.h + sslopt-vars.h + sslopt-case.h + my_valgrind.h + sql_common.h + keycache.h + m_ctype.h + my_attribute.h + my_compiler.h + handler_state.h + handler_ername.h + json_lib.h +) + +# don't use C/C's (possibly outdated) copy of mysqld_error.h +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mysqld_error.h + DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT Development) + +INSTALL(FILES ${HEADERS} + DESTINATION ${INSTALL_INCLUDEDIR}/server COMPONENT Development) +FOREACH(f ${HEADERS_GEN_CONFIGURE}) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${f} + DESTINATION ${INSTALL_INCLUDEDIR}/server COMPONENT Development) +ENDFOREACH(f) +IF(NOT WITH_WSREP) + SET(EXCL_SERVICE_WSREP "service_wsrep.h") +ENDIF() +INSTALL(DIRECTORY mysql/ + DESTINATION ${INSTALL_INCLUDEDIR}/server/mysql COMPONENT Development + FILES_MATCHING PATTERN "*.h" + PATTERN "${EXCL_SERVICE_WSREP}" EXCLUDE +) + +STRING(REPLACE "." "\\." EXCL_RE "${HEADERS};${HEADERS_GEN_CONFIGURE}") +STRING(REPLACE ";" "|" EXCL_RE "${EXCL_RE}") + +MACRO(INSTALL_PRIVATE DIR) + INSTALL(DIRECTORY ${DIR}/. + DESTINATION ${INSTALL_INCLUDEDIR}/server/private COMPONENT Development + FILES_MATCHING PATTERN "*.h" + PATTERN CMakeFiles EXCLUDE + PATTERN mysql EXCLUDE + REGEX "\\./(${EXCL_RE}$)" EXCLUDE) +ENDMACRO() + +INSTALL_PRIVATE(${CMAKE_CURRENT_BINARY_DIR}) +IF(NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + INSTALL_PRIVATE(${CMAKE_CURRENT_SOURCE_DIR}) +ENDIF() + +MACRO(INSTALL_COMPAT_HEADER file footer) + INSTALL(CODE "FILE(WRITE \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDEDIR}/${file} +\"/* Do not edit this file directly, it was auto-generated by cmake */ + +#warning This file should not be included by clients, include only <mysql.h> +${footer} +\")" COMPONENT Development) +ENDMACRO() + +INSTALL_COMPAT_HEADER(my_global.h "") +INSTALL_COMPAT_HEADER(my_alloca.h "") +INSTALL_COMPAT_HEADER(my_config.h "") +INSTALL_COMPAT_HEADER(my_alloca.h "") +INSTALL_COMPAT_HEADER(my_sys.h "") +INSTALL_COMPAT_HEADER(mysql_version.h " +#include <mariadb_version.h> +#define LIBMYSQL_VERSION MARIADB_CLIENT_VERSION_STR +") +INSTALL_COMPAT_HEADER(mysql_com.h " +#include <mariadb_com.h> +") diff --git a/include/aligned.h b/include/aligned.h new file mode 100644 index 00000000..81bd5d3f --- /dev/null +++ b/include/aligned.h @@ -0,0 +1,38 @@ +/* + Copyright (c) 2022, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#if defined __linux__ +# include <malloc.h> +#endif + +inline void *aligned_malloc(size_t size, size_t alignment) +{ +#ifdef _WIN32 + return _aligned_malloc(size, alignment); +#elif defined __linux__ + return memalign(alignment, size); +#else + void *result; + if (posix_memalign(&result, alignment, size)) + result= NULL; + return result; +#endif +} + +inline void aligned_free(void *ptr) +{ + IF_WIN(_aligned_free,free)(ptr); +} diff --git a/include/aria_backup.h b/include/aria_backup.h new file mode 100644 index 00000000..f399f6a6 --- /dev/null +++ b/include/aria_backup.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2018,2020 MariaDB Corporation Ab + + 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, Fifth Floor, Boston, MA 02111-1301 USA */ + +/* Interfaces for doing backups of Aria tables */ + +C_MODE_START + +typedef struct st_aria_table_capabilities +{ + my_off_t header_size; + ulong bitmap_pages_covered; + uint block_size; + uint keypage_header; + enum data_file_type data_file_type; + my_bool checksum; + my_bool transactional; + my_bool encrypted; + /* This is true if the table can be copied without any locks */ + my_bool online_backup_safe; + /* s3 capabilities */ + ulong s3_block_size; + uint8 compression; +} ARIA_TABLE_CAPABILITIES; + +int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap); +int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, + uchar *buffer); +int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, + uchar *buffer, size_t *bytes_read); +C_MODE_END diff --git a/include/assume_aligned.h b/include/assume_aligned.h new file mode 100644 index 00000000..e1b807c4 --- /dev/null +++ b/include/assume_aligned.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2020, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#pragma once + +#include <cassert> +#include <cstring> + +#ifdef _MSC_VER +template <std::size_t Alignment, class T> +static inline T my_assume_aligned(T ptr) +{ + assert(reinterpret_cast<size_t>(ptr) % Alignment == 0); + __assume(reinterpret_cast<size_t>(ptr) % Alignment == 0); + return ptr; +} +#else +template <std::size_t Alignment, class T> +static inline T my_assume_aligned(T ptr) +{ + assert(reinterpret_cast<size_t>(ptr) % Alignment == 0); + return static_cast<T>(__builtin_assume_aligned(ptr, Alignment)); +} +#endif + +template <std::size_t Alignment> +inline void *memcpy_aligned(void *dest, const void *src, size_t n) +{ + static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); + + return std::memcpy(my_assume_aligned<Alignment>(dest), + my_assume_aligned<Alignment>(src), n); +} +template <std::size_t Alignment> +inline void *memmove_aligned(void *dest, const void *src, size_t n) +{ + static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); + + return std::memmove(my_assume_aligned<Alignment>(dest), + my_assume_aligned<Alignment>(src), n); +} +template <std::size_t Alignment> +inline int memcmp_aligned(const void *s1, const void *s2, size_t n) +{ + static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); + + return std::memcmp(my_assume_aligned<Alignment>(s1), + my_assume_aligned<Alignment>(s2), n); +} +template <std::size_t Alignment> +inline void *memset_aligned(void *s, int c, size_t n) +{ + static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); + + return std::memset(my_assume_aligned<Alignment>(s), c, n); +} diff --git a/include/atomic/gcc_builtins.h b/include/atomic/gcc_builtins.h new file mode 100644 index 00000000..5b2b2c90 --- /dev/null +++ b/include/atomic/gcc_builtins.h @@ -0,0 +1,78 @@ +#ifndef ATOMIC_GCC_BUILTINS_INCLUDED +#define ATOMIC_GCC_BUILTINS_INCLUDED + +/* Copyright (c) 2017 MariaDB Foundation + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + + +#define MY_MEMORY_ORDER_RELAXED __ATOMIC_RELAXED +#define MY_MEMORY_ORDER_CONSUME __ATOMIC_CONSUME +#define MY_MEMORY_ORDER_ACQUIRE __ATOMIC_ACQUIRE +#define MY_MEMORY_ORDER_RELEASE __ATOMIC_RELEASE +#define MY_MEMORY_ORDER_ACQ_REL __ATOMIC_ACQ_REL +#define MY_MEMORY_ORDER_SEQ_CST __ATOMIC_SEQ_CST + +#define my_atomic_store32_explicit(P, D, O) __atomic_store_n((P), (D), (O)) +#define my_atomic_store64_explicit(P, D, O) __atomic_store_n((P), (D), (O)) +#define my_atomic_storeptr_explicit(P, D, O) __atomic_store_n((P), (D), (O)) + +#define my_atomic_load32_explicit(P, O) __atomic_load_n((P), (O)) +#define my_atomic_load64_explicit(P, O) __atomic_load_n((P), (O)) +#define my_atomic_loadptr_explicit(P, O) __atomic_load_n((P), (O)) + +#define my_atomic_fas32_explicit(P, D, O) __atomic_exchange_n((P), (D), (O)) +#define my_atomic_fas64_explicit(P, D, O) __atomic_exchange_n((P), (D), (O)) +#define my_atomic_fasptr_explicit(P, D, O) __atomic_exchange_n((P), (D), (O)) + +#define my_atomic_add32_explicit(P, A, O) __atomic_fetch_add((P), (A), (O)) +#define my_atomic_add64_explicit(P, A, O) __atomic_fetch_add((P), (A), (O)) + +#define my_atomic_cas32_weak_explicit(P, E, D, S, F) \ + __atomic_compare_exchange_n((P), (E), (D), 1, (S), (F)) +#define my_atomic_cas64_weak_explicit(P, E, D, S, F) \ + __atomic_compare_exchange_n((P), (E), (D), 1, (S), (F)) +#define my_atomic_casptr_weak_explicit(P, E, D, S, F) \ + __atomic_compare_exchange_n((P), (E), (D), 1, (S), (F)) + +#define my_atomic_cas32_strong_explicit(P, E, D, S, F) \ + __atomic_compare_exchange_n((P), (E), (D), 0, (S), (F)) +#define my_atomic_cas64_strong_explicit(P, E, D, S, F) \ + __atomic_compare_exchange_n((P), (E), (D), 0, (S), (F)) +#define my_atomic_casptr_strong_explicit(P, E, D, S, F) \ + __atomic_compare_exchange_n((P), (E), (D), 0, (S), (F)) + +#define my_atomic_store32(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST) +#define my_atomic_store64(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST) +#define my_atomic_storeptr(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST) + +#define my_atomic_load32(P) __atomic_load_n((P), __ATOMIC_SEQ_CST) +#define my_atomic_load64(P) __atomic_load_n((P), __ATOMIC_SEQ_CST) +#define my_atomic_loadptr(P) __atomic_load_n((P), __ATOMIC_SEQ_CST) + +#define my_atomic_fas32(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST) +#define my_atomic_fas64(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST) +#define my_atomic_fasptr(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST) + +#define my_atomic_add32(P, A) __atomic_fetch_add((P), (A), __ATOMIC_SEQ_CST) +#define my_atomic_add64(P, A) __atomic_fetch_add((P), (A), __ATOMIC_SEQ_CST) + +#define my_atomic_cas32(P, E, D) \ + __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) +#define my_atomic_cas64(P, E, D) \ + __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) +#define my_atomic_casptr(P, E, D) \ + __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) + +#endif /* ATOMIC_GCC_BUILTINS_INCLUDED */ diff --git a/include/atomic/generic-msvc.h b/include/atomic/generic-msvc.h new file mode 100644 index 00000000..ff2a5434 --- /dev/null +++ b/include/atomic/generic-msvc.h @@ -0,0 +1,140 @@ +#ifndef ATOMIC_MSC_INCLUDED +#define ATOMIC_MSC_INCLUDED + +/* 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 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <windows.h> + +static inline int my_atomic_cas32(int32 volatile *a, int32 *cmp, int32 set) +{ + int32 initial_cmp= *cmp; + int32 initial_a= InterlockedCompareExchange((volatile LONG*)a, + set, initial_cmp); + int ret= (initial_a == initial_cmp); + if (!ret) + *cmp= initial_a; + return ret; +} + +static inline int my_atomic_cas64(int64 volatile *a, int64 *cmp, int64 set) +{ + int64 initial_cmp= *cmp; + int64 initial_a= InterlockedCompareExchange64((volatile LONGLONG*)a, + (LONGLONG)set, + (LONGLONG)initial_cmp); + int ret= (initial_a == initial_cmp); + if (!ret) + *cmp= initial_a; + return ret; +} + +static inline int my_atomic_casptr(void * volatile *a, void **cmp, void *set) +{ + void *initial_cmp= *cmp; + void *initial_a= InterlockedCompareExchangePointer(a, set, initial_cmp); + int ret= (initial_a == initial_cmp); + if (!ret) + *cmp= initial_a; + return ret; +} + +static inline int32 my_atomic_add32(int32 volatile *a, int32 v) +{ + return (int32)InterlockedExchangeAdd((volatile LONG*)a, v); +} + +static inline int64 my_atomic_add64(int64 volatile *a, int64 v) +{ + return (int64)InterlockedExchangeAdd64((volatile LONGLONG*)a, (LONGLONG)v); +} + + +/* + According to MSDN: + + Simple reads and writes to properly-aligned 32-bit variables are atomic + operations. + ... + Simple reads and writes to properly aligned 64-bit variables are atomic on + 64-bit Windows. Reads and writes to 64-bit values are not guaranteed to be + atomic on 32-bit Windows. + + https://msdn.microsoft.com/en-us/library/windows/desktop/ms684122(v=vs.85).aspx +*/ + +static inline int32 my_atomic_load32(int32 volatile *a) +{ + int32 value= *a; + MemoryBarrier(); + return value; +} + +static inline int64 my_atomic_load64(int64 volatile *a) +{ +#ifdef _M_X64 + int64 value= *a; + MemoryBarrier(); + return value; +#else + return (int64) InterlockedCompareExchange64((volatile LONGLONG *) a, 0, 0); +#endif +} + +static inline void* my_atomic_loadptr(void * volatile *a) +{ + void *value= *a; + MemoryBarrier(); + return value; +} + +static inline int32 my_atomic_fas32(int32 volatile *a, int32 v) +{ + return (int32)InterlockedExchange((volatile LONG*)a, v); +} + +static inline int64 my_atomic_fas64(int64 volatile *a, int64 v) +{ + return (int64)InterlockedExchange64((volatile LONGLONG*)a, v); +} + +static inline void * my_atomic_fasptr(void * volatile *a, void * v) +{ + return InterlockedExchangePointer(a, v); +} + +static inline void my_atomic_store32(int32 volatile *a, int32 v) +{ + MemoryBarrier(); + *a= v; +} + +static inline void my_atomic_store64(int64 volatile *a, int64 v) +{ +#ifdef _M_X64 + MemoryBarrier(); + *a= v; +#else + (void) InterlockedExchange64((volatile LONGLONG *) a, v); +#endif +} + +static inline void my_atomic_storeptr(void * volatile *a, void *v) +{ + MemoryBarrier(); + *a= v; +} + +#endif /* ATOMIC_MSC_INCLUDED */ diff --git a/include/atomic/solaris.h b/include/atomic/solaris.h new file mode 100644 index 00000000..b48ab46f --- /dev/null +++ b/include/atomic/solaris.h @@ -0,0 +1,117 @@ +#ifndef ATOMIC_SOLARIS_INCLUDED +#define ATOMIC_SOLARIS_INCLUDED + +/* Copyright (c) 2008, 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 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <atomic.h> + +#if defined(__GNUC__) +#define atomic_typeof(T,V) __typeof__(V) +#else +#define atomic_typeof(T,V) T +#endif + +static inline int my_atomic_cas32(int32 volatile *a, int32 *cmp, int32 set) +{ + int ret; + atomic_typeof(uint32_t, *cmp) sav; + sav= atomic_cas_32((volatile uint32_t *)a, (uint32_t)*cmp, (uint32_t)set); + ret= (sav == *cmp); + if (!ret) + *cmp= sav; + return ret; +} + +static inline int my_atomic_cas64(int64 volatile *a, int64 *cmp, int64 set) +{ + int ret; + atomic_typeof(uint64_t, *cmp) sav; + sav= atomic_cas_64((volatile uint64_t *)a, (uint64_t)*cmp, (uint64_t)set); + ret= (sav == *cmp); + if (!ret) + *cmp= sav; + return ret; +} + +static inline int my_atomic_casptr(void * volatile *a, void **cmp, void *set) +{ + int ret; + atomic_typeof(void *, *cmp) sav; + sav= atomic_cas_ptr((volatile void **)a, (void *)*cmp, (void *)set); + ret= (sav == *cmp); + if (!ret) + *cmp= sav; + return ret; +} + +static inline int32 my_atomic_add32(int32 volatile *a, int32 v) +{ + int32 nv= atomic_add_32_nv((volatile uint32_t *)a, v); + return nv - v; +} + +static inline int64 my_atomic_add64(int64 volatile *a, int64 v) +{ + int64 nv= atomic_add_64_nv((volatile uint64_t *)a, v); + return nv - v; +} + +static inline int32 my_atomic_fas32(int32 volatile *a, int32 v) +{ + return atomic_swap_32((volatile uint32_t *)a, (uint32_t)v); +} + +static inline int64 my_atomic_fas64(int64 volatile *a, int64 v) +{ + return atomic_swap_64((volatile uint64_t *)a, (uint64_t)v); +} + +static inline void * my_atomic_fasptr(void * volatile *a, void * v) +{ + return atomic_swap_ptr(a, v); +} + +static inline int32 my_atomic_load32(int32 volatile *a) +{ + return atomic_or_32_nv((volatile uint32_t *)a, 0); +} + +static inline int64 my_atomic_load64(int64 volatile *a) +{ + return atomic_or_64_nv((volatile uint64_t *)a, 0); +} + +static inline void* my_atomic_loadptr(void * volatile *a) +{ + return atomic_add_ptr_nv(a, 0); +} + +static inline void my_atomic_store32(int32 volatile *a, int32 v) +{ + (void) atomic_swap_32((volatile uint32_t *)a, (uint32_t)v); +} + +static inline void my_atomic_store64(int64 volatile *a, int64 v) +{ + (void) atomic_swap_64((volatile uint64_t *)a, (uint64_t)v); +} + +static inline void my_atomic_storeptr(void * volatile *a, void *v) +{ + (void) atomic_swap_ptr((volatile void **)a, (void *)v); +} + +#endif /* ATOMIC_SOLARIS_INCLUDED */ diff --git a/include/big_endian.h b/include/big_endian.h new file mode 100644 index 00000000..6487f829 --- /dev/null +++ b/include/big_endian.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2012, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Data in big-endian format. +*/ +#define float4store(T,A) do { *(T)= ((uchar *) &A)[3];\ + *((T)+1)=(char) ((uchar *) &A)[2];\ + *((T)+2)=(char) ((uchar *) &A)[1];\ + *((T)+3)=(char) ((uchar *) &A)[0]; } while(0) + +#define float4get(V,M) do { float def_temp;\ + ((uchar*) &def_temp)[0]=(M)[3];\ + ((uchar*) &def_temp)[1]=(M)[2];\ + ((uchar*) &def_temp)[2]=(M)[1];\ + ((uchar*) &def_temp)[3]=(M)[0];\ + (V)=def_temp; } while(0) + +#define float8store(T,V) do { *(T)= ((uchar *) &V)[7];\ + *((T)+1)=(char) ((uchar *) &V)[6];\ + *((T)+2)=(char) ((uchar *) &V)[5];\ + *((T)+3)=(char) ((uchar *) &V)[4];\ + *((T)+4)=(char) ((uchar *) &V)[3];\ + *((T)+5)=(char) ((uchar *) &V)[2];\ + *((T)+6)=(char) ((uchar *) &V)[1];\ + *((T)+7)=(char) ((uchar *) &V)[0]; } while(0) + +#define float8get(V,M) do { double def_temp;\ + ((uchar*) &def_temp)[0]=(M)[7];\ + ((uchar*) &def_temp)[1]=(M)[6];\ + ((uchar*) &def_temp)[2]=(M)[5];\ + ((uchar*) &def_temp)[3]=(M)[4];\ + ((uchar*) &def_temp)[4]=(M)[3];\ + ((uchar*) &def_temp)[5]=(M)[2];\ + ((uchar*) &def_temp)[6]=(M)[1];\ + ((uchar*) &def_temp)[7]=(M)[0];\ + (V) = def_temp; } while(0) + +#define ushortget(V,M) do { V = (uint16) (((uint16) ((uchar) (M)[1]))+\ + ((uint16) ((uint16) (M)[0]) << 8)); } while(0) +#define shortget(V,M) do { V = (short) (((short) ((uchar) (M)[1]))+\ + ((short) ((short) (M)[0]) << 8)); } while(0) +#define longget(V,M) do { int32 def_temp;\ + ((uchar*) &def_temp)[0]=(M)[0];\ + ((uchar*) &def_temp)[1]=(M)[1];\ + ((uchar*) &def_temp)[2]=(M)[2];\ + ((uchar*) &def_temp)[3]=(M)[3];\ + (V)=def_temp; } while(0) +#define ulongget(V,M) do { uint32 def_temp;\ + ((uchar*) &def_temp)[0]=(M)[0];\ + ((uchar*) &def_temp)[1]=(M)[1];\ + ((uchar*) &def_temp)[2]=(M)[2];\ + ((uchar*) &def_temp)[3]=(M)[3];\ + (V)=def_temp; } while(0) +#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\ + *(((char*)T)+1)=(char)(def_temp); \ + *(((char*)T)+0)=(char)(def_temp >> 8); } while(0) +#define longstore(T,A) do { *(((char*)T)+3)=((A));\ + *(((char*)T)+2)=(((A) >> 8));\ + *(((char*)T)+1)=(((A) >> 16));\ + *(((char*)T)+0)=(((A) >> 24)); } while(0) + +#define floatget(V,M) memcpy(&V, (M), sizeof(float)) +/* Cast away type qualifiers (necessary as macro takes argument by value). */ +#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float)) +#define doubleget(V,M) memcpy(&V, (M), sizeof(double)) +/* Cast away type qualifiers (necessary as macro takes argument by value). */ +#define doublestore(T,V) memcpy((T), (void*) &V, sizeof(double)) +#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong)) +#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong)) diff --git a/include/byte_order_generic.h b/include/byte_order_generic.h new file mode 100644 index 00000000..d2b729a2 --- /dev/null +++ b/include/byte_order_generic.h @@ -0,0 +1,96 @@ +/* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2020, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Endianness-independent definitions for architectures other + than the x86 architecture. +*/ +#define sint2korr(A) (int16) (((int16) ((uchar) (A)[0])) |\ + ((int16) ((int16) (A)[1]) << 8)) +#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ + (((uint32) 255L << 24) | \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0])) : \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0]))) +#define sint4korr(A) (int32) (((uint32) ((uchar) (A)[0])) |\ + (((uint32) ((uchar) (A)[1]) << 8)) |\ + (((uint32) ((uchar) (A)[2]) << 16)) |\ + (((uint32) ((uchar) (A)[3]) << 24))) +#define sint8korr(A) (longlong) uint8korr(A) +#define uint2korr(A) (uint16) (((uint16) ((uchar) (A)[0])) |\ + ((uint16) ((uchar) (A)[1]) << 8)) +#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) |\ + (((uint32) ((uchar) (A)[1])) << 8) |\ + (((uint32) ((uchar) (A)[2])) << 16)) +#define uint4korr(A) (uint32) (((uint32) ((uchar) (A)[0])) |\ + (((uint32) ((uchar) (A)[1])) << 8) |\ + (((uint32) ((uchar) (A)[2])) << 16) |\ + (((uint32) ((uchar) (A)[3])) << 24)) +#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) |\ + (((uint32) ((uchar) (A)[1])) << 8) |\ + (((uint32) ((uchar) (A)[2])) << 16) |\ + (((uint32) ((uchar) (A)[3])) << 24)) |\ + (((ulonglong) ((uchar) (A)[4])) << 32)) +#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) | \ + (((uint32) ((uchar) (A)[1])) << 8) | \ + (((uint32) ((uchar) (A)[2])) << 16) | \ + (((uint32) ((uchar) (A)[3])) << 24)) | \ + (((ulonglong) ((uchar) (A)[4])) << 32) | \ + (((ulonglong) ((uchar) (A)[5])) << 40)) +#define uint8korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) |\ + (((uint32) ((uchar) (A)[1])) << 8) |\ + (((uint32) ((uchar) (A)[2])) << 16) |\ + (((uint32) ((uchar) (A)[3])) << 24)) |\ + (((ulonglong) (((uint32) ((uchar) (A)[4])) |\ + (((uint32) ((uchar) (A)[5])) << 8) |\ + (((uint32) ((uchar) (A)[6])) << 16) |\ + (((uint32) ((uchar) (A)[7])) << 24))) <<\ + 32)) +#define int2store(T,A) do { uint def_temp= (uint) (A) ;\ + *((uchar*) (T))= (uchar)(def_temp); \ + *((uchar*) (T)+1)=(uchar)((def_temp >> 8)); \ + } while(0) +#define int3store(T,A) do { /*lint -save -e734 */\ + *((uchar*)(T))=(uchar) ((A));\ + *((uchar*) (T)+1)=(uchar) (((A) >> 8));\ + *((uchar*)(T)+2)=(uchar) (((A) >> 16)); \ + /*lint -restore */} while(0) +#define int4store(T,A) do { *((char *)(T))=(char) ((A));\ + *(((char *)(T))+1)=(char) (((A) >> 8));\ + *(((char *)(T))+2)=(char) (((A) >> 16));\ + *(((char *)(T))+3)=(char) (((A) >> 24));\ + } while(0) +#define int5store(T,A) do { *((char *)(T))= (char)((A)); \ + *(((char *)(T))+1)= (char)(((A) >> 8)); \ + *(((char *)(T))+2)= (char)(((A) >> 16)); \ + *(((char *)(T))+3)= (char)(((A) >> 24)); \ + *(((char *)(T))+4)= (char)(((A) >> 32)); \ + } while(0) +#define int6store(T,A) do { *((char *)(T))= (char)((A)); \ + *(((char *)(T))+1)= (char)(((A) >> 8)); \ + *(((char *)(T))+2)= (char)(((A) >> 16)); \ + *(((char *)(T))+3)= (char)(((A) >> 24)); \ + *(((char *)(T))+4)= (char)(((A) >> 32)); \ + *(((char *)(T))+5)= (char)(((A) >> 40)); \ + } while(0) +#define int8store(T,A) do { uint def_temp= (uint) (A), \ + def_temp2= (uint) ((A) >> 32); \ + int4store((T),def_temp); \ + int4store((T+4),def_temp2);\ + } while(0) diff --git a/include/byte_order_generic_x86.h b/include/byte_order_generic_x86.h new file mode 100644 index 00000000..c4756447 --- /dev/null +++ b/include/byte_order_generic_x86.h @@ -0,0 +1,89 @@ +/* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2020, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Optimized function-like macros for the x86 architecture (_WIN32 included). +*/ + +#define sint2korr(A) (*((const int16 *) (A))) +#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ + (((uint32) 255L << 24) | \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0])) : \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0]))) +#define sint4korr(A) (*((const long *) (A))) +#define uint2korr(A) (*((const uint16 *) (A))) +#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) |\ + (((uint32) ((uchar) (A)[1])) << 8) |\ + (((uint32) ((uchar) (A)[2])) << 16)) +#define uint4korr(A) (*((const uint32 *) (A))) +#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) |\ + (((uint32) ((uchar) (A)[1])) << 8) |\ + (((uint32) ((uchar) (A)[2])) << 16) |\ + (((uint32) ((uchar) (A)[3])) << 24)) |\ + (((ulonglong) ((uchar) (A)[4])) << 32)) +#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) | \ + (((uint32) ((uchar) (A)[1])) << 8) | \ + (((uint32) ((uchar) (A)[2])) << 16) | \ + (((uint32) ((uchar) (A)[3])) << 24)) | \ + (((ulonglong) ((uchar) (A)[4])) << 32) | \ + (((ulonglong) ((uchar) (A)[5])) << 40)) +#define uint8korr(A) (*((const ulonglong *) (A))) +#define sint8korr(A) (*((const longlong *) (A))) + +#define int2store(T,A) *((uint16*) (T))= (uint16) (A) +#define int3store(T,A) do { *(T)= (uchar) ((A));\ + *(T+1)=(uchar) (((uint) (A) >> 8));\ + *(T+2)=(uchar) (((A) >> 16));\ + } while (0) +#define int4store(T,A) *((long *) (T))= (long) (A) +#define int5store(T,A) do { *(T)= (uchar)((A));\ + *((T)+1)=(uchar) (((A) >> 8));\ + *((T)+2)=(uchar) (((A) >> 16));\ + *((T)+3)=(uchar) (((A) >> 24));\ + *((T)+4)=(uchar) (((A) >> 32));\ + } while(0) +#define int6store(T,A) do { *(T)= (uchar)((A)); \ + *((T)+1)=(uchar) (((A) >> 8)); \ + *((T)+2)=(uchar) (((A) >> 16)); \ + *((T)+3)=(uchar) (((A) >> 24)); \ + *((T)+4)=(uchar) (((A) >> 32)); \ + *((T)+5)=(uchar) (((A) >> 40)); \ + } while(0) +#define int8store(T,A) *((ulonglong *) (T))= (ulonglong) (A) +typedef union { + double v; + long m[2]; +} doubleget_union; +#define doubleget(V,M) \ +do { doubleget_union _tmp; \ + _tmp.m[0] = *((const long*)(M)); \ + _tmp.m[1] = *(((const long*) (M))+1); \ + (V) = _tmp.v; } while(0) +#define doublestore(T,V) \ +do { *((long *) T) = ((const doubleget_union *)&V)->m[0]; \ + *(((long *) T)+1) = ((const doubleget_union *)&V)->m[1]; \ + } while (0) +#define float4get(V,M) \ +do { *((float *) &(V)) = *((const float*) (M)); } while(0) +#define float8get(V,M) doubleget((V),(M)) +#define float4store(V,M) memcpy((uchar*)(V), (uchar*)(&M), sizeof(float)) +#define floatstore(T,V) memcpy((uchar*)(T), (uchar*)(&V), sizeof(float)) +#define floatget(V,M) memcpy((uchar*)(&V),(uchar*) (M), sizeof(float)) +#define float8store(V,M) doublestore((V),(M)) diff --git a/include/byte_order_generic_x86_64.h b/include/byte_order_generic_x86_64.h new file mode 100644 index 00000000..a25e6a2a --- /dev/null +++ b/include/byte_order_generic_x86_64.h @@ -0,0 +1,125 @@ +/* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2020, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Optimized function-like macros for the x86 architecture (_WIN32 included). +*/ + +#define sint2korr(A) (int16) (*((int16 *) (A))) +#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ + (((uint32) 255L << 24) | \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0])) : \ + (((uint32) (uchar) (A)[2]) << 16) |\ + (((uint32) (uchar) (A)[1]) << 8) | \ + ((uint32) (uchar) (A)[0]))) +#define sint4korr(A) (int32) (*((int32 *) (A))) +#define uint2korr(A) (uint16) (*((uint16 *) (A))) +#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) |\ + (((uint32) ((uchar) (A)[1])) << 8) |\ + (((uint32) ((uchar) (A)[2])) << 16)) +#define uint4korr(A) (uint32) (*((uint32 *) (A))) + + +static inline ulonglong uint5korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(4 + (uchar *) p); + return a | (b << 32); +} +static inline ulonglong uint6korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(uint16 *) (4 + (char *) p); + return a | (b << 32); +} + +#define uint8korr(A) (ulonglong) (*((ulonglong *) (A))) +#define sint8korr(A) (longlong) (*((longlong *) (A))) + +#define int2store(T,A) do { uchar *pT= (uchar*)(T);\ + *((uint16*)(pT))= (uint16) (A);\ + } while (0) + +#define int3store(T,A) do { *(T)= (uchar) ((A));\ + *(T+1)=(uchar) (((uint) (A) >> 8));\ + *(T+2)=(uchar) (((A) >> 16));\ + } while (0) + +#define int4store(T,A) do { uchar *pT= (uchar*)(T);\ + *((uint32 *) (pT))= (uint32) (A); \ + } while (0) + +#define int5store(T,A) do { uchar *pT= (uchar*)(T);\ + *((uint32 *) (pT))= (uint32) (A); \ + *((pT)+4)=(uchar) (((A) >> 32));\ + } while (0) + +#define int6store(T,A) do { uchar *pT= (uchar*)(T);\ + *((uint32 *) (pT))= (uint32) (A); \ + *((uint16*)(pT+4))= (uint16) (A >> 32);\ + } while (0) + +#define int8store(T,A) do { uchar *pT= (uchar*)(T);\ + *((ulonglong *) (pT))= (ulonglong) (A);\ + } while(0) + +#if defined(__GNUC__) + +#define HAVE_mi_uint5korr +#define HAVE_mi_uint6korr +#define HAVE_mi_uint7korr +#define HAVE_mi_uint78orr + +/* Read numbers stored in high-bytes-first order */ + +static inline ulonglong mi_uint5korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(4 + (uchar *) p); + ulonglong v= (a | (b << 32)) << 24; + asm ("bswapq %0" : "=r" (v) : "0" (v)); + return v; +} + +static inline ulonglong mi_uint6korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(uint16 *) (4 + (char *) p); + ulonglong v= (a | (b << 32)) << 16; + asm ("bswapq %0" : "=r" (v) : "0" (v)); + return v; +} + +static inline ulonglong mi_uint7korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(uint16 *) (4 + (char *) p); + ulonglong c= *(6 + (uchar *) p); + ulonglong v= (a | (b << 32) | (c << 48)) << 8; + asm ("bswapq %0" : "=r" (v) : "0" (v)); + return v; +} + +static inline ulonglong mi_uint8korr(const void *p) +{ + ulonglong v= *(ulonglong *) p; + asm ("bswapq %0" : "=r" (v) : "0" (v)); + return v; +} + +#endif diff --git a/include/decimal.h b/include/decimal.h new file mode 100644 index 00000000..02725fe0 --- /dev/null +++ b/include/decimal.h @@ -0,0 +1,128 @@ +/* Copyright (c) 2000, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _decimal_h +#define _decimal_h + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} + decimal_round_mode; +typedef int32 decimal_digit_t; + +/** + intg is the number of *decimal* digits (NOT number of decimal_digit_t's !) + before the point + frac is the number of decimal digits after the point + len is the length of buf (length of allocated space) in decimal_digit_t's, + not in bytes + sign false means positive, true means negative + buf is an array of decimal_digit_t's + */ +typedef struct st_decimal_t { + int intg, frac, len; + my_bool sign; + decimal_digit_t *buf; +} decimal_t; + +int internal_str2dec(const char *from, decimal_t *to, char **end, + my_bool fixed); +int decimal2string(const decimal_t *from, char *to, int *to_len, + decimal_digits_t fixed_precision, + decimal_digits_t fixed_decimals, + char filler); +int decimal2ulonglong(const decimal_t *from, ulonglong *to); +int ulonglong2decimal(ulonglong from, decimal_t *to); +int decimal2longlong(const decimal_t *from, longlong *to); +int longlong2decimal(longlong from, decimal_t *to); +int decimal2double(const decimal_t *from, double *to); +int double2decimal(double from, decimal_t *to); +decimal_digits_t decimal_actual_fraction(const decimal_t *from); +int decimal2bin(const decimal_t *from, uchar *to, decimal_digits_t precision, + decimal_digits_t scale); +int bin2decimal(const uchar *from, decimal_t *to, decimal_digits_t precision, + decimal_digits_t scale); + +uint decimal_size(decimal_digits_t precision, decimal_digits_t scale); +uint decimal_bin_size(decimal_digits_t precision, decimal_digits_t scale); +uint decimal_result_size(decimal_t *from1, decimal_t *from2, char op, + int param); + +decimal_digits_t decimal_intg(const decimal_t *from); +int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to); +int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to); +int decimal_cmp(const decimal_t *from1, const decimal_t *from2); +int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to); +int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, + int scale_incr); +int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to); +int decimal_round(const decimal_t *from, decimal_t *to, int new_scale, + decimal_round_mode mode); +int decimal_is_zero(const decimal_t *from); +void max_decimal(decimal_digits_t precision, decimal_digits_t frac, + decimal_t *to); + +#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0) +#define string2decimal_fixed(A,B,C) internal_str2dec((A), (B), (C), 1) + +/* set a decimal_t to zero */ + +#define decimal_make_zero(dec) do { \ + (dec)->buf[0]=0; \ + (dec)->intg=1; \ + (dec)->frac=0; \ + (dec)->sign=0; \ + } while(0) + +/* + returns the length of the buffer to hold string representation + of the decimal (including decimal dot, possible sign and \0) +*/ + +#define decimal_string_size(dec) (((dec)->intg ? (dec)->intg : 1) + \ + (dec)->frac + ((dec)->frac > 0) + 2) + +/* negate a decimal */ +#define decimal_neg(dec) do { (dec)->sign^=1; } while(0) + +/* + conventions: + + decimal_smth() == 0 -- everything's ok + decimal_smth() <= 1 -- result is usable, but precision loss is possible + decimal_smth() <= 2 -- result can be unusable, most significant digits + could've been lost + decimal_smth() > 2 -- no result was generated +*/ + +#define E_DEC_OK 0 +#define E_DEC_TRUNCATED 1 +#define E_DEC_OVERFLOW 2 +#define E_DEC_DIV_ZERO 4 +#define E_DEC_BAD_NUM 8 +#define E_DEC_OOM 16 + +#define E_DEC_ERROR 31 +#define E_DEC_FATAL_ERROR 30 + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/dur_prop.h b/include/dur_prop.h new file mode 100644 index 00000000..558ce5ac --- /dev/null +++ b/include/dur_prop.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2013, 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef _my_dur_prop_h +#define _my_dur_prop_h + +enum durability_properties +{ + /* + Preserves the durability properties defined by the engine + */ + HA_REGULAR_DURABILITY= 0, + /* + Ignore the durability properties defined by the engine and + write only in-memory entries. + */ + HA_IGNORE_DURABILITY= 1 +}; + +#endif /* _my_dur_prop_h */ diff --git a/include/errmsg.h b/include/errmsg.h new file mode 100644 index 00000000..bd086bba --- /dev/null +++ b/include/errmsg.h @@ -0,0 +1,117 @@ +#ifndef ERRMSG_INCLUDED +#define ERRMSG_INCLUDED + +/* Copyright (c) 2000, 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 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Error messages numbers for MySQL clients. + The error messages itself are in libmysql/errmsg.c + + Error messages for the mysqld daemon are in sql/share/errmsg.txt +*/ + +#ifdef __cplusplus +extern "C" { +#endif +void init_client_errs(void); +void finish_client_errs(void); +extern const char *client_errors[]; /* Error messages */ +#ifdef __cplusplus +} +#endif + +#define CR_MIN_ERROR 2000 /* For easier client code */ +#define CR_MAX_ERROR 2999 +#if !defined(ER) +#define ER(X) (((X) >= CR_ERROR_FIRST && (X) <= CR_ERROR_LAST) \ + ? client_errors[(X)-CR_ERROR_FIRST] \ + : client_errors[CR_UNKNOWN_ERROR-CR_ERROR_FIRST]) + +#endif +#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */ + +/* Do not add error numbers before CR_ERROR_FIRST. */ +/* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */ +#define CR_ERROR_FIRST 2000 /*Copy first error nr.*/ +#define CR_UNKNOWN_ERROR 2000 +#define CR_SOCKET_CREATE_ERROR 2001 +#define CR_CONNECTION_ERROR 2002 +#define CR_CONN_HOST_ERROR 2003 +#define CR_IPSOCK_ERROR 2004 +#define CR_UNKNOWN_HOST 2005 +#define CR_SERVER_GONE_ERROR 2006 +#define CR_VERSION_ERROR 2007 +#define CR_OUT_OF_MEMORY 2008 +#define CR_WRONG_HOST_INFO 2009 +#define CR_LOCALHOST_CONNECTION 2010 +#define CR_TCP_CONNECTION 2011 +#define CR_SERVER_HANDSHAKE_ERR 2012 +#define CR_SERVER_LOST 2013 +#define CR_COMMANDS_OUT_OF_SYNC 2014 +#define CR_NAMEDPIPE_CONNECTION 2015 +#define CR_NAMEDPIPEWAIT_ERROR 2016 +#define CR_NAMEDPIPEOPEN_ERROR 2017 +#define CR_NAMEDPIPESETSTATE_ERROR 2018 +#define CR_CANT_READ_CHARSET 2019 +#define CR_NET_PACKET_TOO_LARGE 2020 +#define CR_EMBEDDED_CONNECTION 2021 +#define CR_PROBE_SLAVE_STATUS 2022 +#define CR_PROBE_SLAVE_HOSTS 2023 +#define CR_PROBE_SLAVE_CONNECT 2024 +#define CR_PROBE_MASTER_CONNECT 2025 +#define CR_SSL_CONNECTION_ERROR 2026 +#define CR_MALFORMED_PACKET 2027 +#define CR_WRONG_LICENSE 2028 + +/* new 4.1 error codes */ +#define CR_NULL_POINTER 2029 +#define CR_NO_PREPARE_STMT 2030 +#define CR_PARAMS_NOT_BOUND 2031 +#define CR_DATA_TRUNCATED 2032 +#define CR_NO_PARAMETERS_EXISTS 2033 +#define CR_INVALID_PARAMETER_NO 2034 +#define CR_INVALID_BUFFER_USE 2035 +#define CR_UNSUPPORTED_PARAM_TYPE 2036 + +#define CR_SHARED_MEMORY_CONNECTION 2037 +#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2038 +#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2039 +#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2040 +#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2041 +#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2042 +#define CR_SHARED_MEMORY_MAP_ERROR 2043 +#define CR_SHARED_MEMORY_EVENT_ERROR 2044 +#define CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR 2045 +#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046 +#define CR_CONN_UNKNOW_PROTOCOL 2047 +#define CR_INVALID_CONN_HANDLE 2048 +#define CR_SECURE_AUTH 2049 +#define CR_FETCH_CANCELED 2050 +#define CR_NO_DATA 2051 +#define CR_NO_STMT_METADATA 2052 +#define CR_NO_RESULT_SET 2053 +#define CR_NOT_IMPLEMENTED 2054 +#define CR_SERVER_LOST_EXTENDED 2055 +#define CR_STMT_CLOSED 2056 +#define CR_NEW_STMT_METADATA 2057 +#define CR_ALREADY_CONNECTED 2058 +#define CR_AUTH_PLUGIN_CANNOT_LOAD 2059 +#define CR_DUPLICATE_CONNECTION_ATTR 2060 +#define CR_AUTH_PLUGIN_ERR 2061 +#define CR_ERROR_LAST /*Copy last error nr:*/ 2061 +/* Add error numbers before CR_ERROR_LAST and change it accordingly. */ + +#endif /* ERRMSG_INCLUDED */ diff --git a/include/ft_global.h b/include/ft_global.h new file mode 100644 index 00000000..9f2d5261 --- /dev/null +++ b/include/ft_global.h @@ -0,0 +1,112 @@ +/* Copyright (c) 2000-2005, 2007 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Written by Sergei A. Golubchik, who has a shared copyright to this code */ + +/* some definitions for full-text indices */ + +/* #include "myisam.h" */ + +#ifndef _ft_global_h +#define _ft_global_h +#ifdef __cplusplus +extern "C" { +#endif + +#include <my_compare.h> + +#define HA_FT_MAXBYTELEN 254 +#define HA_FT_MAXCHARLEN (HA_FT_MAXBYTELEN/3) + +#define DEFAULT_FTB_SYNTAX "+ -><()~*:\"\"&|" + +typedef struct st_ft_info FT_INFO; +struct _ft_vft +{ + int (*read_next)(FT_INFO *, char *); + float (*find_relevance)(FT_INFO *, uchar *, uint); + void (*close_search)(FT_INFO *); + float (*get_relevance)(FT_INFO *); + void (*reinit_search)(FT_INFO *); +}; + +typedef struct st_ft_info_ext FT_INFO_EXT; +struct _ft_vft_ext +{ + uint (*get_version)(); // Extended API version + ulonglong (*get_flags)(); + ulonglong (*get_docid)(FT_INFO_EXT *); + ulonglong (*count_matches)(FT_INFO_EXT *); +}; + +/* Flags for extended FT API */ +#define FTS_ORDERED_RESULT (1LL << 1) +#define FTS_DOCID_IN_RESULT (1LL << 2) + +#define FTS_DOC_ID_COL_NAME "FTS_DOC_ID" + +#ifndef FT_CORE +struct st_ft_info +{ + struct _ft_vft *please; /* INTERCAL style :-) */ +}; + +struct st_ft_info_ext +{ + struct _ft_vft *please; /* INTERCAL style :-) */ + struct _ft_vft_ext *could_you; +}; +#endif + +extern const char *ft_stopword_file; +extern const char *ft_precompiled_stopwords[]; + +extern ulong ft_min_word_len; +extern ulong ft_max_word_len; +extern ulong ft_query_expansion_limit; +extern const char *ft_boolean_syntax; +extern struct st_mysql_ftparser ft_default_parser; + +int ft_init_stopwords(void); +void ft_free_stopwords(void); + +#define FT_NL 0 +#define FT_BOOL 1 +#define FT_SORTED 2 +#define FT_EXPAND 4 /* query expansion */ + +FT_INFO *ft_init_search(uint,void *, uint, uchar *, size_t, + CHARSET_INFO *, uchar *); +my_bool ft_boolean_check_syntax_string(const uchar *, size_t length, + CHARSET_INFO *cs); + +/* Internal symbols for fulltext between maria and MyISAM */ + +#define HA_FT_WTYPE HA_KEYTYPE_FLOAT +#define HA_FT_WLEN 4 +#define FT_SEGS 2 + +#define ft_sintXkorr(A) mi_sint4korr(A) +#define ft_intXstore(T,A) mi_int4store(T,A) + +extern const HA_KEYSEG ft_keysegs[FT_SEGS]; + +typedef union {int32 i; float f;} FT_WEIGTH; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/handler_ername.h b/include/handler_ername.h new file mode 100644 index 00000000..e969daa7 --- /dev/null +++ b/include/handler_ername.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2013, 2021, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Names of all handler error numbers. Used by mysqltest */ + +{ "HA_ERR_KEY_NOT_FOUND", HA_ERR_KEY_NOT_FOUND, "" }, +{ "HA_ERR_FOUND_DUPP_KEY", HA_ERR_FOUND_DUPP_KEY, "" }, +{ "HA_ERR_INTERNAL_ERROR", HA_ERR_INTERNAL_ERROR, "" }, +{ "HA_ERR_RECORD_CHANGED", HA_ERR_RECORD_CHANGED, "" }, +{ "HA_ERR_WRONG_INDEX", HA_ERR_WRONG_INDEX, "" }, +{ "HA_ERR_CRASHED", HA_ERR_CRASHED, "" }, +{ "HA_ERR_WRONG_IN_RECORD", HA_ERR_WRONG_IN_RECORD, "" }, +{ "HA_ERR_OUT_OF_MEM", HA_ERR_OUT_OF_MEM, "" }, +{ "HA_ERR_NOT_A_TABLE", HA_ERR_NOT_A_TABLE, "" }, +{ "HA_ERR_WRONG_COMMAND", HA_ERR_WRONG_COMMAND, "" }, +{ "HA_ERR_OLD_FILE", HA_ERR_OLD_FILE, "" }, +{ "HA_ERR_NO_ACTIVE_RECORD", HA_ERR_NO_ACTIVE_RECORD, "" }, +{ "HA_ERR_RECORD_DELETED", HA_ERR_RECORD_DELETED, "" }, +{ "HA_ERR_RECORD_FILE_FULL", HA_ERR_RECORD_FILE_FULL, "" }, +{ "HA_ERR_INDEX_FILE_FULL", HA_ERR_INDEX_FILE_FULL, "" }, +{ "HA_ERR_END_OF_FILE", HA_ERR_END_OF_FILE, "" }, +{ "HA_ERR_UNSUPPORTED", HA_ERR_UNSUPPORTED, "" }, +{ "HA_ERR_TO_BIG_ROW", HA_ERR_TO_BIG_ROW, "" }, +{ "HA_WRONG_CREATE_OPTION", HA_WRONG_CREATE_OPTION, "" }, +{ "HA_ERR_FOUND_DUPP_UNIQUE", HA_ERR_FOUND_DUPP_UNIQUE, "" }, +{ "HA_ERR_UNKNOWN_CHARSET", HA_ERR_UNKNOWN_CHARSET, "" }, +{ "HA_ERR_WRONG_MRG_TABLE_DEF", HA_ERR_WRONG_MRG_TABLE_DEF, "" }, +{ "HA_ERR_CRASHED_ON_REPAIR", HA_ERR_CRASHED_ON_REPAIR, "" }, +{ "HA_ERR_CRASHED_ON_USAGE", HA_ERR_CRASHED_ON_USAGE, "" }, +{ "HA_ERR_LOCK_WAIT_TIMEOUT", HA_ERR_LOCK_WAIT_TIMEOUT, "" }, +{ "HA_ERR_LOCK_TABLE_FULL", HA_ERR_LOCK_TABLE_FULL, "" }, +{ "HA_ERR_READ_ONLY_TRANSACTION", HA_ERR_READ_ONLY_TRANSACTION, "" }, +{ "HA_ERR_LOCK_DEADLOCK", HA_ERR_LOCK_DEADLOCK, "" }, +{ "HA_ERR_CANNOT_ADD_FOREIGN", HA_ERR_CANNOT_ADD_FOREIGN, "" }, +{ "HA_ERR_NO_REFERENCED_ROW", HA_ERR_NO_REFERENCED_ROW, "" }, +{ "HA_ERR_ROW_IS_REFERENCED", HA_ERR_ROW_IS_REFERENCED, "" }, +{ "HA_ERR_NO_SAVEPOINT", HA_ERR_NO_SAVEPOINT, "" }, +{ "HA_ERR_NON_UNIQUE_BLOCK_SIZE", HA_ERR_NON_UNIQUE_BLOCK_SIZE, "" }, +{ "HA_ERR_NO_SUCH_TABLE", HA_ERR_NO_SUCH_TABLE, "" }, +{ "HA_ERR_TABLE_EXIST", HA_ERR_TABLE_EXIST, "" }, +{ "HA_ERR_NO_CONNECTION", HA_ERR_NO_CONNECTION, "" }, +{ "HA_ERR_NULL_IN_SPATIAL", HA_ERR_NULL_IN_SPATIAL, "" }, +{ "HA_ERR_TABLE_DEF_CHANGED", HA_ERR_TABLE_DEF_CHANGED, "" }, +{ "HA_ERR_NO_PARTITION_FOUND", HA_ERR_NO_PARTITION_FOUND, "" }, +{ "HA_ERR_RBR_LOGGING_FAILED", HA_ERR_RBR_LOGGING_FAILED, "" }, +{ "HA_ERR_DROP_INDEX_FK", HA_ERR_DROP_INDEX_FK, "" }, +{ "HA_ERR_FOREIGN_DUPLICATE_KEY", HA_ERR_FOREIGN_DUPLICATE_KEY, "" }, +{ "HA_ERR_TABLE_NEEDS_UPGRADE", HA_ERR_TABLE_NEEDS_UPGRADE, "" }, +{ "HA_ERR_TABLE_READONLY", HA_ERR_TABLE_READONLY, "" }, +{ "HA_ERR_AUTOINC_READ_FAILED", HA_ERR_AUTOINC_READ_FAILED, "" }, +{ "HA_ERR_AUTOINC_ERANGE", HA_ERR_AUTOINC_ERANGE, "" }, +{ "HA_ERR_GENERIC", HA_ERR_GENERIC, "" }, +{ "HA_ERR_RECORD_IS_THE_SAME", HA_ERR_RECORD_IS_THE_SAME, "" }, +{ "HA_ERR_LOGGING_IMPOSSIBLE", HA_ERR_LOGGING_IMPOSSIBLE, "" }, +{ "HA_ERR_CORRUPT_EVENT", HA_ERR_CORRUPT_EVENT, "" }, +{ "HA_ERR_NEW_FILE", HA_ERR_NEW_FILE, "" }, +{ "HA_ERR_ROWS_EVENT_APPLY", HA_ERR_ROWS_EVENT_APPLY, "" }, +{ "HA_ERR_INITIALIZATION", HA_ERR_INITIALIZATION, "" }, +{ "HA_ERR_FILE_TOO_SHORT", HA_ERR_FILE_TOO_SHORT, "" }, +{ "HA_ERR_WRONG_CRC", HA_ERR_WRONG_CRC, "" }, +{ "HA_ERR_TOO_MANY_CONCURRENT_TRXS", HA_ERR_TOO_MANY_CONCURRENT_TRXS, "" }, +{ "HA_ERR_INDEX_COL_TOO_LONG", HA_ERR_INDEX_COL_TOO_LONG, "" }, +{ "HA_ERR_INDEX_CORRUPT", HA_ERR_INDEX_CORRUPT, "" }, +{ "HA_ERR_UNDO_REC_TOO_BIG", HA_ERR_UNDO_REC_TOO_BIG, "" }, +{ "HA_ERR_ROW_NOT_VISIBLE", HA_ERR_ROW_NOT_VISIBLE, "" }, +{ "HA_ERR_ABORTED_BY_USER", HA_ERR_ABORTED_BY_USER, "" }, +{ "HA_ERR_DISK_FULL", HA_ERR_DISK_FULL, "" }, +{ "HA_ERR_INCOMPATIBLE_DEFINITION", HA_ERR_INCOMPATIBLE_DEFINITION, "" }, +{ "HA_ERR_NO_ENCRYPTION", HA_ERR_NO_ENCRYPTION, "" }, +{ "HA_ERR_COMMIT_ERROR", HA_ERR_COMMIT_ERROR, "" }, diff --git a/include/handler_state.h b/include/handler_state.h new file mode 100644 index 00000000..65604a67 --- /dev/null +++ b/include/handler_state.h @@ -0,0 +1,21 @@ +/* + Map handler error message to sql states. Note that this list MUST be in + increasing order! + See sql_state.c for usage +*/ + +{ HA_ERR_KEY_NOT_FOUND, "02000", "" }, +{ HA_ERR_FOUND_DUPP_KEY, "23000", "" }, +{ HA_ERR_WRONG_COMMAND, "0A000", "" }, +{ HA_ERR_UNSUPPORTED, "0A000", "" }, +{ HA_WRONG_CREATE_OPTION, "0A000", "" }, +{ HA_ERR_FOUND_DUPP_UNIQUE, "23000", "" }, +{ HA_ERR_UNKNOWN_CHARSET, "0A000", "" }, +{ HA_ERR_READ_ONLY_TRANSACTION, "25000", "" }, +{ HA_ERR_LOCK_DEADLOCK, "40001", "" }, +{ HA_ERR_NO_REFERENCED_ROW, "23000", "" }, +{ HA_ERR_ROW_IS_REFERENCED, "23000", "" }, +{ HA_ERR_TABLE_EXIST, "42S01", "" }, +{ HA_ERR_FOREIGN_DUPLICATE_KEY, "23000", "" }, +{ HA_ERR_TABLE_READONLY, "25000", "" }, +{ HA_ERR_AUTOINC_ERANGE, "22003", "" }, diff --git a/include/hash.h b/include/hash.h new file mode 100644 index 00000000..c0a846ac --- /dev/null +++ b/include/hash.h @@ -0,0 +1,107 @@ +/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2011, 2013, Monty Program Ab. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Dynamic hashing of record with different key-length */ + +#ifndef _hash_h +#define _hash_h + +#include "my_sys.h" /* DYNAMIC_ARRAY */ + +/* + This forward declaration is used from C files where the real + definition is included before. Since C does not allow repeated + typedef declarations, even when identical, the definition may not be + repeated. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +/* + Overhead to store an element in hash + Can be used to approximate memory consumption for a hash + */ +#define HASH_OVERHEAD (sizeof(char*)*2) + +/* flags for hash_init */ +#define HASH_UNIQUE 1 /* hash_insert fails on duplicate key */ +#define HASH_THREAD_SPECIFIC 2 /* Mark allocated memory THREAD_SPECIFIC */ + +typedef uint32 my_hash_value_type; +typedef uchar *(*my_hash_get_key)(const uchar *,size_t*,my_bool); +typedef my_hash_value_type (*my_hash_function)(CHARSET_INFO *, + const uchar *, size_t); +typedef void (*my_hash_free_key)(void *); +typedef my_bool (*my_hash_walk_action)(void *,void *); + +typedef struct st_hash { + size_t key_offset,key_length; /* Length of key if const length */ + size_t blength; + ulong records; + uint flags; + DYNAMIC_ARRAY array; /* Place for hash_keys */ + my_hash_get_key get_key; + my_hash_function hash_function; + void (*free)(void *); + CHARSET_INFO *charset; +} HASH; + +/* A search iterator state */ +typedef uint HASH_SEARCH_STATE; + +#define my_hash_init(A,B,C,D,E,F,G,H,I) my_hash_init2(A,B,0,C,D,E,F,G,0,H,I) +my_bool my_hash_init2(PSI_memory_key psi_key, HASH *hash, size_t growth_size, + CHARSET_INFO *charset, size_t default_array_elements, + size_t key_offset, size_t key_length, + my_hash_get_key get_key, my_hash_function hash_function, + void (*free_element)(void*), uint flags); +void my_hash_free(HASH *tree); +void my_hash_reset(HASH *hash); +uchar *my_hash_element(HASH *hash, size_t idx); +uchar *my_hash_search(const HASH *info, const uchar *key, size_t length); +uchar *my_hash_search_using_hash_value(const HASH *info, + my_hash_value_type hash_value, + const uchar *key, size_t length); +my_hash_value_type my_hash_sort(CHARSET_INFO *cs, + const uchar *key, size_t length); +#define my_calc_hash(A, B, C) my_hash_sort((A)->charset, B, C) +uchar *my_hash_first(const HASH *info, const uchar *key, size_t length, + HASH_SEARCH_STATE *state); +uchar *my_hash_first_from_hash_value(const HASH *info, + my_hash_value_type hash_value, + const uchar *key, + size_t length, + HASH_SEARCH_STATE *state); +uchar *my_hash_next(const HASH *info, const uchar *key, size_t length, + HASH_SEARCH_STATE *state); +my_bool my_hash_insert(HASH *info, const uchar *data); +my_bool my_hash_delete(HASH *hash, uchar *record); +my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, + size_t old_key_length); +void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *state, uchar *new_row); +my_bool my_hash_check(HASH *hash); /* Only in debug library */ +my_bool my_hash_iterate(HASH *hash, my_hash_walk_action action, void *argument); + +#define my_hash_clear(H) bzero((char*) (H), sizeof(*(H))) +#define my_hash_inited(H) ((H)->blength != 0) +#define my_hash_init_opt(A,B,C,D,E,F,G,H,I) \ + (!my_hash_inited(B) && my_hash_init(A,B,C,D,E,F,G,H,I)) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/heap.h b/include/heap.h new file mode 100644 index 00000000..2e0e9357 --- /dev/null +++ b/include/heap.h @@ -0,0 +1,271 @@ +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +/* This file should be included when using heap_database_functions */ +/* Author: Michael Widenius */ + +#ifndef _heap_h +#define _heap_h +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _my_base_h +#include <my_base.h> +#endif + +#include <my_pthread.h> +#include <thr_lock.h> + +#include "my_compare.h" +#include "my_tree.h" + + /* defines used by heap-functions */ + +#define HP_MAX_LEVELS 4 /* 128^5 records is enough */ +#define HP_PTRS_IN_NOD 128 + + /* struct used with heap_functions */ + +typedef struct st_heapinfo /* Struct from heap_info */ +{ + ulong records; /* Records in database */ + ulong deleted; /* Deleted records in database */ + ulong max_records; + ulonglong data_length; + ulonglong index_length; + uint reclength; /* Length of one record */ + int errkey; + ulonglong auto_increment; + time_t create_time; +} HEAPINFO; + + + /* Structs used by heap-database-handler */ + +typedef struct st_heap_ptrs +{ + uchar *blocks[HP_PTRS_IN_NOD]; /* pointers to HP_PTRS or records */ +} HP_PTRS; + +struct st_level_info +{ + /* Number of unused slots in *last_blocks HP_PTRS block (0 for 0th level) */ + uint free_ptrs_in_block; + + /* + Maximum number of records that can be 'contained' inside of each element + of last_blocks array. For level 0 - 1, for level 1 - HP_PTRS_IN_NOD, for + level 2 - HP_PTRS_IN_NOD^2 and so forth. + */ + ulong records_under_level; + + /* + Ptr to last allocated HP_PTRS (or records buffer for level 0) on this + level. + */ + HP_PTRS *last_blocks; +}; + + +/* + Heap table records and hash index entries are stored in HP_BLOCKs. + HP_BLOCK is used as a 'growable array' of fixed-size records. Size of record + is recbuffer bytes. + The internal representation is as follows: + HP_BLOCK is a hierarchical structure of 'blocks'. + A block at level 0 is an array records_in_block records. + A block at higher level is an HP_PTRS structure with pointers to blocks at + lower levels. + At the highest level there is one top block. It is stored in HP_BLOCK::root. + + See hp_find_block for a description of how record pointer is obtained from + its index. + See hp_get_new_block +*/ + +typedef struct st_heap_block +{ + HP_PTRS *root; /* Top-level block */ + struct st_level_info level_info[HP_MAX_LEVELS+1]; + uint levels; /* number of used levels */ + uint recbuffer; /* Length of one saved record */ + ulong records_in_block; /* Records in one heap-block */ + ulong last_allocated; /* number of records there is allocated space for */ +} HP_BLOCK; + +struct st_heap_info; /* For reference */ + +typedef struct st_hp_keydef /* Key definition with open */ +{ + uint flag; /* HA_NOSAME | HA_NULL_PART_KEY */ + uint keysegs; /* Number of key-segment */ + uint length; /* Length of key (automatic) */ + uint8 algorithm; /* HASH / BTREE */ + HA_KEYSEG *seg; + HP_BLOCK block; /* Where keys are saved */ + /* + Number of buckets used in hash table. Used only to provide + #records estimates for heap key scans. + */ + ha_rows hash_buckets; + TREE rb_tree; + int (*write_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo, + const uchar *record, uchar *recpos); + int (*delete_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo, + const uchar *record, uchar *recpos, int flag); + uint (*get_key_length)(struct st_hp_keydef *keydef, const uchar *key); +} HP_KEYDEF; + +typedef struct st_heap_share +{ + HP_BLOCK block; + HP_KEYDEF *keydef; + ulonglong data_length,index_length,max_table_size; + ulonglong auto_increment; + ulong min_records,max_records; /* Params to open */ + ulong records; /* records */ + ulong blength; /* records rounded up to 2^n */ + ulong deleted; /* Deleted records in database */ + uint key_stat_version; /* version to indicate insert/delete */ + uint key_version; /* Updated on key change */ + uint file_version; /* Update on clear */ + uint reclength; /* Length of one record */ + uint visible; /* Offset to the visible/deleted mark */ + uint changed; + uint keys,max_key_length; + uint currently_disabled_keys; /* saved value from "keys" when disabled */ + uint open_count; + uchar *del_link; /* Link to next block with del. rec */ + char * name; /* Name of "memory-file" */ + time_t create_time; + THR_LOCK lock; + my_bool delete_on_close; + my_bool internal; /* Internal temporary table */ + LIST open_list; + uint auto_key; + uint auto_key_type; /* real type of the auto key segment */ +} HP_SHARE; + +struct st_hp_hash_info; + +typedef struct st_heap_info +{ + HP_SHARE *s; + uchar *current_ptr; + struct st_hp_hash_info *current_hash_ptr; + ulong current_record,next_block; + int lastinx,errkey; + int mode; /* Mode of file (READONLY..) */ + uint opt_flag,update; + uchar *lastkey; /* Last used key with rkey */ + uchar *recbuf; /* Record buffer for rb-tree keys */ + enum ha_rkey_function last_find_flag; + TREE_ELEMENT *parents[MAX_TREE_HEIGHT+1]; + TREE_ELEMENT **last_pos; + uint key_version; /* Version at last read */ + uint file_version; /* Version at scan */ + uint lastkey_len; + my_bool implicit_emptied; + THR_LOCK_DATA lock; + LIST open_list; +} HP_INFO; + + +typedef struct st_heap_create_info +{ + HP_KEYDEF *keydef; + uint auto_key; /* keynr [1 - maxkey] for auto key */ + uint auto_key_type; + uint keys; + uint reclength; + ulong max_records; + ulong min_records; + ulonglong max_table_size; + ulonglong auto_increment; + my_bool with_auto_increment; + my_bool internal_table; + /* + TRUE if heap_create should 'pin' the created share by setting + open_count to 1. Is only looked at if not internal_table. + */ + my_bool pin_share; +} HP_CREATE_INFO; + + /* Prototypes for heap-functions */ + +extern HP_INFO *heap_open(const char *name, int mode); +extern HP_INFO *heap_open_from_share(HP_SHARE *share, int mode); +extern HP_INFO *heap_open_from_share_and_register(HP_SHARE *share, int mode); +extern void heap_release_share(HP_SHARE *share, my_bool internal_table); +extern int heap_close(HP_INFO *info); +extern int heap_write(HP_INFO *info,const uchar *buff); +extern int heap_update(HP_INFO *info,const uchar *old,const uchar *newdata); +extern int heap_rrnd(HP_INFO *info,uchar *buf,uchar *pos); +extern int heap_scan_init(HP_INFO *info); +extern int heap_scan(HP_INFO *info, uchar *record); +extern int heap_delete(HP_INFO *info,const uchar *buff); +extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag); +extern int heap_create(const char *name, + HP_CREATE_INFO *create_info, HP_SHARE **share, + my_bool *created_new_share); +extern int heap_delete_table(const char *name); +extern void heap_drop_table(HP_INFO *info); +extern int heap_extra(HP_INFO *info,enum ha_extra_function function); +extern int heap_reset(HP_INFO *info); +extern int heap_rename(const char *old_name,const char *new_name); +extern int heap_panic(enum ha_panic_function flag); +extern int heap_rsame(HP_INFO *info,uchar *record,int inx); +extern int heap_rnext(HP_INFO *info,uchar *record); +extern int heap_rprev(HP_INFO *info,uchar *record); +extern int heap_rfirst(HP_INFO *info,uchar *record,int inx); +extern int heap_rlast(HP_INFO *info,uchar *record,int inx); +extern void heap_clear(HP_INFO *info); +extern void heap_clear_keys(HP_INFO *info); +extern int heap_disable_indexes(HP_INFO *info); +extern int heap_enable_indexes(HP_INFO *info); +extern int heap_indexes_are_disabled(HP_INFO *info); +extern void heap_update_auto_increment(HP_INFO *info, const uchar *record); +ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, + const key_range *min_key, + const key_range *max_key); +int hp_panic(enum ha_panic_function flag); +int heap_rkey(HP_INFO *info, uchar *record, int inx, const uchar *key, + key_part_map keypart_map, enum ha_rkey_function find_flag); +extern uchar * heap_find(HP_INFO *info,int inx,const uchar *key); +extern int heap_check_heap(const HP_INFO *info, my_bool print_status); +extern uchar *heap_position(HP_INFO *info); + +/* The following is for programs that uses the old HEAP interface where + pointer to rows where a long instead of a (uchar*). +*/ + +#if defined(WANT_OLD_HEAP_VERSION) || defined(OLD_HEAP_VERSION) +extern int heap_rrnd_old(HP_INFO *info,uchar *buf,ulong pos); +extern ulong heap_position_old(HP_INFO *info); +#endif +#ifdef OLD_HEAP_VERSION +typedef ulong HEAP_PTR; +#define heap_position(A) heap_position_old(A) +#define heap_rrnd(A,B,C) heap_rrnd_old(A,B,C) +#else +typedef uchar *HEAP_PTR; +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/ilist.h b/include/ilist.h new file mode 100644 index 00000000..3349959e --- /dev/null +++ b/include/ilist.h @@ -0,0 +1,272 @@ +/* + Copyright (c) 2019, 2020, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#ifndef ILIST_H +#define ILIST_H + +#include "my_dbug.h" + +#include <cstddef> +#include <iterator> + +// Derive your class from this struct to insert to a linked list. +template <class Tag= void> struct ilist_node +{ +#ifndef DBUG_OFF + ilist_node() noexcept : next(NULL), prev(NULL) {} +#else + ilist_node() = default; +#endif + + ilist_node(ilist_node *next, ilist_node *prev) noexcept + : next(next), prev(prev) + { + } + + ilist_node *next; + ilist_node *prev; +}; + +// Modelled after std::list<T> +template <class T, class Tag= void> class ilist +{ +public: + typedef ilist_node<Tag> ListNode; + class Iterator; + + // All containers in C++ should define these types to implement generic + // container interface. + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef T *pointer; + typedef const T *const_pointer; + typedef Iterator iterator; + typedef Iterator const_iterator; /* FIXME */ + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const iterator> const_reverse_iterator; + + class Iterator + { + public: + // All iterators in C++ should define these types to implement generic + // iterator interface. + typedef std::bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef T *pointer; + typedef T &reference; + + explicit Iterator(ListNode *node) noexcept : node_(node) + { + DBUG_ASSERT(node_ != nullptr); + } + + Iterator &operator++() noexcept + { + node_= node_->next; + DBUG_ASSERT(node_ != nullptr); + return *this; + } + Iterator operator++(int) noexcept + { + Iterator tmp(*this); + operator++(); + return tmp; + } + + Iterator &operator--() noexcept + { + node_= node_->prev; + DBUG_ASSERT(node_ != nullptr); + return *this; + } + Iterator operator--(int) noexcept + { + Iterator tmp(*this); + operator--(); + return tmp; + } + + reference operator*() noexcept { return *static_cast<pointer>(node_); } + const_reference operator*() const noexcept + { + return *static_cast<pointer>(node_); + } + pointer operator->() noexcept { return static_cast<pointer>(node_); } + + friend bool operator==(const Iterator &lhs, const Iterator &rhs) noexcept + { + return lhs.node_ == rhs.node_; + } + friend bool operator!=(const Iterator &lhs, const Iterator &rhs) noexcept + { + return !(lhs == rhs); + } + + private: + ListNode *node_; + + friend class ilist; + }; + + ilist() noexcept : sentinel_(&sentinel_, &sentinel_) {} + + reference front() noexcept { return *begin(); } + reference back() noexcept { return *--end(); } + const_reference front() const noexcept { return *begin(); } + const_reference back() const noexcept { return *--end(); } + + iterator begin() noexcept { return iterator(sentinel_.next); } + const_iterator begin() const noexcept + { + return iterator(const_cast<ListNode *>(sentinel_.next)); + } + iterator end() noexcept { return iterator(&sentinel_); } + const_iterator end() const noexcept + { + return iterator(const_cast<ListNode *>(&sentinel_)); + } + + reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const noexcept + { + return reverse_iterator(end()); + } + reverse_iterator rend() noexcept { return reverse_iterator(begin()); } + const_reverse_iterator rend() const noexcept + { + return reverse_iterator(begin()); + } + + bool empty() const noexcept { return sentinel_.next == &sentinel_; } + + // Not implemented because it's O(N) + // size_type size() const + // { + // return static_cast<size_type>(std::distance(begin(), end())); + // } + + void clear() noexcept + { + sentinel_.next= &sentinel_; + sentinel_.prev= &sentinel_; + } + + iterator insert(iterator pos, reference value) noexcept + { + ListNode *curr= pos.node_; + ListNode *prev= pos.node_->prev; + + prev->next= &value; + curr->prev= &value; + + static_cast<ListNode &>(value).prev= prev; + static_cast<ListNode &>(value).next= curr; + + return iterator(&value); + } + + iterator erase(iterator pos) noexcept + { + ListNode *prev= pos.node_->prev; + ListNode *next= pos.node_->next; + + prev->next= next; + next->prev= prev; + +#ifndef DBUG_OFF + ListNode *curr= pos.node_; + curr->prev= nullptr; + curr->next= nullptr; +#endif + + return Iterator(next); + } + + void push_back(reference value) noexcept { insert(end(), value); } + void pop_back() noexcept { erase(end()); } + + void push_front(reference value) noexcept { insert(begin(), value); } + void pop_front() noexcept { erase(begin()); } + + // STL version is O(n) but this is O(1) because an element can't be inserted + // several times in the same ilist. + void remove(reference value) noexcept { erase(iterator(&value)); } + +private: + ListNode sentinel_; +}; + +// Similar to ilist but also has O(1) size() method. +template <class T, class Tag= void> class sized_ilist : public ilist<T, Tag> +{ + typedef ilist<T, Tag> BASE; + +public: + // All containers in C++ should define these types to implement generic + // container interface. + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef T *pointer; + typedef const T *const_pointer; + typedef typename BASE::Iterator iterator; + typedef const typename BASE::Iterator const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const iterator> const_reverse_iterator; + + sized_ilist() noexcept : size_(0) {} + + size_type size() const noexcept { return size_; } + + void clear() noexcept + { + BASE::clear(); + size_= 0; + } + + iterator insert(iterator pos, reference value) noexcept + { + ++size_; + return BASE::insert(pos, value); + } + + iterator erase(iterator pos) noexcept + { + --size_; + return BASE::erase(pos); + } + + void push_back(reference value) noexcept { insert(BASE::end(), value); } + void pop_back() noexcept { erase(BASE::end()); } + + void push_front(reference value) noexcept { insert(BASE::begin(), value); } + void pop_front() noexcept { erase(BASE::begin()); } + + void remove(reference value) noexcept { erase(iterator(&value)); } + +private: + size_type size_; +}; + +#endif diff --git a/include/json_lib.h b/include/json_lib.h new file mode 100644 index 00000000..6342e36a --- /dev/null +++ b/include/json_lib.h @@ -0,0 +1,451 @@ +#ifndef JSON_LIB_INCLUDED +#define JSON_LIB_INCLUDED + +#include <my_sys.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define JSON_DEPTH_LIMIT 32 + +/* + When error happens, the c_next of the JSON engine contains the + character that caused the error, and the c_str is the position + in string where the error occurs. +*/ +enum json_errors { + JE_BAD_CHR= -1, /* Invalid character, charset handler cannot read it. */ + + JE_NOT_JSON_CHR= -2, /* Character met not used in JSON. */ + /* ASCII 00-08 for instance. */ + + JE_EOS= -3, /* Unexpected end of string. */ + + JE_SYN= -4, /* The next character breaks the JSON syntax. */ + + JE_STRING_CONST= -5, /* Character disallowed in string constant. */ + + JE_ESCAPING= -6, /* Error in the escaping. */ + + JE_DEPTH= -7, /* The limit on the JSON depth was overrun. */ +}; + + +typedef struct st_json_string_t +{ + const uchar *c_str; /* Current position in JSON string */ + const uchar *str_end; /* The end on the string. */ + my_wc_t c_next; /* UNICODE of the last read character */ + int c_next_len; /* character lenght of the last read character. */ + int error; /* error code. */ + + CHARSET_INFO *cs; /* Character set of the JSON string. */ + + my_charset_conv_mb_wc wc; /* UNICODE conversion function. */ + /* It's taken out of the cs just to speed calls. */ +} json_string_t; + + +void json_string_set_cs(json_string_t *s, CHARSET_INFO *i_cs); +void json_string_set_str(json_string_t *s, + const uchar *str, const uchar *end); +#define json_next_char(j) \ + ((j)->c_next_len= (j)->wc((j)->cs, &(j)->c_next, (j)->c_str, (j)->str_end)) +#define json_eos(j) ((j)->c_str >= (j)->str_end) +/* + read_string_const_chr() reads the next character of the string constant + and saves it to the js->c_next. + It takes into account possible escapings, so if for instance + the string is '\b', the read_string_const_chr() sets 8. +*/ +int json_read_string_const_chr(json_string_t *js); + + +/* + Various JSON-related operations expect JSON path as a parameter. + The path is a string like this "$.keyA[2].*" + The path itself is a number of steps specifying either a key or a position + in an array. Some of them can be wildcards. + So the representation of the JSON path is the json_path_t class + containing an array of json_path_step_t objects. +*/ + + +/* Path step types - actually bitmasks to let '&' or '|' operations. */ +enum json_path_step_types +{ + JSON_PATH_KEY_NULL=0, + JSON_PATH_KEY=1, /* Must be equal to JSON_VALUE_OBJECT. */ + JSON_PATH_ARRAY=2, /* Must be equal to JSON_VALUE_ARRAY. */ + JSON_PATH_KEY_OR_ARRAY=3, + JSON_PATH_WILD=4, /* Step like .* or [*] */ + JSON_PATH_DOUBLE_WILD=8, /* Step like **.k or **[1] */ + JSON_PATH_KEY_WILD= 1+4, + JSON_PATH_KEY_DOUBLEWILD= 1+8, + JSON_PATH_ARRAY_WILD= 2+4, + JSON_PATH_ARRAY_DOUBLEWILD= 2+8, + JSON_PATH_NEGATIVE_INDEX= 16, + JSON_PATH_ARRAY_RANGE= 32 +}; + + +typedef struct st_json_path_step_t +{ + enum json_path_step_types type; /* The type of the step - */ + /* see json_path_step_types */ + const uchar *key; /* Pointer to the beginning of the key. */ + const uchar *key_end; /* Pointer to the end of the key. */ + int n_item; /* Item number in an array. No meaning for the key step. */ + int n_item_end; /* Last index of the range. */ +} json_path_step_t; + + +typedef struct st_json_path_t +{ + json_string_t s; /* The string to be parsed. */ + json_path_step_t steps[JSON_DEPTH_LIMIT]; /* Steps of the path. */ + json_path_step_t *last_step; /* Points to the last step. */ + + int mode_strict; /* TRUE if the path specified as 'strict' */ + enum json_path_step_types types_used; /* The '|' of all step's 'type'-s */ +} json_path_t; + + +int json_path_setup(json_path_t *p, + CHARSET_INFO *i_cs, const uchar *str, const uchar *end); + + +/* + The set of functions and structures below provides interface + to the JSON text parser. + Running the parser normally goes like this: + + json_engine_t j_eng; // structure keeps parser's data + json_scan_start(j_eng) // begin the parsing + + do + { + // The parser has read next piece of JSON + // and set fields of j_eng structure accordingly. + // So let's see what we have: + switch (j_eng.state) + { + case JST_KEY: + // Handle key name. See the json_read_keyname_chr() + // Probably compare it with the keyname we're looking for + case JST_VALUE: + // Handle value. It is either value of the key or an array item. + // see the json_read_value() + case JST_OBJ_START: + // parser found an object (the '{' in JSON) + case JST_OBJ_END: + // parser found the end of the object (the '}' in JSON) + case JST_ARRAY_START: + // parser found an array (the '[' in JSON) + case JST_ARRAY_END: + // parser found the end of the array (the ']' in JSON) + + }; + } while (json_scan_next() == 0); // parse next structure + + + if (j_eng.s.error) // we need to check why the loop ended. + // Did we get to the end of JSON, or came upon error. + { + signal_error_in_JSON() + } + + + Parts of JSON can be quickly skipped. If we are not interested + in a particular key, we can just skip it with json_skip_key() call. + Similarly json_skip_level() goes right to the end of an object + or an array. +*/ + + +/* These are JSON parser states that user can expect and handle. */ +enum json_states { + JST_VALUE, /* value found */ + JST_KEY, /* key found */ + JST_OBJ_START, /* object */ + JST_OBJ_END, /* object ended */ + JST_ARRAY_START, /* array */ + JST_ARRAY_END, /* array ended */ + NR_JSON_USER_STATES +}; + + +enum json_value_types +{ + JSON_VALUE_UNINITIALIZED=0, + JSON_VALUE_OBJECT=1, + JSON_VALUE_ARRAY=2, + JSON_VALUE_STRING=3, + JSON_VALUE_NUMBER=4, + JSON_VALUE_TRUE=5, + JSON_VALUE_FALSE=6, + JSON_VALUE_NULL=7 +}; + + +enum json_num_flags +{ + JSON_NUM_NEG=1, /* Number is negative. */ + JSON_NUM_FRAC_PART=2, /* The fractional part is not empty. */ + JSON_NUM_EXP=4, /* The number has the 'e' part. */ +}; + + +typedef struct st_json_engine_t +{ + json_string_t s; /* String to parse. */ + int sav_c_len; /* Length of the current character. + Can be more than 1 for multibyte charsets */ + + int state; /* The state of the parser. One of 'enum json_states'. + It tells us what construction of JSON we've just read. */ + + /* These values are only set after the json_read_value() call. */ + enum json_value_types value_type; /* type of the value.*/ + const uchar *value; /* Points to the value. */ + const uchar *value_begin;/* Points to where the value starts in the JSON. */ + int value_escaped; /* Flag telling if the string value has escaping.*/ + uint num_flags; /* the details of the JSON_VALUE_NUMBER, is it negative, + or if it has the fractional part. + See the enum json_num_flags. */ + + /* + In most cases the 'value' and 'value_begin' are equal. + They only differ if the value is a string constants. Then 'value_begin' + points to the starting quotation mark, while the 'value' - to + the first character of the string. + */ + + const uchar *value_end; /* Points to the next character after the value. */ + int value_len; /* The length of the value. Does not count quotations for */ + /* string constants. */ + + int stack[JSON_DEPTH_LIMIT]; /* Keeps the stack of nested JSON structures. */ + int stack_p; /* The 'stack' pointer. */ + volatile uchar *killed_ptr; +} json_engine_t; + + +int json_scan_start(json_engine_t *je, + CHARSET_INFO *i_cs, const uchar *str, const uchar *end); +int json_scan_next(json_engine_t *j); + + +/* + json_read_keyname_chr() function assists parsing the name of an JSON key. + It only can be called when the json_engine is in JST_KEY. + The json_read_keyname_chr() reads one character of the name of the key, + and puts it in j_eng.s.next_c. + Typical usage is like this: + + if (j_eng.state == JST_KEY) + { + while (json_read_keyname_chr(&j) == 0) + { + //handle next character i.e. match it against the pattern + } + } +*/ + +int json_read_keyname_chr(json_engine_t *j); + + +/* + Check if the name of the current JSON key matches + the step of the path. +*/ +int json_key_matches(json_engine_t *je, json_string_t *k); + + +/* + json_read_value() function parses the JSON value syntax, + so that we can handle the value of a key or an array item. + It only returns meaningful result when the engine is in + the JST_VALUE state. + + Typical usage is like this: + + if (j_eng.state == JST_VALUE) + { + json_read_value(&j_eng); + switch(j_eng.value_type) + { + case JSON_VALUE_STRING: + // get the string + str= j_eng.value; + str_length= j_eng.value_len; + case JSON_VALUE_NUMBER: + // get the number + ... etc + } +*/ +int json_read_value(json_engine_t *j); + + +/* + json_skip_key() makes parser skip the content of the current + JSON key quickly. + It can be called only when the json_engine state is JST_KEY. + Typical usage is: + + if (j_eng.state == JST_KEY) + { + if (key_does_not_match(j_eng)) + json_skip_key(j_eng); + } +*/ + +int json_skip_key(json_engine_t *j); + + +typedef const int *json_level_t; + +/* + json_skip_to_level() makes parser quickly get out of nested + loops and arrays. It is used when we're not interested in what is + there in the rest of these structures. + The 'level' should be remembered in advance. + json_level_t level= json_get_level(j); + .... // getting into the nested JSON structures + json_skip_to_level(j, level); +*/ +#define json_get_level(j) (j->stack_p) + +int json_skip_to_level(json_engine_t *j, int level); + +/* + json_skip_level() works as above with just current structure. + So it gets to the end of the current JSON array or object. +*/ +#define json_skip_level(json_engine) \ + json_skip_to_level((json_engine), (json_engine)->stack_p) + + +/* + works as json_skip_level() but also counts items on the current + level skipped. +*/ +int json_skip_level_and_count(json_engine_t *j, int *n_items_skipped); + +#define json_skip_array_item json_skip_key + +/* + Checks if the current value is of scalar type - + not an OBJECT nor ARRAY. +*/ +#define json_value_scalar(je) ((je)->value_type > JSON_VALUE_ARRAY) + + +/* + Look for the JSON PATH in the json string. + Function can be called several times with same JSON/PATH to + find multiple matches. + On the first call, the json_engine_t parameter should be + initialized with the JSON string, and the json_path_t with the JSON path + appropriately. The 'p_cur_step' should point at the first + step of the path. + The 'array_counters' is the array of JSON_DEPTH_LIMIT size. + It stores the array counters of the parsed JSON. + If function returns 0, it means it found the match. The position of + the match is je->s.c_str. Then we can call the json_find_path() + with same engine/path/p_cur_step to get the next match. + Non-zero return means no matches found. + Check je->s.error to see if there was an error in JSON. +*/ +int json_find_path(json_engine_t *je, + json_path_t *p, json_path_step_t **p_cur_step, + int *array_counters); + + +typedef struct st_json_find_paths_t +{ + uint n_paths; + json_path_t *paths; + uint cur_depth; + uint *path_depths; + int array_counters[JSON_DEPTH_LIMIT]; +} json_find_paths_t; + + +int json_find_paths_first(json_engine_t *je, json_find_paths_t *state, + uint n_paths, json_path_t *paths, uint *path_depths); +int json_find_paths_next(json_engine_t *je, json_find_paths_t *state); + + +#define JSON_ERROR_OUT_OF_SPACE (-1) +#define JSON_ERROR_ILLEGAL_SYMBOL (-2) + +/* + Convert JSON string constant into ordinary string constant + which can involve unpacking json escapes and changing character set. + Returns negative integer in the case of an error, + the length of the result otherwise. +*/ +int json_unescape(CHARSET_INFO *json_cs, + const uchar *json_str, const uchar *json_end, + CHARSET_INFO *res_cs, + uchar *res, uchar *res_end); + +/* + Convert a string constant into JSON string constant. + This can involve appropriate escaping and changing the character set. + Returns the length of the result on success, + on error returns a negative error code. + Some error codes: + JSON_ERROR_OUT_OF_SPACE Not enough space in the provided buffer + JSON_ERROR_ILLEGAL_SYMBOL Source symbol cannot be represented in JSON +*/ +int json_escape(CHARSET_INFO *str_cs, const uchar *str, const uchar *str_end, + CHARSET_INFO *json_cs, uchar *json, uchar *json_end); + + +/* + Appends the ASCII string to the json with the charset conversion. +*/ +int json_append_ascii(CHARSET_INFO *json_cs, + uchar *json, uchar *json_end, + const uchar *ascii, const uchar *ascii_end); + + +/* + Scan the JSON and return paths met one-by-one. + json_get_path_start(&p) + while (json_get_path_next(&p)) + { + handle_the_next_path(); + } +*/ + +int json_get_path_start(json_engine_t *je, CHARSET_INFO *i_cs, + const uchar *str, const uchar *end, + json_path_t *p); + + +int json_get_path_next(json_engine_t *je, json_path_t *p); + +int json_path_compare(const json_path_t *a, const json_path_t *b, + enum json_value_types vt, const int* array_size_counter); + +int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs); + +int json_locate_key(const char *js, const char *js_end, + const char *kname, + const char **key_start, const char **key_end, + int *comma_pos); + +int json_normalize(DYNAMIC_STRING *result, + const char *s, size_t size, CHARSET_INFO *cs); + +int json_skip_array_and_count(json_engine_t *j, int* n_item); + +#ifdef __cplusplus +} +#endif + +#endif /* JSON_LIB_INCLUDED */ diff --git a/include/keycache.h b/include/keycache.h new file mode 100644 index 00000000..14fd9c80 --- /dev/null +++ b/include/keycache.h @@ -0,0 +1,212 @@ +/* Copyright (c) 2003, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Key cache variable structures */ + +#ifndef _keycache_h +#define _keycache_h + +#include "my_sys.h" /* flush_type */ + +C_MODE_START + +/* + Currently the default key cache is created as non-partitioned at + the start of the server unless the server is started with the parameter + --key-cache-partitions that is greater than 0 +*/ + +#define DEFAULT_KEY_CACHE_PARTITIONS 0 + +/* + MAX_KEY_CACHE_PARTITIONS cannot be greater than + sizeof(MYISAM_SHARE::dirty_part_map) + Currently sizeof(MYISAM_SHARE::dirty_part_map)=sizeof(ulonglong) +*/ + +#define MAX_KEY_CACHE_PARTITIONS 64 + +/* The structure to get statistical data about a key cache */ + +typedef struct st_key_cache_statistics +{ + ulonglong mem_size; /* memory for cache buffers/auxiliary structures */ + ulonglong block_size; /* size of the each buffers in the key cache */ + ulonglong blocks_used; /* maximum number of used blocks/buffers */ + ulonglong blocks_unused; /* number of currently unused blocks */ + ulonglong blocks_changed; /* number of currently dirty blocks */ + ulonglong blocks_warm; /* number of blocks in warm sub-chain */ + ulonglong read_requests; /* number of read requests (read hits) */ + ulonglong reads; /* number of actual reads from files into buffers */ + ulonglong write_requests; /* number of write requests (write hits) */ + ulonglong writes; /* number of actual writes from buffers into files */ +} KEY_CACHE_STATISTICS; + +#define NUM_LONG_KEY_CACHE_STAT_VARIABLES 3 + +/* The type of a key cache object */ +typedef enum key_cache_type +{ + SIMPLE_KEY_CACHE, + PARTITIONED_KEY_CACHE +} KEY_CACHE_TYPE; + + +typedef + int (*INIT_KEY_CACHE) + (void *, uint key_cache_block_size, + size_t use_mem, uint division_limit, uint age_threshold, + uint changed_blocks_hash_size); +typedef + int (*RESIZE_KEY_CACHE) + (void *, uint key_cache_block_size, + size_t use_mem, uint division_limit, uint age_threshold, + uint changed_blocks_hash_size); +typedef + void (*CHANGE_KEY_CACHE_PARAM) + (void *keycache_cb, + uint division_limit, uint age_threshold); +typedef + uchar* (*KEY_CACHE_READ) + (void *keycache_cb, + File file, my_off_t filepos, int level, + uchar *buff, uint length, + uint block_length, int return_buffer); +typedef + int (*KEY_CACHE_INSERT) + (void *keycache_cb, + File file, my_off_t filepos, int level, + uchar *buff, uint length); +typedef + int (*KEY_CACHE_WRITE) + (void *keycache_cb, + File file, void *file_extra, + my_off_t filepos, int level, + uchar *buff, uint length, + uint block_length, int force_write); +typedef + int (*FLUSH_KEY_BLOCKS) + (void *keycache_cb, + int file, void *file_extra, + enum flush_type type); +typedef + int (*RESET_KEY_CACHE_COUNTERS) + (const char *name, void *keycache_cb); +typedef + void (*END_KEY_CACHE) + (void *keycache_cb, my_bool cleanup); +typedef + void (*GET_KEY_CACHE_STATISTICS) + (void *keycache_cb, uint partition_no, + KEY_CACHE_STATISTICS *key_cache_stats); + +/* + An object of the type KEY_CACHE_FUNCS contains pointers to all functions + from the key cache interface. + Currently a key cache can be of two types: simple and partitioned. + For each of them its own static structure of the type KEY_CACHE_FUNCS is + defined . The structures contain the pointers to the implementations of + the interface functions used by simple key caches and partitioned key + caches respectively. Pointers to these structures are assigned to key cache + objects at the time of their creation. +*/ + +typedef struct st_key_cache_funcs +{ + INIT_KEY_CACHE init; + RESIZE_KEY_CACHE resize; + CHANGE_KEY_CACHE_PARAM change_param; + KEY_CACHE_READ read; + KEY_CACHE_INSERT insert; + KEY_CACHE_WRITE write; + FLUSH_KEY_BLOCKS flush; + RESET_KEY_CACHE_COUNTERS reset_counters; + END_KEY_CACHE end; + GET_KEY_CACHE_STATISTICS get_stats; +} KEY_CACHE_FUNCS; + + +typedef struct st_key_cache +{ + KEY_CACHE_TYPE key_cache_type; /* type of the key cache used for debugging */ + void *keycache_cb; /* control block of the used key cache */ + KEY_CACHE_FUNCS *interface_funcs; /* interface functions of the key cache */ + ulonglong param_buff_size; /* size the memory allocated for the cache */ + ulonglong param_block_size; /* size of the blocks in the key cache */ + ulonglong param_division_limit;/* min. percentage of warm blocks */ + ulonglong param_age_threshold; /* determines when hot block is downgraded */ + ulonglong param_partitions; /* number of the key cache partitions */ + ulonglong changed_blocks_hash_size; /* number of hash buckets for changed files */ + my_bool key_cache_inited; /* <=> key cache has been created */ + my_bool can_be_used; /* usage of cache for read/write is allowed */ + my_bool in_init; /* set to 1 in MySQL during init/resize */ + uint partitions; /* actual number of partitions */ + size_t key_cache_mem_size; /* specified size of the cache memory */ + pthread_mutex_t op_lock; /* to serialize operations like 'resize' */ +} KEY_CACHE; + + +/* The default key cache */ +extern KEY_CACHE dflt_key_cache_var, *dflt_key_cache; + +extern int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold, uint changed_blocks_hash_size, + uint partitions); +extern int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold, uint changed_blocks_hash_size); +extern void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, + uint age_threshold); +extern uchar *key_cache_read(KEY_CACHE *keycache, + File file, my_off_t filepos, int level, + uchar *buff, uint length, + uint block_length,int return_buffer); +extern int key_cache_insert(KEY_CACHE *keycache, + File file, my_off_t filepos, int level, + uchar *buff, uint length); +extern int key_cache_write(KEY_CACHE *keycache, + File file, void *file_extra, + my_off_t filepos, int level, + uchar *buff, uint length, + uint block_length, int force_write); +extern int flush_key_blocks(KEY_CACHE *keycache, + int file, void *file_extra, + enum flush_type type); +extern void end_key_cache(KEY_CACHE *keycache, my_bool cleanup); +extern void get_key_cache_statistics(KEY_CACHE *keycache, + uint partition_no, + KEY_CACHE_STATISTICS *key_cache_stats); + +/* Functions to handle multiple key caches */ +extern my_bool multi_keycache_init(void); +extern void multi_keycache_free(void); +extern KEY_CACHE *multi_key_cache_search(uchar *key, uint length, + KEY_CACHE *def); +extern my_bool multi_key_cache_set(const uchar *key, uint length, + KEY_CACHE *key_cache); +extern void multi_key_cache_change(KEY_CACHE *old_data, + KEY_CACHE *new_data); +extern int reset_key_cache_counters(const char *name, + KEY_CACHE *key_cache, void *); +extern int repartition_key_cache(KEY_CACHE *keycache, + uint key_cache_block_size, + size_t use_mem, + uint division_limit, + uint age_threshold, + uint changed_blocks_hash_size, + uint partitions); +C_MODE_END +#endif /* _keycache_h */ diff --git a/include/lf.h b/include/lf.h new file mode 100644 index 00000000..267a66ae --- /dev/null +++ b/include/lf.h @@ -0,0 +1,184 @@ +/* Copyright (c) 2007, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef INCLUDE_LF_INCLUDED +#define INCLUDE_LF_INCLUDED + +#include <my_atomic.h> + +C_MODE_START + +/* + wait-free dynamic array, see lf_dynarray.c + + 4 levels of 256 elements each mean 4311810304 elements in an array - it + should be enough for a while +*/ +#define LF_DYNARRAY_LEVEL_LENGTH 256 +#define LF_DYNARRAY_LEVELS 4 + +typedef struct { + void * volatile level[LF_DYNARRAY_LEVELS]; + uint size_of_element; +} LF_DYNARRAY; + +typedef int (*lf_dynarray_func)(void *, void *); + +void lf_dynarray_init(LF_DYNARRAY *array, uint element_size); +void lf_dynarray_destroy(LF_DYNARRAY *array); + +void *lf_dynarray_value(LF_DYNARRAY *array, uint idx); +void *lf_dynarray_lvalue(LF_DYNARRAY *array, uint idx); +int lf_dynarray_iterate(LF_DYNARRAY *array, lf_dynarray_func func, void *arg); + +/* + pin manager for memory allocator, lf_alloc-pin.c +*/ + +#define LF_PINBOX_PINS 4 +#define LF_PURGATORY_SIZE 100 + +typedef void lf_pinbox_free_func(void *, void *, void*); + +typedef struct { + LF_DYNARRAY pinarray; + lf_pinbox_free_func *free_func; + void *free_func_arg; + uint free_ptr_offset; + uint32 volatile pinstack_top_ver; /* this is a versioned pointer */ + uint32 volatile pins_in_array; /* number of elements in array */ +} LF_PINBOX; + +typedef struct { + void * volatile pin[LF_PINBOX_PINS]; + LF_PINBOX *pinbox; + void *purgatory; + uint32 purgatory_count; + uint32 volatile link; + /* avoid false sharing */ + char pad[CPU_LEVEL1_DCACHE_LINESIZE]; +} LF_PINS; + +/* compile-time assert to make sure we have enough pins. */ +#define lf_pin(PINS, PIN, ADDR) \ + do { \ + compile_time_assert(PIN < LF_PINBOX_PINS); \ + my_atomic_storeptr(&(PINS)->pin[PIN], (ADDR)); \ + } while(0) + +#define lf_unpin(PINS, PIN) lf_pin(PINS, PIN, NULL) +#define lf_assert_pin(PINS, PIN) assert((PINS)->pin[PIN] != 0) +#define lf_assert_unpin(PINS, PIN) assert((PINS)->pin[PIN] == 0) + +void lf_pinbox_init(LF_PINBOX *pinbox, uint free_ptr_offset, + lf_pinbox_free_func *free_func, void * free_func_arg); +void lf_pinbox_destroy(LF_PINBOX *pinbox); + +LF_PINS *lf_pinbox_get_pins(LF_PINBOX *pinbox); +void lf_pinbox_put_pins(LF_PINS *pins); +void lf_pinbox_free(LF_PINS *pins, void *addr); + +/* + memory allocator, lf_alloc-pin.c +*/ + +typedef struct st_lf_allocator { + LF_PINBOX pinbox; + uchar * volatile top; + uint element_size; + uint32 volatile mallocs; + void (*constructor)(uchar *); /* called, when an object is malloc()'ed */ + void (*destructor)(uchar *); /* called, when an object is free()'d */ +} LF_ALLOCATOR; + +void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset); +void lf_alloc_destroy(LF_ALLOCATOR *allocator); +uint lf_alloc_pool_count(LF_ALLOCATOR *allocator); +/* + shortcut macros to access underlying pinbox functions from an LF_ALLOCATOR + see lf_pinbox_get_pins() and lf_pinbox_put_pins() +*/ +#define lf_alloc_free(PINS, PTR) lf_pinbox_free((PINS), (PTR)) +#define lf_alloc_get_pins(A) lf_pinbox_get_pins(&(A)->pinbox) +#define lf_alloc_put_pins(PINS) lf_pinbox_put_pins(PINS) +#define lf_alloc_direct_free(ALLOC, ADDR) \ + do { \ + if ((ALLOC)->destructor) \ + (ALLOC)->destructor((uchar*) ADDR); \ + my_free(ADDR); \ + } while(0) + +void *lf_alloc_new(LF_PINS *pins); + +C_MODE_END + +/* + extendible hash, lf_hash.cc +*/ +#include <hash.h> + +C_MODE_START + +typedef struct st_lf_hash LF_HASH; +typedef void (*lf_hash_initializer)(LF_HASH *hash, void *dst, const void *src); + +#define LF_HASH_UNIQUE 1 + +/* lf_hash overhead per element (that is, sizeof(LF_SLIST) */ +extern const int LF_HASH_OVERHEAD; + +struct st_lf_hash { + LF_DYNARRAY array; /* hash itself */ + LF_ALLOCATOR alloc; /* allocator for elements */ + my_hash_get_key get_key; /* see HASH */ + lf_hash_initializer initializer; /* called when an element is inserted */ + my_hash_function hash_function; /* see HASH */ + CHARSET_INFO *charset; /* see HASH */ + uint key_offset, key_length; /* see HASH */ + uint element_size; /* size of memcpy'ed area on insert */ + uint flags; /* LF_HASH_UNIQUE, etc */ + int32 volatile size; /* size of array */ + int32 volatile count; /* number of elements in the hash */ +}; + +void lf_hash_init(LF_HASH *hash, uint element_size, uint flags, + uint key_offset, uint key_length, my_hash_get_key get_key, + CHARSET_INFO *charset); +void lf_hash_destroy(LF_HASH *hash); +int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data); +void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen); +void *lf_hash_search_using_hash_value(LF_HASH *hash, LF_PINS *pins, + my_hash_value_type hash_value, + const void *key, uint keylen); +int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen); +int lf_hash_iterate(LF_HASH *hash, LF_PINS *pins, + my_hash_walk_action action, void *argument); +#define lf_hash_size(hash) \ + my_atomic_load32_explicit(&(hash)->count, MY_MEMORY_ORDER_RELAXED) +/* + shortcut macros to access underlying pinbox functions from an LF_HASH + see lf_pinbox_get_pins() and lf_pinbox_put_pins() +*/ +#define lf_hash_get_pins(HASH) lf_alloc_get_pins(&(HASH)->alloc) +#define lf_hash_put_pins(PINS) lf_pinbox_put_pins(PINS) +#define lf_hash_search_unpin(PINS) lf_unpin((PINS), 2) +/* + cleanup +*/ + +C_MODE_END + +#endif + diff --git a/include/little_endian.h b/include/little_endian.h new file mode 100644 index 00000000..dcddbdd9 --- /dev/null +++ b/include/little_endian.h @@ -0,0 +1,75 @@ +/* Copyright (c) 2012, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Data in little-endian format. +*/ + +#ifndef MY_BYTE_ORDER_ARCH_OPTIMIZED +#define float4get(V,M) memcpy(&V, (M), sizeof(float)) +#define float4store(V,M) memcpy(V, (&M), sizeof(float)) +#define float8get(V,M) doubleget((V),(M)) +#define float8store(V,M) doublestore((V),(M)) + +/* Bi-endian hardware.... */ +#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) +#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((uchar *) &V)[4];\ + *(((char*)T)+1)=(char) ((uchar *) &V)[5];\ + *(((char*)T)+2)=(char) ((uchar *) &V)[6];\ + *(((char*)T)+3)=(char) ((uchar *) &V)[7];\ + *(((char*)T)+4)=(char) ((uchar *) &V)[0];\ + *(((char*)T)+5)=(char) ((uchar *) &V)[1];\ + *(((char*)T)+6)=(char) ((uchar *) &V)[2];\ + *(((char*)T)+7)=(char) ((uchar *) &V)[3]; }\ + while(0) +#define doubleget(V,M) do { double def_temp;\ + ((uchar*) &def_temp)[0]=(M)[4];\ + ((uchar*) &def_temp)[1]=(M)[5];\ + ((uchar*) &def_temp)[2]=(M)[6];\ + ((uchar*) &def_temp)[3]=(M)[7];\ + ((uchar*) &def_temp)[4]=(M)[0];\ + ((uchar*) &def_temp)[5]=(M)[1];\ + ((uchar*) &def_temp)[6]=(M)[2];\ + ((uchar*) &def_temp)[7]=(M)[3];\ + (V) = def_temp; } while(0) +#else /* Bi-endian hardware.... */ + +/* Cast away type qualifiers (necessary as macro takes argument by value). */ +#define doublestore(T,V) memcpy((T), (void*) &V, sizeof(double)) +#define doubleget(V,M) memcpy(&V, (M), sizeof(double)) + +#endif /* Bi-endian hardware.... */ + +#endif /* !MY_BYTE_ORDER_ARCH_OPTIMIZED */ + +#define ushortget(V,M) do { uchar *pM= (uchar*)(M);V = uint2korr(pM);} while(0) +#define shortget(V,M) do { uchar *pM= (uchar*)(M);V = sint2korr(pM);} while(0) +#define longget(V,M) do { uchar *pM= (uchar*)(M);V = sint4korr(pM);} while(0) +#define ulongget(V,M) do { uchar *pM= (uchar*)(M);V = uint4korr(pM);} while(0) +#define shortstore(T,V) int2store(T,V) +#define longstore(T,V) int4store(T,V) + +#ifndef floatstore +/* Cast away type qualifiers (necessary as macro takes argument by value). */ +#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float)) +#define floatget(V,M) memcpy(&V, (M), sizeof(float)) +#endif +#ifndef doubleget +#define doubleget(V,M) memcpy(&V, (M), sizeof(double)) +#define doublestore(T,V) memcpy((T), (void *) &V, sizeof(double)) +#endif /* doubleget */ + +#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong)) +#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong)) diff --git a/include/m_ctype.h b/include/m_ctype.h new file mode 100644 index 00000000..3adcb474 --- /dev/null +++ b/include/m_ctype.h @@ -0,0 +1,1875 @@ +/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. + Copyright (c) 2009, 2020, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + A better implementation of the UNIX ctype(3) library. +*/ + +#ifndef _m_ctype_h +#define _m_ctype_h + +#include <my_attribute.h> +#include <m_string.h> + +enum loglevel { + ERROR_LEVEL= 0, + WARNING_LEVEL= 1, + INFORMATION_LEVEL= 2 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +#define MY_CS_CHARACTER_SET_NAME_SIZE 32 +#define MY_CS_COLLATION_NAME_SIZE 64 + +#define MY_CS_CTYPE_TABLE_SIZE 257 +#define MY_CS_TO_LOWER_TABLE_SIZE 256 +#define MY_CS_TO_UPPER_TABLE_SIZE 256 +#define MY_CS_SORT_ORDER_TABLE_SIZE 256 +#define MY_CS_TO_UNI_TABLE_SIZE 256 + +#define CHARSET_DIR "charsets/" + +#define my_wc_t ulong + +#define MY_CS_REPLACEMENT_CHARACTER 0xFFFD + +/** + Maximum character length of a string produced by wc_to_printable(). + Note, wc_to_printable() is currently limited to BMP. + One non-printable or non-convertable character can produce a string + with at most 5 characters: \hhhh. + If we ever modify wc_to_printable() to support supplementary characters, + e.g. \+hhhhhh, this constant should be changed to 8. + Note, maximum octet length of a wc_to_printable() result can be calculated + as: (MY_CS_PRINTABLE_CHAR_LENGTH*cs->mbminlen). +*/ +#define MY_CS_PRINTABLE_CHAR_LENGTH 5 + + +/* + On i386 we store Unicode->CS conversion tables for + some character sets using Big-endian order, + to copy two bytes at once. + This gives some performance improvement. +*/ +#ifdef __i386__ +#define MB2(x) (((x) >> 8) + (((x) & 0xFF) << 8)) +#define MY_PUT_MB2(s, code) { *((uint16*)(s))= (code); } +#else +#define MB2(x) (x) +#define MY_PUT_MB2(s, code) { (s)[0]= code >> 8; (s)[1]= code & 0xFF; } +#endif + +typedef const struct my_charset_handler_st MY_CHARSET_HANDLER; +typedef const struct my_collation_handler_st MY_COLLATION_HANDLER; + +typedef const struct casefold_info_st MY_CASEFOLD_INFO; +typedef const struct uni_ctype_st MY_UNI_CTYPE; +typedef const struct my_uni_idx_st MY_UNI_IDX; +typedef uint16 decimal_digits_t; + + +typedef struct casefold_info_char_t +{ + uint32 toupper; + uint32 tolower; +} MY_CASEFOLD_CHARACTER; + + +struct casefold_info_st +{ + my_wc_t maxchar; + const MY_CASEFOLD_CHARACTER * const *page; + const uint16 * const *simple_weight; /* For general_ci-alike collations */ +}; + + +#define MY_UCA_MAX_CONTRACTION 6 +/* + The DUCET tables in ctype-uca.c are dumped with a limit of 8 weights + per character. cs->strxfrm_multiply is set to 8 for all UCA based collations. + + In language-specific UCA collations (with tailorings) we also do not allow + a single character to have more than 8 weights to stay with the same + strxfrm_multiply limit. Note, contractions are allowed to have twice longer + weight strings (up to 16 weights). As a contraction consists of at + least 2 characters, this makes sure that strxfrm_multiply ratio of 8 + is respected. +*/ +#define MY_UCA_MAX_WEIGHT_SIZE (8+1) /* Including 0 terminator */ +#define MY_UCA_CONTRACTION_MAX_WEIGHT_SIZE (2*8+1) /* Including 0 terminator */ +#define MY_UCA_WEIGHT_LEVELS 3 + +typedef struct my_contraction_t +{ + my_wc_t ch[MY_UCA_MAX_CONTRACTION]; /* Character sequence */ + uint16 weight[MY_UCA_CONTRACTION_MAX_WEIGHT_SIZE];/* Its weight string, 0-terminated */ + my_bool with_context; +} MY_CONTRACTION; + + +typedef struct my_contraction_list_t +{ + size_t nitems; /* Number of items in the list */ + MY_CONTRACTION *item; /* List of contractions */ + char *flags; /* Character flags, e.g. "is contraction head") */ +} MY_CONTRACTIONS; + +my_bool my_uca_can_be_contraction_head(const MY_CONTRACTIONS *c, my_wc_t wc); +my_bool my_uca_can_be_contraction_tail(const MY_CONTRACTIONS *c, my_wc_t wc); +const uint16 *my_uca_contraction2_weight(const MY_CONTRACTIONS *c, + my_wc_t wc1, my_wc_t wc2); + + +typedef struct my_uca_weight2_t +{ + uint16 weight[2]; +} MY_UCA_WEIGHT2; + + +/* + In DUCET as of Unicode-14.0.0: + - All characters in the range U+0000..U+007F (i.e. using one byte in utf8) + have not more than two weights on all weight levels. + - All characters in the range U+0080..U+07FF (i.e. using two bytes in utf8) + have not more than four weights on all weight levels. + Therefore the limit of 4 weights should cover all byte pairs + (i.e. two ASCII characters or one 2-byte character) + that are a subject for the "process 2 bytes at a time" optimization. + If some collation reorders any character from the mentioned ranges + in the way that it produces more weights, such character will not + be optimized, but will be correctly processed the slower mb_wc-based + method (1 character at a time). +*/ +#define MY_UCA_2BYTES_MAX_WEIGHT_SIZE (4+1) /* Including 0 terminator */ + +typedef struct my_uca_2bytes_item_t +{ + uint16 weight[MY_UCA_2BYTES_MAX_WEIGHT_SIZE]; +} MY_UCA_2BYTES_ITEM; + + +typedef struct my_uca_level_booster_t +{ + /* + A helper array to process 2 bytes at a time during string comparison. + It maps all 2-bytes sequences that make: + - two ASCII characters or + - one 2-byte character + to their weights. The weight length is limited to + MY_UCA_2BYTES_MAX_WEIGHT_SIZE-1 weights. + This array is used in the main loop optimization. + */ + MY_UCA_2BYTES_ITEM weight_strings_2bytes[0x10000]; + /* + A helper array to process 2bytes at a time during string comparison, + with an even more efficient way than the above one. + The weight size is limited to 2 weights, so it's used for the cases + when 2 input bytes produce 1 or 2 weights. + This limit makes the code using this array even simpler and faster. + This array is used for prefix optimization. + */ + MY_UCA_WEIGHT2 weight_strings_2bytes_to_1_or_2_weights[0x10000]; +} MY_UCA_LEVEL_BOOSTER; + + +typedef struct my_uca_contraction_hash_t +{ + size_t nitems_alloced; + MY_CONTRACTION *item; +} MY_UCA_CONTRACTION_HASH; + + +/* Collation weights on a single level (e.g. primary, secondary, tertiary) */ +typedef struct my_uca_level_info_st +{ + my_wc_t maxchar; + uchar *lengths; + uint16 **weights; + MY_CONTRACTIONS contractions; + uint levelno; + MY_UCA_CONTRACTION_HASH contraction_hash; + MY_UCA_LEVEL_BOOSTER *booster; +} MY_UCA_WEIGHT_LEVEL; + + +typedef struct uca_info_st +{ + MY_UCA_WEIGHT_LEVEL level[MY_UCA_WEIGHT_LEVELS]; + + /* Logical positions */ + my_wc_t first_non_ignorable; + my_wc_t last_non_ignorable; + my_wc_t first_primary_ignorable; + my_wc_t last_primary_ignorable; + my_wc_t first_secondary_ignorable; + my_wc_t last_secondary_ignorable; + my_wc_t first_tertiary_ignorable; + my_wc_t last_tertiary_ignorable; + my_wc_t first_trailing; + my_wc_t last_trailing; + my_wc_t first_variable; + my_wc_t last_variable; + + /* Unicode version */ + uint version; + +} MY_UCA_INFO; + + + +extern MY_UCA_INFO my_uca_v400; + + +struct uni_ctype_st +{ + uchar pctype; + const uchar *ctype; +}; + +extern MY_UNI_CTYPE my_uni_ctype[256]; + +/* wm_wc and wc_mb return codes */ +#define MY_CS_ILSEQ 0 /* Wrong by sequence: wb_wc */ +#define MY_CS_ILUNI 0 /* Cannot encode Unicode to charset: wc_mb */ +#define MY_CS_TOOSMALL -101 /* Need at least one byte: wc_mb and mb_wc */ +#define MY_CS_TOOSMALL2 -102 /* Need at least two bytes: wc_mb and mb_wc */ +#define MY_CS_TOOSMALL3 -103 /* Need at least three bytes: wc_mb and mb_wc */ +/* These following three are currently not really used */ +#define MY_CS_TOOSMALL4 -104 /* Need at least 4 bytes: wc_mb and mb_wc */ +#define MY_CS_TOOSMALL5 -105 /* Need at least 5 bytes: wc_mb and mb_wc */ +#define MY_CS_TOOSMALL6 -106 /* Need at least 6 bytes: wc_mb and mb_wc */ +/* A helper macros for "need at least n bytes" */ +#define MY_CS_TOOSMALLN(n) (-100-(n)) + +#define MY_CS_MBMAXLEN 6 /* Maximum supported mbmaxlen */ +#define MY_CS_IS_TOOSMALL(rc) ((rc) >= MY_CS_TOOSMALL6 && (rc) <= MY_CS_TOOSMALL) + +#define MY_SEQ_INTTAIL 1 +#define MY_SEQ_SPACES 2 +#define MY_SEQ_NONSPACES 3 /* Skip non-space characters, including bad bytes */ + + /* My charsets_list flags */ +#define MY_CS_COMPILED 1 /* compiled-in sets */ +#define MY_CS_CONFIG 2 /* sets that have a *.conf file */ +#define MY_CS_INDEX 4 /* sets listed in the Index file */ +#define MY_CS_LOADED 8 /* sets that are currently loaded */ +#define MY_CS_BINSORT 16 /* if binary sort order */ +#define MY_CS_PRIMARY 32 /* if primary collation */ +#define MY_CS_STRNXFRM 64 /* if strnxfrm is used for sort */ +#define MY_CS_UNICODE 128 /* is a charset is BMP Unicode */ +#define MY_CS_READY 256 /* if a charset is initialized */ +#define MY_CS_AVAILABLE 512 /* If either compiled-in or loaded*/ +#define MY_CS_CSSORT 1024 /* if case sensitive sort order */ +#define MY_CS_HIDDEN 2048 /* don't display in SHOW */ +#define MY_CS_PUREASCII 4096 /* if a charset is pure ascii */ +#define MY_CS_NONASCII 8192 /* if not ASCII-compatible */ +#define MY_CS_UNICODE_SUPPLEMENT 16384 /* Non-BMP Unicode characters */ +#define MY_CS_LOWER_SORT 32768 /* If use lower case as weight */ +#define MY_CS_STRNXFRM_BAD_NWEIGHTS 0x10000 /* strnxfrm ignores "nweights" */ +#define MY_CS_NOPAD 0x20000 /* if does not ignore trailing spaces */ +#define MY_CS_NON1TO1 0x40000 /* Has a complex mapping from characters + to weights, e.g. contractions, expansions, + ignorable characters */ +#define MY_CHARSET_UNDEFINED 0 + +/* Character repertoire flags */ +typedef enum enum_repertoire_t +{ + MY_REPERTOIRE_NONE= 0, + MY_REPERTOIRE_ASCII= 1, /* Pure ASCII U+0000..U+007F */ + MY_REPERTOIRE_EXTENDED= 2, /* Extended characters: U+0080..U+FFFF */ + MY_REPERTOIRE_UNICODE30= 3 /* ASCII | EXTENDED: U+0000..U+FFFF */ +} my_repertoire_t; + + +/* ID compatibility */ +typedef enum enum_collation_id_type +{ + MY_COLLATION_ID_TYPE_PRECISE= 0, + MY_COLLATION_ID_TYPE_COMPAT_100800= 1 +} my_collation_id_type_t; + + +/* Collation name display modes */ +typedef enum enum_collation_name_mode +{ + MY_COLLATION_NAME_MODE_FULL= 0, + MY_COLLATION_NAME_MODE_CONTEXT= 1 +} my_collation_name_mode_t; + + +/* Level flags */ +#define MY_CS_LEVEL_BIT_PRIMARY 0x00 +#define MY_CS_LEVEL_BIT_SECONDARY 0x01 +#define MY_CS_LEVEL_BIT_TERTIARY 0x02 +#define MY_CS_LEVEL_BIT_QUATERNARY 0x03 + +#define MY_CS_COLL_LEVELS_S1 (1<<MY_CS_LEVEL_BIT_PRIMARY) + +#define MY_CS_COLL_LEVELS_AI_CS (1<<MY_CS_LEVEL_BIT_PRIMARY)| \ + (1<<MY_CS_LEVEL_BIT_TERTIARY) + +#define MY_CS_COLL_LEVELS_S2 (1<<MY_CS_LEVEL_BIT_PRIMARY)| \ + (1<<MY_CS_LEVEL_BIT_SECONDARY) + +#define MY_CS_COLL_LEVELS_S3 (1<<MY_CS_LEVEL_BIT_PRIMARY)| \ + (1<<MY_CS_LEVEL_BIT_SECONDARY) | \ + (1<<MY_CS_LEVEL_BIT_TERTIARY) + +#define MY_CS_COLL_LEVELS_S4 (1<<MY_CS_LEVEL_BIT_PRIMARY)| \ + (1<<MY_CS_LEVEL_BIT_SECONDARY) | \ + (1<<MY_CS_LEVEL_BIT_TERTIARY) | \ + (1<<MY_CS_LEVEL_BIT_QUATERNARY) + + +/* Flags for strxfrm */ +#define MY_STRXFRM_LEVEL1 0x00000001 /* for primary weights */ +#define MY_STRXFRM_LEVEL2 0x00000002 /* for secondary weights */ +#define MY_STRXFRM_LEVEL3 0x00000004 /* for tertiary weights */ +#define MY_STRXFRM_LEVEL4 0x00000008 /* fourth level weights */ +#define MY_STRXFRM_LEVEL5 0x00000010 /* fifth level weights */ +#define MY_STRXFRM_LEVEL6 0x00000020 /* sixth level weights */ +#define MY_STRXFRM_LEVEL_ALL 0x0000003F /* Bit OR for the above six */ +#define MY_STRXFRM_NLEVELS 6 /* Number of possible levels*/ + +#define MY_STRXFRM_PAD_WITH_SPACE 0x00000040 /* if pad result with spaces */ +#define MY_STRXFRM_PAD_TO_MAXLEN 0x00000080 /* if pad tail(for filesort) */ + +#define MY_STRXFRM_DESC_LEVEL1 0x00000100 /* if desc order for level1 */ +#define MY_STRXFRM_DESC_LEVEL2 0x00000200 /* if desc order for level2 */ +#define MY_STRXFRM_DESC_LEVEL3 0x00000300 /* if desc order for level3 */ +#define MY_STRXFRM_DESC_LEVEL4 0x00000800 /* if desc order for level4 */ +#define MY_STRXFRM_DESC_LEVEL5 0x00001000 /* if desc order for level5 */ +#define MY_STRXFRM_DESC_LEVEL6 0x00002000 /* if desc order for level6 */ +#define MY_STRXFRM_DESC_SHIFT 8 + +#define MY_STRXFRM_UNUSED_00004000 0x00004000 /* for future extensions */ +#define MY_STRXFRM_UNUSED_00008000 0x00008000 /* for future extensions */ + +#define MY_STRXFRM_REVERSE_LEVEL1 0x00010000 /* if reverse order for level1 */ +#define MY_STRXFRM_REVERSE_LEVEL2 0x00020000 /* if reverse order for level2 */ +#define MY_STRXFRM_REVERSE_LEVEL3 0x00040000 /* if reverse order for level3 */ +#define MY_STRXFRM_REVERSE_LEVEL4 0x00080000 /* if reverse order for level4 */ +#define MY_STRXFRM_REVERSE_LEVEL5 0x00100000 /* if reverse order for level5 */ +#define MY_STRXFRM_REVERSE_LEVEL6 0x00200000 /* if reverse order for level6 */ +#define MY_STRXFRM_REVERSE_SHIFT 16 + +/* Flags to strnncollsp_nchars */ +/* + MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES - + defines if inside strnncollsp_nchars() + short strings should be virtually extended to "nchars" + characters by emulating trimmed trailing spaces. + + This flag is needed when comparing packed strings of the CHAR + data type, when trailing spaces are trimmed on storage (like in InnoDB), + however the actual values (after unpacking) will have those trailing + spaces. + + If this flag is passed, strnncollsp_nchars() performs both + truncating longer strings and extending shorter strings + to exactly "nchars". + + If this flag is not passed, strnncollsp_nchars() only truncates longer + strings to "nchars", but does not extend shorter strings to "nchars". +*/ +#define MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES 1 + + +/* + Collation IDs for MariaDB that should not conflict with MySQL. + We reserve 256..511, because MySQL will most likely use this range + when the range 0..255 is full. + + We use the next 256 IDs starting from 512 and divide + them into 8 chunks, 32 collations each, as follows: + + 512 + (0..31) for single byte collations (e.g. latin9) + 512 + (32..63) reserved (e.g. for utf32le, or more single byte collations) + 512 + (64..95) for utf8 + 512 + (96..127) for utf8mb4 + 512 + (128..159) for ucs2 + 512 + (160..192) for utf16 + 512 + (192..223) for utf16le + 512 + (224..255) for utf32 +*/ +#define MY_PAGE2_COLLATION_ID_8BIT 0x200 +#define MY_PAGE2_COLLATION_ID_RESERVED 0x220 +#define MY_PAGE2_COLLATION_ID_UTF8 0x240 +#define MY_PAGE2_COLLATION_ID_UTF8MB4 0x260 +#define MY_PAGE2_COLLATION_ID_UCS2 0x280 +#define MY_PAGE2_COLLATION_ID_UTF16 0x2A0 +#define MY_PAGE2_COLLATION_ID_UTF16LE 0x2C0 +#define MY_PAGE2_COLLATION_ID_UTF32 0x2E0 + +struct my_uni_idx_st +{ + uint16 from; + uint16 to; + const uchar *tab; +}; + +typedef struct +{ + uint beg; + uint end; + uint mb_len; +} my_match_t; + +enum my_lex_states +{ + MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT, + MY_LEX_IDENT_SEP, MY_LEX_IDENT_START, + MY_LEX_REAL, MY_LEX_HEX_NUMBER, MY_LEX_BIN_NUMBER, + MY_LEX_CMP_OP, MY_LEX_LONG_CMP_OP, MY_LEX_STRING, MY_LEX_COMMENT, MY_LEX_END, + MY_LEX_OPERATOR_OR_IDENT, MY_LEX_NUMBER_IDENT, MY_LEX_INT_OR_REAL, + MY_LEX_REAL_OR_POINT, MY_LEX_BOOL, MY_LEX_EOL, MY_LEX_ESCAPE, + MY_LEX_LONG_COMMENT, MY_LEX_END_LONG_COMMENT, MY_LEX_SEMICOLON, + MY_LEX_SET_VAR, MY_LEX_USER_END, MY_LEX_HOSTNAME, MY_LEX_SKIP, + MY_LEX_USER_VARIABLE_DELIMITER, MY_LEX_SYSTEM_VAR, + MY_LEX_IDENT_OR_KEYWORD, + MY_LEX_IDENT_OR_HEX, MY_LEX_IDENT_OR_BIN, MY_LEX_IDENT_OR_NCHAR, + MY_LEX_STRING_OR_DELIMITER, MY_LEX_MINUS_OR_COMMENT, MY_LEX_PLACEHOLDER, + MY_LEX_COMMA +}; + +struct charset_info_st; + +typedef struct my_charset_loader_st +{ + char error[128]; + void *(*once_alloc)(size_t); + void *(*malloc)(size_t); + void *(*realloc)(void *, size_t); + void (*free)(void *); + void (*reporter)(enum loglevel, const char *format, ...); + int (*add_collation)(struct charset_info_st *cs); +} MY_CHARSET_LOADER; + + +extern int (*my_string_stack_guard)(int); + +/* See strings/CHARSET_INFO.txt for information about this structure */ +struct my_collation_handler_st +{ + my_bool (*init)(struct charset_info_st *, MY_CHARSET_LOADER *); + /* Collation routines */ + int (*strnncoll)(CHARSET_INFO *, + const uchar *, size_t, const uchar *, size_t, my_bool); + int (*strnncollsp)(CHARSET_INFO *, + const uchar *, size_t, const uchar *, size_t); + /* + strnncollsp_nchars() - similar to strnncollsp() but assumes that both + strings were originally CHAR(N) values with the + same N, then were optionally space-padded, + or optionally space-trimmed. + + In other words, this function compares in the way + if we insert both values into a CHAR(N) column + and then compare the two column values. + + It compares the same amount of characters from the two strings. + This is especially important for NOPAD collations. + + If CHAR_LENGTH of the two strings are different, + the shorter string is virtually padded with trailing spaces + up to CHAR_LENGTH of the longer string, to guarantee that the + same amount of characters are compared. + This is important if the two CHAR(N) strings are space-trimmed + (e.g. like in InnoDB compact format for CHAR). + + The function compares not more than "nchars" characters only. + This can be useful to compare CHAR(N) space-padded strings + (when the exact N is known) without having to truncate them before + the comparison. + + For example, Field_string stores a "CHAR(3) CHARACTER SET utf8mb4" value + of "aaa" as 12 bytes in a record buffer: + - 3 bytes of the actual data, followed by + - 9 bytes of spaces (just fillers, not real data) + The caller can pass nchars=3 to compare CHAR(3) record values. + In such case, the comparator won't go inside the 9 bytes of the fillers. + + If N is not known, the caller can pass max(len1,len2) as the "nchars" value + (i.e. the maximum of the OCTET_LENGTH of the two strings). + + Notes on complex collations. + + This function counts contraction parts as individual characters. + For example, the Czech letter 'ch' (in Czech collations) + is ordinarily counted by the "nchars" limit as TWO characters + (although it is only one letter). + This corresponds to what CHAR(N) does in INSERT. + + If the "nchars" limit tears apart a contraction, only the part fitting + into "nchars" characters is used. For example, in case of a Czech collation, + the string "ach" with nchars=2 is compared as 'ac': the contraction + 'ch' is torn apart and the letter 'c' acts as an individual character. + This emulates the same comparison result with the scenario when we insert + 'ach' into a CHAR(2) column and then compare it. + */ + int (*strnncollsp_nchars)(CHARSET_INFO *, + const uchar *str1, size_t len1, + const uchar *str2, size_t len2, + size_t nchars, + uint flags); + size_t (*strnxfrm)(CHARSET_INFO *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags); + size_t (*strnxfrmlen)(CHARSET_INFO *, size_t); + my_bool (*like_range)(CHARSET_INFO *, + const char *s, size_t s_length, + pchar w_prefix, pchar w_one, pchar w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_len, size_t *max_len); + int (*wildcmp)(CHARSET_INFO *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape,int w_one, int w_many); + + int (*strcasecmp)(CHARSET_INFO *, const char *, const char *); + + uint (*instr)(CHARSET_INFO *, + const char *b, size_t b_length, + const char *s, size_t s_length, + my_match_t *match, uint nmatch); + + /* Hash calculation */ + void (*hash_sort)(CHARSET_INFO *cs, const uchar *key, size_t len, + ulong *nr1, ulong *nr2); + my_bool (*propagate)(CHARSET_INFO *cs, const uchar *str, size_t len); + /* + Make minimum and maximum strings for the collation. + Put not more than "nchars" characters. + */ + size_t (*min_str)(CHARSET_INFO *cs, uchar *dst, size_t dstlen, size_t nchars); + size_t (*max_str)(CHARSET_INFO *cs, uchar *dst, size_t dstlen, size_t nchars); + + uint (*get_id)(CHARSET_INFO *cs, my_collation_id_type_t type); + LEX_CSTRING (*get_collation_name)(CHARSET_INFO *cs, + my_collation_name_mode_t mode); +}; + + +extern MY_COLLATION_HANDLER my_collation_8bit_bin_handler; +extern MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler; +extern MY_COLLATION_HANDLER my_collation_8bit_nopad_bin_handler; +extern MY_COLLATION_HANDLER my_collation_8bit_simple_nopad_ci_handler; + +/* Some typedef to make it easy for C++ to make function pointers */ +typedef int (*my_charset_conv_mb_wc)(CHARSET_INFO *, my_wc_t *, + const uchar *, const uchar *); +typedef int (*my_charset_conv_wc_mb)(CHARSET_INFO *, my_wc_t, + uchar *, uchar *); +typedef size_t (*my_charset_conv_case)(CHARSET_INFO *, + const char *, size_t, char *, size_t); + +/* + A structure to return the statistics of a native string copying, + when no Unicode conversion is involved. + + The structure is OK to be uninitialized before calling a copying routine. + A copying routine must populate the structure as follows: + - m_source_end_pos must be set by to a non-NULL value + in the range of the input string. + - m_well_formed_error_pos must be set to NULL if the string was + well formed, or to the position of the leftmost bad byte sequence. +*/ +typedef struct +{ + const char *m_source_end_pos; /* Position where reading stopped */ + const char *m_well_formed_error_pos; /* Position where a bad byte was found*/ +} MY_STRCOPY_STATUS; + + +/* + A structure to return the statistics of a Unicode string conversion. +*/ +typedef struct +{ + const char *m_cannot_convert_error_pos; +} MY_STRCONV_STATUS; + + +/* See strings/CHARSET_INFO.txt about information on this structure */ +struct my_charset_handler_st +{ + my_bool (*init)(struct charset_info_st *, MY_CHARSET_LOADER *loader); + /* Multibyte routines */ + size_t (*numchars)(CHARSET_INFO *, const char *b, const char *e); + size_t (*charpos)(CHARSET_INFO *, const char *b, const char *e, + size_t pos); + size_t (*lengthsp)(CHARSET_INFO *, const char *ptr, size_t length); + size_t (*numcells)(CHARSET_INFO *, const char *b, const char *e); + + /* Unicode conversion */ + my_charset_conv_mb_wc mb_wc; + my_charset_conv_wc_mb wc_mb; + + /* CTYPE scanner */ + int (*ctype)(CHARSET_INFO *cs, int *ctype, + const uchar *s, const uchar *e); + + /* Functions for case and sort conversion */ + size_t (*caseup_str)(CHARSET_INFO *, char *); + size_t (*casedn_str)(CHARSET_INFO *, char *); + + my_charset_conv_case caseup; + my_charset_conv_case casedn; + + /* Charset dependent snprintf() */ + size_t (*snprintf)(CHARSET_INFO *, char *to, size_t n, + const char *fmt, + ...) ATTRIBUTE_FORMAT_FPTR(printf, 4, 5); + size_t (*long10_to_str)(CHARSET_INFO *, char *to, size_t n, + int radix, long int val); + size_t (*longlong10_to_str)(CHARSET_INFO *, char *to, size_t n, + int radix, longlong val); + + void (*fill)(CHARSET_INFO *, char *to, size_t len, int fill); + + /* String-to-number conversion routines */ + long (*strntol)(CHARSET_INFO *, const char *s, size_t l, + int base, char **e, int *err); + ulong (*strntoul)(CHARSET_INFO *, const char *s, size_t l, + int base, char **e, int *err); + longlong (*strntoll)(CHARSET_INFO *, const char *s, size_t l, + int base, char **e, int *err); + ulonglong (*strntoull)(CHARSET_INFO *, const char *s, size_t l, + int base, char **e, int *err); + double (*strntod)(CHARSET_INFO *, char *s, size_t l, char **e, + int *err); + longlong (*strtoll10)(CHARSET_INFO *cs, + const char *nptr, char **endptr, int *error); + ulonglong (*strntoull10rnd)(CHARSET_INFO *cs, + const char *str, size_t length, + int unsigned_fl, + char **endptr, int *error); + size_t (*scan)(CHARSET_INFO *, const char *b, const char *e, + int sq); + + /* String copying routines and helpers for them */ + /* + charlen() - calculate length of the left-most character in bytes. + @param cs Character set + @param str The beginning of the string + @param end The end of the string + + @return MY_CS_ILSEQ if a bad byte sequence was found. + @return MY_CS_TOOSMALLN(x) if the string ended unexpectedly. + @return a positive number in the range 1..mbmaxlen, + if a valid character was found. + */ + int (*charlen)(CHARSET_INFO *cs, const uchar *str, const uchar *end); + /* + well_formed_char_length() - returns character length of a string. + + @param cs Character set + @param str The beginning of the string + @param end The end of the string + @param nchars Not more than "nchars" left-most characters are checked. + @param status[OUT] Additional statistics is returned here. + "status" can be uninitialized before the call, + and it is fully initialized after the call. + + status->m_source_end_pos is set to the position where reading stopped. + + If a bad byte sequence is found, the function returns immediately and + status->m_well_formed_error_pos is set to the position where a bad byte + sequence was found. + + status->m_well_formed_error_pos is set to NULL if no bad bytes were found. + If status->m_well_formed_error_pos is NULL after the call, that means: + - either the function reached the end of the string, + - or all "nchars" characters were read. + The caller can check status->m_source_end_pos to detect which of these two + happened. + */ + size_t (*well_formed_char_length)(CHARSET_INFO *cs, + const char *str, const char *end, + size_t nchars, + MY_STRCOPY_STATUS *status); + + /* + copy_fix() - copy a string, replace bad bytes to '?'. + Not more than "nchars" characters are copied. + + status->m_source_end_pos is set to a position in the range + between "src" and "src + src_length", where reading stopped. + + status->m_well_formed_error_pos is set to NULL if the string + in the range "src" and "status->m_source_end_pos" was well formed, + or is set to a position between "src" and "src + src_length" where + the leftmost bad byte sequence was found. + */ + size_t (*copy_fix)(CHARSET_INFO *, + char *dst, size_t dst_length, + const char *src, size_t src_length, + size_t nchars, MY_STRCOPY_STATUS *status); + /** + Write a character to the target string, using its native code. + For Unicode character sets (utf8, ucs2, utf16, utf16le, utf32, filename) + native codes are equivalent to Unicode code points. + For 8bit character sets the native code is just the byte value. + For Asian characters sets: + - MB1 native code is just the byte value (e.g. on the ASCII range) + - MB2 native code is ((b0 << 8) + b1). + - MB3 native code is ((b0 <<16) + (b1 << 8) + b2) + Note, CHARSET_INFO::min_sort_char and CHARSET_INFO::max_sort_char + are defined in native notation and should be written using + my_ci_native_to_mb() rather than my_ci_wc_mb(). + */ + my_charset_conv_wc_mb native_to_mb; + my_charset_conv_wc_mb wc_to_printable; + + uint (*caseup_multiply)(CHARSET_INFO *cs); + uint (*casedn_multiply)(CHARSET_INFO *cs); +}; + +extern MY_CHARSET_HANDLER my_charset_8bit_handler; +extern MY_CHARSET_HANDLER my_charset_ucs2_handler; +extern MY_CHARSET_HANDLER my_charset_utf8mb3_handler; + + +/* + We define this CHARSET_INFO_DEFINED here to prevent a repeat of the + typedef in hash.c, which will cause a compiler error. +*/ +#define CHARSET_INFO_DEFINED + + +/* See strings/CHARSET_INFO.txt about information on this structure */ +struct charset_info_st +{ + uint number; + uint primary_number; + uint binary_number; + uint state; + LEX_CSTRING cs_name; + LEX_CSTRING coll_name; + const char *comment; + const char *tailoring; + const uchar *m_ctype; + const uchar *to_lower; + const uchar *to_upper; + const uchar *sort_order; + MY_UCA_INFO *uca; + const uint16 *tab_to_uni; + MY_UNI_IDX *tab_from_uni; + MY_CASEFOLD_INFO *casefold; + const uchar *state_map; + const uchar *ident_map; + uint strxfrm_multiply; + uint mbminlen; + uint mbmaxlen; + /* + min_sort_char and max_sort_char represent the minimum + and the maximum character in the collation respectively. + + For Unicode collations, these numbers are Unicode code points. + For non-Unicode collations these numbers are native character codes. + For example, in all 8bit collations these numbers are + in the range 0x00..0xFF. + + min_sort_char and max_sort_char normally should not be used directly. + They are used internally in the following virtual functions: + - MY_COLLATION_HANDLER::like_range() + - MY_COLLATION_HANDLER::min_str() + - MY_COLLATION_HANDLER::max_str() + */ + my_wc_t min_sort_char; + my_wc_t max_sort_char; + uchar pad_char; + my_bool escape_with_backslash_is_dangerous; + uchar levels_for_order; + + MY_CHARSET_HANDLER *cset; + MY_COLLATION_HANDLER *coll; + +#ifdef __cplusplus + /* Character set routines */ + bool use_mb() const + { + return mbmaxlen > 1; + } + + size_t numchars(const char *b, const char *e) const + { + return (cset->numchars)(this, b, e); + } + + size_t charpos(const char *b, const char *e, size_t pos) const + { + return (cset->charpos)(this, b, e, pos); + } + size_t charpos(const uchar *b, const uchar *e, size_t pos) const + { + return (cset->charpos)(this, (const char *) b, (const char*) e, pos); + } + + size_t lengthsp(const char *str, size_t length) const + { + return (cset->lengthsp)(this, str, length); + } + + size_t numcells(const char *b, const char *e) const + { + return (cset->numcells)(this, b, e); + } + + size_t caseup(const char *src, size_t srclen, + char *dst, size_t dstlen) const + { + return (cset->caseup)(this, src, srclen, dst, dstlen); + } + + size_t casedn(const char *src, size_t srclen, + char *dst, size_t dstlen) const + { + return (cset->casedn)(this, src, srclen, dst, dstlen); + } + + uint caseup_multiply() const + { + return (cset->caseup_multiply)(this); + } + + uint casedn_multiply() const + { + return (cset->casedn_multiply)(this); + } + + size_t long10_to_str(char *dst, size_t dstlen, + int radix, long int val) const + { + return (cset->long10_to_str)(this, dst, dstlen, radix, val); + } + + size_t (longlong10_to_str)(char *dst, size_t dstlen, + int radix, longlong val) const + { + return (cset->longlong10_to_str)(this, dst, dstlen, radix, val); + } + + int mb_wc(my_wc_t *wc, const uchar *b, const uchar *e) const + { + return (cset->mb_wc)(this, wc, b, e); + } + + int wc_mb(my_wc_t wc, uchar *s, uchar *e) const + { + return (cset->wc_mb)(this, wc, s, e); + } + + int native_to_mb(my_wc_t wc, uchar *s, uchar *e) const + { + return (cset->native_to_mb)(this, wc, s, e); + } + + int wc_to_printable(my_wc_t wc, uchar *s, uchar *e) const + { + return (cset->wc_to_printable)(this, wc, s, e); + } + + int ctype(int *to, const uchar *s, const uchar *e) const + { + return (cset->ctype)(this, to, s, e); + } + + void fill(char *to, size_t len, int ch) const + { + (cset->fill)(this, to, len, ch); + } + + long strntol(const char *str, size_t length, + int base, char **endptr, int *error) const + { + return (cset->strntol)(this, str, length, base, endptr, error); + } + + ulong strntoul(const char *str, size_t length, + int base, char **endptr, int *error) const + { + return (cset->strntoul)(this, str, length, base, endptr, error); + } + + longlong strntoll(const char *str, size_t length, + int base, char **endptr, int *error) const + { + return (cset->strntoll)(this, str, length, base, endptr, error); + } + + ulonglong strntoull(const char *str, size_t length, + int base, char **endptr, int *error) const + { + return (cset->strntoull)(this, str, length, base, endptr, error); + } + + double strntod(char *str, size_t length, + char **endptr, int *error) const + { + return (cset->strntod)(this, str, length, endptr, error); + } + + longlong strtoll10(const char *str, char **endptr, int *error) const + { + return (cset->strtoll10)(this, str, endptr, error); + } + + ulonglong strntoull10rnd(const char *str, size_t length, int unsigned_fl, + char **endptr, int *error) const + { + return (cset->strntoull10rnd)(this, str, length, unsigned_fl, endptr, error); + } + + size_t scan(const char *b, const char *e, int seq) const + { + return (cset->scan)(this, b, e, seq); + } + + int charlen(const uchar *str, const uchar *end) const + { + return (cset->charlen)(this, str, end); + } + int charlen(const char *str, const char *end) const + { + return (cset->charlen)(this, (const uchar *) str, (const uchar *) end); + } + + uint charlen_fix(const uchar *str, const uchar *end) const + { + int char_length= (cset->charlen)(this, str, end); + DBUG_ASSERT(str < end); + return char_length > 0 ? (uint) char_length : (uint) 1U; + } + uint charlen_fix(const char *str, const char *end) const + { + return charlen_fix((const uchar *) str, (const uchar *) end); + } + + size_t well_formed_char_length(const char *str, const char *end, + size_t nchars, + MY_STRCOPY_STATUS *status) const + { + return (cset->well_formed_char_length)(this, str, end, nchars, status); + } + + size_t copy_fix(char *dst, size_t dst_length, + const char *src, size_t src_length, + size_t nchars, MY_STRCOPY_STATUS *status) const + { + return (cset->copy_fix)(this, dst, dst_length, src, src_length, nchars, + status); + } + + /* Collation routines */ + uint default_flag() const + { + return state & MY_CS_PRIMARY; + } + + uint binsort_flag() const + { + return state & MY_CS_BINSORT; + } + + uint compiled_flag() const + { + return state & MY_CS_COMPILED; + } + + int strnncoll(const uchar *a, size_t alen, + const uchar *b, size_t blen, my_bool b_is_prefix= FALSE) const + { + return (coll->strnncoll)(this, a, alen, b, blen, b_is_prefix); + } + int strnncoll(const char *a, size_t alen, + const char *b, size_t blen, my_bool b_is_prefix= FALSE) const + { + return (coll->strnncoll)(this, + (const uchar *) a, alen, + (const uchar *) b, blen, b_is_prefix); + } + + int strnncollsp(const uchar *a, size_t alen, + const uchar *b, size_t blen) const + { + return (coll->strnncollsp)(this, a, alen, b, blen); + } + int strnncollsp(const char *a, size_t alen, + const char *b, size_t blen) const + { + return (coll->strnncollsp)(this, (uchar *) a, alen, (uchar *) b, blen); + } + + int strnncollsp(const LEX_CSTRING &a, const LEX_CSTRING &b) const + { + return (coll->strnncollsp)(this, (uchar *) a.str, a.length, + (uchar *) b.str, b.length); + } + + size_t strnxfrm(char *dst, size_t dstlen, uint nweights, + const char *src, size_t srclen, uint flags) const + { + return (coll->strnxfrm)(this, + (uchar *) dst, dstlen, nweights, + (const uchar *) src, srclen, flags); + } + size_t strnxfrm(uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags) const + { + return (coll->strnxfrm)(this, + dst, dstlen, nweights, + src, srclen, flags); + } + size_t strnxfrm(uchar *dst, size_t dstlen, + const uchar *src, size_t srclen) const + { + return (coll->strnxfrm)(this, + dst, dstlen, (uint) dstlen, + src, srclen, MY_STRXFRM_PAD_WITH_SPACE); + } + + size_t strnxfrmlen(size_t length) const + { + return (coll->strnxfrmlen)(this, length); + } + + my_bool like_range(const char *s, size_t s_length, + pchar w_prefix, pchar w_one, pchar w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_len, size_t *max_len) const + { + return (coll->like_range)(this, s, s_length, + w_prefix, w_one, w_many, + res_length, min_str, max_str, + min_len, max_len); + } + + int wildcmp(const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape,int w_one, int w_many) const + { + return (coll->wildcmp)(this, str, str_end, wildstr, wildend, escape, w_one, w_many); + } + + uint instr(const char *b, size_t b_length, + const char *s, size_t s_length, + my_match_t *match, uint nmatch) const + { + return (coll->instr)(this, b, b_length, s, s_length, match, nmatch); + } + + void hash_sort(const uchar *key, size_t len, ulong *nr1, ulong *nr2) const + { + (coll->hash_sort)(this, key, len, nr1, nr2); + } + + my_bool propagate(const uchar *str, size_t len) const + { + return (coll->propagate)(this, str, len); + } + + size_t min_str(uchar *dst, size_t dstlen, size_t nchars) const + { + return (coll->min_str)(this, dst, dstlen, nchars); + } + + size_t max_str(uchar *dst, size_t dstlen, size_t nchars) const + { + return (coll->max_str)(this, dst, dstlen, nchars); + } + + uint get_id(my_collation_id_type_t type) const + { + return (coll->get_id)(this, type); + } + + LEX_CSTRING get_collation_name(my_collation_name_mode_t mode) const + { + return (coll->get_collation_name)(this, mode); + } +#endif /* __cplusplus */ +}; + + +/* Character set routines */ + +static inline my_bool +my_ci_init_charset(struct charset_info_st *ci, MY_CHARSET_LOADER *loader) +{ + if (!ci->cset->init) + return FALSE; + return (ci->cset->init)(ci, loader); +} + + +static inline my_bool +my_ci_use_mb(CHARSET_INFO *ci) +{ + return ci->mbmaxlen > 1 ? TRUE : FALSE; +} + +static inline size_t +my_ci_numchars(CHARSET_INFO *cs, const char *b, const char *e) +{ + return (cs->cset->numchars)(cs, b, e); +} + +static inline size_t +my_ci_charpos(CHARSET_INFO *cs, const char *b, const char *e, size_t pos) +{ + return (cs->cset->charpos)(cs, b, e, pos); +} + +static inline size_t +my_ci_lengthsp(CHARSET_INFO *cs, const char *str, size_t length) +{ + return (cs->cset->lengthsp)(cs, str, length); +} + +static inline size_t +my_ci_numcells(CHARSET_INFO *cs, const char *b, const char *e) +{ + return (cs->cset->numcells)(cs, b, e); +} + +static inline size_t +my_ci_caseup(CHARSET_INFO *ci, + const char *src, size_t srclen, + char *dst, size_t dstlen) +{ + return (ci->cset->caseup)(ci, src, srclen, dst, dstlen); +} + +static inline size_t +my_ci_casedn(CHARSET_INFO *ci, + const char *src, size_t srclen, + char *dst, size_t dstlen) +{ + return (ci->cset->casedn)(ci, src, srclen, dst, dstlen); +} + +static inline size_t +my_ci_long10_to_str(CHARSET_INFO *cs, char *dst, size_t dstlen, + int radix, long int val) +{ + return (cs->cset->long10_to_str)(cs, dst, dstlen, radix, val); +} + +static inline size_t +my_ci_longlong10_to_str(CHARSET_INFO *cs, char *dst, size_t dstlen, + int radix, longlong val) +{ + return (cs->cset->longlong10_to_str)(cs, dst, dstlen, radix, val); +} + +#define my_ci_mb_wc(s, pwc, b, e) ((s)->cset->mb_wc)(s, pwc, b, e) +#define my_ci_wc_mb(s, wc, b, e) ((s)->cset->wc_mb)(s, wc, b, e) +#define my_ci_native_to_mb(s, wc, b, e) ((s)->cset->native_to_mb)(s, wc, b, e) +#define my_ci_ctype(s, pctype, b, e) ((s)->cset->ctype)(s, pctype, b, e) + +static inline void +my_ci_fill(CHARSET_INFO *cs, char *to, size_t len, int ch) +{ + (cs->cset->fill)(cs, to, len, ch); +} + +static inline long +my_ci_strntol(CHARSET_INFO *cs, const char *str, size_t length, + int base, char **endptr, int *error) +{ + return (cs->cset->strntol)(cs, str, length, base, endptr, error); +} + +static inline ulong +my_ci_strntoul(CHARSET_INFO *cs, const char *str, size_t length, + int base, char **endptr, int *error) +{ + return (cs->cset->strntoul)(cs, str, length, base, endptr, error); +} + +static inline longlong +my_ci_strntoll(CHARSET_INFO *cs, const char *str, size_t length, + int base, char **endptr, int *error) +{ + return (cs->cset->strntoll)(cs, str, length, base, endptr, error); +} + +static inline ulonglong +my_ci_strntoull(CHARSET_INFO *cs, const char *str, size_t length, + int base, char **endptr, int *error) +{ + return (cs->cset->strntoull)(cs, str, length, base, endptr, error); +} + +static inline double +my_ci_strntod(CHARSET_INFO *cs, char *str, size_t length, + char **endptr, int *error) +{ + return (cs->cset->strntod)(cs, str, length, endptr, error); +} + +static inline longlong +my_ci_strtoll10(CHARSET_INFO *cs, const char *str, char **endptr, int *error) +{ + return (cs->cset->strtoll10)(cs, str, endptr, error); +} + +static inline ulonglong +my_ci_strntoull10rnd(CHARSET_INFO *cs, + const char *str, size_t length, int unsigned_fl, + char **endptr, int *error) +{ + return (cs->cset->strntoull10rnd)(cs, str, length, unsigned_fl, endptr, error); +} + + +static inline size_t +my_ci_scan(CHARSET_INFO *cs, const char *b, const char *e, int seq) +{ + return (cs->cset->scan)(cs, b, e, seq); +} + + +/** + Return length of the leftmost character in a string. + @param cs - character set + @param str - the beginning of the string + @param end - the string end (the next byte after the string) + @return <=0 on errors (EOL, wrong byte sequence) + @return 1 on a single byte character + @return >1 on a multi-byte character + + Note, inlike my_ismbchar(), 1 is returned for a single byte character. +*/ + +static inline int +my_ci_charlen(CHARSET_INFO *cs, const uchar *str, const uchar *end) +{ + return (cs->cset->charlen)(cs, str, end); +} + + +static inline size_t +my_ci_well_formed_char_length(CHARSET_INFO *cs, + const char *str, const char *end, + size_t nchars, + MY_STRCOPY_STATUS *status) +{ + return (cs->cset->well_formed_char_length)(cs, str, end, nchars, status); +} + + +static inline size_t +my_ci_copy_fix(CHARSET_INFO *cs, + char *dst, size_t dst_length, + const char *src, size_t src_length, + size_t nchars, MY_STRCOPY_STATUS *status) +{ + return (cs->cset->copy_fix)(cs, dst, dst_length, src, src_length, nchars, + status); +} + + +/* Collation routines */ + +static inline my_bool +my_ci_init_collation(struct charset_info_st *ci, MY_CHARSET_LOADER *loader) +{ + if (!ci->coll->init) + return FALSE; + return (ci->coll->init)(ci, loader); +} + + +static inline int +my_ci_strnncoll(CHARSET_INFO *ci, + const uchar *a, size_t alen, + const uchar *b, size_t blen, + my_bool b_is_prefix) +{ + return (ci->coll->strnncoll)(ci, a, alen, b, blen, b_is_prefix); +} + +static inline int +my_ci_strnncollsp(CHARSET_INFO *ci, + const uchar *a, size_t alen, + const uchar *b, size_t blen) +{ + return (ci->coll->strnncollsp)(ci, a, alen, b, blen); +} + + +static inline my_bool +my_ci_like_range(CHARSET_INFO *ci, + const char *s, size_t s_length, + pchar w_prefix, pchar w_one, pchar w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_len, size_t *max_len) +{ + return (ci->coll->like_range)(ci, s, s_length, + w_prefix, w_one, w_many, + res_length, min_str, max_str, + min_len, max_len); +} + + +static inline uint +my_ci_instr(CHARSET_INFO *ci, + const char *b, size_t b_length, + const char *s, size_t s_length, + my_match_t *match, uint nmatch) +{ + return (ci->coll->instr)(ci, b, b_length, s, s_length, match, nmatch); +} + + +static inline void +my_ci_hash_sort(CHARSET_INFO *ci, + const uchar *key, size_t len, + ulong *nr1, ulong *nr2) +{ + (ci->coll->hash_sort)(ci, key, len, nr1, nr2); +} + + +#define ILLEGAL_CHARSET_INFO_NUMBER (~0U) + +extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_bin; +extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_latin1; +extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_latin1_nopad; +extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_filename; +extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_utf8mb3_general_ci; + +extern struct charset_info_st my_charset_big5_bin; +extern struct charset_info_st my_charset_big5_chinese_ci; +extern struct charset_info_st my_charset_big5_nopad_bin; +extern struct charset_info_st my_charset_big5_chinese_nopad_ci; +extern struct charset_info_st my_charset_cp1250_czech_cs; +extern struct charset_info_st my_charset_cp932_bin; +extern struct charset_info_st my_charset_cp932_japanese_ci; +extern struct charset_info_st my_charset_cp932_nopad_bin; +extern struct charset_info_st my_charset_cp932_japanese_nopad_ci; +extern struct charset_info_st my_charset_eucjpms_bin; +extern struct charset_info_st my_charset_eucjpms_japanese_ci; +extern struct charset_info_st my_charset_eucjpms_nopad_bin; +extern struct charset_info_st my_charset_eucjpms_japanese_nopad_ci; +extern struct charset_info_st my_charset_euckr_bin; +extern struct charset_info_st my_charset_euckr_korean_ci; +extern struct charset_info_st my_charset_euckr_nopad_bin; +extern struct charset_info_st my_charset_euckr_korean_nopad_ci; +extern struct charset_info_st my_charset_gb2312_bin; +extern struct charset_info_st my_charset_gb2312_chinese_ci; +extern struct charset_info_st my_charset_gb2312_nopad_bin; +extern struct charset_info_st my_charset_gb2312_chinese_nopad_ci; +extern struct charset_info_st my_charset_gbk_bin; +extern struct charset_info_st my_charset_gbk_chinese_ci; +extern struct charset_info_st my_charset_gbk_nopad_bin; +extern struct charset_info_st my_charset_gbk_chinese_nopad_ci; +extern struct charset_info_st my_charset_latin1_bin; +extern struct charset_info_st my_charset_latin1_nopad_bin; +extern struct charset_info_st my_charset_latin1_german2_ci; +extern struct charset_info_st my_charset_latin2_czech_cs; +extern struct charset_info_st my_charset_sjis_bin; +extern struct charset_info_st my_charset_sjis_japanese_ci; +extern struct charset_info_st my_charset_sjis_nopad_bin; +extern struct charset_info_st my_charset_sjis_japanese_nopad_ci; +extern struct charset_info_st my_charset_tis620_bin; +extern struct charset_info_st my_charset_tis620_thai_ci; +extern struct charset_info_st my_charset_tis620_nopad_bin; +extern struct charset_info_st my_charset_tis620_thai_nopad_ci; +extern struct charset_info_st my_charset_ucs2_bin; +extern struct charset_info_st my_charset_ucs2_general_ci; +extern struct charset_info_st my_charset_ucs2_nopad_bin; +extern struct charset_info_st my_charset_ucs2_general_nopad_ci; +extern struct charset_info_st my_charset_ucs2_general_mysql500_ci; +extern struct charset_info_st my_charset_ucs2_unicode_ci; +extern struct charset_info_st my_charset_ucs2_unicode_nopad_ci; +extern struct charset_info_st my_charset_ucs2_general_mysql500_ci; +extern struct charset_info_st my_charset_ujis_bin; +extern struct charset_info_st my_charset_ujis_japanese_ci; +extern struct charset_info_st my_charset_ujis_nopad_bin; +extern struct charset_info_st my_charset_ujis_japanese_nopad_ci; +extern struct charset_info_st my_charset_utf16_bin; +extern struct charset_info_st my_charset_utf16_general_ci; +extern struct charset_info_st my_charset_utf16_unicode_ci; +extern struct charset_info_st my_charset_utf16_unicode_nopad_ci; +extern struct charset_info_st my_charset_utf16le_bin; +extern struct charset_info_st my_charset_utf16le_general_ci; +extern struct charset_info_st my_charset_utf16_general_nopad_ci; +extern struct charset_info_st my_charset_utf16_nopad_bin; +extern struct charset_info_st my_charset_utf16le_nopad_bin; +extern struct charset_info_st my_charset_utf16le_general_nopad_ci; +extern struct charset_info_st my_charset_utf32_bin; +extern struct charset_info_st my_charset_utf32_general_ci; +extern struct charset_info_st my_charset_utf32_unicode_ci; +extern struct charset_info_st my_charset_utf32_unicode_nopad_ci; +extern struct charset_info_st my_charset_utf32_nopad_bin; +extern struct charset_info_st my_charset_utf32_general_nopad_ci; +extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_utf8mb3_bin; +extern struct charset_info_st my_charset_utf8mb3_nopad_bin; +extern struct charset_info_st my_charset_utf8mb3_general_nopad_ci; +extern struct charset_info_st my_charset_utf8mb3_general_mysql500_ci; +extern struct charset_info_st my_charset_utf8mb3_unicode_ci; +extern struct charset_info_st my_charset_utf8mb3_unicode_nopad_ci; +extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_utf8mb4_bin; +extern struct charset_info_st my_charset_utf8mb4_general_ci; +extern struct charset_info_st my_charset_utf8mb4_nopad_bin; +extern struct charset_info_st my_charset_utf8mb4_general_nopad_ci; +extern struct charset_info_st my_charset_utf8mb4_unicode_ci; +extern struct charset_info_st my_charset_utf8mb4_unicode_nopad_ci; + +/* + Contextually typed collations, e.g.: + CHAR(10) COLLATE DEFAULT + CHAR(10) BINARY +*/ +extern struct charset_info_st my_collation_contextually_typed_default; +extern struct charset_info_st my_collation_contextually_typed_binary; + + +#define MY_UTF8MB3 "utf8mb3" +#define MY_UTF8MB4 "utf8mb4" + +my_bool my_cs_have_contractions(CHARSET_INFO *cs); +my_bool my_cs_can_be_contraction_head(CHARSET_INFO *cs, my_wc_t wc); +my_bool my_cs_can_be_contraction_tail(CHARSET_INFO *cs, my_wc_t wc); +const uint16 *my_cs_contraction2_weight(CHARSET_INFO *cs, my_wc_t wc1, + my_wc_t wc2); + +/* declarations for simple charsets */ +extern size_t my_strnxfrm_simple(CHARSET_INFO *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags); +size_t my_strnxfrmlen_simple(CHARSET_INFO *, size_t); +extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, size_t, + const uchar *, size_t, my_bool); + +extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, size_t, + const uchar *, size_t); + +extern void my_hash_sort_simple(CHARSET_INFO *cs, + const uchar *key, size_t len, + ulong *nr1, ulong *nr2); + +extern void my_hash_sort_simple_nopad(CHARSET_INFO *cs, + const uchar *key, size_t len, + ulong *nr1, ulong *nr2); + +extern void my_hash_sort_bin(CHARSET_INFO *cs, + const uchar *key, size_t len, ulong *nr1, + ulong *nr2); + +/** + Compare a string to an array of spaces, for PAD SPACE comparison. + The function iterates through the string and compares every byte to 0x20. + @param - the string + @param - its length + @return <0 - if a byte less than 0x20 was found in the string. + @return 0 - if all bytes in the string were 0x20, or if length was 0. + @return >0 - if a byte greater than 0x20 was found in the string. +*/ +extern int my_strnncollsp_padspace_bin(const uchar *str, size_t length); + +extern size_t my_lengthsp_8bit(CHARSET_INFO *cs, const char *ptr, size_t length); + +extern uint my_instr_simple(CHARSET_INFO *, + const char *b, size_t b_length, + const char *s, size_t s_length, + my_match_t *match, uint nmatch); + +size_t my_copy_8bit(CHARSET_INFO *, + char *dst, size_t dst_length, + const char *src, size_t src_length, + size_t nchars, MY_STRCOPY_STATUS *); +size_t my_copy_fix_mb(CHARSET_INFO *cs, + char *dst, size_t dst_length, + const char *src, size_t src_length, + size_t nchars, MY_STRCOPY_STATUS *); + +/* Functions for 8bit */ +extern size_t my_caseup_str_8bit(CHARSET_INFO *, char *); +extern size_t my_casedn_str_8bit(CHARSET_INFO *, char *); +extern size_t my_caseup_8bit(CHARSET_INFO *, + const char *src, size_t srclen, + char *dst, size_t dstlen); +extern size_t my_casedn_8bit(CHARSET_INFO *, + const char *src, size_t srclen, + char *dst, size_t dstlen); + +extern int my_strcasecmp_8bit(CHARSET_INFO * cs, const char *, const char *); + +int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e); +int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e); +int my_wc_mb_bin(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e); + +int my_mb_ctype_8bit(CHARSET_INFO *,int *, const uchar *,const uchar *); +int my_mb_ctype_mb(CHARSET_INFO *,int *, const uchar *,const uchar *); + +size_t my_scan_8bit(CHARSET_INFO *cs, const char *b, const char *e, int sq); + +size_t my_snprintf_8bit(CHARSET_INFO *, char *to, size_t n, + const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 4, 5); + +long my_strntol_8bit(CHARSET_INFO *, const char *s, size_t l, int base, + char **e, int *err); +ulong my_strntoul_8bit(CHARSET_INFO *, const char *s, size_t l, int base, + char **e, int *err); +longlong my_strntoll_8bit(CHARSET_INFO *, const char *s, size_t l, int base, + char **e, int *err); +ulonglong my_strntoull_8bit(CHARSET_INFO *, const char *s, size_t l, int base, + char **e, int *err); +double my_strntod_8bit(CHARSET_INFO *, char *s, size_t l,char **e, + int *err); +size_t my_long10_to_str_8bit(CHARSET_INFO *, char *to, size_t l, int radix, + long int val); +size_t my_longlong10_to_str_8bit(CHARSET_INFO *, char *to, size_t l, int radix, + longlong val); + +longlong my_strtoll10_8bit(CHARSET_INFO *cs, + const char *nptr, char **endptr, int *error); +longlong my_strtoll10_ucs2(CHARSET_INFO *cs, + const char *nptr, char **endptr, int *error); + +ulonglong my_strntoull10rnd_8bit(CHARSET_INFO *cs, + const char *str, size_t length, int + unsigned_fl, char **endptr, int *error); +ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs, + const char *str, size_t length, + int unsigned_fl, char **endptr, int *error); + +void my_fill_8bit(CHARSET_INFO *cs, char* to, size_t l, int fill); + +/* For 8-bit character set */ +my_bool my_like_range_simple(CHARSET_INFO *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + +/* For ASCII-based multi-byte character sets with mbminlen=1 */ +my_bool my_like_range_mb(CHARSET_INFO *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + +/* For other character sets, with arbitrary mbminlen and mbmaxlen numbers */ +my_bool my_like_range_generic(CHARSET_INFO *cs, + const char *ptr, size_t ptr_length, + pbool escape, pbool w_one, pbool w_many, + size_t res_length, + char *min_str, char *max_str, + size_t *min_length, size_t *max_length); + +int my_wildcmp_8bit(CHARSET_INFO *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); + +int my_wildcmp_bin(CHARSET_INFO *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); + +size_t my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e); +size_t my_numcells_8bit(CHARSET_INFO *, const char *b, const char *e); +size_t my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, size_t pos); +size_t my_well_formed_char_length_8bit(CHARSET_INFO *cs, + const char *b, const char *e, + size_t nchars, + MY_STRCOPY_STATUS *status); +int my_charlen_8bit(CHARSET_INFO *, const uchar *str, const uchar *end); + + +/* Functions for multibyte charsets */ +extern size_t my_caseup_str_mb(CHARSET_INFO *, char *); +extern size_t my_casedn_str_mb(CHARSET_INFO *, char *); +extern size_t my_caseup_mb(CHARSET_INFO *, + const char *src, size_t srclen, + char *dst, size_t dstlen); +extern size_t my_casedn_mb(CHARSET_INFO *, + const char *src, size_t srclen, + char *dst, size_t dstlen); +extern size_t my_caseup_ujis(CHARSET_INFO *, + const char *src, size_t srclen, + char *dst, size_t dstlen); +extern size_t my_casedn_ujis(CHARSET_INFO *, + const char *src, size_t srclen, + char *dst, size_t dstlen); +extern int my_strcasecmp_mb(CHARSET_INFO * cs,const char *, const char *); + +int my_wildcmp_mb(CHARSET_INFO *, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); +size_t my_numchars_mb(CHARSET_INFO *, const char *b, const char *e); +size_t my_numcells_mb(CHARSET_INFO *, const char *b, const char *e); +size_t my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, size_t pos); +uint my_instr_mb(CHARSET_INFO *, + const char *b, size_t b_length, + const char *s, size_t s_length, + my_match_t *match, uint nmatch); + +int my_wildcmp_mb_bin(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many); + +int my_strcasecmp_mb_bin(CHARSET_INFO * cs __attribute__((unused)), + const char *s, const char *t); + +void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), + const uchar *key, size_t len,ulong *nr1, ulong *nr2); + +void my_hash_sort_mb_nopad_bin(CHARSET_INFO *cs __attribute__((unused)), + const uchar *key, size_t len, + ulong *nr1, ulong *nr2); + +size_t my_strnxfrm_mb(CHARSET_INFO *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags); + +size_t my_strnxfrm_mb_nopad(CHARSET_INFO *, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags); + +size_t my_strnxfrmlen_unicode(CHARSET_INFO *, size_t); + +size_t my_strnxfrm_unicode_full_bin(CHARSET_INFO *, + uchar *dst, size_t dstlen, + uint nweights, const uchar *src, + size_t srclen, uint flags); + +size_t my_strnxfrm_unicode_full_nopad_bin(CHARSET_INFO *, + uchar *dst, size_t dstlen, + uint nweights, const uchar *src, + size_t srclen, uint flags); + +size_t my_strnxfrmlen_unicode_full_bin(CHARSET_INFO *, size_t); + +int my_wildcmp_unicode(CHARSET_INFO *cs, + const char *str, const char *str_end, + const char *wildstr, const char *wildend, + int escape, int w_one, int w_many, + MY_CASEFOLD_INFO *weights); + +extern my_bool my_parse_charset_xml(MY_CHARSET_LOADER *loader, + const char *buf, size_t buflen); +extern char *my_strchr(CHARSET_INFO *cs, const char *str, const char *end, + pchar c); +extern size_t my_strcspn(CHARSET_INFO *cs, const char *str, const char *end, + const char *accept); + +my_bool my_propagate_simple(CHARSET_INFO *cs, const uchar *str, size_t len); +my_bool my_propagate_complex(CHARSET_INFO *cs, const uchar *str, size_t len); + +uint my_ci_get_id_generic(CHARSET_INFO *cs, my_collation_id_type_t type); +LEX_CSTRING my_ci_get_collation_name_generic(CHARSET_INFO *cs, + my_collation_name_mode_t mode); + +typedef struct +{ + size_t char_length; + my_repertoire_t repertoire; +} MY_STRING_METADATA; + +void my_string_metadata_get(MY_STRING_METADATA *metadata, + CHARSET_INFO *cs, const char *str, size_t len); +my_repertoire_t my_string_repertoire(CHARSET_INFO *cs, + const char *str, size_t len); +my_bool my_charset_is_ascii_based(CHARSET_INFO *cs); +my_repertoire_t my_charset_repertoire(CHARSET_INFO *cs); + +uint my_strxfrm_flag_normalize(CHARSET_INFO *cs, uint flags); +void my_strxfrm_desc_and_reverse(uchar *str, uchar *strend, + uint flags, uint level); +size_t my_strxfrm_pad_desc_and_reverse(CHARSET_INFO *cs, + uchar *str, uchar *frmend, uchar *strend, + uint nweights, uint flags, uint level); +size_t my_strxfrm_pad_desc_and_reverse_nopad(CHARSET_INFO *cs, + uchar *str, uchar *frmend, + uchar *strend, uint nweights, + uint flags, uint level); + +const MY_CONTRACTIONS *my_charset_get_contractions(CHARSET_INFO *cs, + int level); + +extern size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n, + const char* fmt, va_list ap); + +/* + Convert a string between two character sets. + Bad byte sequences as well as characters that cannot be + encoded in the destination character set are replaced to '?'. +*/ +uint32 my_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, + const char *from, uint32 from_length, + CHARSET_INFO *from_cs, uint *errors); + +/** + An extended version of my_convert(), to pass non-default mb_wc() and wc_mb(). + For example, String::copy_printable() which is used in + Protocol::store_warning() uses this to escape control + and non-convertible characters. +*/ +uint32 my_convert_using_func(char *to, size_t to_length, CHARSET_INFO *to_cs, + my_charset_conv_wc_mb mb_wc, + const char *from, size_t from_length, + CHARSET_INFO *from_cs, + my_charset_conv_mb_wc wc_mb, + uint *errors); +/* + Convert a string between two character sets. + Bad byte sequences as well as characters that cannot be + encoded in the destination character set are replaced to '?'. + Not more than "nchars" characters are copied. + Conversion statistics is returned in "status" and is set as follows: + - status->m_native_copy_status.m_source_end_pos - to the position + between (src) and (src+src_length), where the function stopped reading + the source string. + - status->m_native_copy_status.m_well_formed_error_pos - to the position + between (src) and (src+src_length), where the first badly formed byte + sequence was found, or to NULL if the string was well formed in the + given range. + - status->m_cannot_convert_error_pos - to the position + between (src) and (src+src_length), where the first character that + cannot be represented in the destination character set was found, + or to NULL if all characters in the given range were successfully + converted. + + "src" is allowed to be a NULL pointer. In this case "src_length" must + be equal to 0. All "status" members are initialized to NULL, and 0 is + returned. +*/ +size_t my_convert_fix(CHARSET_INFO *dstcs, char *dst, size_t dst_length, + CHARSET_INFO *srccs, const char *src, size_t src_length, + size_t nchars, + MY_STRCOPY_STATUS *copy_status, + MY_STRCONV_STATUS *conv_status); + +#define _MY_U 01 /* Upper case */ +#define _MY_L 02 /* Lower case */ +#define _MY_NMR 04 /* Numeral (digit) */ +#define _MY_SPC 010 /* Spacing character */ +#define _MY_PNT 020 /* Punctuation */ +#define _MY_CTR 040 /* Control character */ +#define _MY_B 0100 /* Blank */ +#define _MY_X 0200 /* heXadecimal digit */ + + +#define my_isascii(c) (!((c) & ~0177)) +#define my_toascii(c) ((c) & 0177) +#define my_tocntrl(c) ((c) & 31) +#define my_toprint(c) ((c) | 64) +#define my_toupper(s,c) (char) ((s)->to_upper[(uchar) (c)]) +#define my_tolower(s,c) (char) ((s)->to_lower[(uchar) (c)]) +#define my_isalpha(s, c) (((s)->m_ctype+1)[(uchar) (c)] & (_MY_U | _MY_L)) +#define my_isupper(s, c) (((s)->m_ctype+1)[(uchar) (c)] & _MY_U) +#define my_islower(s, c) (((s)->m_ctype+1)[(uchar) (c)] & _MY_L) +#define my_isdigit(s, c) (((s)->m_ctype+1)[(uchar) (c)] & _MY_NMR) +#define my_isxdigit(s, c) (((s)->m_ctype+1)[(uchar) (c)] & _MY_X) +#define my_isalnum(s, c) (((s)->m_ctype+1)[(uchar) (c)] & (_MY_U | _MY_L | _MY_NMR)) +#define my_isspace(s, c) (((s)->m_ctype+1)[(uchar) (c)] & _MY_SPC) +#define my_ispunct(s, c) (((s)->m_ctype+1)[(uchar) (c)] & _MY_PNT) +#define my_isprint(s, c) (((s)->m_ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR | _MY_B)) +#define my_isgraph(s, c) (((s)->m_ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR)) +#define my_iscntrl(s, c) (((s)->m_ctype+1)[(uchar) (c)] & _MY_CTR) + +/* Some macros that should be cleaned up a little */ +#define my_isvar(s,c) (my_isalnum(s,c) || (c) == '_') +#define my_isvar_start(s,c) (my_isalpha(s,c) || (c) == '_') + +#define my_binary_compare(s) ((s)->state & MY_CS_BINSORT) +#define use_strnxfrm(s) ((s)->state & MY_CS_STRNXFRM) +#define my_strnncoll(s, a, b, c, d) ((s)->coll->strnncoll((s), (a), (b), (c), (d), 0)) +#define my_strcasecmp(s, a, b) ((s)->coll->strcasecmp((s), (a), (b))) + +/** + Detect if the leftmost character in a string is a valid multi-byte character + and return its length, or return 0 otherwise. + @param cs - character set + @param str - the beginning of the string + @param end - the string end (the next byte after the string) + @return >0, for a multi-byte character + @return 0, for a single byte character, broken sequence, empty string. +*/ +static inline +uint my_ismbchar(CHARSET_INFO *cs, const char *str, const char *end) +{ + int char_length= (cs->cset->charlen)(cs, (const uchar *) str, + (const uchar *) end); + return char_length > 1 ? (uint) char_length : 0U; +} + + +/** + Convert broken and incomplete byte sequences to 1 byte. +*/ +static inline +uint my_ci_charlen_fix(CHARSET_INFO *cs, const uchar *str, const uchar *end) +{ + int char_length= my_ci_charlen(cs, str, end); + DBUG_ASSERT(str < end); + return char_length > 0 ? (uint) char_length : (uint) 1U; +} + + +/* + A compatibility replacement pure C function for the former + cs->cset->well_formed_len(). + In C++ code please use Well_formed_prefix::length() instead. +*/ +static inline size_t +my_well_formed_length(CHARSET_INFO *cs, const char *b, const char *e, + size_t nchars, int *error) +{ + MY_STRCOPY_STATUS status; + (void) my_ci_well_formed_char_length(cs, b, e, nchars, &status); + *error= status.m_well_formed_error_pos == NULL ? 0 : 1; + return (size_t) (status.m_source_end_pos - b); +} + + +#define my_caseup_str(s, a) ((s)->cset->caseup_str((s), (a))) +#define my_casedn_str(s, a) ((s)->cset->casedn_str((s), (a))) + +/* XXX: still need to take care of this one */ +#ifdef MY_CHARSET_TIS620 +#error The TIS620 charset is broken at the moment. Tell tim to fix it. +#define USE_TIS620 +#include "t_ctype.h" +#endif + +int my_wc_mb_utf8mb4_bmp_only(CHARSET_INFO *cs, my_wc_t wc, uchar *r, + uchar *e); + +#ifdef __cplusplus +} +#endif + +#endif /* _m_ctype_h */ diff --git a/include/m_string.h b/include/m_string.h new file mode 100644 index 00000000..0360cd38 --- /dev/null +++ b/include/m_string.h @@ -0,0 +1,311 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2019, 2021, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* There may be problems included in all of these. Try to test in + configure which ones are needed? */ + +/* This is needed for the definitions of strchr... on solaris */ + +#ifndef _m_string_h +#define _m_string_h + +#include "my_decimal_limits.h" + +#ifndef __USE_GNU +#define __USE_GNU /* We want to use stpcpy */ +#endif +#if defined(HAVE_STRINGS_H) +#include <strings.h> +#endif +#if defined(HAVE_STRING_H) +#include <string.h> +#endif + +/* This is needed for the definitions of memcpy... on solaris */ +#if defined(HAVE_MEMORY_H) && !defined(__cplusplus) +#include <memory.h> +#endif + +#if !defined(HAVE_MEMCPY) && !defined(HAVE_MEMMOVE) +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memset(A,C,B) bfill((A),(B),(C)) +# define memmove(d, s, n) bmove ((d), (s), (n)) +#elif defined(HAVE_MEMMOVE) +# define bmove(d, s, n) memmove((d), (s), (n)) +#endif + +/* Unixware 7 */ +#if !defined(HAVE_BFILL) +# define bfill(A,B,C) memset((A),(C),(B)) +#endif + +# define bmove_align(A,B,C) memcpy((A),(B),(C)) + +# define bcmp(A,B,C) memcmp((A),(B),(C)) + +#if !defined(bzero) +# define bzero(A,B) memset((A),0,(B)) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifdef DBUG_OFF +#if defined(HAVE_STPCPY) && defined(__GNUC__) && !defined(__INTEL_COMPILER) +#define strmov(A,B) __builtin_stpcpy((A),(B)) +#elif defined(HAVE_STPCPY) +#define strmov(A,B) stpcpy((A),(B)) +#endif +#endif + +/* Declared in int2str() */ +extern const char _dig_vec_upper[]; +extern const char _dig_vec_lower[]; + +extern char *strmov_overlapp(char *dest, const char *src); + +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) +#define LINT_INIT_STRUCT(var) bzero(&var, sizeof(var)) /* No uninitialize-warning */ +#else +#define LINT_INIT_STRUCT(var) +#endif + +/* Prototypes for string functions */ + +extern void bmove_upp(uchar *dst,const uchar *src,size_t len); +extern void bchange(uchar *dst,size_t old_len,const uchar *src, + size_t new_len,size_t tot_len); +extern void strappend(char *s,size_t len,pchar fill); +extern char *strend(const char *s); +extern char *strcend(const char *, pchar); +extern char *strfill(char * s,size_t len,pchar fill); +extern char *strmake(char *dst,const char *src,size_t length); + +#if !defined(__GNUC__) || (__GNUC__ < 4) +#define strmake_buf(D,S) strmake(D, S, sizeof(D) - 1) +#else +#define strmake_buf(D,S) ({ \ + __typeof__ (D) __x __attribute__((unused)) = { 2 }; \ + strmake(D, S, sizeof(D) - 1); \ + }) +#endif + +#ifndef strmov +extern char *strmov(char *dst,const char *src); +#endif +extern char *strnmov(char *dst, const char *src, size_t n); +extern char *strcont(const char *src, const char *set); +extern char *strxmov(char *dst, const char *src, ...); +extern char *strxnmov(char *dst, size_t len, const char *src, ...); + +/* Prototypes of normal stringfunctions (with may ours) */ +#ifndef HAVE_STRNLEN +extern size_t strnlen(const char *s, size_t n); +#endif + +extern int is_prefix(const char *, const char *); + +/* Conversion routines */ +typedef enum { + MY_GCVT_ARG_FLOAT, + MY_GCVT_ARG_DOUBLE +} my_gcvt_arg_type; + +double my_strtod(const char *str, char **end, int *error); +double my_atof(const char *nptr); +size_t my_fcvt(double x, int precision, char *to, my_bool *error); +size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to, + my_bool *error); + +/* + The longest string my_fcvt can return is 311 + "precision" bytes. + Here we assume that we never cal my_fcvt() with + precision >= DECIMAL_NOT_SPECIFIED + (+ 1 byte for the terminating '\0'). +*/ +#define FLOATING_POINT_BUFFER (311 + DECIMAL_NOT_SPECIFIED) + +/* + We want to use the 'e' format in some cases even if we have enough space + for the 'f' one just to mimic sprintf("%.15g") behavior for large integers, + and to improve it for numbers < 10^(-4). + That is, for |x| < 1 we require |x| >= 10^(-15), and for |x| > 1 we require + it to be integer and be <= 10^DBL_DIG for the 'f' format to be used. + We don't lose precision, but make cases like "1e200" or "0.00001" look nicer. +*/ +#define MAX_DECPT_FOR_F_FORMAT DBL_DIG + +/* + The maximum possible field width for my_gcvt() conversion. + (DBL_DIG + 2) significant digits + sign + "." + ("e-NNN" or + MAX_DECPT_FOR_F_FORMAT zeros for cases when |x|<1 and the 'f' format is used). +*/ +#define MY_GCVT_MAX_FIELD_WIDTH (DBL_DIG + 4 + MY_MAX(5, MAX_DECPT_FOR_F_FORMAT)) \ + +extern char *llstr(longlong value,char *buff); +extern char *ullstr(longlong value,char *buff); +#ifndef HAVE_STRTOUL +extern long strtol(const char *str, char **ptr, int base); +extern ulong strtoul(const char *str, char **ptr, int base); +#endif + +extern char *int2str(long val, char *dst, int radix, int upcase); +extern char *int10_to_str(long val,char *dst,int radix); +extern char *str2int(const char *src,int radix,long lower,long upper, + long *val); +longlong my_strtoll10(const char *nptr, char **endptr, int *error); +#if SIZEOF_LONG == SIZEOF_LONG_LONG +#define ll2str(A,B,C,D) int2str((A),(B),(C),(D)) +#define longlong10_to_str(A,B,C) int10_to_str((A),(B),(C)) +#undef strtoll +#define strtoll(A,B,C) strtol((A),(B),(C)) +#define strtoull(A,B,C) strtoul((A),(B),(C)) +#ifndef HAVE_STRTOULL +#define HAVE_STRTOULL +#endif +#ifndef HAVE_STRTOLL +#define HAVE_STRTOLL +#endif +#else +#ifdef HAVE_LONG_LONG +extern char *ll2str(longlong val,char *dst,int radix, int upcase); +extern char *longlong10_to_str(longlong val,char *dst,int radix); +#if (!defined(HAVE_STRTOULL) || defined(NO_STRTOLL_PROTO)) +extern longlong strtoll(const char *str, char **ptr, int base); +extern ulonglong strtoull(const char *str, char **ptr, int base); +#endif +#endif +#endif +#define longlong2str(A,B,C) ll2str((A),(B),(C),1) + +#if defined(__cplusplus) +} +#endif + +#include <mysql/plugin.h> + +#ifdef __cplusplus +#include <type_traits> +template<typename T> inline constexpr const char *_swl_check(T s) +{ + static_assert(std::is_same<T, const char (&)[sizeof(T)]>::value + || std::is_same<T, const char [sizeof(T)]>::value, + "Wrong argument for STRING_WITH_LEN()"); + return s; +} +#define STRING_WITH_LEN(X) _swl_check<decltype(X)>(X), ((size_t) (sizeof(X) - 1)) +#else +#define STRING_WITH_LEN(X) (X ""), ((size_t) (sizeof(X) - 1)) +#endif + +#define USTRING_WITH_LEN(X) (uchar*) STRING_WITH_LEN(X) +#define C_STRING_WITH_LEN(X) (char *) STRING_WITH_LEN(X) +#define LEX_STRING_WITH_LEN(X) (X).str, (X).length + +typedef struct st_mysql_const_lex_string LEX_CSTRING; + +/* A variant with const and unsigned */ +struct st_mysql_const_unsigned_lex_string +{ + const uchar *str; + size_t length; +}; +typedef struct st_mysql_const_unsigned_lex_string LEX_CUSTRING; + +static inline void lex_string_set(LEX_CSTRING *lex_str, const char *c_str) +{ + lex_str->str= c_str; + lex_str->length= strlen(c_str); +} +static inline void lex_string_set3(LEX_CSTRING *lex_str, const char *c_str, + size_t len) +{ + lex_str->str= c_str; + lex_str->length= len; +} + +/* + Copies src into dst and ensures dst is a NULL terminated C string. + + Returns 1 if the src string was truncated due to too small size of dst. + Returns 0 if src completely fit within dst. Pads the remaining dst with '\0' + + Note: dst_size must be > 0 +*/ +static inline int safe_strcpy(char *dst, size_t dst_size, const char *src) +{ + DBUG_ASSERT(dst_size > 0); + + /* 1) IF there is a 0 byte in the first dst_size bytes of src, strncpy will + * 0-terminate dst, and pad dst with additional 0 bytes out to dst_size. + * + * 2) IF there is no 0 byte in the first dst_size bytes of src, strncpy will + * copy dst_size bytes, and the final byte won't be 0. + * + * In GCC 8+, the `-Wstringop-truncation` warning will object to strncpy() + * being used in this way, so we need to disable this warning for this + * single statement. + */ + +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" +#endif + strncpy(dst, src, dst_size); +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic pop +#endif + + if (dst[dst_size-1]) + { + /* Only possible in case (2), meaning src was truncated. */ + dst[dst_size-1]= 0; + return 1; + } + return 0; +} + +/* + Appends src to dst and ensures dst is a NULL terminated C string. + + Returns 1 if the src string was truncated due to too small size of dst. + Returns 0 if src completely fit within the remaining dst space. Pads the + remaining dst with '\0'. + + Note: dst_size must be > 0 +*/ +static inline int safe_strcat(char *dst, size_t dst_size, const char *src) +{ + size_t init_len= strlen(dst); + if (init_len >= dst_size - 1) + return 1; + return safe_strcpy(dst + init_len, dst_size - init_len, src); +} + +#ifdef __cplusplus +static inline char *safe_str(char *str) +{ return str ? str : const_cast<char*>(""); } +#endif + +static inline const char *safe_str(const char *str) +{ return str ? str : ""; } + +static inline size_t safe_strlen(const char *str) +{ return str ? strlen(str) : 0; } + +#endif diff --git a/include/ma_dyncol.h b/include/ma_dyncol.h new file mode 100644 index 00000000..f697c907 --- /dev/null +++ b/include/ma_dyncol.h @@ -0,0 +1,251 @@ +/* Copyright (c) 2011, Monty Program Ab + Copyright (c) 2011, Oleksandr Byelkin + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#ifndef ma_dyncol_h +#define ma_dyncol_h +#ifdef __cplusplus +extern "C" { +#endif + +#include <decimal.h> +#include <my_decimal_limits.h> +#include <mysql_time.h> + +#ifndef _my_sys_h +typedef struct st_dynamic_string +{ + char *str; + size_t length,max_length,alloc_increment; +} DYNAMIC_STRING; +#endif + +#ifndef MY_GLOBAL_INCLUDED +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +typedef struct st_mysql_lex_string LEX_STRING; +#endif + +/* + Limits of implementation +*/ +#define MAX_TOTAL_NAME_LENGTH 65535 +#define MAX_NAME_LENGTH (MAX_TOTAL_NAME_LENGTH/4) + +/* NO and OK is the same used just to show semantics */ +#define ER_DYNCOL_NO ER_DYNCOL_OK + +#ifdef HAVE_CHARSET_utf8mb4 +#define DYNCOL_UTF (&my_charset_utf8mb4_general_ci) +#else +#define DYNCOL_UTF (&my_charset_utf8mb3_general_ci) +#endif + +/* escape json strings */ +#define DYNCOL_JSON_ESC ((char)1) + +enum enum_dyncol_func_result +{ + ER_DYNCOL_OK= 0, + ER_DYNCOL_YES= 1, /* For functions returning 0/1 */ + ER_DYNCOL_FORMAT= -1, /* Wrong format of the encoded string */ + ER_DYNCOL_LIMIT= -2, /* Some limit reached */ + ER_DYNCOL_RESOURCE= -3, /* Out of resources */ + ER_DYNCOL_DATA= -4, /* Incorrect input data */ + ER_DYNCOL_UNKNOWN_CHARSET= -5, /* Unknown character set */ + ER_DYNCOL_TRUNCATED= 2 /* OK, but data was truncated */ +}; + +typedef DYNAMIC_STRING DYNAMIC_COLUMN; + +enum enum_dynamic_column_type +{ + DYN_COL_NULL= 0, + DYN_COL_INT, + DYN_COL_UINT, + DYN_COL_DOUBLE, + DYN_COL_STRING, + DYN_COL_DECIMAL, + DYN_COL_DATETIME, + DYN_COL_DATE, + DYN_COL_TIME, + DYN_COL_DYNCOL +}; + +typedef enum enum_dynamic_column_type DYNAMIC_COLUMN_TYPE; + +struct st_dynamic_column_value +{ + DYNAMIC_COLUMN_TYPE type; + union + { + long long long_value; + unsigned long long ulong_value; + double double_value; + struct { + MYSQL_LEX_STRING value; + CHARSET_INFO *charset; + } string; + struct { + decimal_digit_t buffer[DECIMAL_BUFF_LENGTH]; + decimal_t value; + } decimal; + MYSQL_TIME time_value; + } x; +}; + +typedef struct st_dynamic_column_value DYNAMIC_COLUMN_VALUE; + +#ifdef MADYNCOL_DEPRECATED +enum enum_dyncol_func_result +dynamic_column_create(DYNAMIC_COLUMN *str, + uint column_nr, DYNAMIC_COLUMN_VALUE *value); + +enum enum_dyncol_func_result +dynamic_column_create_many(DYNAMIC_COLUMN *str, + uint column_count, + uint *column_numbers, + DYNAMIC_COLUMN_VALUE *values); +enum enum_dyncol_func_result +dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr, + DYNAMIC_COLUMN_VALUE *value); +enum enum_dyncol_func_result +dynamic_column_update_many(DYNAMIC_COLUMN *str, + uint add_column_count, + uint *column_numbers, + DYNAMIC_COLUMN_VALUE *values); + +enum enum_dyncol_func_result +dynamic_column_exists(DYNAMIC_COLUMN *org, uint column_nr); + +enum enum_dyncol_func_result +dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint); + +enum enum_dyncol_func_result +dynamic_column_get(DYNAMIC_COLUMN *org, uint column_nr, + DYNAMIC_COLUMN_VALUE *store_it_here); +#endif + +/* new functions */ +enum enum_dyncol_func_result +mariadb_dyncol_create_many_num(DYNAMIC_COLUMN *str, + uint column_count, + uint *column_numbers, + DYNAMIC_COLUMN_VALUE *values, + my_bool new_string); +enum enum_dyncol_func_result +mariadb_dyncol_create_many_named(DYNAMIC_COLUMN *str, + uint column_count, + MYSQL_LEX_STRING *column_keys, + DYNAMIC_COLUMN_VALUE *values, + my_bool new_string); + + +enum enum_dyncol_func_result +mariadb_dyncol_update_many_num(DYNAMIC_COLUMN *str, + uint add_column_count, + uint *column_keys, + DYNAMIC_COLUMN_VALUE *values); +enum enum_dyncol_func_result +mariadb_dyncol_update_many_named(DYNAMIC_COLUMN *str, + uint add_column_count, + MYSQL_LEX_STRING *column_keys, + DYNAMIC_COLUMN_VALUE *values); + + +enum enum_dyncol_func_result +mariadb_dyncol_exists_num(DYNAMIC_COLUMN *org, uint column_nr); +enum enum_dyncol_func_result +mariadb_dyncol_exists_named(DYNAMIC_COLUMN *str, MYSQL_LEX_STRING *name); + +/* List of not NULL columns */ +enum enum_dyncol_func_result +mariadb_dyncol_list_num(DYNAMIC_COLUMN *str, uint *count, uint **nums); +enum enum_dyncol_func_result +mariadb_dyncol_list_named(DYNAMIC_COLUMN *str, uint *count, + MYSQL_LEX_STRING **names); + +/* + if the column do not exists it is NULL +*/ +enum enum_dyncol_func_result +mariadb_dyncol_get_num(DYNAMIC_COLUMN *org, uint column_nr, + DYNAMIC_COLUMN_VALUE *store_it_here); +enum enum_dyncol_func_result +mariadb_dyncol_get_named(DYNAMIC_COLUMN *str, MYSQL_LEX_STRING *name, + DYNAMIC_COLUMN_VALUE *store_it_here); + +my_bool mariadb_dyncol_has_names(DYNAMIC_COLUMN *str); + +enum enum_dyncol_func_result +mariadb_dyncol_check(DYNAMIC_COLUMN *str); + +enum enum_dyncol_func_result +mariadb_dyncol_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json); + +#define mariadb_dyncol_init(A) memset((A), 0, sizeof(*(A))) +void mariadb_dyncol_free(DYNAMIC_COLUMN *str); + +/* conversion of values to 3 base types */ +enum enum_dyncol_func_result +mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val, + CHARSET_INFO *cs, my_bool quote); +enum enum_dyncol_func_result +mariadb_dyncol_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val); +enum enum_dyncol_func_result +mariadb_dyncol_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val); + + +enum enum_dyncol_func_result +mariadb_dyncol_unpack(DYNAMIC_COLUMN *str, + uint *count, + MYSQL_LEX_STRING **names, DYNAMIC_COLUMN_VALUE **vals); + +void mariadb_dyncol_unpack_free(MYSQL_LEX_STRING *names, + DYNAMIC_COLUMN_VALUE *vals); + +int mariadb_dyncol_column_cmp_named(const MYSQL_LEX_STRING *s1, + const MYSQL_LEX_STRING *s2); + +enum enum_dyncol_func_result +mariadb_dyncol_column_count(DYNAMIC_COLUMN *str, uint *column_count); + +#define mariadb_dyncol_value_init(V) (V)->type= DYN_COL_NULL + +/* + Prepare value for using as decimal +*/ +void mariadb_dyncol_prepare_decimal(DYNAMIC_COLUMN_VALUE *value); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/maria.h b/include/maria.h new file mode 100644 index 00000000..7fdf95f7 --- /dev/null +++ b/include/maria.h @@ -0,0 +1,154 @@ +/* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. + Copyright (c) 2009, 2019, MariaDB Corporation. + + 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; either version 2 of the License, or + (at your option) any later version. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* This file should be included when using maria functions */ + +#ifndef _maria_h +#define _maria_h +#include <my_base.h> +#include <m_ctype.h> +#include "my_compare.h" +#include "ft_global.h" +#include <myisamchk.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MARIA_UNIQUE_HASH_LENGTH 4 +extern my_bool maria_delay_key_write; +uint maria_max_key_length(void); +#define maria_max_key_segments() HA_MAX_KEY_SEG + +struct st_maria_bit_buff; +struct st_maria_page; +struct st_maria_s_param; +struct st_maria_share; +typedef struct st_maria_decode_tree MARIA_DECODE_TREE; +typedef struct st_maria_handler MARIA_HA; +typedef struct st_maria_key MARIA_KEY; +typedef ulonglong MARIA_RECORD_POS; + +typedef struct st_maria_keydef /* Key definition with open & info */ +{ + struct st_maria_share *share; /* Pointer to base (set in open) */ + mysql_rwlock_t root_lock; /* locking of tree */ + uint16 keysegs; /* Number of key-segment */ + uint16 flag; /* NOSAME, PACK_USED */ + + uint8 key_alg; /* BTREE, RTREE */ + uint8 key_nr; /* key number (auto) */ + uint16 block_length; /* Length of keyblock (auto) */ + uint16 underflow_block_length; /* When to execute underflow */ + uint16 keylength; /* Tot length of keyparts (auto) */ + uint16 minlength; /* min length of (packed) key (auto) */ + uint16 maxlength; /* max length of (packed) key (auto) */ + uint16 max_store_length; /* Size to store key + overhead */ + uint32 write_comp_flag; /* compare flag for write key (auto) */ + uint32 version; /* For concurrent read/write */ + uint32 ftkey_nr; /* full-text index number */ + + HA_KEYSEG *seg, *end; + struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */ + int (*bin_search)(const MARIA_KEY *key, const struct st_maria_page *page, + uint32 comp_flag, uchar **ret_pos, uchar *buff, + my_bool *was_last_key); + uint (*get_key)(MARIA_KEY *key, uint page_flag, uint nod_flag, + uchar **page); + uchar *(*skip_key)(MARIA_KEY *key, uint page_flag, uint nod_flag, + uchar *page); + int (*pack_key)(const MARIA_KEY *key, uint nod_flag, + uchar *next_key, uchar *org_key, uchar *prev_key, + struct st_maria_s_param *s_temp); + void (*store_key)(struct st_maria_keydef *keyinfo, uchar *key_pos, + struct st_maria_s_param *s_temp); + my_bool (*ck_insert)(MARIA_HA *inf, MARIA_KEY *key); + my_bool (*ck_delete)(MARIA_HA *inf, MARIA_KEY *klen); + MARIA_KEY *(*make_key)(MARIA_HA *info, MARIA_KEY *int_key, uint keynr, + uchar *key, const uchar *record, + MARIA_RECORD_POS filepos, ulonglong trid); +} MARIA_KEYDEF; + + +typedef struct st_maria_unique_def /* Segment definition of unique */ +{ + uint16 keysegs; /* Number of key-segment */ + uint8 key; /* Mapped to which key */ + uint8 null_are_equal; + HA_KEYSEG *seg, *end; +} MARIA_UNIQUEDEF; + +/* + Note that null markers should always be first in a row ! + When creating a column, one should only specify: + type, length, null_bit and null_pos +*/ + +typedef struct st_maria_columndef /* column information */ +{ + enum en_fieldtype type; + uint32 offset; /* Offset to position in row */ + uint16 length; /* length of field */ + uint16 column_nr; + /* Intern variable (size of total storage area for the row) */ + uint16 fill_length; + uint16 null_pos; /* Position for null marker */ + uint16 empty_pos; /* Position for empty marker */ + uint8 null_bit; /* If column may be NULL */ + /* Intern. Set if column should be zero packed (part of empty_bits) */ + uint8 empty_bit; + +#ifndef NOT_PACKED_DATABASES + void(*unpack)(struct st_maria_columndef *rec, + struct st_maria_bit_buff *buff, + uchar *start, uchar *end); + enum en_fieldtype base_type; + uint space_length_bits, pack_type; + MARIA_DECODE_TREE *huff_tree; +#endif +} MARIA_COLUMNDEF; + + +typedef struct st_maria_create_info +{ + const char *index_file_name, *data_file_name; /* If using symlinks */ + ha_rows max_rows; + ha_rows reloc_rows; + ulonglong auto_increment; + ulonglong data_file_length; + ulonglong key_file_length; + ulong s3_block_size; + /* Size of null bitmap at start of row */ + uint null_bytes; + uint old_options; + uint compression_algorithm; + enum data_file_type org_data_file_type; + uint16 language; + my_bool with_auto_increment, transactional, encrypted; +} MARIA_CREATE_INFO; + +extern int maria_create(const char *name, enum data_file_type record_type, + uint keys, MARIA_KEYDEF *keydef, + uint columns, MARIA_COLUMNDEF *columndef, + uint uniques, MARIA_UNIQUEDEF *uniquedef, + MARIA_CREATE_INFO *create_info, uint flags); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/include/mariadb_capi_rename.h b/include/mariadb_capi_rename.h new file mode 100644 index 00000000..58e16fdc --- /dev/null +++ b/include/mariadb_capi_rename.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2022, MariaDB + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Renaming C API symbols inside server + * client.c defines a number of functions from the C API, that are used in replication, in number of storage engine plugins, mariadb-backup. + * That can cause a problem if a plugin loads libmariadb/libmysql or a library, that has dependency on them. The known case is ODBC driver. + * Thus the header re-names those functions for internal use. + */ + +#ifndef MARIADB_CAPI_RENAME_INCLUDED +#define MARIADB_CAPI_RENAME_INCLUDED + +#if !defined(EMBEDDED_LIBRARY) && !defined(MYSQL_DYNAMIC_PLUGIN) + +#define MARIADB_ADD_PREFIX(_SYMBOL) server_##_SYMBOL +#define mysql_real_connect MARIADB_ADD_PREFIX(mysql_real_connect) +#define mysql_init MARIADB_ADD_PREFIX(mysql_init) +#define mysql_close MARIADB_ADD_PREFIX(mysql_close) +#define mysql_options MARIADB_ADD_PREFIX(mysql_options) +#define mysql_load_plugin MARIADB_ADD_PREFIX(mysql_load_plugin) +#define mysql_load_plugin_v MARIADB_ADD_PREFIX(mysql_load_plugin_v) +#define mysql_client_find_plugin MARIADB_ADD_PREFIX(mysql_client_find_plugin) +#define mysql_real_query MARIADB_ADD_PREFIX(mysql_real_query) +#define mysql_send_query MARIADB_ADD_PREFIX(mysql_send_query) +#define mysql_free_result MARIADB_ADD_PREFIX(mysql_free_result) +#define mysql_get_socket MARIADB_ADD_PREFIX(mysql_get_socket) +#define mysql_set_character_set MARIADB_ADD_PREFIX(mysql_set_character_set) +#define mysql_get_server_version MARIADB_ADD_PREFIX(mysql_get_server_version) +#define mysql_error MARIADB_ADD_PREFIX(mysql_error) +#define mysql_errno MARIADB_ADD_PREFIX(mysql_errno) +#define mysql_num_fields MARIADB_ADD_PREFIX(mysql_num_fields) +#define mysql_num_rows MARIADB_ADD_PREFIX(mysql_num_rows) +#define mysql_options4 MARIADB_ADD_PREFIX(mysql_options4) +#define mysql_fetch_lengths MARIADB_ADD_PREFIX(mysql_fetch_lengths) +#define mysql_fetch_row MARIADB_ADD_PREFIX(mysql_fetch_row) +#define mysql_affected_rows MARIADB_ADD_PREFIX(mysql_affected_rows) +#define mysql_store_result MARIADB_ADD_PREFIX(mysql_store_result) +#define mysql_select_db MARIADB_ADD_PREFIX(mysql_select_db) +#define mysql_get_ssl_cipher MARIADB_ADD_PREFIX(mysql_get_ssl_cipher) +#define mysql_ssl_set MARIADB_ADD_PREFIX(mysql_ssl_set) +#define mysql_client_register_plugin MARIADB_ADD_PREFIX(mysql_client_register_plugin) + +#endif // !EMBEDDED_LIBRARY && !MYSQL_DYNAMIC_PLUGIN + +#endif // !MARIADB_CAPI_RENAME_INCLUDED diff --git a/include/my_alarm.h b/include/my_alarm.h new file mode 100644 index 00000000..652b460c --- /dev/null +++ b/include/my_alarm.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + File to include when we want to use alarm or a loop_counter to display + some information when a program is running +*/ +#ifndef _my_alarm_h +#define _my_alarm_h +#ifdef __cplusplus +extern "C" { +#endif + +extern int volatile my_have_got_alarm; +extern ulong my_time_to_wait_for_lock; + +#if defined(HAVE_ALARM) && !defined(NO_ALARM_LOOP) +#include <signal.h> +#ifdef HAVE_SIGHANDLER_T +#define sig_return sighandler_t +#elif defined(SOLARIS) || defined(__sun) || defined(__APPLE__) || \ + defined(_AIX) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__DragonFly__) +typedef void (*sig_return)(int); /* Returns type from signal */ +#else +typedef void (*sig_return)(void); /* Returns type from signal */ +#endif +#define ALARM_VARIABLES uint alarm_old=0; \ + sig_return alarm_signal=0 +#define ALARM_INIT my_have_got_alarm=0 ; \ + alarm_old=(uint) alarm(MY_HOW_OFTEN_TO_ALARM); \ + alarm_signal=signal(SIGALRM,my_set_alarm_variable); +#define ALARM_END (void) signal(SIGALRM,alarm_signal); \ + (void) alarm(alarm_old); +#define ALARM_TEST my_have_got_alarm +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY +#define ALARM_REINIT (void) alarm(MY_HOW_OFTEN_TO_ALARM); \ + (void) signal(SIGALRM,my_set_alarm_variable);\ + my_have_got_alarm=0; +#else +#define ALARM_REINIT (void) alarm((uint) MY_HOW_OFTEN_TO_ALARM); \ + my_have_got_alarm=0; +#endif /* SIGNAL_HANDLER_RESET_ON_DELIVERY */ +#else +#define ALARM_VARIABLES long alarm_pos=0,alarm_end_pos=MY_HOW_OFTEN_TO_WRITE-1 +#define ALARM_INIT +#define ALARM_END +#define ALARM_TEST (alarm_pos++ >= alarm_end_pos) +#define ALARM_REINIT (alarm_end_pos+=MY_HOW_OFTEN_TO_WRITE) +#endif /* HAVE_ALARM */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/my_alloc.h b/include/my_alloc.h new file mode 100644 index 00000000..caa4be8f --- /dev/null +++ b/include/my_alloc.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2000, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Data structures for mysys/my_alloc.c (root memory allocator) +*/ + +#ifndef _my_alloc_h +#define _my_alloc_h + +#include "mysql/psi/psi_base.h" + +#define ALLOC_MAX_BLOCK_TO_DROP 4096 +#define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_used_mem +{ /* struct for once_alloc (block) */ + struct st_used_mem *next; /* Next block in use */ + size_t left; /* memory left in block */ + size_t size; /* size of block */ +} USED_MEM; + + +typedef struct st_mem_root +{ + USED_MEM *free; /* blocks with free memory in it */ + USED_MEM *used; /* blocks almost without free memory */ + USED_MEM *pre_alloc; /* preallocated block */ + /* if block have less memory it will be put in 'used' list */ + size_t min_malloc; + size_t block_size; /* initial block size */ + unsigned int block_num; /* allocated blocks counter */ + /* + first free block in queue test counter (if it exceed + MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list) + */ + unsigned short first_block_usage; + unsigned short flags; + +#ifdef PROTECT_STATEMENT_MEMROOT + int read_only; +#endif + + void (*error_handler)(void); + + PSI_memory_key psi_key; +} MEM_ROOT; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/my_alloca.h b/include/my_alloca.h new file mode 100644 index 00000000..85fa64e9 --- /dev/null +++ b/include/my_alloca.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2023, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MY_ALLOCA_INCLUDED +#define MY_ALLOCA_INCLUDED + +#ifdef _WIN32 +#include <malloc.h> /*for alloca*/ +/* + MSVC may define "alloca" when compiling in /Ze mode + (with extensions from Microsoft), but otherwise only + the _alloca function is defined: +*/ +#ifndef alloca +#define alloca _alloca +#endif +#else +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif +#endif + +#if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43) +#pragma alloca +#endif /* _AIX */ + +/* + If the GCC/LLVM compiler from the MinGW is used, + alloca may not be defined when using the MSVC CRT: +*/ +#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) && !defined(alloca) +#define alloca __builtin_alloca +#endif /* GNUC */ + +#endif /* MY_ALLOCA_INCLUDED */ diff --git a/include/my_atomic.h b/include/my_atomic.h new file mode 100644 index 00000000..270134a6 --- /dev/null +++ b/include/my_atomic.h @@ -0,0 +1,156 @@ +#ifndef MY_ATOMIC_INCLUDED +#define MY_ATOMIC_INCLUDED + +/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2018, 2022, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + This header defines five atomic operations: + + my_atomic_add#(&var, what) + my_atomic_add#_explicit(&var, what, memory_order) + 'Fetch and Add' + add 'what' to *var, and return the old value of *var + All memory orders are valid. + + my_atomic_fas#(&var, what) + my_atomic_fas#_explicit(&var, what, memory_order) + 'Fetch And Store' + store 'what' in *var, and return the old value of *var + All memory orders are valid. + + my_atomic_cas#(&var, &old, new) + my_atomic_cas#_weak_explicit(&var, &old, new, succ, fail) + my_atomic_cas#_strong_explicit(&var, &old, new, succ, fail) + 'Compare And Swap' + if *var is equal to *old, then store 'new' in *var, and return TRUE + otherwise store *var in *old, and return FALSE + succ - the memory synchronization ordering for the read-modify-write + operation if the comparison succeeds. All memory orders are valid. + fail - the memory synchronization ordering for the load operation if the + comparison fails. Cannot be MY_MEMORY_ORDER_RELEASE or + MY_MEMORY_ORDER_ACQ_REL and cannot specify stronger ordering than succ. + + The weak form is allowed to fail spuriously, that is, act as if *var != *old + even if they are equal. When a compare-and-exchange is in a loop, the weak + version will yield better performance on some platforms. When a weak + compare-and-exchange would require a loop and a strong one would not, the + strong one is preferable. + + my_atomic_load#(&var) + my_atomic_load#_explicit(&var, memory_order) + return *var + Order must be one of MY_MEMORY_ORDER_RELAXED, MY_MEMORY_ORDER_CONSUME, + MY_MEMORY_ORDER_ACQUIRE, MY_MEMORY_ORDER_SEQ_CST. + + my_atomic_store#(&var, what) + my_atomic_store#_explicit(&var, what, memory_order) + store 'what' in *var + Order must be one of MY_MEMORY_ORDER_RELAXED, MY_MEMORY_ORDER_RELEASE, + MY_MEMORY_ORDER_SEQ_CST. + + '#' is substituted by a size suffix - 8, 16, 32, 64, or ptr + (e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr). + + The first version orders memory accesses according to MY_MEMORY_ORDER_SEQ_CST, + the second version (with _explicit suffix) orders memory accesses according to + given memory order. + + memory_order specifies how non-atomic memory accesses are to be ordered around + an atomic operation: + + MY_MEMORY_ORDER_RELAXED - there are no constraints on reordering of memory + accesses around the atomic variable. + MY_MEMORY_ORDER_CONSUME - no reads in the current thread dependent on the + value currently loaded can be reordered before this + load. This ensures that writes to dependent + variables in other threads that release the same + atomic variable are visible in the current thread. + On most platforms, this affects compiler + optimization only. + MY_MEMORY_ORDER_ACQUIRE - no reads in the current thread can be reordered + before this load. This ensures that all writes in + other threads that release the same atomic variable + are visible in the current thread. + MY_MEMORY_ORDER_RELEASE - no writes in the current thread can be reordered + after this store. This ensures that all writes in + the current thread are visible in other threads that + acquire the same atomic variable. + MY_MEMORY_ORDER_ACQ_REL - no reads in the current thread can be reordered + before this load as well as no writes in the current + thread can be reordered after this store. The + operation is read-modify-write operation. It is + ensured that all writes in another threads that + release the same atomic variable are visible before + the modification and the modification is visible in + other threads that acquire the same atomic variable. + MY_MEMORY_ORDER_SEQ_CST - The operation has the same semantics as + acquire-release operation, and additionally has + sequentially-consistent operation ordering. + + We choose implementation as follows: on Windows using Visual C++ the native + implementation should be preferable. When using gcc we prefer the Solaris + implementation before the gcc because of stability preference, we choose gcc + builtins if available. +*/ + +#if defined(_MSC_VER) +#include "atomic/generic-msvc.h" +#elif defined(HAVE_SOLARIS_ATOMIC) +#include "atomic/solaris.h" +#elif defined(HAVE_GCC_C11_ATOMICS) +#include "atomic/gcc_builtins.h" +#endif + +#ifndef MY_MEMORY_ORDER_SEQ_CST +#define MY_MEMORY_ORDER_RELAXED +#define MY_MEMORY_ORDER_CONSUME +#define MY_MEMORY_ORDER_ACQUIRE +#define MY_MEMORY_ORDER_RELEASE +#define MY_MEMORY_ORDER_ACQ_REL +#define MY_MEMORY_ORDER_SEQ_CST + +#define my_atomic_store32_explicit(P, D, O) my_atomic_store32((P), (D)) +#define my_atomic_store64_explicit(P, D, O) my_atomic_store64((P), (D)) +#define my_atomic_storeptr_explicit(P, D, O) my_atomic_storeptr((P), (D)) + +#define my_atomic_load32_explicit(P, O) my_atomic_load32((P)) +#define my_atomic_load64_explicit(P, O) my_atomic_load64((P)) +#define my_atomic_loadptr_explicit(P, O) my_atomic_loadptr((P)) + +#define my_atomic_fas32_explicit(P, D, O) my_atomic_fas32((P), (D)) +#define my_atomic_fas64_explicit(P, D, O) my_atomic_fas64((P), (D)) +#define my_atomic_fasptr_explicit(P, D, O) my_atomic_fasptr((P), (D)) + +#define my_atomic_add32_explicit(P, A, O) my_atomic_add32((P), (A)) +#define my_atomic_add64_explicit(P, A, O) my_atomic_add64((P), (A)) +#define my_atomic_addptr_explicit(P, A, O) my_atomic_addptr((P), (A)) + +#define my_atomic_cas32_weak_explicit(P, E, D, S, F) \ + my_atomic_cas32((P), (E), (D)) +#define my_atomic_cas64_weak_explicit(P, E, D, S, F) \ + my_atomic_cas64((P), (E), (D)) +#define my_atomic_casptr_weak_explicit(P, E, D, S, F) \ + my_atomic_casptr((P), (E), (D)) + +#define my_atomic_cas32_strong_explicit(P, E, D, S, F) \ + my_atomic_cas32((P), (E), (D)) +#define my_atomic_cas64_strong_explicit(P, E, D, S, F) \ + my_atomic_cas64((P), (E), (D)) +#define my_atomic_casptr_strong_explicit(P, E, D, S, F) \ + my_atomic_casptr((P), (E), (D)) +#endif +#endif /* MY_ATOMIC_INCLUDED */ diff --git a/include/my_atomic_wrapper.h b/include/my_atomic_wrapper.h new file mode 100644 index 00000000..7b35b14d --- /dev/null +++ b/include/my_atomic_wrapper.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2020, 2021, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#pragma once +#ifdef __cplusplus +#include <atomic> +/** + A wrapper for std::atomic, defaulting to std::memory_order_relaxed. + + When it comes to atomic loads or stores at std::memory_order_relaxed + on IA-32 or AMD64, this wrapper is only introducing some constraints + to the C++ compiler, to prevent some optimizations of loads or + stores. + + On POWER and ARM, atomic loads and stores involve different instructions + from normal loads and stores and will thus incur some overhead. + + Because atomic read-modify-write operations will always incur + overhead, we intentionally do not define + operator++(), operator--(), operator+=(), operator-=(), or similar, + to make the overhead stand out in the users of this code. +*/ +template <typename Type> class Atomic_relaxed +{ + std::atomic<Type> m; +public: + Atomic_relaxed(const Atomic_relaxed<Type> &rhs) + { m.store(rhs, std::memory_order_relaxed); } + Atomic_relaxed(Type val) : m(val) {} + Atomic_relaxed() = default; + + Type load(std::memory_order o= std::memory_order_relaxed) const + { return m.load(o); } + void store(Type i, std::memory_order o= std::memory_order_relaxed) + { m.store(i, o); } + operator Type() const { return m.load(); } + Type operator=(const Type i) { store(i); return i; } + Type operator=(const Atomic_relaxed<Type> &rhs) { return *this= Type{rhs}; } + Type operator+=(const Type i) { return fetch_add(i); } + Type fetch_add(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_add(i, o); } + Type fetch_sub(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_sub(i, o); } + Type fetch_xor(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_xor(i, o); } + Type fetch_and(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_and(i, o); } + Type fetch_or(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_or(i, o); } + bool compare_exchange_strong(Type& i1, const Type i2, + std::memory_order o1= std::memory_order_relaxed, + std::memory_order o2= std::memory_order_relaxed) + { return m.compare_exchange_strong(i1, i2, o1, o2); } + Type exchange(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.exchange(i, o); } +}; +#endif /* __cplusplus */ diff --git a/include/my_attribute.h b/include/my_attribute.h new file mode 100644 index 00000000..c8e98070 --- /dev/null +++ b/include/my_attribute.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2000, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Helper macros used for setting different __attributes__ + on functions in a portable fashion +*/ + +#ifndef _my_attribute_h +#define _my_attribute_h + +#if defined(__GNUC__) +# ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +# endif +#endif + +/* + Disable __attribute__() on gcc < 2.7, g++ < 3.4, and non-gcc compilers. + Some forms of __attribute__ are actually supported in earlier versions of + g++, but we just disable them all because we only use them to generate + compilation warnings. +*/ +#ifndef __attribute__ +# if !defined(__GNUC__) && !defined(__clang__) +# define __attribute__(A) +# elif defined(__GNUC__) +# ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +# endif +# if GCC_VERSION < 2008 +# define __attribute__(A) +# elif defined(__cplusplus) && GCC_VERSION < 3004 +# define __attribute__(A) +# endif +# endif +#endif + +/* + __attribute__((format(...))) is only supported in gcc >= 2.8 and g++ >= 3.4 + But that's already covered by the __attribute__ tests above, so this is + just a convenience macro. +*/ +#ifndef ATTRIBUTE_FORMAT +# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) +#endif + +/* + + __attribute__((format(...))) on a function pointer is not supported + until gcc 3.1 +*/ +#ifndef ATTRIBUTE_FORMAT_FPTR +# if (GCC_VERSION >= 3001) +# define ATTRIBUTE_FORMAT_FPTR(style, m, n) ATTRIBUTE_FORMAT(style, m, n) +# else +# define ATTRIBUTE_FORMAT_FPTR(style, m, n) +# endif /* GNUC >= 3.1 */ +#endif + + +#endif diff --git a/include/my_base.h b/include/my_base.h new file mode 100644 index 00000000..9a5a4e94 --- /dev/null +++ b/include/my_base.h @@ -0,0 +1,686 @@ +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 1995, 2021, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + + +/* This file includes constants used with all databases */ + +#ifndef _my_base_h +#define _my_base_h + +#include <my_dir.h> /* This includes types */ +#include <my_sys.h> +#include <m_string.h> +#include <errno.h> + +#ifndef EOVERFLOW +#define EOVERFLOW 84 +#endif + +#include <my_list.h> + +/* The following is bits in the flag parameter to ha_open() */ + +#define HA_OPEN_ABORT_IF_LOCKED 0U /* default */ +#define HA_OPEN_WAIT_IF_LOCKED 1U +#define HA_OPEN_IGNORE_IF_LOCKED 2U /* Ignore lock error */ +#define HA_OPEN_TMP_TABLE 4U /* Table is a temp table */ +#define HA_OPEN_DELAY_KEY_WRITE 8U /* Don't update index */ +#define HA_OPEN_ABORT_IF_CRASHED 16U +#define HA_OPEN_FOR_REPAIR 32U /* open even if crashed */ +#define HA_OPEN_FROM_SQL_LAYER 64U +#define HA_OPEN_MMAP 128U /* open memory mapped */ +#define HA_OPEN_COPY 256U /* Open copy (for repair) */ +/* Internal temp table, used for temporary results */ +#define HA_OPEN_INTERNAL_TABLE 512U +#define HA_OPEN_NO_PSI_CALL 1024U /* Don't call/connect PSI */ +#define HA_OPEN_MERGE_TABLE 2048U +#define HA_OPEN_FOR_CREATE 4096U +#define HA_OPEN_FOR_DROP (1U << 13) /* Open part of drop */ + +/* + Allow opening even if table is incompatible as this is for ALTER TABLE which + will fix the table structure. +*/ +#define HA_OPEN_FOR_ALTER 8192U + +/* Open table for FLUSH */ +#define HA_OPEN_FOR_FLUSH 8192U + + +/* The following is parameter to ha_rkey() how to use key */ + +/* + We define a complete-field prefix of a key value as a prefix where + the last included field in the prefix contains the full field, not + just some bytes from the start of the field. A partial-field prefix + is allowed to contain only a few first bytes from the last included + field. + + Below HA_READ_KEY_EXACT, ..., HA_READ_BEFORE_KEY can take a + complete-field prefix of a key value as the search + key. HA_READ_PREFIX and HA_READ_PREFIX_LAST could also take a + partial-field prefix, but currently (4.0.10) they are only used with + complete-field prefixes. MySQL uses a padding trick to implement + LIKE 'abc%' queries. + + NOTE that in InnoDB HA_READ_PREFIX_LAST will NOT work with a + partial-field prefix because InnoDB currently strips spaces from the + end of varchar fields! +*/ + +enum ha_rkey_function { + HA_READ_KEY_EXACT, /* Find first record else error */ + HA_READ_KEY_OR_NEXT, /* Record or next record */ + HA_READ_KEY_OR_PREV, /* Record or previous */ + HA_READ_AFTER_KEY, /* Find next rec. after key-record */ + HA_READ_BEFORE_KEY, /* Find next rec. before key-record */ + HA_READ_PREFIX, /* Key which as same prefix */ + HA_READ_PREFIX_LAST, /* Last key with the same prefix */ + HA_READ_PREFIX_LAST_OR_PREV, /* Last or prev key with the same prefix */ + HA_READ_MBR_CONTAIN, + HA_READ_MBR_INTERSECT, + HA_READ_MBR_WITHIN, + HA_READ_MBR_DISJOINT, + HA_READ_MBR_EQUAL +}; + + /* Key algorithm types */ + +enum ha_key_alg { + HA_KEY_ALG_UNDEF= 0, /* Not specified (old file) */ + HA_KEY_ALG_BTREE= 1, /* B-tree, default one */ + HA_KEY_ALG_RTREE= 2, /* R-tree, for spatial searches */ + HA_KEY_ALG_HASH= 3, /* HASH keys (HEAP tables) */ + HA_KEY_ALG_FULLTEXT= 4, /* FULLTEXT (MyISAM tables) */ + HA_KEY_ALG_LONG_HASH= 5 /* long BLOB keys */ +}; + + /* Storage media types */ + +enum ha_storage_media { + HA_SM_DEFAULT= 0, /* Not specified (engine default) */ + HA_SM_DISK= 1, /* DISK storage */ + HA_SM_MEMORY= 2 /* MAIN MEMORY storage */ +}; + + /* The following is parameter to ha_extra() */ + +enum ha_extra_function { + HA_EXTRA_NORMAL=0, /* Optimize for space (def) */ + HA_EXTRA_QUICK=1, /* Optimize for speed */ + HA_EXTRA_NOT_USED=2, /* Should be ignored by handler */ + HA_EXTRA_CACHE=3, /* Cache record in HA_rrnd() */ + HA_EXTRA_NO_CACHE=4, /* End caching of records (def) */ + HA_EXTRA_NO_READCHECK=5, /* No readcheck on update */ + HA_EXTRA_READCHECK=6, /* Use readcheck (def) */ + HA_EXTRA_KEYREAD=7, /* Read only key to database */ + HA_EXTRA_NO_KEYREAD=8, /* Normal read of records (def) */ + HA_EXTRA_NO_USER_CHANGE=9, /* No user is allowed to write */ + HA_EXTRA_KEY_CACHE=10, + HA_EXTRA_NO_KEY_CACHE=11, + HA_EXTRA_WAIT_LOCK=12, /* Wait until file is available (def) */ + HA_EXTRA_NO_WAIT_LOCK=13, /* If file is locked, return quickly */ + HA_EXTRA_WRITE_CACHE=14, /* Use write cache in ha_write() */ + HA_EXTRA_FLUSH_CACHE=15, /* flush write_record_cache */ + HA_EXTRA_NO_KEYS=16, /* Remove all update of keys */ + HA_EXTRA_KEYREAD_CHANGE_POS=17, /* Keyread, but change pos */ + /* xxxxchk -r must be used */ + HA_EXTRA_REMEMBER_POS=18, /* Remember pos for next/prev */ + HA_EXTRA_RESTORE_POS=19, + HA_EXTRA_REINIT_CACHE=20, /* init cache from current record */ + HA_EXTRA_FORCE_REOPEN=21, /* Datafile have changed on disk */ + HA_EXTRA_FLUSH, /* Flush tables to disk */ + HA_EXTRA_NO_ROWS, /* Don't write rows */ + HA_EXTRA_RESET_STATE, /* Reset positions */ + HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/ + HA_EXTRA_NO_IGNORE_DUP_KEY, + HA_EXTRA_PREPARE_FOR_DROP, + HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */ + HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */ + /* + On-the-fly switching between unique and non-unique key inserting. + */ + HA_EXTRA_CHANGE_KEY_TO_UNIQUE, + HA_EXTRA_CHANGE_KEY_TO_DUP, + /* + When using HA_EXTRA_KEYREAD, overwrite only key member fields and keep + other fields intact. When this is off (by default) InnoDB will use memcpy + to overwrite entire row. + */ + HA_EXTRA_KEYREAD_PRESERVE_FIELDS, + HA_EXTRA_MMAP, + /* + Ignore if the a tuple is not found, continue processing the + transaction and ignore that 'row'. Needed for idempotency + handling on the slave + */ + HA_EXTRA_IGNORE_NO_KEY, + HA_EXTRA_NO_IGNORE_NO_KEY, + /* + Mark the table as a log table. For some handlers (e.g. CSV) this results + in a special locking for the table. + */ + HA_EXTRA_MARK_AS_LOG_TABLE, + /* + Informs handler that write_row() which tries to insert new row into the + table and encounters some already existing row with same primary/unique + key can replace old row with new row instead of reporting error (basically + it informs handler that we do REPLACE instead of simple INSERT). + Off by default. + */ + HA_EXTRA_WRITE_CAN_REPLACE, + HA_EXTRA_WRITE_CANNOT_REPLACE, + /* + Inform handler that delete_row()/update_row() cannot batch deletes/updates + and should perform them immediately. This may be needed when table has + AFTER DELETE/UPDATE triggers which access to subject table. + These flags are reset by the handler::extra(HA_EXTRA_RESET) call. + */ + HA_EXTRA_DELETE_CANNOT_BATCH, + HA_EXTRA_UPDATE_CANNOT_BATCH, + /* + Inform handler that an "INSERT...ON DUPLICATE KEY UPDATE" will be + executed. This condition is unset by HA_EXTRA_NO_IGNORE_DUP_KEY. + */ + HA_EXTRA_INSERT_WITH_UPDATE, + /* Inform handler that we will do a rename */ + HA_EXTRA_PREPARE_FOR_RENAME, + /* + Special actions for MERGE tables. + */ + HA_EXTRA_ADD_CHILDREN_LIST, + HA_EXTRA_ATTACH_CHILDREN, + HA_EXTRA_IS_ATTACHED_CHILDREN, + HA_EXTRA_DETACH_CHILDREN, + HA_EXTRA_DETACH_CHILD, + /* Inform handler we will force a close as part of flush */ + HA_EXTRA_PREPARE_FOR_FORCED_CLOSE, + /* Inform handler that we will do an alter table */ + HA_EXTRA_PREPARE_FOR_ALTER_TABLE, + /* + Used in ha_partition::handle_ordered_index_scan() to inform engine + that we are starting an ordered index scan. Needed by Spider + */ + HA_EXTRA_STARTING_ORDERED_INDEX_SCAN, + /** Start writing rows during ALTER TABLE...ALGORITHM=COPY. */ + HA_EXTRA_BEGIN_ALTER_COPY, + /** Finish writing rows during ALTER TABLE...ALGORITHM=COPY. */ + HA_EXTRA_END_ALTER_COPY +}; + +/* Compatible option, to be deleted in 6.0 */ +#define HA_EXTRA_PREPARE_FOR_DELETE HA_EXTRA_PREPARE_FOR_DROP + + /* The following is parameter to ha_panic() */ + +enum ha_panic_function { + HA_PANIC_CLOSE, /* Close all databases */ + HA_PANIC_WRITE, /* Unlock and write status */ + HA_PANIC_READ /* Lock and read keyinfo */ +}; + + /* The following is parameter to ha_create(); keytypes */ + +enum ha_base_keytype { + HA_KEYTYPE_END=0, + HA_KEYTYPE_TEXT=1, /* Key is sorted as letters */ + HA_KEYTYPE_BINARY=2, /* Key is sorted as unsigned chars */ + HA_KEYTYPE_SHORT_INT=3, + HA_KEYTYPE_LONG_INT=4, + HA_KEYTYPE_FLOAT=5, + HA_KEYTYPE_DOUBLE=6, + HA_KEYTYPE_NUM=7, /* Not packed num with pre-space */ + HA_KEYTYPE_USHORT_INT=8, + HA_KEYTYPE_ULONG_INT=9, + HA_KEYTYPE_LONGLONG=10, + HA_KEYTYPE_ULONGLONG=11, + HA_KEYTYPE_INT24=12, + HA_KEYTYPE_UINT24=13, + HA_KEYTYPE_INT8=14, + /* Varchar (0-255 bytes) with length packed with 1 byte */ + HA_KEYTYPE_VARTEXT1=15, /* Key is sorted as letters */ + HA_KEYTYPE_VARBINARY1=16, /* Key is sorted as unsigned chars */ + /* Varchar (0-65535 bytes) with length packed with 2 bytes */ + HA_KEYTYPE_VARTEXT2=17, /* Key is sorted as letters */ + HA_KEYTYPE_VARBINARY2=18, /* Key is sorted as unsigned chars */ + HA_KEYTYPE_BIT=19 +}; + +#define HA_MAX_KEYTYPE 31 /* Must be log2-1 */ + +/* + These flags kan be OR:ed to key-flag + Note that these can only be up to 16 bits! +*/ + +#define HA_NOSAME 1U /* Set if not dupplicated records */ +#define HA_PACK_KEY 2U /* Pack string key to previous key */ +#define HA_AUTO_KEY 16U /* MEMORY/MyISAM/Aria internal */ +#define HA_BINARY_PACK_KEY 32U /* Packing of all keys to prev key */ +#define HA_FULLTEXT 128U /* For full-text search */ +#define HA_SPATIAL 1024U /* For spatial search */ +#define HA_NULL_ARE_EQUAL 2048U /* NULL in key are cmp as equal */ +#define HA_GENERATED_KEY 8192U /* Automatically generated key */ + + /* The combination of the above can be used for key type comparison. */ +#define HA_KEYFLAG_MASK (HA_NOSAME | HA_AUTO_KEY | HA_FULLTEXT | \ + HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY) + +/* + Key contains partial segments. + + This flag is internal to the MySQL server by design. It is not supposed + neither to be saved in FRM-files, nor to be passed to storage engines. + It is intended to pass information into internal static sort_keys(KEY *, + KEY *) function. + + This flag can be calculated -- it's based on key lengths comparison. +*/ +#define HA_KEY_HAS_PART_KEY_SEG 65536 +/* Internal Flag Can be calculated */ +#define HA_INVISIBLE_KEY 2<<18 + /* Automatic bits in key-flag */ + +#define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ +#define HA_VAR_LENGTH_KEY 8 +#define HA_NULL_PART_KEY 64 +#define HA_USES_COMMENT 4096 +#define HA_USES_PARSER 16384 /* Fulltext index uses [pre]parser */ +#define HA_USES_BLOCK_SIZE ((uint) 32768) +#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */ + +/* This flag can be used only in KEY::ext_key_flags */ +#define HA_EXT_NOSAME 131072 + + /* These flags can be added to key-seg-flag */ + +#define HA_SPACE_PACK 1 /* Pack space in key-seg */ +#define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */ +#define HA_VAR_LENGTH_PART 8 +#define HA_NULL_PART 16 +#define HA_BLOB_PART 32 +#define HA_SWAP_KEY 64 +#define HA_REVERSE_SORT 128 /* Sort key in reverse order */ +#define HA_NO_SORT 256 /* do not bother sorting on this keyseg */ + +#define HA_BIT_PART 1024 +#define HA_CAN_MEMCMP 2048 /* internal, never stored in frm */ + + /* optionbits for database */ +#define HA_OPTION_PACK_RECORD 1U +#define HA_OPTION_PACK_KEYS 2U +#define HA_OPTION_COMPRESS_RECORD 4U +#define HA_OPTION_LONG_BLOB_PTR 8U /* new ISAM format */ +#define HA_OPTION_TMP_TABLE 16U +#define HA_OPTION_CHECKSUM 32U +#define HA_OPTION_DELAY_KEY_WRITE 64U +#define HA_OPTION_NO_PACK_KEYS 128U /* Reserved for MySQL */ +/* unused 256 */ +#define HA_OPTION_RELIES_ON_SQL_LAYER 512U +#define HA_OPTION_NULL_FIELDS 1024U +#define HA_OPTION_PAGE_CHECKSUM 2048U +/* + STATS_PERSISTENT=1 has been specified in the SQL command (either CREATE + or ALTER TABLE). Table and index statistics that are collected by the + storage engine and used by the optimizer for query optimization will be + stored on disk and will not change after a server restart. +*/ +#define HA_OPTION_STATS_PERSISTENT 4096U +/* + STATS_PERSISTENT=0 has been specified in CREATE/ALTER TABLE. Statistics + for the table will be wiped away on server shutdown and new ones recalculated + after the server is started again. If none of HA_OPTION_STATS_PERSISTENT or + HA_OPTION_NO_STATS_PERSISTENT is set, this means that the setting is not + explicitly set at table level and the corresponding table will use whatever + is the global server default. +*/ +#define HA_OPTION_NO_STATS_PERSISTENT 8192U + +/* .frm has extra create options in linked-list format */ +#define HA_OPTION_TEXT_CREATE_OPTIONS_legacy (1U << 14) /* 5.2 to 5.5, unused since 10.0 */ +#define HA_OPTION_TEMP_COMPRESS_RECORD (1U << 15) /* set by isamchk */ +#define HA_OPTION_READ_ONLY_DATA (1U << 16) /* Set by isamchk */ +#define HA_OPTION_NO_CHECKSUM (1U << 17) +#define HA_OPTION_NO_DELAY_KEY_WRITE (1U << 18) + + /* Bits in flag to create() */ + +#define HA_DONT_TOUCH_DATA 1U /* Don't empty datafile (isamchk) */ +#define HA_PACK_RECORD 2U /* Request packed record format */ +#define HA_CREATE_TMP_TABLE 4U +#define HA_CREATE_CHECKSUM 8U +#define HA_CREATE_KEEP_FILES 16U /* don't overwrite .MYD and MYI */ +#define HA_CREATE_PAGE_CHECKSUM 32U +#define HA_CREATE_DELAY_KEY_WRITE 64U +#define HA_CREATE_RELIES_ON_SQL_LAYER 128U +#define HA_CREATE_INTERNAL_TABLE 256U +#define HA_PRESERVE_INSERT_ORDER 512U +#define HA_CREATE_NO_ROLLBACK 1024U + +/* Flags used by start_bulk_insert */ + +#define HA_CREATE_UNIQUE_INDEX_BY_SORT 1U + + +/* + The following flags (OR-ed) are passed to handler::info() method. + The method copies misc handler information out of the storage engine + to data structures accessible from MySQL + + Same flags are also passed down to mi_status, myrg_status, etc. +*/ + +/* this one is not used */ +#define HA_STATUS_POS 1U +/* + assuming the table keeps shared actual copy of the 'info' and + local, possibly outdated copy, the following flag means that + it should not try to get the actual data (locking the shared structure) + slightly outdated version will suffice +*/ +#define HA_STATUS_NO_LOCK 2U +/* update the time of the last modification (in handler::update_time) */ +#define HA_STATUS_TIME 4U +/* + update the 'constant' part of the info: + handler::max_data_file_length, max_index_file_length, create_time + sortkey, ref_length, block_size, data_file_name, index_file_name. + handler::table->s->keys_in_use, keys_for_keyread, rec_per_key +*/ +#define HA_STATUS_CONST 8U +/* + update the 'variable' part of the info: + handler::records, deleted, data_file_length, index_file_length, + check_time, mean_rec_length +*/ +#define HA_STATUS_VARIABLE 16U +/* + get the information about the key that caused last duplicate value error + update handler::errkey and handler::dupp_ref + see handler::get_dup_key() +*/ +#define HA_STATUS_ERRKEY 32U +/* + update handler::auto_increment_value +*/ +#define HA_STATUS_AUTO 64U +/* + Get also delete_length when HA_STATUS_VARIABLE is called. It's ok to set it also + when only HA_STATUS_VARIABLE but it won't be used. +*/ +#define HA_STATUS_VARIABLE_EXTRA 128U +/* + Treat empty table as empty (ignore HA_STATUS_TIME hack). +*/ +#define HA_STATUS_OPEN 256U + +/* + Errorcodes given by handler functions + + opt_sum_query() assumes these codes are > 1 + Do not add error numbers before HA_ERR_FIRST. + If necessary to add lower numbers, change HA_ERR_FIRST accordingly. +*/ +#define HA_ERR_FIRST 120 /* Copy of first error nr.*/ + +#define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */ +#define HA_ERR_FOUND_DUPP_KEY 121 /* Duplicate key on write */ +#define HA_ERR_INTERNAL_ERROR 122 /* Internal error */ +#define HA_ERR_RECORD_CHANGED 123 /* Update with is recoverable */ +#define HA_ERR_WRONG_INDEX 124 /* Wrong index given to function */ +#define HA_ERR_CRASHED 126 /* Indexfile is crashed */ +#define HA_ERR_WRONG_IN_RECORD 127 /* Record-file is crashed */ +#define HA_ERR_OUT_OF_MEM 128 /* Out of memory */ +#define HA_ERR_RETRY_INIT 129 /* Initialization failed and should be retried */ +#define HA_ERR_NOT_A_TABLE 130 /* not a MYI file - no signature */ +#define HA_ERR_WRONG_COMMAND 131 /* Command not supported */ +#define HA_ERR_OLD_FILE 132 /* old databasfile */ +#define HA_ERR_NO_ACTIVE_RECORD 133 /* No record read in update() */ +#define HA_ERR_RECORD_DELETED 134 /* A record is not there */ +#define HA_ERR_RECORD_FILE_FULL 135 /* No more room in file */ +#define HA_ERR_INDEX_FILE_FULL 136 /* No more room in file */ +#define HA_ERR_END_OF_FILE 137 /* end in next/prev/first/last */ +#define HA_ERR_UNSUPPORTED 138 /* unsupported extension used */ +#define HA_ERR_TO_BIG_ROW 139 /* Too big row */ +#define HA_WRONG_CREATE_OPTION 140 /* Wrong create option */ +#define HA_ERR_FOUND_DUPP_UNIQUE 141 /* Duplicate unique on write */ +#define HA_ERR_UNKNOWN_CHARSET 142 /* Can't open charset */ +#define HA_ERR_WRONG_MRG_TABLE_DEF 143 /* conflicting tables in MERGE */ +#define HA_ERR_CRASHED_ON_REPAIR 144 /* Last (automatic?) repair failed */ +#define HA_ERR_CRASHED_ON_USAGE 145 /* Table must be repaired */ +#define HA_ERR_LOCK_WAIT_TIMEOUT 146 +#define HA_ERR_LOCK_TABLE_FULL 147 +#define HA_ERR_READ_ONLY_TRANSACTION 148 /* Updates not allowed */ +#define HA_ERR_LOCK_DEADLOCK 149 +#define HA_ERR_CANNOT_ADD_FOREIGN 150 /* Cannot add a foreign key constr. */ +#define HA_ERR_NO_REFERENCED_ROW 151 /* Cannot add a child row */ +#define HA_ERR_ROW_IS_REFERENCED 152 /* Cannot delete a parent row */ +#define HA_ERR_NO_SAVEPOINT 153 /* No savepoint with that name */ +#define HA_ERR_NON_UNIQUE_BLOCK_SIZE 154 /* Non unique key block size */ +#define HA_ERR_NO_SUCH_TABLE 155 /* The table does not exist in engine */ +#define HA_ERR_TABLE_EXIST 156 /* The table existed in storage engine */ +#define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */ +/* NULLs are not supported in spatial index */ +#define HA_ERR_NULL_IN_SPATIAL 158 +#define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ +/* There's no partition in table for given value */ +#define HA_ERR_NO_PARTITION_FOUND 160 +#define HA_ERR_RBR_LOGGING_FAILED 161 /* Row-based binlogging of row failed */ +#define HA_ERR_DROP_INDEX_FK 162 /* Index needed in foreign key constr */ +/* + Upholding foreign key constraints would lead to a duplicate key error + in some other table. +*/ +#define HA_ERR_FOREIGN_DUPLICATE_KEY 163 +/* The table changed in storage engine */ +#define HA_ERR_TABLE_NEEDS_UPGRADE 164 +#define HA_ERR_TABLE_READONLY 165 /* The table is not writable */ + +#define HA_ERR_AUTOINC_READ_FAILED 166 /* Failed to get next autoinc value */ +#define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set row autoinc value */ +#define HA_ERR_GENERIC 168 /* Generic error */ +/* row not actually updated: new values same as the old values */ +#define HA_ERR_RECORD_IS_THE_SAME 169 +#define HA_ERR_LOGGING_IMPOSSIBLE 170 /* It is not possible to log this + statement */ +#define HA_ERR_CORRUPT_EVENT 171 /* The event was corrupt, leading to + illegal data being read */ +#define HA_ERR_NEW_FILE 172 /* New file format */ +#define HA_ERR_ROWS_EVENT_APPLY 173 /* The event could not be processed + no other handler error happened */ +#define HA_ERR_INITIALIZATION 174 /* Error during initialization */ +#define HA_ERR_FILE_TOO_SHORT 175 /* File too short */ +#define HA_ERR_WRONG_CRC 176 /* Wrong CRC on page */ +#define HA_ERR_TOO_MANY_CONCURRENT_TRXS 177 /*Too many active concurrent transactions */ +/* There's no explicitly listed partition in table for the given value */ +#define HA_ERR_NOT_IN_LOCK_PARTITIONS 178 +#define HA_ERR_INDEX_COL_TOO_LONG 179 /* Index column length exceeds limit */ +#define HA_ERR_INDEX_CORRUPT 180 /* Index corrupted */ +#define HA_ERR_UNDO_REC_TOO_BIG 181 /* Undo log record too big */ +#define HA_FTS_INVALID_DOCID 182 /* Invalid InnoDB Doc ID */ +/* #define HA_ERR_TABLE_IN_FK_CHECK 183 */ /* Table being used in foreign key check */ +#define HA_ERR_TABLESPACE_EXISTS 184 /* The tablespace existed in storage engine */ +#define HA_ERR_TOO_MANY_FIELDS 185 /* Table has too many columns */ +#define HA_ERR_ROW_IN_WRONG_PARTITION 186 /* Row in wrong partition */ +#define HA_ERR_ROW_NOT_VISIBLE 187 +#define HA_ERR_ABORTED_BY_USER 188 +#define HA_ERR_DISK_FULL 189 +#define HA_ERR_INCOMPATIBLE_DEFINITION 190 +#define HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE 191 /* Too many words in a phrase */ +#define HA_ERR_DECRYPTION_FAILED 192 /* Table encrypted but decrypt failed */ +#define HA_ERR_FK_DEPTH_EXCEEDED 193 /* FK cascade depth exceeded */ +#define HA_ERR_TABLESPACE_MISSING 194 /* Missing Tablespace */ +#define HA_ERR_SEQUENCE_INVALID_DATA 195 +#define HA_ERR_SEQUENCE_RUN_OUT 196 +#define HA_ERR_COMMIT_ERROR 197 +#define HA_ERR_PARTITION_LIST 198 +#define HA_ERR_NO_ENCRYPTION 199 +#define HA_ERR_LAST 199 /* Copy of last error nr * */ + +/* Number of different errors */ +#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) + +/* aliases */ +#define HA_ERR_TABLE_CORRUPT HA_ERR_WRONG_IN_RECORD +#define HA_ERR_QUERY_INTERRUPTED HA_ERR_ABORTED_BY_USER +#define HA_ERR_NOT_ALLOWED_COMMAND HA_ERR_WRONG_COMMAND + + /* Other constants */ + +#define HA_NAMELEN 64 /* Max length of saved filename */ +#define NO_SUCH_KEY (~(uint)0) /* used as a key no. */ + +typedef ulong key_part_map; +#define HA_WHOLE_KEY (~(key_part_map)0) + + /* Intern constants in databases */ + + /* bits in _search */ +#define SEARCH_FIND 1U +#define SEARCH_NO_FIND 2U +#define SEARCH_SAME 4U +#define SEARCH_BIGGER 8U +#define SEARCH_SMALLER 16U +#define SEARCH_SAVE_BUFF 32U +#define SEARCH_UPDATE 64U +#define SEARCH_PREFIX 128U +#define SEARCH_LAST 256U +#define MBR_CONTAIN 512U +#define MBR_INTERSECT 1024U +#define MBR_WITHIN 2048U +#define MBR_DISJOINT 4096U +#define MBR_EQUAL 8192U +#define MBR_DATA 16384U +#define SEARCH_NULL_ARE_EQUAL 32768U /* NULL in keys are equal */ +#define SEARCH_NULL_ARE_NOT_EQUAL 65536U/* NULL in keys are not equal */ +/* Use this when inserting a key in position order */ +#define SEARCH_INSERT (SEARCH_NULL_ARE_NOT_EQUAL*2) +/* Only part of the key is specified while reading */ +#define SEARCH_PART_KEY (SEARCH_INSERT*2) +/* Used when user key (key 2) contains transaction id's */ +#define SEARCH_USER_KEY_HAS_TRANSID (SEARCH_PART_KEY*2) +/* Used when page key (key 1) contains transaction id's */ +#define SEARCH_PAGE_KEY_HAS_TRANSID (SEARCH_USER_KEY_HAS_TRANSID*2) + + /* bits in opt_flag */ +#define QUICK_USED 1U +#define READ_CACHE_USED 2U +#define READ_CHECK_USED 4U +#define KEY_READ_USED 8U +#define WRITE_CACHE_USED 16U +#define OPT_NO_ROWS 32U + + /* bits in update */ +#define HA_STATE_CHANGED 1U /* Database has changed */ +#define HA_STATE_AKTIV 2U /* Has a current record */ +#define HA_STATE_WRITTEN 4U /* Record is written */ +#define HA_STATE_DELETED 8U +#define HA_STATE_NEXT_FOUND 16U /* Next found record (record before) */ +#define HA_STATE_PREV_FOUND 32U /* Prev found record (record after) */ +#define HA_STATE_NO_KEY 64U /* Last read didn't find record */ +#define HA_STATE_KEY_CHANGED 128U +#define HA_STATE_WRITE_AT_END 256U /* set in _ps_find_writepos */ +#define HA_STATE_BUFF_SAVED 512U /* If current keybuff is info->buff */ +#define HA_STATE_ROW_CHANGED 1024U /* To invalidate ROW cache */ +#define HA_STATE_EXTEND_BLOCK 2048U +#define HA_STATE_RNEXT_SAME 4096U /* rnext_same occupied lastkey2 */ + +/* myisampack expects no more than 32 field types. */ +enum en_fieldtype { + FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE, + FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO, + FIELD_VARCHAR,FIELD_CHECK, + FIELD_enum_val_count +}; + +enum data_file_type { + STATIC_RECORD, DYNAMIC_RECORD, COMPRESSED_RECORD, BLOCK_RECORD, NO_RECORD +}; + +/* For key ranges */ + +#define NO_MIN_RANGE 1U +#define NO_MAX_RANGE 2U +#define NEAR_MIN 4U +#define NEAR_MAX 8U +#define UNIQUE_RANGE 16U +#define EQ_RANGE 32U +#define NULL_RANGE 64U +#define GEOM_FLAG 128U + +typedef struct st_key_range +{ + const uchar *key; + uint length; + key_part_map keypart_map; + enum ha_rkey_function flag; +} key_range; + +typedef void *range_id_t; + +typedef struct st_key_multi_range +{ + key_range start_key; + key_range end_key; + range_id_t ptr; /* Free to use by caller (ptr to row etc) */ + /* + A set of range flags that describe both endpoints: UNIQUE_RANGE, + NULL_RANGE, EQ_RANGE, GEOM_FLAG. + (Flags that describe one endpoint, NO_{MIN|MAX}_RANGE, NEAR_{MIN|MAX} will + not be set here) + */ + uint range_flag; +} KEY_MULTI_RANGE; + + +/* Store first and last leaf page accessed by records_in_range */ + +typedef struct st_page_range +{ + ulonglong first_page; + ulonglong last_page; +} page_range; + +#define UNUSED_PAGE_NO ULONGLONG_MAX +#define unused_page_range { UNUSED_PAGE_NO, UNUSED_PAGE_NO } + +/* For number of records */ +#ifdef BIG_TABLES +#define rows2double(A) ulonglong2double(A) +typedef my_off_t ha_rows; +#else +#define rows2double(A) (double) (A) +typedef ulong ha_rows; +#endif + +#define HA_POS_ERROR (~ (ha_rows) 0) +#define HA_OFFSET_ERROR (~ (my_off_t) 0) +#define HA_ROWS_MAX HA_POS_ERROR + +#if SIZEOF_OFF_T == 4 +#define MAX_FILE_SIZE INT_MAX32 +#else +#define MAX_FILE_SIZE LONGLONG_MAX +#endif + +#define HA_VARCHAR_PACKLENGTH(field_length) ((field_length) < 256 ? 1 :2) + +/* invalidator function reference for Query Cache */ +C_MODE_START +typedef void (* invalidator_by_filename)(const char * filename); +C_MODE_END + +#endif /* _my_base_h */ diff --git a/include/my_bit.h b/include/my_bit.h new file mode 100644 index 00000000..8ee8b41c --- /dev/null +++ b/include/my_bit.h @@ -0,0 +1,219 @@ +/* Copyright (c) 2007, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2020, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MY_BIT_INCLUDED +#define MY_BIT_INCLUDED + +/* + Some useful bit functions +*/ + +C_MODE_START + +extern const uchar _my_bits_reverse_table[256]; + + +/* + my_bit_log2_xxx() + + In the given value, find the highest bit set, + which is the smallest X that satisfies the condition: (2^X >= value). + Can be used as a reverse operation for (1<<X), to find X. + + Examples: + - returns 0 for (1<<0) + - returns 1 for (1<<1) + - returns 2 for (1<<2) + - returns 2 for 3, which has (1<<2) as the highest bit set. + + Note, the behaviour of log2(0) is not defined. + Let's return 0 for the input 0, for the code simplicity. + See the 000x branch. It covers both (1<<0) and 0. +*/ +static inline CONSTEXPR uint my_bit_log2_hex_digit(uint8 value) +{ + return value & 0x0C ? /*1100*/ (value & 0x08 ? /*1000*/ 3 : /*0100*/ 2) : + /*0010*/ (value & 0x02 ? /*0010*/ 1 : /*000x*/ 0); +} +static inline CONSTEXPR uint my_bit_log2_uint8(uint8 value) +{ + return value & 0xF0 ? my_bit_log2_hex_digit((uint8) (value >> 4)) + 4: + my_bit_log2_hex_digit(value); +} +static inline CONSTEXPR uint my_bit_log2_uint16(uint16 value) +{ + return value & 0xFF00 ? my_bit_log2_uint8((uint8) (value >> 8)) + 8 : + my_bit_log2_uint8((uint8) value); +} +static inline CONSTEXPR uint my_bit_log2_uint32(uint32 value) +{ + return value & 0xFFFF0000UL ? + my_bit_log2_uint16((uint16) (value >> 16)) + 16 : + my_bit_log2_uint16((uint16) value); +} +static inline CONSTEXPR uint my_bit_log2_uint64(ulonglong value) +{ + return value & 0xFFFFFFFF00000000ULL ? + my_bit_log2_uint32((uint32) (value >> 32)) + 32 : + my_bit_log2_uint32((uint32) value); +} +static inline CONSTEXPR uint my_bit_log2_size_t(size_t value) +{ +#ifdef __cplusplus + static_assert(sizeof(size_t) <= sizeof(ulonglong), + "size_t <= ulonglong is an assumption that needs to be fixed " + "for this architecture. Please create an issue on " + "https://jira.mariadb.org"); +#endif + return my_bit_log2_uint64((ulonglong) value); +} + + +/* +Count bits in 32bit integer + + Algorithm by Sean Anderson, according to: + http://graphics.stanford.edu/~seander/bithacks.html + under "Counting bits set, in parallel" + + (Original code public domain). +*/ +static inline uint my_count_bits_uint32(uint32 v) +{ + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; +} + + +static inline uint my_count_bits(ulonglong x) +{ + return my_count_bits_uint32((uint32)x) + my_count_bits_uint32((uint32)(x >> 32)); +} + + + + +/* + Next highest power of two + + SYNOPSIS + my_round_up_to_next_power() + v Value to check + + RETURN + Next or equal power of 2 + Note: 0 will return 0 + + NOTES + Algorithm by Sean Anderson, according to: + http://graphics.stanford.edu/~seander/bithacks.html + (Original code public domain) + + Comments shows how this works with 01100000000000000000000000001011 +*/ + +static inline uint32 my_round_up_to_next_power(uint32 v) +{ + v--; /* 01100000000000000000000000001010 */ + v|= v >> 1; /* 01110000000000000000000000001111 */ + v|= v >> 2; /* 01111100000000000000000000001111 */ + v|= v >> 4; /* 01111111110000000000000000001111 */ + v|= v >> 8; /* 01111111111111111100000000001111 */ + v|= v >> 16; /* 01111111111111111111111111111111 */ + return v+1; /* 10000000000000000000000000000000 */ +} + +static inline uint32 my_clear_highest_bit(uint32 v) +{ + uint32 w=v >> 1; + w|= w >> 1; + w|= w >> 2; + w|= w >> 4; + w|= w >> 8; + w|= w >> 16; + return v & w; +} + +static inline uint32 my_reverse_bits(uint32 key) +{ + return + ((uint32)_my_bits_reverse_table[ key & 255] << 24) | + ((uint32)_my_bits_reverse_table[(key>> 8) & 255] << 16) | + ((uint32)_my_bits_reverse_table[(key>>16) & 255] << 8) | + (uint32)_my_bits_reverse_table[(key>>24) ]; +} + +/* + a number with the n lowest bits set + an overflow-safe version of (1 << n) - 1 +*/ +static inline uint64 my_set_bits(int n) +{ + return (((1ULL << (n - 1)) - 1) << 1) | 1; +} + +/* Create a mask of the significant bits for the last byte (1,3,7,..255) */ +static inline uchar last_byte_mask(uint bits) +{ + /* Get the number of used bits-1 (0..7) in the last byte */ + unsigned int const used = (bits - 1U) & 7U; + /* Return bitmask for the significant bits */ + return (uchar) ((2U << used) - 1); +} + +#ifdef _MSC_VER +#include <intrin.h> +#endif + +/* + Find the position of the first(least significant) bit set in + the argument. Returns 64 if the argument was 0. +*/ +static inline uint my_find_first_bit(ulonglong n) +{ + if(!n) + return 64; +#if defined(__GNUC__) + return __builtin_ctzll(n); +#elif defined(_MSC_VER) +#if defined(_M_IX86) + unsigned long bit; + if( _BitScanForward(&bit, (uint)n)) + return bit; + _BitScanForward(&bit, (uint)(n>>32)); + return bit + 32; +#else + unsigned long bit; + _BitScanForward64(&bit, n); + return bit; +#endif +#else + /* Generic case */ + uint shift= 0; + static const uchar last_bit[16] = { 32, 0, 1, 0, + 2, 0, 1, 0, + 3, 0, 1, 0, + 2, 0, 1, 0}; + uint bit; + while ((bit = last_bit[(n >> shift) & 0xF]) == 32) + shift+= 4; + return shift+bit; +#endif +} +C_MODE_END + +#endif /* MY_BIT_INCLUDED */ diff --git a/include/my_bitmap.h b/include/my_bitmap.h new file mode 100644 index 00000000..f88a6fe8 --- /dev/null +++ b/include/my_bitmap.h @@ -0,0 +1,127 @@ +/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2020, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_bitmap_h_ +#define _my_bitmap_h_ + +#define MY_BIT_NONE (~(uint) 0) + +#include <m_string.h> +#include <my_pthread.h> + +typedef uint32 my_bitmap_map; + +typedef struct st_bitmap +{ + my_bitmap_map *bitmap; + my_bitmap_map *last_word_ptr; + my_bitmap_map last_word_mask; + uint32 n_bits; /* number of bits occupied by the above */ +} MY_BITMAP; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Reset memory. Faster then doing a full bzero */ +#define my_bitmap_clear(A) ((A)->bitmap= 0) + +extern void create_last_word_mask(MY_BITMAP *map); +extern my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits); +extern my_bool bitmap_is_clear_all(const MY_BITMAP *map); +extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size); +extern my_bool bitmap_is_set_all(const MY_BITMAP *map); +extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2); +extern my_bool bitmap_is_overlapping(const MY_BITMAP *map1, + const MY_BITMAP *map2); +extern my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit); +extern my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit); +extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit); +extern my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit); +extern my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, + const MY_BITMAP *map2); +extern my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array, + uint bitmap_count, + uint start_bit, uint end_bit); + +extern uint bitmap_set_next(MY_BITMAP *map); +extern uint bitmap_get_first(const MY_BITMAP *map); +extern uint bitmap_get_first_set(const MY_BITMAP *map); +extern uint bitmap_bits_set(const MY_BITMAP *map); +extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit); +extern void my_bitmap_free(MY_BITMAP *map); +extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit); +extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size); +extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_invert(MY_BITMAP *map); +extern void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2); + +/* Fast, not thread safe, bitmap functions */ +#define bitmap_buffer_size(bits) (((bits)+31)/32)*4 +#define no_bytes_in_map(map) (((map)->n_bits + 7)/8) +#define no_words_in_map(map) (((map)->n_bits + 31)/32) +#define bytes_word_aligned(bytes) (4*((bytes + 3)/4)) +/* The following functions must be compatible with create_last_word_mask()! */ +static inline void +bitmap_set_bit(MY_BITMAP *map,uint bit) +{ + uchar *b= (uchar*) map->bitmap + bit / 8; + DBUG_ASSERT(bit < map->n_bits); + *b= (uchar) (*b | 1U << (bit & 7)); +} +static inline void +bitmap_flip_bit(MY_BITMAP *map,uint bit) +{ + uchar *b= (uchar*) map->bitmap + bit / 8; + DBUG_ASSERT(bit < map->n_bits); + *b= (uchar) (*b ^ 1U << (bit & 7)); +} +static inline void +bitmap_clear_bit(MY_BITMAP *map,uint bit) +{ + uchar *b= (uchar*) map->bitmap + bit / 8; + DBUG_ASSERT(bit < map->n_bits); + *b= (uchar) (*b & ~(1U << (bit & 7))); +} +static inline uint +bitmap_is_set(const MY_BITMAP *map,uint bit) +{ + const uchar *b= (const uchar*) map->bitmap + bit / 8; + DBUG_ASSERT(bit < map->n_bits); + return !!(*b & (1U << (bit & 7))); +} + +static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) +{ + if (memcmp(map1->bitmap, map2->bitmap, 4*(no_words_in_map(map1)-1)) != 0) + return FALSE; + return ((*map1->last_word_ptr | map1->last_word_mask) == + (*map2->last_word_ptr | map2->last_word_mask)); +} + +#define bitmap_clear_all(MAP) \ + { memset((MAP)->bitmap, 0, 4*no_words_in_map((MAP))); } +#define bitmap_set_all(MAP) \ + (memset((MAP)->bitmap, 0xFF, 4*no_words_in_map((MAP)))) + +#ifdef __cplusplus +} +#endif + +#endif /* _my_bitmap_h_ */ diff --git a/include/my_byteorder.h b/include/my_byteorder.h new file mode 100644 index 00000000..a70330ca --- /dev/null +++ b/include/my_byteorder.h @@ -0,0 +1,54 @@ +#ifndef MY_BYTEORDER_INCLUDED +#define MY_BYTEORDER_INCLUDED + +/* Copyright (c) 2001, 2012, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + + +/* + Macro for reading 32-bit integer from network byte order (big-endian) + from an unaligned memory location. +*/ +#define int4net(A) (int32) (((uint32) ((uchar) (A)[3])) | \ + (((uint32) ((uchar) (A)[2])) << 8) | \ + (((uint32) ((uchar) (A)[1])) << 16) | \ + (((uint32) ((uchar) (A)[0])) << 24)) + +/* + Function-like macros for reading and storing in machine independent + format (low byte first). There are 'korr' (assume 'corrector') variants + for integer types, but 'get' (assume 'getter') for floating point types. +*/ +#if (defined(__i386__) || defined(_M_IX86)) && !defined(WITH_UBSAN) +#define MY_BYTE_ORDER_ARCH_OPTIMIZED +#include "byte_order_generic_x86.h" +#elif (defined(__x86_64__) || defined (_M_X64)) && !defined(WITH_UBSAN) +#include "byte_order_generic_x86_64.h" +#else +#include "byte_order_generic.h" +#endif + +/* + Function-like macros for reading and storing in machine format from/to + short/long to/from some place in memory V should be a variable (not on + a register) and M a pointer to byte. +*/ +#ifdef WORDS_BIGENDIAN +#include "big_endian.h" +#else +#include "little_endian.h" +#endif + +#endif /* MY_BYTEORDER_INCLUDED */ diff --git a/include/my_check_opt.h b/include/my_check_opt.h new file mode 100644 index 00000000..f5ec522e --- /dev/null +++ b/include/my_check_opt.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2000, 2013, 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_check_opt_h +#define _my_check_opt_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + All given definitions needed for MyISAM storage engine: + myisamchk.c or/and ha_myisam.cc or/and micheck.c + Some definitions are needed by the MySQL parser. +*/ + +#define T_AUTO_INC (1UL << 0) +#define T_AUTO_REPAIR (1UL << 1) +#define T_BACKUP_DATA (1UL << 2) +#define T_CALC_CHECKSUM (1UL << 3) +#define T_CHECK (1UL << 4) +#define T_CHECK_ONLY_CHANGED (1UL << 5) +#define T_CREATE_MISSING_KEYS (1UL << 6) +#define T_DESCRIPT (1UL << 7) +#define T_DONT_CHECK_CHECKSUM (1UL << 8) +#define T_EXTEND (1UL << 9) +#define T_FAST (1UL << 10) +#define T_FORCE_CREATE (1UL << 11) +#define T_FORCE_UNIQUENESS (1UL << 12) +#define T_INFO (1UL << 13) +/** CHECK TABLE...MEDIUM (the default) */ +#define T_MEDIUM (1UL << 14) +/** CHECK TABLE...QUICK */ +#define T_QUICK (1UL << 15) +#define T_READONLY (1UL << 16) +#define T_REP (1UL << 17) +#define T_REP_BY_SORT (1UL << 18) +#define T_REP_PARALLEL (1UL << 19) +#define T_RETRY_WITHOUT_QUICK (1UL << 20) +#define T_SAFE_REPAIR (1UL << 21) +#define T_SILENT (1UL << 22) +#define T_SORT_INDEX (1UL << 23) +#define T_SORT_RECORDS (1UL << 24) +#define T_STATISTICS (1UL << 25) +#define T_UNPACK (1UL << 26) +#define T_UPDATE_STATE (1UL << 27) +#define T_VERBOSE (1UL << 28) +#define T_VERY_SILENT (1UL << 29) +#define T_WAIT_FOREVER (1UL << 30) +#define T_WRITE_LOOP (1UL << 31) +#define T_ZEROFILL (1ULL << 32) +#define T_ZEROFILL_KEEP_LSN (1ULL << 33) +/** If repair should not bump create_rename_lsn */ +#define T_NO_CREATE_RENAME_LSN (1ULL << 34) +/** If repair shouldn't do any locks */ +#define T_NO_LOCKS (1ULL << 35) +#define T_CREATE_UNIQUE_BY_SORT (1ULL << 36) +#define T_SUPPRESS_ERR_HANDLING (1ULL << 37) +#define T_FORCE_SORT_MEMORY (1ULL << 38) + +#define T_REP_ANY (T_REP | T_REP_BY_SORT | T_REP_PARALLEL) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/my_compare.h b/include/my_compare.h new file mode 100644 index 00000000..048e679e --- /dev/null +++ b/include/my_compare.h @@ -0,0 +1,286 @@ +/* Copyright (c) 2011, Oracle and/or its affiliates. + Copyright (c) 1991, 2021, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_compare_h +#define _my_compare_h + +#include "myisampack.h" +#ifdef __cplusplus +extern "C" { +#endif + +#include "m_ctype.h" /* CHARSET_INFO */ + +/* + There is a hard limit for the maximum number of keys as there are only + 8 bits in the index file header for the number of keys in a table. + This means that 0..255 keys can exist for a table. The idea of + HA_MAX_POSSIBLE_KEY is to ensure that one can use myisamchk & tools on + a MyISAM table for which one has more keys than MyISAM is normally + compiled for. If you don't have this, you will get a core dump when + running myisamchk compiled for 128 keys on a table with 255 keys. +*/ + +#define HA_MAX_POSSIBLE_KEY 255 /* For myisamchk */ +/* + The following defines can be increased if necessary. + But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and HA_MAX_KEY_LENGTH. +*/ + +#define HA_MAX_KEY_LENGTH 1000 /* Max length in bytes */ +#define HA_MAX_KEY_SEG 32 /* Max segments for key */ + +#define HA_MAX_POSSIBLE_KEY_BUFF (HA_MAX_KEY_LENGTH + 24+ 6+6) +#define HA_MAX_KEY_BUFF (HA_MAX_KEY_LENGTH+HA_MAX_KEY_SEG*6+8+8) + +typedef struct st_HA_KEYSEG /* Key-portion */ +{ + CHARSET_INFO *charset; + uint32 start; /* Start of key in record */ + uint32 null_pos; /* position to NULL indicator */ + uint16 bit_pos; /* Position to bit part */ + uint16 flag; + uint16 length; /* Keylength */ + uint16 language; + uint8 type; /* Type of key (for sort) */ + uint8 null_bit; /* bitmask to test for NULL */ + uint8 bit_start; + uint8 bit_length; /* Length of bit part */ +} HA_KEYSEG; + +#define get_key_length(length,key) \ +{ if (*(const uchar*) (key) != 255) \ + length= (uint) *(const uchar*) ((key)++); \ + else \ + { length= mi_uint2korr((key)+1); (key)+=3; } \ +} + +#define get_key_length_rdonly(length,key) \ +{ if (*(const uchar*) (key) != 255) \ + length= ((uint) *(const uchar*) ((key))); \ + else \ + { length= mi_uint2korr((key)+1); } \ +} + +#define get_key_pack_length(length,length_pack,key) \ +{ if (*(const uchar*) (key) != 255) \ + { length= (uint) *(const uchar*) ((key)++); length_pack= 1; }\ + else \ + { length=mi_uint2korr((key)+1); (key)+= 3; length_pack= 3; } \ +} + +#define store_key_length_inc(key,length) \ +{ if ((length) < 255) \ + { *(key)++= (uchar)(length); } \ + else \ + { *(key)=255; mi_int2store((key)+1,(length)); (key)+=3; } \ +} + +#define size_to_store_key_length(length) ((length) < 255 ? 1 : 3) + +static inline uchar get_rec_bits(const uchar *ptr, uchar ofs, uint len) +{ + uint16 val= ptr[0]; + if (ofs + len > 8) + val|= (uint16)(((uint) ptr[1]) << 8); + return (uchar) ((val >> ofs) & ((1 << len) - 1)); +} + +static inline void set_rec_bits(uint16 bits, uchar *ptr, uchar ofs, uint len) +{ + ptr[0]= (uchar) ((ptr[0] & ~(((1 << len) - 1) << ofs)) | (bits << ofs)); + if (ofs + len > 8) + ptr[1]= (uchar) ((ptr[1] & ~((1 << (len - 8 + ofs)) - 1)) | + bits >> (8 - ofs)); +} + +#define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \ + set_rec_bits(0, bit_ptr, bit_ofs, bit_len) + + +/* + Compare two VARCHAR values. + @param charset_info - The character set and collation + @param a - The pointer to the first string + @param a_length - The length of the first string + @param b - The pointer to the second string + @param b_length - The length of the second string + @param b_is_prefix - Whether "b" is a prefix of "a", + e.g. in a prefix key (partial length key). + @returns - The result of comparison + + - If "b_is_prefix" is FALSE, then the two strings are compared + taking into account the PAD SPACE/NO PAD attribute of the collation. + + - If "b_is_prefix" is TRUE, then trailing spaces are compared in NO PAD style. + This is done e.g. when we compare a column value to its prefix key value + (the value of "a" to the value of "key_a"): + CREATE TABLE t1 (a VARCHAR(10), KEY(key_a(5)); +*/ +static inline int ha_compare_char_varying(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + my_bool b_is_prefix) +{ + if (!b_is_prefix) + return charset_info->coll->strnncollsp(charset_info, a, a_length, + b, b_length); + return charset_info->coll->strnncoll(charset_info, + a, a_length, + b, b_length, TRUE/*prefix*/); +} + + +/* + Compare two CHAR values of the same declared character length, + e.g. CHAR(5) to CHAR(5). + + @param charset_info - The character set and collation + @param a - The pointer to the first string + @param a_length - The length of the first string + @param b - The pointer to the second string + @param b_length - The length of the second string + @param nchars - The declared length (in characters) + @param b_is_prefix - Whether "b" is a prefix of "a", + e.g. in a prefix key (partial length key). + @returns - The result of comparison + + - If "b_is_prefix" is FALSE, then the two strings are compared + taking into account the PAD SPACE/NO PAD attribute of the collation. + Additionally, this function assumes that the underlying storage could + optionally apply trailing space compression, so values can come into this + comparison function in different states: + - all trailing spaces removed + - some trailing spaced removed + - no trailing spaces removed (exactly "nchars" characters on the two sides) + This function virtually reconstructs trailing spaces up to the defined + length specified in "nchars". + If either of the sides have more than "nchar" characters, + then only leftmost "nchar" characters are compared. + + - If "b_is_prefix" is TRUE, then trailing spaces are compared in NO PAD style. + This is done e.g. when we compare a column value to its prefix key value + (the value of "a" to the value of "key_a"): + CREATE TABLE t1 (a CHAR(10), KEY(key_a(5)); +*/ +static inline int ha_compare_char_fixed(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + size_t nchars, + my_bool b_is_prefix) +{ + if (!b_is_prefix) + return charset_info->coll->strnncollsp_nchars(charset_info, + a, a_length, + b, b_length, + nchars, + MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES); + return charset_info->coll->strnncoll(charset_info, + a, a_length, + b, b_length, TRUE/*prefix*/); +} + + +/* + A function to compare words of a text. + This is a common operation in full-text search: + SELECT MATCH (title) AGAINST ('word') FROM t1; +*/ +static inline int ha_compare_word(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length) +{ + return charset_info->coll->strnncollsp(charset_info, + a, a_length, + b, b_length); +} + + +/* + A function to compare a word of a text to a word prefix. + This is a common operation in full-text search: + SELECT MATCH (title) AGAINST ('wor*' IN BOOLEAN MODE) FROM t1; +*/ +static inline int ha_compare_word_prefix(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length) +{ + return charset_info->coll->strnncoll(charset_info, + a, a_length, + b, b_length, + TRUE/*b_is_prefix*/); +} + + +/* + Compare words (full match or prefix match), e.g. for full-text search. +*/ +static inline int ha_compare_word_or_prefix(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + my_bool b_is_prefix) +{ + if (!b_is_prefix) + return ha_compare_word(charset_info, a, a_length, b, b_length); + return ha_compare_word_prefix(charset_info, a, a_length, b, b_length); +} + + +extern int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, + const uchar *b, uint key_length, uint nextflag, + uint *diff_pos); +extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, const uchar *a); + +/* + Inside an in-memory data record, memory pointers to pieces of the + record (like BLOBs) are stored in their native byte order and in + this amount of bytes. +*/ +#define portable_sizeof_char_ptr 8 +#ifdef __cplusplus +} +#endif + +/** + Return values for pushed index condition or rowid filter check functions. + + 0=CHECK_NEG - The filter is not satisfied. The engine should discard this + index tuple and continue the scan. + 1=CHECK_POS - The filter is satisfied. Current index tuple should be + returned to the SQL layer. + 2=CHECK_OUT_OF_RANGE - the index tuple is outside of the range that we're + scanning. (Example: if we're scanning "t.key BETWEEN 10 AND + 20" and got a "t.key=21" tuple) Tthe engine should stop + scanning and return HA_ERR_END_OF_FILE right away). + 3=CHECK_ABORTED_BY_USER - the engine must stop scanning and should return + HA_ERR_ABORTED_BY_USER right away + -1=CHECK_ERROR - Reserved for internal errors in engines. Should not be + returned by ICP or rowid filter check functions. +*/ + +typedef enum check_result { + CHECK_ERROR=-1, + CHECK_NEG=0, + CHECK_POS=1, + CHECK_OUT_OF_RANGE=2, + CHECK_ABORTED_BY_USER=3 +} check_result_t; + +typedef check_result_t (*index_cond_func_t)(void *param); +typedef check_result_t (*rowid_filter_func_t)(void *param); +typedef int (*rowid_filter_is_active_func_t)(void *param); + +#endif /* _my_compare_h */ diff --git a/include/my_compiler.h b/include/my_compiler.h new file mode 100644 index 00000000..b979b5a5 --- /dev/null +++ b/include/my_compiler.h @@ -0,0 +1,181 @@ +#ifndef MY_COMPILER_INCLUDED +#define MY_COMPILER_INCLUDED + +/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, 2022, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + Header for compiler-dependent features. + + Intended to contain a set of reusable wrappers for preprocessor + macros, attributes, pragmas, and any other features that are + specific to a target compiler. +*/ + +/** + Compiler-dependent internal convenience macros. +*/ + +/* C vs C++ */ +#ifdef __cplusplus +#define CONSTEXPR constexpr +#else +#define CONSTEXPR +#endif /* __cplusplus */ + + +/* GNU C/C++ */ +#if defined __GNUC__ +# define MY_ALIGN_EXT + +/* + __builtin_unreachable() removes the "statement may fall through" warning-as- + error when MY_ASSERT_UNREACHABLE() is used in "case xxx:" in switch (...) + statements. + abort() is there to prevent the execution from reaching the + __builtin_unreachable() as this may cause misleading stack traces. +*/ +# define MY_ASSERT_UNREACHABLE() { abort(); __builtin_unreachable(); } + +/* Microsoft Visual C++ */ +#elif defined _MSC_VER +# define MY_ALIGNOF(type) __alignof(type) +# define MY_ALIGNED(n) __declspec(align(n)) + +/* Oracle Solaris Studio */ +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# if __SUNPRO_C >= 0x590 +# define MY_ALIGN_EXT +# endif + +/* IBM XL C/C++ */ +#elif defined __xlC__ +# if __xlC__ >= 0x0600 +# define MY_ALIGN_EXT +# endif + +/* HP aCC */ +#elif defined(__HP_aCC) || defined(__HP_cc) +# if (__HP_aCC >= 60000) || (__HP_cc >= 60000) +# define MY_ALIGN_EXT +# endif +#endif + +#ifdef MY_ALIGN_EXT +/** Specifies the minimum alignment of a type. */ +# define MY_ALIGNOF(type) __alignof__(type) +/** Determine the alignment requirement of a type. */ +# define MY_ALIGNED(n) __attribute__((__aligned__((n)))) +#endif + +/** + Generic (compiler-independent) features. +*/ + +#ifndef MY_ALIGNOF +# ifdef __cplusplus + template<typename type> struct my_alignof_helper { char m1; type m2; }; + /* Invalid for non-POD types, but most compilers give the right answer. */ +# define MY_ALIGNOF(type) offsetof(my_alignof_helper<type>, m2) +# else +# define MY_ALIGNOF(type) offsetof(struct { char m1; type m2; }, m2) +# endif +#endif + +#ifndef MY_ASSERT_UNREACHABLE +# define MY_ASSERT_UNREACHABLE() do { abort(); } while (0) +#endif + +/** + C++ Type Traits +*/ + +#ifdef __cplusplus + +/** + Opaque storage with a particular alignment. +*/ +# if defined(MY_ALIGNED) +/* Partial specialization used due to MSVC++. */ +template<size_t alignment> struct my_alignment_imp; +template<> struct MY_ALIGNED(1) my_alignment_imp<1> {}; +template<> struct MY_ALIGNED(2) my_alignment_imp<2> {}; +template<> struct MY_ALIGNED(4) my_alignment_imp<4> {}; +template<> struct MY_ALIGNED(8) my_alignment_imp<8> {}; +template<> struct MY_ALIGNED(16) my_alignment_imp<16> {}; +/* ... expand as necessary. */ +# else +template<size_t alignment> +struct my_alignment_imp { double m1; }; +# endif + +/** + A POD type with a given size and alignment. + + @remark If the compiler does not support a alignment attribute + (MY_ALIGN macro), the default alignment of a double is + used instead. + + @tparam size The minimum size. + @tparam alignment The desired alignment: 1, 2, 4, 8 or 16. +*/ +template <size_t size, size_t alignment> +struct my_aligned_storage +{ + union + { + char data[size]; + my_alignment_imp<alignment> align; + }; +}; + +#endif /* __cplusplus */ + +# ifndef MY_ALIGNED +/* + Make sure MY_ALIGNED can be used also on platforms where we don't + have a way of aligning data structures. +*/ +#define MY_ALIGNED(size) +#endif + +#ifdef __GNUC__ +# define ATTRIBUTE_NORETURN __attribute__((noreturn)) +# define ATTRIBUTE_NOINLINE __attribute__((noinline)) +/** Starting with GCC 4.3, the "cold" attribute is used to inform the +compiler that a function is unlikely executed. The function is +optimized for size rather than speed and on many targets it is placed +into special subsection of the text section so all cold functions +appears close together improving code locality of non-cold parts of +program. The paths leading to call of cold functions within code are +marked as unlikely by the branch prediction mechanism. optimize a +rarely invoked function for size instead for speed. */ +# define ATTRIBUTE_COLD __attribute__((cold)) +#elif defined _MSC_VER +# define ATTRIBUTE_NORETURN __declspec(noreturn) +# define ATTRIBUTE_NOINLINE __declspec(noinline) +#else +# define ATTRIBUTE_NORETURN /* empty */ +# define ATTRIBUTE_NOINLINE /* empty */ +#endif + +#ifndef ATTRIBUTE_COLD +# define ATTRIBUTE_COLD /* empty */ +#endif + +#include <my_attribute.h> + +#endif /* MY_COMPILER_INCLUDED */ diff --git a/include/my_counter.h b/include/my_counter.h new file mode 100644 index 00000000..f85b8e80 --- /dev/null +++ b/include/my_counter.h @@ -0,0 +1,49 @@ +#ifndef MY_COUNTER_H_INCLUDED +#define MY_COUNTER_H_INCLUDED +/* + Copyright (C) 2018 MariaDB Foundation + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <atomic> + + +template <typename Type> class Atomic_counter +{ + std::atomic<Type> m_counter; + + Type add(Type i) { return m_counter.fetch_add(i, std::memory_order_relaxed); } + Type sub(Type i) { return m_counter.fetch_sub(i, std::memory_order_relaxed); } + +public: + Atomic_counter(const Atomic_counter<Type> &rhs) + { m_counter.store(rhs, std::memory_order_relaxed); } + Atomic_counter(Type val): m_counter(val) {} + Atomic_counter() = default; + + Type operator++(int) { return add(1); } + Type operator--(int) { return sub(1); } + + Type operator++() { return add(1) + 1; } + Type operator--() { return sub(1) - 1; } + + Type operator+=(const Type i) { return add(i) + i; } + Type operator-=(const Type i) { return sub(i) - i; } + + operator Type() const { return m_counter.load(std::memory_order_relaxed); } + Type operator=(const Type val) + { m_counter.store(val, std::memory_order_relaxed); return val; } +}; +#endif /* MY_COUNTER_H_INCLUDED */ diff --git a/include/my_cpu.h b/include/my_cpu.h new file mode 100644 index 00000000..e536ff28 --- /dev/null +++ b/include/my_cpu.h @@ -0,0 +1,142 @@ +#ifndef MY_CPU_INCLUDED +#define MY_CPU_INCLUDED +/* Copyright (c) 2013, 2020, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +/* instructions for specific cpu's */ + +/* + Macros for adjusting thread priority (hardware multi-threading) + The defines are the same ones used by the linux kernel +*/ + +#ifdef _ARCH_PWR8 +#include <sys/platform/ppc.h> +/* Very low priority */ +#define HMT_very_low() __ppc_set_ppr_very_low() +/* Low priority */ +#define HMT_low() __ppc_set_ppr_low() +/* Medium low priority */ +#define HMT_medium_low() __ppc_set_ppr_med_low() +/* Medium priority */ +#define HMT_medium() __ppc_set_ppr_med() +/* Medium high priority */ +#define HMT_medium_high() __ppc_set_ppr_med_high() +/* High priority */ +#define HMT_high() asm volatile("or 3,3,3") +#else +#define HMT_very_low() +#define HMT_low() +#define HMT_medium_low() +#define HMT_medium() +#define HMT_medium_high() +#define HMT_high() +#endif + +#if defined __i386__ || defined __x86_64__ || defined _WIN32 +# define HAVE_PAUSE_INSTRUCTION /* added in Intel Pentium 4 */ +#endif + +#ifdef _WIN32 +#elif defined HAVE_PAUSE_INSTRUCTION +#elif defined(_ARCH_PWR8) +#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) +#else +# include "my_global.h" +# include "my_atomic.h" +#endif + +static inline void MY_RELAX_CPU(void) +{ +#ifdef _WIN32 + /* + In the Win32 API, the x86 PAUSE instruction is executed by calling + the YieldProcessor macro defined in WinNT.h. It is a CPU architecture- + independent way by using YieldProcessor. + */ + YieldProcessor(); +#elif defined HAVE_PAUSE_INSTRUCTION + /* + According to the gcc info page, asm volatile means that the + instruction has important side-effects and must not be removed. + Also asm volatile may trigger a memory barrier (spilling all registers + to memory). + */ +#ifdef __SUNPRO_CC + asm ("pause" ); +#else + __asm__ __volatile__ ("pause"); +#endif +#elif defined(_ARCH_PWR8) + __ppc_get_timebase(); +#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) + /* Mainly, prevent the compiler from optimizing away delay loops */ + __asm__ __volatile__ ("":::"memory"); +#else + int32 var, oldval = 0; + my_atomic_cas32_strong_explicit(&var, &oldval, 1, MY_MEMORY_ORDER_RELAXED, + MY_MEMORY_ORDER_RELAXED); +#endif +} + + +#ifdef HAVE_PAUSE_INSTRUCTION +# ifdef __cplusplus +extern "C" { +# endif +extern unsigned my_cpu_relax_multiplier; +void my_cpu_init(void); +# ifdef __cplusplus +} +# endif +#else +# define my_cpu_relax_multiplier 200 +# define my_cpu_init() /* nothing */ +#endif + +/* + LF_BACKOFF should be used to improve performance on hyperthreaded CPUs. Intel + recommends to use it in spin loops also on non-HT machines to reduce power + consumption (see e.g http://softwarecommunity.intel.com/articles/eng/2004.htm) + + Running benchmarks for spinlocks implemented with InterlockedCompareExchange + and YieldProcessor shows that much better performance is achieved by calling + YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting + loop count in the range 200-300 brought best results. +*/ + +static inline int LF_BACKOFF(void) +{ + unsigned i= my_cpu_relax_multiplier; + while (i--) + MY_RELAX_CPU(); + return 1; +} + +/** + Run a delay loop while waiting for a shared resource to be released. + @param delay originally, roughly microseconds on 100 MHz Intel Pentium +*/ +static inline void ut_delay(unsigned delay) +{ + unsigned i= my_cpu_relax_multiplier / 4 * delay; + HMT_low(); + while (i--) + MY_RELAX_CPU(); + HMT_medium(); +} + +#endif diff --git a/include/my_crypt.h b/include/my_crypt.h new file mode 100644 index 00000000..eced2cd4 --- /dev/null +++ b/include/my_crypt.h @@ -0,0 +1,24 @@ +/* + Copyright (c) 2014 Google Inc. + Copyright (c) 2014, 2015 MariaDB Corporation + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MY_CRYPT_INCLUDED +#define MY_CRYPT_INCLUDED + +#include <my_config.h> /* HAVE_EncryptAes128{Ctr,Gcm} */ +#include <mysql/service_my_crypt.h> + +#endif /* MY_CRYPT_INCLUDED */ diff --git a/include/my_dbug.h b/include/my_dbug.h new file mode 100644 index 00000000..02caadbf --- /dev/null +++ b/include/my_dbug.h @@ -0,0 +1,248 @@ +/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (C) 2000, 2019, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_dbug_h +#define _my_dbug_h + +#ifndef _WIN32 +#include <signal.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif +#if !defined(DBUG_OFF) && !defined(_lint) + +struct _db_stack_frame_ { + const char *func; /* function name of the previous stack frame */ + const char *file; /* filename of the function of previous frame */ + uint level; /* this nesting level, highest bit enables tracing */ + int line; /* line of DBUG_RETURN */ + struct _db_stack_frame_ *prev; /* pointer to the previous frame */ +}; + +struct _db_code_state_; +extern my_bool _dbug_on_; +extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int); +extern int _db_explain_(struct _db_code_state_ *cs, char *buf, size_t len); +extern int _db_explain_init_(char *buf, size_t len); +extern int _db_is_pushed_(void); +extern void _db_setjmp_(void); +extern void _db_longjmp_(void); +extern void _db_process_(const char *name); +extern void _db_push_(const char *control); +extern void _db_pop_(void); +extern void _db_set_(const char *control); +extern void _db_set_init_(const char *control); +extern void _db_enter_(const char *_func_, const char *_file_, uint _line_, + struct _db_stack_frame_ *_stack_frame_); +extern void _db_return_(struct _db_stack_frame_ *_stack_frame_); +extern int _db_pargs_(uint _line_,const char *keyword); +extern void _db_doprnt_(const char *format,...) +#ifdef WAITING_FOR_BUGFIX_TO_VSPRINTF + ATTRIBUTE_FORMAT(printf, 1, 2) +#endif + ; +extern void _db_dump_(uint _line_,const char *keyword, + const unsigned char *memory, size_t length); +extern void _db_end_(void); +extern void _db_lock_file_(void); +extern void _db_unlock_file_(void); +ATTRIBUTE_COLD +extern my_bool _db_my_assert(const char *file, int line, const char *msg); +extern FILE *_db_fp_(void); +extern void _db_flush_(void); +extern void dbug_swap_code_state(void **code_state_store); +extern void dbug_free_code_state(void **code_state_store); +extern const char* _db_get_func_(void); +extern int (*dbug_sanity)(void); + +#ifdef DBUG_TRACE +#define DBUG_LEAVE do { \ + _db_stack_frame_.line= __LINE__; \ + _db_return_ (&_db_stack_frame_); \ + _db_stack_frame_.line= 0; \ + } while(0) + +#define DBUG_PRINT(keyword,arglist) \ + do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0) + +#ifdef HAVE_ATTRIBUTE_CLEANUP +#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_ __attribute__((cleanup(_db_return_))); \ + _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_) +#define DBUG_RETURN(a1) do { _db_stack_frame_.line=__LINE__; return(a1);} while(0) +#define DBUG_VOID_RETURN do { _db_stack_frame_.line=__LINE__; return;} while(0) +#else +#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \ + _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_) +#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0) +#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0) +#endif + +#else +#define DBUG_LEAVE +#define DBUG_ENTER(a) +#define DBUG_RETURN(a1) return(a1) +#define DBUG_VOID_RETURN return +#define DBUG_PRINT(keyword,arglist) do{} while(0) +#endif + +#define DBUG_EXECUTE(keyword,a1) \ + do {if (_db_keyword_(0, (keyword), 0)) { a1 }} while(0) +#define DBUG_EXECUTE_IF(keyword,a1) \ + do {if (_db_keyword_(0, (keyword), 1)) { a1 }} while(0) + +#define DBUG_IF(keyword) _db_keyword_(0, (keyword), 1) + +#define DBUG_PUSH_EMPTY if (_dbug_on_) { DBUG_PUSH(""); } +#define DBUG_POP_EMPTY if (_dbug_on_) { DBUG_POP(); } +#define DBUG_PUSH(a1) _db_push_ (a1) +#define DBUG_POP() _db_pop_ () +#define DBUG_SET(a1) _db_set_ (a1) +#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1) +#define DBUG_PROCESS(a1) _db_process_(a1) +#define DBUG_FILE _db_fp_() +#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2) +#define DBUG_END() _db_end_ () +#define DBUG_LOCK_FILE _db_lock_file_() +#define DBUG_UNLOCK_FILE _db_unlock_file_() +#define DBUG_ASSERT(A) do { \ + if (unlikely(!(A)) && _db_my_assert(__FILE__, __LINE__, #A)) assert(A); \ +} while (0) +#define DBUG_SLOW_ASSERT(A) DBUG_ASSERT(A) +#define DBUG_ASSERT_EXISTS +#define DBUG_EXPLAIN(buf,len) _db_explain_(0, (buf),(len)) +#define DBUG_EXPLAIN_INITIAL(buf,len) _db_explain_init_((buf),(len)) +#define DEBUGGER_OFF do { _dbug_on_= 0; } while(0) +#define DEBUGGER_ON do { _dbug_on_= 1; } while(0) +#define IF_DBUG(A,B) A +#define IF_DBUG_ASSERT(A,B) A +#define DBUG_SWAP_CODE_STATE(arg) dbug_swap_code_state(arg) +#define DBUG_FREE_CODE_STATE(arg) dbug_free_code_state(arg) +#undef DBUG_ASSERT_AS_PRINTF + +#ifndef _WIN32 +#define DBUG_ABORT() (_db_flush_(), abort()) +#else +/* + Avoid popup with abort/retry/ignore buttons. When BUG#31745 is fixed we can + call abort() instead of _exit(3) (now it would cause a "test signal" popup). +*/ +#include <crtdbg.h> +#define DBUG_ABORT() (_db_flush_(),\ + (void)_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE),\ + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR),\ + TerminateProcess(GetCurrentProcess(),3)) +#endif + +/* + Make the program fail, without creating a core file. + abort() will send SIGABRT which (most likely) generates core. + Use SIGKILL instead, which cannot be caught. + We also pause the current thread, until the signal is actually delivered. + An alternative would be to use _exit(EXIT_FAILURE), + but then valgrind would report lots of memory leaks. + */ +#ifdef _WIN32 +#define DBUG_SUICIDE() DBUG_ABORT() +#else +extern void _db_suicide_(void); +#define DBUG_SUICIDE() (_db_flush_(), _db_suicide_()) +#endif /* _WIN32 */ + +#else /* No debugger */ + +#define DBUG_ENTER(a1) +#define DBUG_VIOLATION_HELPER_LEAVE do { } while(0) +#define DBUG_LEAVE +#define DBUG_RETURN(a1) do { return(a1); } while(0) +#define DBUG_VOID_RETURN do { return; } while(0) +#define DBUG_PRINT(keyword, arglist) do { } while(0) +#define DBUG_EXECUTE(keyword,a1) do { } while(0) +#define DBUG_EXECUTE_IF(keyword,a1) do { } while(0) +#define DBUG_IF(keyword) 0 +#define DBUG_PRINT(keyword,arglist) do { } while(0) +#define DBUG_PUSH_EMPTY do { } while(0) +#define DBUG_POP_EMPTY do { } while(0) +#define DBUG_PUSH(a1) do { } while(0) +#define DBUG_SET(a1) do { } while(0) +#define DBUG_SET_INITIAL(a1) do { } while(0) +#define DBUG_POP() do { } while(0) +#define DBUG_PROCESS(a1) do { } while(0) +#define DBUG_DUMP(keyword,a1,a2) do { } while(0) +#define DBUG_END() do { } while(0) +#define DBUG_SLOW_ASSERT(A) do { } while(0) +#define DBUG_LOCK_FILE do { } while(0) +#define DBUG_FILE (stderr) +#define DBUG_UNLOCK_FILE do { } while(0) +#define DBUG_EXPLAIN(buf,len) +#define DBUG_EXPLAIN_INITIAL(buf,len) +#define DEBUGGER_OFF do { } while(0) +#define DEBUGGER_ON do { } while(0) +#define IF_DBUG(A,B) B +#define DBUG_SWAP_CODE_STATE(arg) do { } while(0) +#define DBUG_FREE_CODE_STATE(arg) do { } while(0) +#define DBUG_ABORT() do { } while(0) +#define DBUG_CRASH_ENTER(func) +#define DBUG_CRASH_RETURN(val) do { return(val); } while(0) +#define DBUG_CRASH_VOID_RETURN do { return; } while(0) +#define DBUG_SUICIDE() ((void) 0) + +#ifdef DBUG_ASSERT_AS_PRINTF +extern void (*my_dbug_assert_failed)(const char *assert_expr, const char* file, unsigned long line); +#define DBUG_ASSERT(assert_expr) do { if (!(assert_expr)) { my_dbug_assert_failed(#assert_expr, __FILE__, __LINE__); }} while (0) +#define DBUG_ASSERT_EXISTS +#define IF_DBUG_ASSERT(A,B) A +#else +#define DBUG_ASSERT(A) do { } while(0) +#define IF_DBUG_ASSERT(A,B) B +#endif /* DBUG_ASSERT_AS_PRINTF */ +#endif /* !defined(DBUG_OFF) && !defined(_lint) */ + +#ifdef EXTRA_DEBUG +/** + Sync points allow us to force the server to reach a certain line of code + and block there until the client tells the server it is ok to go on. + The client tells the server to block with SELECT GET_LOCK() + and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult + concurrency problems +*/ +#define DBUG_SYNC_POINT(lock_name,lock_timeout) \ + debug_sync_point(lock_name,lock_timeout) +void debug_sync_point(const char* lock_name, uint lock_timeout); +#else +#define DBUG_SYNC_POINT(lock_name,lock_timeout) +#endif /* EXTRA_DEBUG */ + +#ifdef __cplusplus +} +/* + DBUG_LOG() was initially intended for InnoDB. To be able to use it elsewhere + one should #include <sstream>. We intentionally avoid including it here to save + compilation time. +*/ +# ifdef DBUG_OFF +# define DBUG_LOG(keyword, v) do {} while (0) +# else +# define DBUG_LOG(keyword, v) do { \ + if (_db_pargs_(__LINE__, keyword)) { \ + std::ostringstream _db_s; _db_s << v; \ + _db_doprnt_("%s", _db_s.str().c_str()); \ + }} while (0) +# endif +#endif + +#endif /* _my_dbug_h */ diff --git a/include/my_decimal_limits.h b/include/my_decimal_limits.h new file mode 100644 index 00000000..5bfd54d6 --- /dev/null +++ b/include/my_decimal_limits.h @@ -0,0 +1,51 @@ +#ifndef MY_DECIMAL_LIMITS_INCLUDED +#define MY_DECIMAL_LIMITS_INCLUDED +/* Copyright (c) 2011 Monty Program Ab + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#define DECIMAL_LONGLONG_DIGITS 22 +#define DECIMAL_LONG_DIGITS 10 +#define DECIMAL_LONG3_DIGITS 8 + +/** maximum length of buffer in our big digits (uint32). */ +#define DECIMAL_BUFF_LENGTH 9 + +/* the number of digits that my_decimal can possibly contain */ +#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9) + + +/** + maximum guaranteed precision of number in decimal digits (number of our + digits * number of decimal digits in one our big digit - number of decimal + digits in one our big digit decreased by 1 (because we always put decimal + point on the border of our big digits)) + + With normal precision we can handle 65 digits. MariaDB can store in + the .frm up to 63 digits. By default we use DECIMAL_NOT_SPECIFIED digits + when converting strings to decimal, so we don't want to set this too high. + To not use up all digits for the scale we limit the number of decimals to + 38. +*/ +#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2) +#define DECIMAL_MAX_SCALE 38 +#define DECIMAL_NOT_SPECIFIED 39 + +/** + maximum length of string representation (number of maximum decimal + digits + 1 position for sign + 1 position for decimal point, no terminator) +*/ +#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2) + +#endif /* MY_DECIMAL_LIMITS_INCLUDED */ diff --git a/include/my_default.h b/include/my_default.h new file mode 100644 index 00000000..0f158bbb --- /dev/null +++ b/include/my_default.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2013 Monty Program Ab + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Definitions for mysys/my_default.c */ + +#ifndef MY_DEFAULT_INCLUDED +#define MY_DEFAULT_INCLUDED + +C_MODE_START + +extern MYSQL_PLUGIN_IMPORT const char *my_defaults_extra_file; +extern const char *my_defaults_group_suffix; +extern MYSQL_PLUGIN_IMPORT const char *my_defaults_file; +extern my_bool my_defaults_mark_files; + +extern int get_defaults_options(char **argv); +extern int my_load_defaults(const char *conf_file, const char **groups, + int *argc, char ***argv, const char ***); +extern int load_defaults(const char *conf_file, const char **groups, + int *argc, char ***argv); +extern void free_defaults(char **argv); +extern void my_print_default_files(const char *conf_file); +extern void print_defaults(const char *conf_file, const char **groups); + + +/** Simplify load_defaults() common use */ +#define load_defaults_or_exit(A, B, C, D) switch (load_defaults(A, B, C, D)) { \ + case 0: break; \ + case 4: my_end(0); exit(0); \ + default: my_end(0); exit(1); } + +C_MODE_END + +#endif /* MY_DEFAULT_INCLUDED */ diff --git a/include/my_dir.h b/include/my_dir.h new file mode 100644 index 00000000..ecd37b29 --- /dev/null +++ b/include/my_dir.h @@ -0,0 +1,116 @@ +/* Copyright (c) 2000, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MY_DIR_H +#define MY_DIR_H + +#include <sys/stat.h> + +#ifdef __cplusplus +extern "C" { +#endif + + /* Defines for my_dir and my_stat */ + +#define MY_S_IFMT S_IFMT /* type of file */ +#define MY_S_IFDIR S_IFDIR /* directory */ +#define MY_S_IFCHR S_IFCHR /* character special */ +#define MY_S_IFBLK S_IFBLK /* block special */ +#define MY_S_IFREG S_IFREG /* regular */ +#define MY_S_IFIFO S_IFIFO /* fifo */ +#define MY_S_ISUID S_ISUID /* set user id on execution */ +#define MY_S_ISGID S_ISGID /* set group id on execution */ +#define MY_S_ISVTX S_ISVTX /* save swapped text even after use */ + +#ifndef S_IREAD +#define MY_S_IREAD S_IRUSR /* read permission, owner */ +#define MY_S_IWRITE S_IWUSR /* write permission, owner */ +#define MY_S_IEXEC S_IXUSR /* execute/search permission, owner */ +#else +#define MY_S_IREAD S_IREAD /* read permission, owner */ +#define MY_S_IWRITE S_IWRITE /* write permission, owner */ +#define MY_S_IEXEC S_IEXEC /* execute/search permission, owner */ +#endif + +#define MY_S_ISDIR(m) (((m) & MY_S_IFMT) == MY_S_IFDIR) +#define MY_S_ISCHR(m) (((m) & MY_S_IFMT) == MY_S_IFCHR) +#define MY_S_ISBLK(m) (((m) & MY_S_IFMT) == MY_S_IFBLK) +#define MY_S_ISREG(m) (((m) & MY_S_IFMT) == MY_S_IFREG) +#define MY_S_ISFIFO(m) (((m) & MY_S_IFMT) == MY_S_IFIFO) + +/* Ensure these doesn't clash with anything in my_sys.h */ +#define MY_WANT_SORT 8192 /* my_lib; sort files */ +#define MY_WANT_STAT 16384 /* my_lib; stat files */ +#define MY_DONT_SORT 0 + + /* typedefs for my_dir & my_stat */ + +#ifdef USE_MY_STAT_STRUCT + +typedef struct my_stat +{ + dev_t st_dev; /* major & minor device numbers */ + ino_t st_ino; /* inode number */ + ushort st_mode; /* file permissions (& suid sgid .. bits) */ + short st_nlink; /* number of links to file */ + ushort st_uid; /* user id */ + ushort st_gid; /* group id */ + dev_t st_rdev; /* more major & minor device numbers (???) */ + off_t st_size; /* size of file */ + time_t st_atime; /* time for last read */ + time_t st_mtime; /* time for last contents modify */ + time_t st_ctime; /* time for last inode or contents modify */ +} MY_STAT; + +#else + +#if defined(_MSC_VER) +#define MY_STAT struct _stati64 /* 64 bit file size */ +#else +#define MY_STAT struct stat /* Original struct has what we need */ +#endif + +#endif /* USE_MY_STAT_STRUCT */ + +/* Struct describing one file returned from my_dir */ +typedef struct fileinfo +{ + char *name; + MY_STAT *mystat; +} FILEINFO; + +typedef struct st_my_dir /* Struct returned from my_dir */ +{ + /* + These members are just copies of parts of DYNAMIC_ARRAY structure, + which is allocated right after the end of MY_DIR structure (MEM_ROOT + for storing names is also resides there). We've left them here because + we don't want to change code that uses my_dir. + */ + struct fileinfo *dir_entry; + size_t number_of_files; +} MY_DIR; + +extern MY_DIR *my_dir(const char *path,myf MyFlags); +extern void my_dirend(MY_DIR *buffer); +extern MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags); +extern int my_fstat(int filenr, MY_STAT *stat_area, myf MyFlags); + +#ifdef __cplusplus +} +#endif + +#endif /* MY_DIR_H */ + diff --git a/include/my_getopt.h b/include/my_getopt.h new file mode 100644 index 00000000..ffff706e --- /dev/null +++ b/include/my_getopt.h @@ -0,0 +1,133 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_getopt_h +#define _my_getopt_h + +#include "my_sys.h" /* loglevel */ +/* my_getopt and my_default are almost always used together */ +#include <my_default.h> + +C_MODE_START + +#define GET_NO_ARG 1 +#define GET_BOOL 2 +#define GET_INT 3 +#define GET_UINT 4 +#define GET_LONG 5 +#define GET_ULONG 6 +#define GET_LL 7 +#define GET_ULL 8 +#define GET_STR 9 +#define GET_STR_ALLOC 10 +#define GET_DISABLED 11 +#define GET_ENUM 12 +#define GET_SET 13 +#define GET_DOUBLE 14 +#define GET_FLAGSET 15 +#define GET_BIT 16 + +#define GET_ASK_ADDR 128 +#define GET_AUTO 64 +#define GET_TYPE_MASK 63 + +/** + Enumeration of the my_option::arg_type attributes. + It should be noted that for historical reasons variables with the combination + arg_type=NO_ARG, my_option::var_type=GET_BOOL still accepts + arguments. This is someone counter intuitive and care should be taken + if the code is refactored. +*/ +enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; + +struct st_typelib; + +struct my_option +{ + const char *name; /**< Name of the option. name=NULL + marks the end of the my_option[] + array. + */ + int id; /**< For 0<id<255 it's means one + character for a short option + (like -A), if >255 no short option + is created, but a long option still + can be identified uniquely in the + my_get_one_option() callback. + If an opton needs neither special + treatment in the my_get_one_option() + nor one-letter short equivalent + use id=0 + */ + const char *comment; /**< option comment, for autom. --help. + if it's NULL the option is not + visible in --help. + */ + void *value; /**< A pointer to the variable value */ + void *u_max_value; /**< The user def. max variable value */ + struct st_typelib *typelib; /**< Pointer to possible values */ + ulong var_type; /**< GET_BOOL, GET_ULL, etc */ + enum get_opt_arg_type arg_type; /**< e.g. REQUIRED_ARG or OPT_ARG */ + longlong def_value; /**< Default value */ + longlong min_value; /**< Min allowed value (for numbers) */ + ulonglong max_value; /**< Max allowed value (for numbers) */ + longlong sub_size; /**< Unused */ + long block_size; /**< Value should be a mult. of this (for numbers) */ + void *app_type; /**< To be used by an application */ +}; + +typedef my_bool (*my_get_one_option)(const struct my_option *, const char *, const char *); + +/** + Used to retrieve a reference to the object (variable) that holds the value + for the given option. For example, if var_type is GET_UINT, the function + must return a pointer to a variable of type uint. A argument is stored in + the location pointed to by the returned pointer. +*/ +typedef void *(*my_getopt_value)(const char *, uint, const struct my_option *, + int *); + + +extern char *disabled_my_option; +extern char *autoset_my_option; +extern my_bool my_getopt_print_errors; +extern my_bool my_getopt_skip_unknown; +extern my_bool my_getopt_prefix_matching; +extern my_bool my_handle_options_init_variables; +extern my_error_reporter my_getopt_error_reporter; +extern my_getopt_value my_getopt_get_addr; + +extern int handle_options (int *argc, char ***argv, + const struct my_option *longopts, my_get_one_option) + __attribute__((nonnull)); +extern void my_cleanup_options(const struct my_option *options); +extern void my_print_help(const struct my_option *options); +extern void my_print_variables(const struct my_option *options); + +ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, + my_bool *fix); +longlong getopt_ll_limit_value(longlong, const struct my_option *, + my_bool *fix); +double getopt_double_limit_value(double num, const struct my_option *optp, + my_bool *fix); + +ulonglong getopt_double2ulonglong(double); +double getopt_ulonglong2double(ulonglong); + +C_MODE_END + +#endif /* _my_getopt_h */ + diff --git a/include/my_global.h b/include/my_global.h new file mode 100644 index 00000000..54f76bf5 --- /dev/null +++ b/include/my_global.h @@ -0,0 +1,1199 @@ +/* + Copyright (c) 2001, 2013, Oracle and/or its affiliates. + Copyright (c) 2009, 2022, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* This is the include file that should be included 'first' in every C file. */ + +#ifndef MY_GLOBAL_INCLUDED +#define MY_GLOBAL_INCLUDED + +/* + MDEV-25602 Deprecate __WIN__ symbol. +*/ +#if defined (_MSC_VER) && !defined(__clang__) +#pragma deprecated("__WIN__") +#elif defined (__GNUC__) +#pragma GCC poison __WIN__ +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +/* + Following functions have bugs, when used with UTF-8 active codepage. + #include <winservice.h> will use the non-buggy wrappers +*/ +#pragma deprecated("CreateServiceA", "OpenServiceA", "ChangeServiceConfigA") +#endif + +/* + InnoDB depends on some MySQL internals which other plugins should not + need. This is because of InnoDB's foreign key support, "safe" binlog + truncation, and other similar legacy features. + + We define accessors for these internals unconditionally, but do not + expose them in mysql/plugin.h. They are declared in ha_innodb.h for + InnoDB's use. +*/ +#define INNODB_COMPATIBILITY_HOOKS + +#ifdef __CYGWIN__ +/* We use a Unix API, so pretend it's not Windows */ +#undef WIN +#undef WIN32 +#undef _WIN +#undef _WIN32 +#undef _WIN64 +#undef _WIN32 +#undef __WIN32__ +#define HAVE_ERRNO_AS_DEFINE +#define _POSIX_MONOTONIC_CLOCK +#define _POSIX_THREAD_CPUTIME +#endif /* __CYGWIN__ */ + +#if defined(__OpenBSD__) && (OpenBSD >= 200411) +#define HAVE_ERRNO_AS_DEFINE +#endif + +#if defined(i386) && !defined(__i386__) +#define __i386__ +#endif + +/* Macros to make switching between C and C++ mode easier */ +#ifdef __cplusplus +#define C_MODE_START extern "C" { +#define C_MODE_END } +#else +#define C_MODE_START +#define C_MODE_END +#endif + +#ifdef __cplusplus +#define CPP_UNNAMED_NS_START namespace { +#define CPP_UNNAMED_NS_END } +#endif + +#include <my_config.h> + +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE +#define HAVE_PSI_INTERFACE +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + +/* Make it easier to add conditional code in _expressions_ */ +#ifdef _WIN32 +#define IF_WIN(A,B) A +#else +#define IF_WIN(A,B) B +#endif + +#ifdef EMBEDDED_LIBRARY +#define IF_EMBEDDED(A,B) A +#else +#define IF_EMBEDDED(A,B) B +#endif + +#ifdef WITH_PARTITION_STORAGE_ENGINE +#define IF_PARTITIONING(A,B) A +#else +#define IF_PARTITIONING(A,B) B +#endif + +#if defined (_WIN32) +/* + off_t is 32 bit long. We do not use C runtime functions + with off_t but native Win32 file IO APIs, that work with + 64 bit offsets. +*/ +#undef SIZEOF_OFF_T +#define SIZEOF_OFF_T 8 + +/* + Prevent inclusion of Windows GDI headers - they define symbol + ERROR that conflicts with mysql headers. +*/ +#ifndef NOGDI +#define NOGDI +#endif + +/* Include common headers.*/ +#include <winsock2.h> +#include <ws2tcpip.h> /* SOCKET */ +#include <io.h> /* access(), chmod() */ +#include <process.h> /* getpid() */ + +#define sleep(a) Sleep((a)*1000) + +/* Define missing access() modes. */ +#define F_OK 0 +#define W_OK 2 +#define R_OK 4 /* Test for read permission. */ + +/* Define missing file locking constants. */ +#define F_RDLCK 1 +#define F_WRLCK 2 +#define F_UNLCK 3 +#define F_TO_EOF 0x3FFFFFFF + +#endif /* _WIN32*/ + +/* + The macros below are used to allow build of Universal/fat binaries of + MySQL and MySQL applications under darwin. +*/ +#if defined(__APPLE__) && defined(__MACH__) +# undef SIZEOF_CHARP +# undef SIZEOF_INT +# undef SIZEOF_LONG +# undef SIZEOF_LONG_LONG +# undef SIZEOF_OFF_T +# undef WORDS_BIGENDIAN +# define SIZEOF_INT 4 +# define SIZEOF_LONG_LONG 8 +# define SIZEOF_OFF_T 8 +# if defined(__i386__) || defined(__ppc__) +# define SIZEOF_CHARP 4 +# define SIZEOF_LONG 4 +# elif defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__) || defined(__arm64__) +# define SIZEOF_CHARP 8 +# define SIZEOF_LONG 8 +# else +# error Building FAT binary for an unknown architecture. +# endif +# if defined(__ppc__) || defined(__ppc64__) +# define WORDS_BIGENDIAN +# endif +#endif /* defined(__APPLE__) && defined(__MACH__) */ + + +/* + The macros below are borrowed from include/linux/compiler.h in the + Linux kernel. Use them to indicate the likelihood of the truthfulness + of a condition. This serves two purposes - newer versions of gcc will be + able to optimize for branch predication, which could yield siginficant + performance gains in frequently executed sections of the code, and the + other reason to use them is for documentation +*/ + +#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) +#define __builtin_expect(x, expected_value) (x) +#endif + +/* Fix problem with S_ISLNK() on Linux */ +#if defined(TARGET_OS_LINUX) || defined(__GLIBC__) +#undef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +/* + Temporary solution to solve bug#7156. Include "sys/types.h" before + the thread headers, else the function madvise() will not be defined +*/ +#if defined(HAVE_SYS_TYPES_H) && ( defined(sun) || defined(__sun) ) +#include <sys/types.h> +#endif + +#define __EXTENSIONS__ 1 /* We want some extension */ +#ifndef __STDC_EXT__ +#define __STDC_EXT__ 1 /* To get large file support on hpux */ +#endif + +/* + Solaris 9 include file <sys/feature_tests.h> refers to X/Open document + + System Interfaces and Headers, Issue 5 + + saying we should define _XOPEN_SOURCE=500 to get POSIX.1c prototypes, + but apparently other systems (namely FreeBSD) don't agree. + + On a newer Solaris 10, the above file recognizes also _XOPEN_SOURCE=600. + Furthermore, it tests that if a program requires older standard + (_XOPEN_SOURCE<600 or _POSIX_C_SOURCE<200112L) it cannot be + run on a new compiler (that defines _STDC_C99) and issues an #error. + It's also an #error if a program requires new standard (_XOPEN_SOURCE=600 + or _POSIX_C_SOURCE=200112L) and a compiler does not define _STDC_C99. + + To add more to this mess, Sun Studio C compiler defines _STDC_C99 while + C++ compiler does not! + + So, in a desperate attempt to get correct prototypes for both + C and C++ code, we define either _XOPEN_SOURCE=600 or _XOPEN_SOURCE=500 + depending on the compiler's announced C standard support. + + Cleaner solutions are welcome. +*/ +#ifdef __sun +#if __STDC_VERSION__ - 0 >= 199901L +#define _XOPEN_SOURCE 600 +#else +#define _XOPEN_SOURCE 500 +#endif +#endif + + +#ifdef _AIX +/* + AIX includes inttypes.h from sys/types.h + Explicitly request format macros before the first inclusion of inttypes.h +*/ +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif // !defined(__STDC_FORMAT_MACROS) +#endif + + +#if !defined(_WIN32) +#ifndef _POSIX_PTHREAD_SEMANTICS +#define _POSIX_PTHREAD_SEMANTICS /* We want posix threads */ +#endif + +#if !defined(SCO) +#define _REENTRANT 1 /* Some thread libraries require this */ +#endif +#if !defined(_THREAD_SAFE) && !defined(_AIX) +#define _THREAD_SAFE /* Required for OSF1 */ +#endif +#if defined(HPUX10) || defined(HPUX11) +C_MODE_START /* HPUX needs this, signal.h bug */ +#include <pthread.h> +C_MODE_END +#else +#include <pthread.h> /* AIX must have this included first */ +#endif +#if !defined(SCO) && !defined(_REENTRANT) +#define _REENTRANT 1 /* Threads requires reentrant code */ +#endif +#endif /* !defined(_WIN32) */ + +/* gcc/egcs issues */ + +#if defined(__GNUC) && defined(__EXCEPTIONS) +#error "Please add -fno-exceptions to CXXFLAGS and reconfigure/recompile" +#endif + +#if defined(_lint) && !defined(lint) +#define lint +#endif + +#ifndef stdin +#include <stdio.h> +#endif +#include <stdarg.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STDDEF_H +#include <stddef.h> +#endif + +#include <math.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#ifdef HAVE_FLOAT_H +#include <float.h> +#endif +#ifdef HAVE_FENV_H +#include <fenv.h> /* For fesetround() */ +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif /* TIME_WITH_SYS_TIME */ +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <errno.h> /* Recommended by debian */ +/* We need the following to go around a problem with openssl on solaris */ +#if defined(HAVE_CRYPT_H) +#include <crypt.h> +#endif + +/* Add checking if we are using likely/unlikely wrong */ +#ifdef CHECK_UNLIKELY +C_MODE_START +extern void init_my_likely(), end_my_likely(FILE *); +extern int my_likely_ok(const char *file_name, uint line); +extern int my_likely_fail(const char *file_name, uint line); +C_MODE_END + +#define likely(A) ((A) ? (my_likely_ok(__FILE__, __LINE__),1) : (my_likely_fail(__FILE__, __LINE__), 0)) +#define unlikely(A) ((A) ? (my_likely_fail(__FILE__, __LINE__),1) : (my_likely_ok(__FILE__, __LINE__), 0)) +/* + These macros should be used when the check fails often when running benchmarks but + we know for sure that the check is correct in a production environment +*/ +#define checked_likely(A) (A) +#define checked_unlikely(A) (A) +#else +/** + The semantics of builtin_expect() are that + 1) its two arguments are long + 2) it's likely that they are == + Those of our likely(x) are that x can be bool/int/longlong/pointer. +*/ + +#define likely(x) __builtin_expect(((x) != 0),1) +#define unlikely(x) __builtin_expect(((x) != 0),0) +#define checked_likely(x) likely(x) +#define checked_unlikely(x) unlikely(x) +#endif /* CHECK_UNLIKELY */ + +/* + A lot of our programs uses asserts, so better to always include it + This also fixes a problem when people uses DBUG_ASSERT without including + assert.h +*/ +#include <assert.h> + +/* an assert that works at compile-time. only for constant expression */ +#ifdef _some_old_compiler_that_does_not_understand_the_construct_below_ +#define compile_time_assert(X) do { } while(0) +#else +#define compile_time_assert(X) \ + do \ + { \ + typedef char compile_time_assert[(X) ? 1 : -1] __attribute__((unused)); \ + } while(0) +#endif + +/* Go around some bugs in different OS and compilers */ +#if defined (HPUX11) && defined(_LARGEFILE_SOURCE) +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H) +#include <sys/stream.h> /* HPUX 10.20 defines ulong here. UGLY !!! */ +#define HAVE_ULONG +#endif +#if defined(HPUX10) && defined(_LARGEFILE64_SOURCE) +/* Fix bug in setrlimit */ +#undef setrlimit +#define setrlimit cma_setrlimit64 +#endif +/* Declare madvise where it is not declared for C++, like Solaris */ +#if HAVE_MADVISE && !HAVE_DECL_MADVISE && defined(__cplusplus) +extern "C" int madvise(void *addr, size_t len, int behav); +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +/** FreeBSD equivalent */ +#if defined(MADV_CORE) && !defined(MADV_DODUMP) +#define MADV_DODUMP MADV_CORE +#define MADV_DONTDUMP MADV_NOCORE +#define DODUMP_STR "MADV_CORE" +#define DONTDUMP_STR "MADV_NOCORE" +#else +#define DODUMP_STR "MADV_DODUMP" +#define DONTDUMP_STR "MADV_DONTDUMP" +#endif + + +#define QUOTE_ARG(x) #x /* Quote argument (before cpp) */ +#define STRINGIFY_ARG(x) QUOTE_ARG(x) /* Quote argument, after cpp */ + +/* Paranoid settings. Define I_AM_PARANOID if you are paranoid */ +#ifdef I_AM_PARANOID +#define DONT_ALLOW_USER_CHANGE 1 +#define DONT_USE_MYSQL_PWD 1 +#endif + +/* Does the system remember a signal handler after a signal ? */ +#if !defined(HAVE_BSD_SIGNALS) && !defined(HAVE_SIGACTION) +#define SIGNAL_HANDLER_RESET_ON_DELIVERY +#endif + +/* don't assume that STDERR_FILENO is 2, mysqld can freopen */ +#undef STDERR_FILENO + +#ifndef SO_EXT +#ifdef _WIN32 +#define SO_EXT ".dll" +#else +#define SO_EXT ".so" +#endif +#endif + +/* + Suppress uninitialized variable warning without generating code. +*/ +#if defined(__GNUC__) +/* GCC specific self-initialization which inhibits the warning. */ +#define UNINIT_VAR(x) x= x +#elif defined(_lint) || defined(FORCE_INIT_OF_VARS) +#define UNINIT_VAR(x) x= 0 +#else +#define UNINIT_VAR(x) x +#endif + +/* This is only to be used when resetting variables in a class constructor */ +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) +#define LINT_INIT(x) x= 0 +#else +#define LINT_INIT(x) +#endif + +#if !defined(HAVE_UINT) +#undef HAVE_UINT +#define HAVE_UINT +typedef unsigned int uint; +typedef unsigned short ushort; +#endif + +#define swap_variables(t, a, b) do { t dummy; dummy= a; a= b; b= dummy; } while(0) +#define MY_TEST(a) ((a) ? 1 : 0) +#define set_if_bigger(a,b) do { if ((a) < (b)) (a)=(b); } while(0) +#define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0) +#define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1)) +#define test_all_bits(a,b) (((a) & (b)) == (b)) +#define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0]))) + +/* Define some general constants */ +#ifndef TRUE +#define TRUE (1) /* Logical true */ +#define FALSE (0) /* Logical false */ +#endif + +#include <my_compiler.h> +#include <my_alloca.h> + +/* + Wen using the embedded library, users might run into link problems, + duplicate declaration of __cxa_pure_virtual, solved by declaring it a + weak symbol. +*/ +#if defined(USE_MYSYS_NEW) && ! defined(DONT_DECLARE_CXA_PURE_VIRTUAL) +C_MODE_START +int __cxa_pure_virtual () __attribute__ ((weak)); +C_MODE_END +#endif + +/* The DBUG_ON flag always takes precedence over default DBUG_OFF */ +#if defined(DBUG_ON) && defined(DBUG_OFF) +#undef DBUG_OFF +#endif + +/* We might be forced to turn debug off, if not turned off already */ +#if (defined(FORCE_DBUG_OFF) || defined(_lint)) && !defined(DBUG_OFF) +# define DBUG_OFF +# ifdef DBUG_ON +# undef DBUG_ON +# endif +#endif + +#ifdef DBUG_OFF +#undef EXTRA_DEBUG +#endif + +/* Some types that is different between systems */ + +typedef int File; /* File descriptor */ +#ifdef _WIN32 +typedef SOCKET my_socket; +#else +typedef int my_socket; /* File descriptor for sockets */ +#define INVALID_SOCKET -1 +#endif +/* Type for functions that handles signals */ +#define sig_handler RETSIGTYPE +#if defined(__GNUC__) && !defined(_lint) +typedef char pchar; /* Mixed prototypes can take char */ +typedef char puchar; /* Mixed prototypes can take char */ +typedef char pbool; /* Mixed prototypes can take char */ +typedef short pshort; /* Mixed prototypes can take short int */ +typedef float pfloat; /* Mixed prototypes can take float */ +#else +typedef int pchar; /* Mixed prototypes can't take char */ +typedef uint puchar; /* Mixed prototypes can't take char */ +typedef int pbool; /* Mixed prototypes can't take char */ +typedef int pshort; /* Mixed prototypes can't take short int */ +typedef double pfloat; /* Mixed prototypes can't take float */ +#endif +C_MODE_START +typedef int (*qsort_cmp)(const void *,const void *); +typedef int (*qsort_cmp2)(void*, const void *,const void *); +C_MODE_END +#define qsort_t RETQSORTTYPE /* Broken GCC can't handle typedef !!!! */ +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +typedef SOCKET_SIZE_TYPE size_socket; + +#ifndef SOCKOPT_OPTLEN_TYPE +#define SOCKOPT_OPTLEN_TYPE size_socket +#endif + +/* file create flags */ + +#ifndef O_SHARE /* Probably not windows */ +#define O_SHARE 0 /* Flag to my_open for shared files */ +#ifndef O_BINARY +#define O_BINARY 0 /* Flag to my_open for binary files */ +#endif +#ifndef FILE_BINARY +#define FILE_BINARY O_BINARY /* Flag to my_fopen for binary streams */ +#endif +#ifdef HAVE_FCNTL +#define HAVE_FCNTL_LOCK +#define F_TO_EOF 0L /* Param to lockf() to lock rest of file */ +#endif +#endif /* O_SHARE */ + +#ifndef O_SEQUENTIAL +#define O_SEQUENTIAL 0 +#endif +#ifndef O_SHORT_LIVED +#define O_SHORT_LIVED 0 +#endif +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif +#ifdef __GLIBC__ +#define STR_O_CLOEXEC "e" +#else +#define STR_O_CLOEXEC "" +#endif +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#else +#define HAVE_SOCK_CLOEXEC +#endif +#ifndef O_TEXT +#define O_TEXT 0 +#endif + +/* additional file share flags for win32 */ +#ifdef _WIN32 +#define _SH_DENYRWD 0x110 /* deny read/write mode & delete */ +#define _SH_DENYWRD 0x120 /* deny write mode & delete */ +#define _SH_DENYRDD 0x130 /* deny read mode & delete */ +#define _SH_DENYDEL 0x140 /* deny delete only */ +#endif /* _WIN32 */ + + +/* General constants */ +#define FN_LEN 256 /* Max file name len */ +#define FN_HEADLEN 253 /* Max length of filepart of file name */ +#define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */ +#define FN_REFLEN 512 /* Max length of full path-name */ +#define FN_EXTCHAR '.' +#define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */ +#define FN_CURLIB '.' /* ./ is used as abbrev for current dir */ +#define FN_PARENTDIR ".." /* Parent directory; Must be a string */ + +#ifdef _WIN32 +#define FN_LIBCHAR '\\' +#define FN_LIBCHAR2 '/' +#define FN_DIRSEP "/\\" /* Valid directory separators */ +#define FN_EXEEXT ".exe" +#define FN_SOEXT ".dll" +#define FN_ROOTDIR "\\" +#define FN_DEVCHAR ':' +#define FN_NETWORK_DRIVES /* Uses \\ to indicate network drives */ +#define FN_NO_CASE_SENCE /* Files are not case-sensitive */ +#else +#define FN_LIBCHAR '/' +#define FN_LIBCHAR2 '/' +#define FN_DIRSEP "/" /* Valid directory separators */ +#define FN_EXEEXT "" +#define FN_SOEXT ".so" +#define FN_ROOTDIR "/" +#endif + +/* + MY_FILE_MIN is Windows speciality and is used to quickly detect + the mismatch of CRT and mysys file IO usage on Windows at runtime. + CRT file descriptors can be in the range 0-2047, whereas descriptors returned + by my_open() will start with 2048. If a file descriptor with value less then + MY_FILE_MIN is passed to mysys IO function, chances are it stems from + open()/fileno() and not my_open()/my_fileno. + + For Posix, mysys functions are light wrappers around libc, and MY_FILE_MIN + is logically 0. +*/ + +#ifdef _WIN32 +#define MY_FILE_MIN 2048 +#else +#define MY_FILE_MIN 0 +#endif + +/* + MY_NFILE is the default size of my_file_info array. + + It is larger on Windows, because it all file handles are stored in my_file_info + Default size is 16384 and this should be enough for most cases.If it is not + enough, --max-open-files with larger value can be used. + + For Posix , my_file_info array is only used to store filenames for + error reporting and its size is not a limitation for number of open files. +*/ +#ifdef _WIN32 +#define MY_NFILE (16384 + MY_FILE_MIN) +#else +#define MY_NFILE 64 +#endif + +#ifndef OS_FILE_LIMIT +#define OS_FILE_LIMIT UINT_MAX +#endif + +/* + Io buffer size; Must be a power of 2 and a multiple of 512. May be + smaller what the disk page size. This influences the speed of the + isam btree library. eg to big to slow. +*/ +#define IO_SIZE 4096U +/* + How much overhead does malloc have. The code often allocates + something like 1024-MALLOC_OVERHEAD bytes +*/ +#define MALLOC_OVERHEAD 8 + + /* get memory in huncs */ +#define ONCE_ALLOC_INIT (uint) 4096 + /* Typical record cache */ +#define RECORD_CACHE_SIZE (uint) (128*1024) + /* Typical key cache */ +#define KEY_CACHE_SIZE (uint) (128L*1024L*1024L) + /* Default size of a key cache block */ +#define KEY_CACHE_BLOCK_SIZE (uint) 1024 + + /* Some things that this system doesn't have */ + +#ifdef _WIN32 +#define NO_DIR_LIBRARY /* Not standard dir-library */ +#endif + +/* Some defines of functions for portability */ + +#undef remove /* Crashes MySQL on SCO 5.0.0 */ +#ifndef _WIN32 +#define closesocket(A) close(A) +#endif + +#if defined(_MSC_VER) +#if !defined(_WIN64) +inline double my_ulonglong2double(unsigned long long value) +{ + long long nr=(long long) value; + if (nr >= 0) + return (double) nr; + return (18446744073709551616.0 + (double) nr); +} +#define ulonglong2double my_ulonglong2double +#define my_off_t2double my_ulonglong2double +#endif /* _WIN64 */ +inline unsigned long long my_double2ulonglong(double d) +{ + double t= d - (double) 0x8000000000000000ULL; + + if (t >= 0) + return ((unsigned long long) t) + 0x8000000000000000ULL; + return (unsigned long long) d; +} +#define double2ulonglong my_double2ulonglong +#endif + +#ifndef ulonglong2double +#define ulonglong2double(A) ((double) (ulonglong) (A)) +#define my_off_t2double(A) ((double) (my_off_t) (A)) +#endif +#ifndef double2ulonglong +#define double2ulonglong(A) ((ulonglong) (double) (A)) +#endif + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif +#define ulong_to_double(X) ((double) (ulong) (X)) + +#ifndef STACK_DIRECTION +#error "please add -DSTACK_DIRECTION=1 or -1 to your CPPFLAGS" +#endif + +#if !defined(HAVE_STRTOK_R) +#define strtok_r(A,B,C) strtok((A),(B)) +#endif + +#if SIZEOF_LONG_LONG >= 8 +#define HAVE_LONG_LONG 1 +#else +#error WHAT? sizeof(long long) < 8 ??? +#endif + +/* + Some pre-ANSI-C99 systems like AIX 5.1 and Linux/GCC 2.95 define + ULONGLONG_MAX, LONGLONG_MIN, LONGLONG_MAX; we use them if they're defined. +*/ + +#if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN) +#define LONGLONG_MIN ((long long) 0x8000000000000000LL) +#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL) +#endif +/* Max length needed for a buffer to hold a longlong or ulonglong + end \0 */ +#define LONGLONG_BUFFER_SIZE 21 + +#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX) +/* First check for ANSI C99 definition: */ +#ifdef ULLONG_MAX +#define ULONGLONG_MAX ULLONG_MAX +#else +#define ULONGLONG_MAX ((unsigned long long)(~0ULL)) +#endif +#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/ + +#define INT_MIN64 (~0x7FFFFFFFFFFFFFFFLL) +#define INT_MAX64 0x7FFFFFFFFFFFFFFFLL +#define INT_MIN32 (~0x7FFFFFFFL) +#define INT_MAX32 0x7FFFFFFFL +#define UINT_MAX32 0xFFFFFFFFL +#define INT_MIN24 (~0x007FFFFF) +#define INT_MAX24 0x007FFFFF +#define UINT_MAX24 0x00FFFFFF +#define INT_MIN16 (~0x7FFF) +#define INT_MAX16 0x7FFF +#define UINT_MAX16 0xFFFF +#define INT_MIN8 (~0x7F) +#define INT_MAX8 0x7F +#define UINT_MAX8 0xFF + +/* From limits.h instead */ +#ifndef DBL_MIN +#define DBL_MIN 4.94065645841246544e-324 +#define FLT_MIN ((float)1.40129846432481707e-45) +#endif +#ifndef DBL_MAX +#define DBL_MAX 1.79769313486231470e+308 +#define FLT_MAX ((float)3.40282346638528860e+38) +#endif +#ifndef SIZE_T_MAX +#define SIZE_T_MAX (~((size_t) 0)) +#endif + +/* Define missing math constants. */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_E +#define M_E 2.7182818284590452354 +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif + +/* + Max size that must be added to a so that we know Size to make + addressable obj. +*/ +#if SIZEOF_CHARP == 4 +typedef long my_ptrdiff_t; +#else +typedef long long my_ptrdiff_t; +#endif + +#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) +#define MY_ALIGN_DOWN(A,L) ((A) & ~((L) - 1)) +#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) +#define ALIGN_MAX_UNIT (sizeof(double)) +/* Size to make addressable obj. */ +#define ALIGN_PTR(A, t) ((t*) MY_ALIGN((A), sizeof(double))) +#define ADD_TO_PTR(ptr,size,type) (type) ((uchar*) (ptr)+size) +#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((uchar*) (A) - (uchar*) (B)) +#define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1)) + +/* + Custom version of standard offsetof() macro which can be used to get + offsets of members in class for non-POD types (according to the current + version of C++ standard offsetof() macro can't be used in such cases and + attempt to do so causes warnings to be emitted, OTOH in many cases it is + still OK to assume that all instances of the class has the same offsets + for the same members). + + This is temporary solution which should be removed once File_parser class + and related routines are refactored. +*/ + +#define my_offsetof(TYPE, MEMBER) PTR_BYTE_DIFF(&((TYPE *)0x10)->MEMBER, 0x10) + +#define NullS (char *) 0 + +#ifdef STDCALL +#undef STDCALL +#endif + +#ifdef _WIN32 +#define STDCALL __stdcall +#else +#define STDCALL +#endif + +/* Typdefs for easier portability */ + +#ifndef HAVE_UCHAR +typedef unsigned char uchar; /* Short for unsigned char */ +#endif + +#ifndef HAVE_INT8 +typedef signed char int8; /* Signed integer >= 8 bits */ +#endif +#ifndef HAVE_UINT8 +typedef unsigned char uint8; /* Unsigned integer >= 8 bits */ +#endif +#ifndef HAVE_INT16 +typedef short int16; +#endif +#ifndef HAVE_UINT16 +typedef unsigned short uint16; +#endif +#if SIZEOF_INT == 4 +#ifndef HAVE_INT32 +typedef int int32; +#endif +#ifndef HAVE_UINT32 +typedef unsigned int uint32; +#endif +#elif SIZEOF_LONG == 4 +#ifndef HAVE_INT32 +typedef long int32; +#endif +#ifndef HAVE_UINT32 +typedef unsigned long uint32; +#endif +#else +#error Neither int or long is of 4 bytes width +#endif + +#if !defined(HAVE_ULONG) && !defined(__USE_MISC) +typedef unsigned long ulong; /* Short for unsigned long */ +#endif +#ifndef longlong_defined +/* + Using [unsigned] long long is preferable as [u]longlong because we use + [unsigned] long long unconditionally in many places, + for example in constants with [U]LL suffix. +*/ +#if defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8 +typedef unsigned long long int ulonglong; /* ulong or unsigned long long */ +typedef long long int longlong; +#else +typedef unsigned long ulonglong; /* ulong or unsigned long long */ +typedef long longlong; +#endif +#endif +#ifndef HAVE_INT64 +typedef longlong int64; +#endif +#ifndef HAVE_UINT64 +typedef ulonglong uint64; +#endif + +#if defined(NO_CLIENT_LONG_LONG) +typedef unsigned long my_ulonglong; +#elif defined (_WIN32) +typedef unsigned __int64 my_ulonglong; +#else +typedef unsigned long long my_ulonglong; +#endif + +#if SIZEOF_CHARP == SIZEOF_INT +typedef unsigned int intptr; +#elif SIZEOF_CHARP == SIZEOF_LONG +typedef unsigned long intptr; +#elif SIZEOF_CHARP == SIZEOF_LONG_LONG +typedef unsigned long long intptr; +#else +#error sizeof(void *) is neither sizeof(int) nor sizeof(long) nor sizeof(long long) +#endif + +#define MY_ERRPTR ((void*)(intptr)1) + +#if defined(_WIN32) +typedef unsigned long long my_off_t; +typedef unsigned long long os_off_t; +#else +typedef off_t os_off_t; +#if SIZEOF_OFF_T > 4 +typedef ulonglong my_off_t; +#else +typedef unsigned long my_off_t; +#endif +#endif /*_WIN32*/ +#define MY_FILEPOS_ERROR (~(my_off_t) 0) + +/* + TODO Convert these to use Bitmap class. + */ +typedef ulonglong table_map; /* Used for table bits in join */ + +/* often used type names - opaque declarations */ +typedef const struct charset_info_st CHARSET_INFO; +typedef struct st_mysql_lex_string LEX_STRING; + +#if defined(_WIN32) +#define socket_errno WSAGetLastError() +#define SOCKET_EINTR WSAEINTR +#define SOCKET_ETIMEDOUT WSAETIMEDOUT +#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK +#define SOCKET_EADDRINUSE WSAEADDRINUSE +#define SOCKET_ECONNRESET WSAECONNRESET +#define SOCKET_ENFILE ENFILE +#define SOCKET_EMFILE EMFILE +#else /* Unix */ +#define socket_errno errno +#define closesocket(A) close(A) +#define SOCKET_EINTR EINTR +#define SOCKET_EAGAIN EAGAIN +#define SOCKET_EWOULDBLOCK EWOULDBLOCK +#define SOCKET_EADDRINUSE EADDRINUSE +#define SOCKET_ETIMEDOUT ETIMEDOUT +#define SOCKET_ECONNRESET ECONNRESET +#define SOCKET_ENFILE ENFILE +#define SOCKET_EMFILE EMFILE +#endif + +#include <mysql/plugin.h> /* my_bool */ + +typedef ulong myf; /* Type of MyFlags in my_funcs */ + +#define MYF(v) (myf) (v) + +/* + Defines to make it possible to prioritize register assignments. No + longer that important with modern compilers. +*/ +#ifndef USING_X +#define reg1 register +#define reg2 register +#define reg3 register +#define reg4 register +#define reg5 register +#define reg6 register +#define reg7 register +#define reg8 register +#define reg9 register +#define reg10 register +#define reg11 register +#define reg12 register +#define reg13 register +#define reg14 register +#define reg15 register +#define reg16 register +#endif + +/* + MYSQL_PLUGIN_IMPORT macro is used to export mysqld data + (i.e variables) for usage in storage engine loadable plugins. + Outside of Windows, it is dummy. +*/ +#ifndef MYSQL_PLUGIN_IMPORT +#if (defined(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN)) +#define MYSQL_PLUGIN_IMPORT __declspec(dllimport) +#else +#define MYSQL_PLUGIN_IMPORT +#endif +#endif + +#include <my_dbug.h> + +/* Some helper macros */ +#define YESNO(X) ((X) ? "yes" : "no") + +#define MY_HOW_OFTEN_TO_ALARM 2 /* How often we want info on screen */ +#define MY_HOW_OFTEN_TO_WRITE 10000 /* How often we want info on screen */ + +#include <my_byteorder.h> + +#ifdef HAVE_CHARSET_utf8mb4 +#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8mb4" +#elif defined(HAVE_CHARSET_utf8mb3) +#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8mb3" +#else +#define MYSQL_UNIVERSAL_CLIENT_CHARSET MYSQL_DEFAULT_CHARSET_NAME +#endif + +#if defined(EMBEDDED_LIBRARY) && !defined(HAVE_EMBEDDED_PRIVILEGE_CONTROL) +#define NO_EMBEDDED_ACCESS_CHECKS +#endif + +#ifdef _WIN32 +#define dlsym(lib, name) (void*)GetProcAddress((HMODULE)lib, name) +#define dlopen(libname, unused) LoadLibraryEx(libname, NULL, 0) +#define RTLD_DEFAULT GetModuleHandle(NULL) +#define dlclose(lib) FreeLibrary((HMODULE)lib) +static inline char *dlerror(void) +{ + static char win_errormsg[2048]; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + 0, GetLastError(), + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + win_errormsg, 2048, NULL); + return win_errormsg; +} +#define HAVE_DLOPEN 1 +#define HAVE_DLERROR 1 +#endif + +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#ifdef HAVE_DLOPEN +#ifndef HAVE_DLERROR +#define dlerror() "" +#endif +#ifndef HAVE_DLADDR +#define dladdr(A, B) 0 +/* Dummy definition in case we're missing dladdr() */ +typedef struct { const char *dli_fname, dli_fbase; } Dl_info; +#endif +#else +#define dlerror() "No support for dynamic loading (static build?)" +#define dlopen(A,B) 0 +#define dlsym(A,B) 0 +#define dlclose(A) 0 +#define dladdr(A, B) 0 +/* Dummy definition in case we're missing dladdr() */ +typedef struct { const char *dli_fname, dli_fbase; } Dl_info; +#endif + +/* + * Include standard definitions of operator new and delete. + */ +#ifdef __cplusplus +#include <new> +#endif + +/* Length of decimal number represented by INT32. */ +#define MY_INT32_NUM_DECIMAL_DIGITS 11 + +/* Length of decimal number represented by INT64. */ +#define MY_INT64_NUM_DECIMAL_DIGITS 21 + +#ifdef __cplusplus +#include <limits> /* should be included before min/max macros */ +#endif + +/* Define some useful general macros (should be done after all headers). */ +#define MY_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MY_MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define CMP_NUM(a,b) (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1) + +/* + Only Linux is known to need an explicit sync of the directory to make sure a + file creation/deletion/renaming in(from,to) this directory durable. +*/ +#ifdef TARGET_OS_LINUX +#define NEED_EXPLICIT_SYNC_DIR 1 +#else +/* + On linux default rwlock scheduling policy is good enough for + waiting_threads.c, on other systems use our special implementation + (which is slower). + + QQ perhaps this should be tested in configure ? how ? +*/ +#define WT_RWLOCKS_USE_MUTEXES 1 +#endif + +#if !defined(__cplusplus) && !defined(bool) +#define bool In_C_you_should_use_my_bool_instead() +#endif + +/* Provide __func__ macro definition for platforms that miss it. */ +#if !defined (__func__) +#if defined(__STDC_VERSION__) && __STDC_VERSION__ < 199901L +# if __GNUC__ >= 2 +# define __func__ __FUNCTION__ +# else +# define __func__ "<unknown>" +# endif +#elif defined(_MSC_VER) +# if _MSC_VER < 1300 +# define __func__ "<unknown>" +# else +# define __func__ __FUNCTION__ +# endif +#elif defined(__BORLANDC__) +# define __func__ __FUNC__ +#else +# define __func__ "<unknown>" +#endif +#endif /* !defined(__func__) */ + +/* Defines that are unique to the embedded version of MySQL */ + +#ifdef EMBEDDED_LIBRARY + +/* Things we don't need in the embedded version of MySQL */ +/* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */ + +#else +#define HAVE_REPLICATION +#define HAVE_EXTERNAL_CLIENT +#endif /* EMBEDDED_LIBRARY */ + +/* + Provide defaults for the CPU cache line size, if it has not been detected by + CMake using getconf +*/ +#if !defined(CPU_LEVEL1_DCACHE_LINESIZE) || CPU_LEVEL1_DCACHE_LINESIZE == 0 + #if defined(CPU_LEVEL1_DCACHE_LINESIZE) && CPU_LEVEL1_DCACHE_LINESIZE == 0 + #undef CPU_LEVEL1_DCACHE_LINESIZE + #endif + + #if defined(__s390__) + #define CPU_LEVEL1_DCACHE_LINESIZE 256 + #elif defined(__powerpc__) || defined(__aarch64__) + #define CPU_LEVEL1_DCACHE_LINESIZE 128 + #else + #define CPU_LEVEL1_DCACHE_LINESIZE 64 + #endif +#endif + +#define FLOATING_POINT_DECIMALS 31 + +/* Keep client compatible with earlier versions */ +#ifdef MYSQL_SERVER +#define NOT_FIXED_DEC DECIMAL_NOT_SPECIFIED +#else +#define NOT_FIXED_DEC FLOATING_POINT_DECIMALS +#endif +#endif /* my_global_h */ diff --git a/include/my_handler_errors.h b/include/my_handler_errors.h new file mode 100644 index 00000000..df414888 --- /dev/null +++ b/include/my_handler_errors.h @@ -0,0 +1,116 @@ +#ifndef MYSYS_MY_HANDLER_ERRORS_INCLUDED +#define MYSYS_MY_HANDLER_ERRORS_INCLUDED + +/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. + Copyright (c) 2011, 2013, SkySQL Ab. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Errors a handler can give you +*/ + +static const char *handler_error_messages[]= +{ + /* 120 */ + "Didn't find the key on read or update", + "Duplicate key on write or update", + "Internal (unspecified) error in handler", + "Someone has changed the row since it was read (even though the table was locked to prevent it)", + "Wrong index given to a function", + "Undefined handler error 125", + "Index is corrupted", + "Table file is corrupted", + "Out of memory in engine", + "Undefined handler error 129", + /* 130 */ + "Incorrect file format", + "Command not supported by the engine", + "Old database file", + "No record read before update", + "Record was already deleted (or record file crashed)", + "No more room in record file", + "No more room in index file", + "No more records (read after end of file)", + "Unsupported extension used for table", + "Too big row", + /* 140 */ + "Wrong create options", + "Duplicate unique key on write or update", + "Unknown character set used in table", + "Conflicting table definitions in sub-tables of MERGE table", + "Table is crashed and last repair failed", + "Table was marked as crashed and should be repaired", + "Lock timed out; Retry transaction", + "Lock table is full; Restart program with a larger lock table", + "Updates are not allowed under a read only transactions", + "Lock deadlock; Retry transaction", + /* 150 */ + "Foreign key constraint is incorrectly formed", + "Cannot add a child row", + "Cannot delete a parent row", + "No savepoint with that name", + "Non unique key block size", + "The table does not exist in the storage engine", + "The table already existed in the storage engine", + "Could not connect to the storage engine", + "Unexpected null pointer found when using spatial index", + "The table changed in the storage engine", + /* 160 */ + "There's no partition in the table for the given value", + "Row-based binary logging of row failed", + "Index needed in foreign key constraint", + "Upholding foreign key constraints would lead to a duplicate key error in some other table", + "Table needs to be upgraded before it can be used", + "Table is read only", + "Failed to get next auto increment value", + "Failed to set row auto increment value", + "Unknown (generic) error from engine", + "Record was not updated. New values were the same as original values", + /* 170 */ + "It is not possible to log this statement", + "The event was corrupt, leading to illegal data being read", + "The table is of a new format not supported by this version", + "The event could not be processed. No other handler error happened", + "Fatal error during initialization of handler", + "File too short; Expected more data in file", + "Read page with wrong checksum", + "Too many active concurrent transactions", + "Record not matching the given partition set", + "Index column length exceeds limit", + /* 180 */ + "Index corrupted", + "Undo record too big", + "Invalid InnoDB FTS Doc ID", + "Table is being used in foreign key check", + "Tablespace already exists", + "Too many columns", + "Row in wrong partition", + "Row is not visible by the current transaction", + "Operation was interrupted by end user (probably kill command?)", + "Disk full", + /* 190 */ + "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry or dump and restore the table to fix this", + "Too many words in a FTS phrase or proximity search", + "Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.", + "Foreign key cascade delete/update exceeds max depth", + "Tablespace is missing for a table", + "Sequence has been run out", + "Sequence values are conflicting", + "Error during commit", + "Cannot select partitions", + "Cannot initialize encryption. Check that all encryption parameters have been set" +}; + +#endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */ diff --git a/include/my_libwrap.h b/include/my_libwrap.h new file mode 100644 index 00000000..b5200804 --- /dev/null +++ b/include/my_libwrap.h @@ -0,0 +1,32 @@ +#ifndef MY_LIBWRAP_INCLUDED +#define MY_LIBWRAP_INCLUDED + +/* Copyright (c) 2000, 2006 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef HAVE_LIBWRAP +#include <tcpd.h> +#include <syslog.h> +#ifdef NEED_SYS_SYSLOG_H +#include <sys/syslog.h> +#endif /* NEED_SYS_SYSLOG_H */ + +extern void my_fromhost(struct request_info *req); +extern int my_hosts_access(struct request_info *req); +extern char *my_eval_client(struct request_info *req); + +#endif /* HAVE_LIBWRAP */ +#endif /* MY_LIBWRAP_INCLUDED */ diff --git a/include/my_list.h b/include/my_list.h new file mode 100644 index 00000000..0bb785bd --- /dev/null +++ b/include/my_list.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2000, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _list_h_ +#define _list_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_list { + struct st_list *prev,*next; + void *data; +} LIST; + +typedef int (*list_walk_action)(void *,void *); + +extern LIST *list_add(LIST *root,LIST *element); +extern LIST *list_delete(LIST *root,LIST *element); +extern LIST *list_cons(void *data,LIST *root); +extern LIST *list_reverse(LIST *root); +extern void list_free(LIST *root,unsigned int free_data); +extern unsigned int list_length(LIST *); +extern int list_walk(LIST *,list_walk_action action,unsigned char * argument); + +#define list_rest(a) ((a)->next) +#define list_push(a,b) (a)=list_cons((b),(a)) +#define list_pop(A) {LIST *old=(A); (A)=list_delete(old,old); my_free(old); } + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/my_md5.h b/include/my_md5.h new file mode 100644 index 00000000..c3919bf1 --- /dev/null +++ b/include/my_md5.h @@ -0,0 +1,52 @@ +#ifndef MY_MD5_INCLUDED +#define MY_MD5_INCLUDED + +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2013 Monty Program Ab + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include "m_string.h" + +#define MD5_HASH_SIZE 16 /* Hash size in bytes */ + +/* + Wrapper function for MD5 implementation. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#define compute_md5_hash(A,B,C) my_md5(A,B,C) + +/* + Convert an array of bytes to a hexadecimal representation. + + Used to generate a hexadecimal representation of a message digest. +*/ +static inline void array_to_hex(char *to, const unsigned char *str, uint len) +{ + const unsigned char *str_end= str + len; + for (; str != str_end; ++str) + { + *to++= _dig_vec_lower[((uchar) *str) >> 4]; + *to++= _dig_vec_lower[((uchar) *str) & 0x0F]; + } +} + +#ifdef __cplusplus +} +#endif + +#endif /* MY_MD5_INCLUDED */ diff --git a/include/my_minidump.h b/include/my_minidump.h new file mode 100644 index 00000000..0c0e843b --- /dev/null +++ b/include/my_minidump.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2021, MariaDB Corporation + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <windows.h> +#ifdef __cplusplus +extern "C" { +#endif + +BOOL my_create_minidump(DWORD pid, BOOL verbose); + +#ifdef __cplusplus +} +#endif diff --git a/include/my_net.h b/include/my_net.h new file mode 100644 index 00000000..f56ae09a --- /dev/null +++ b/include/my_net.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2000, 2010, 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + This file is also used to make handling of sockets and ioctl() + portable across systems. + +*/ + +#ifndef _my_net_h +#define _my_net_h + +C_MODE_START + +#include <errno.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#if defined(HAVE_POLL_H) +#include <poll.h> +#elif defined(HAVE_SYS_POLL_H) +#include <sys/poll.h> +#endif /* defined(HAVE_POLL_H) */ +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#if !defined(_WIN32) +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#if !defined(alpha_linux_port) +#include <netinet/tcp.h> +#endif +#endif + +#if defined(_WIN32) +#define O_NONBLOCK 1 /* For emulation of fcntl() */ + +/* + SHUT_RDWR is called SD_BOTH in windows and + is defined to 2 in winsock2.h + #define SD_BOTH 0x02 +*/ +#define SHUT_RDWR 0x02 +#else +#include <netdb.h> /* getaddrinfo() & co */ +#endif + +/* + On OSes which don't have the in_addr_t, we guess that using uint32 + is the best possible choice. We guess this from the fact that on + HP-UX64bit & FreeBSD64bit & Solaris64bit, in_addr_t is equivalent to + uint32. And on Linux32bit too. +*/ +#ifndef HAVE_IN_ADDR_T +#define in_addr_t uint32 +#endif + + +C_MODE_END +#endif diff --git a/include/my_nosys.h b/include/my_nosys.h new file mode 100644 index 00000000..ff13a04d --- /dev/null +++ b/include/my_nosys.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2000, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Header to remove use of my_functions in functions where we need speed and + where calls to posix functions should work +*/ +#ifndef _my_nosys_h +#define _my_nosys_h +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __MY_NOSYS__ +#define __MY_NOSYS__ + +#ifndef HAVE_STDLIB_H +#include <malloc.h> +#endif + +#undef my_read +#undef my_write +#undef my_seek +#define my_read(a,b,c,d) my_quick_read(a,b,c,d) +#define my_write(a,b,c,d) my_quick_write(a,b,c) +extern size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count, + myf myFlags); +extern size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count); + +#endif /* __MY_NOSYS__ */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/my_pthread.h b/include/my_pthread.h new file mode 100644 index 00000000..3e68538b --- /dev/null +++ b/include/my_pthread.h @@ -0,0 +1,814 @@ +/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. + Copyright (c) 2009, 2020, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Defines to make different thread packages compatible */ + +#ifndef _my_pthread_h +#define _my_pthread_h + +#ifndef ETIME +#define ETIME ETIMEDOUT /* For FreeBSD */ +#endif + +#ifdef __cplusplus +#define EXTERNC extern "C" +extern "C" { +#else +#define EXTERNC +#endif /* __cplusplus */ + +#if defined(_WIN32) +typedef CRITICAL_SECTION pthread_mutex_t; +typedef DWORD pthread_t; +typedef struct thread_attr { + DWORD dwStackSize ; + DWORD dwCreatingFlag ; +} pthread_attr_t ; + +typedef struct { int dummy; } pthread_condattr_t; + +/* Implementation of posix conditions */ + +typedef struct st_pthread_link { + DWORD thread_id; + struct st_pthread_link *next; +} pthread_link; + +/** + Implementation of Windows condition variables. + We use native conditions on Vista and later, and fallback to own + implementation on earlier OS version. +*/ +typedef CONDITION_VARIABLE pthread_cond_t; + + +typedef int pthread_mutexattr_t; +#define pthread_self() GetCurrentThreadId() +#define pthread_handler_t EXTERNC void * __cdecl +typedef void * (__cdecl *pthread_handler)(void *); + +typedef INIT_ONCE my_pthread_once_t; +#define MY_PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT; + +#if !STRUCT_TIMESPEC_HAS_TV_SEC || !STRUCT_TIMESPEC_HAS_TV_NSEC +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif + +int win_pthread_mutex_trylock(pthread_mutex_t *mutex); +int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *); +int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime); +int pthread_cond_signal(pthread_cond_t *cond); +int pthread_cond_broadcast(pthread_cond_t *cond); +int pthread_cond_destroy(pthread_cond_t *cond); +int pthread_attr_init(pthread_attr_t *connect_att); +int pthread_attr_setstacksize(pthread_attr_t *connect_att,size_t stack); +int pthread_attr_destroy(pthread_attr_t *connect_att); +int my_pthread_once(my_pthread_once_t *once_control,void (*init_routine)(void)); + +static inline struct tm *localtime_r(const time_t *timep, struct tm *tmp) +{ + localtime_s(tmp, timep); + return tmp; +} + +static inline struct tm *gmtime_r(const time_t *clock, struct tm *res) +{ + gmtime_s(res, clock); + return res; +} + +void pthread_exit(void *a); +int pthread_join(pthread_t thread, void **value_ptr); +int pthread_cancel(pthread_t thread); + +#ifndef ETIMEDOUT +#define ETIMEDOUT 145 /* Win32 doesn't have this */ +#endif + +#define HAVE_LOCALTIME_R 1 +#define _REENTRANT 1 +#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1 + +#undef SAFE_MUTEX /* This will cause conflicts */ +#define pthread_key(T,V) DWORD V +#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF) +#define pthread_key_delete(A) TlsFree(A) +#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V))) +#define pthread_setspecific(A,B) (!TlsSetValue((A),(LPVOID)(B))) +#define pthread_getspecific(A) (TlsGetValue(A)) +#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A)) +#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V)) + +#define pthread_equal(A,B) ((A) == (B)) +#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0) +#define pthread_mutex_lock(A) (EnterCriticalSection(A),0) +#define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A)) +#define pthread_mutex_unlock(A) (LeaveCriticalSection(A), 0) +#define pthread_mutex_destroy(A) (DeleteCriticalSection(A), 0) +#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH) + + +/* Dummy defines for easier code */ +#define pthread_attr_setdetachstate(A,B) pthread_dummy(0) +#define pthread_attr_setscope(A,B) +#define pthread_detach_this_thread() +#define pthread_condattr_init(A) +#define pthread_condattr_destroy(A) +#define pthread_yield() SwitchToThread() +#define my_sigset(A,B) signal(A,B) + +#else /* Normal threads */ + +#ifdef HAVE_rts_threads +#define sigwait org_sigwait +#include <signal.h> +#undef sigwait +#endif +#include <pthread.h> +#ifndef _REENTRANT +#define _REENTRANT +#endif +#ifdef HAVE_THR_SETCONCURRENCY +#include <thread.h> /* Probably solaris */ +#endif +#ifdef HAVE_SCHED_H +#include <sched.h> +#endif +#ifdef HAVE_SYNCH_H +#include <synch.h> +#endif + +#define pthread_key(T,V) pthread_key_t V +#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V)) +#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V)) +#define pthread_detach_this_thread() +#define pthread_handler_t EXTERNC void * +typedef void *(* pthread_handler)(void *); + +#define my_pthread_once_t pthread_once_t +#if defined(PTHREAD_ONCE_INITIALIZER) +#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INITIALIZER +#else +#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT +#endif +#define my_pthread_once(C,F) pthread_once(C,F) + +/* Test first for RTS or FSU threads */ + +#if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) +#define HAVE_rts_threads +extern int my_pthread_create_detached; +#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) +#define PTHREAD_CREATE_DETACHED &my_pthread_create_detached +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_GLOBAL +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_LOCAL +#define USE_ALARM_THREAD +#endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */ + +#if defined(_BSDI_VERSION) && _BSDI_VERSION < 199910 +int sigwait(sigset_t *set, int *sig); +#endif + +static inline int my_sigwait(sigset_t *set, int *sig, int *code) +{ +#ifdef HAVE_SIGWAITINFO + siginfo_t siginfo; + *sig= sigwaitinfo(set, &siginfo); + *code= siginfo.si_code; + return *sig < 0 ? errno : 0; +#else + *code= 0; + return sigwait(set, sig); +#endif +} + +#if defined(HAVE_SIGTHREADMASK) && !defined(HAVE_PTHREAD_SIGMASK) +#define pthread_sigmask(A,B,C) sigthreadmask((A),(B),(C)) +#endif + +#if !defined(HAVE_SIGWAIT) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(_AIX) +int sigwait(sigset_t *setp, int *sigp); /* Use our implementation */ +#endif + + +/* + We define my_sigset() and use that instead of the system sigset() so that + we can favor an implementation based on sigaction(). On some systems, such + as Mac OS X, sigset() results in flags such as SA_RESTART being set, and + we want to make sure that no such flags are set. +*/ +#if defined(HAVE_SIGACTION) && !defined(my_sigset) +#define my_sigset(A,B) do { struct sigaction l_s; sigset_t l_set; \ + DBUG_ASSERT((A) != 0); \ + sigemptyset(&l_set); \ + l_s.sa_handler = (B); \ + l_s.sa_mask = l_set; \ + l_s.sa_flags = 0; \ + sigaction((A), &l_s, NULL); \ + } while (0) +#elif defined(HAVE_SIGSET) && !defined(my_sigset) +#define my_sigset(A,B) sigset((A),(B)) +#elif !defined(my_sigset) +#define my_sigset(A,B) signal((A),(B)) +#endif + +#if !defined(HAVE_PTHREAD_ATTR_SETSCOPE) +#define pthread_attr_setscope(A,B) +#undef HAVE_GETHOSTBYADDR_R /* No definition */ +#endif + +#define my_pthread_getspecific(A,B) ((A) pthread_getspecific(B)) + +#ifndef HAVE_LOCALTIME_R +struct tm *localtime_r(const time_t *clock, struct tm *res); +#endif + +#ifndef HAVE_GMTIME_R +struct tm *gmtime_r(const time_t *clock, struct tm *res); +#endif + +#ifdef HAVE_PTHREAD_CONDATTR_CREATE +/* DCE threads on HPUX 10.20 */ +#define pthread_condattr_init pthread_condattr_create +#define pthread_condattr_destroy pthread_condattr_delete +#endif + +/* FSU THREADS */ +#if !defined(HAVE_PTHREAD_KEY_DELETE) && !defined(pthread_key_delete) +#define pthread_key_delete(A) pthread_dummy(0) +#endif + +#if defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT) +/* This is set on AIX_3_2 and Siemens unix (and DEC OSF/1 3.2 too) */ +#define pthread_key_create(A,B) \ + pthread_keycreate(A,(B) ?\ + (pthread_destructor_t) (B) :\ + (pthread_destructor_t) pthread_dummy) +#define pthread_attr_init(A) pthread_attr_create(A) +#define pthread_attr_destroy(A) pthread_attr_delete(A) +#define pthread_attr_setdetachstate(A,B) pthread_dummy(0) +#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D)) +#ifndef pthread_sigmask +#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) +#endif +#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH) +#undef pthread_detach_this_thread +#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } +#else /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */ +#define HAVE_PTHREAD_KILL 1 +#endif + +#endif /* defined(_WIN32) */ + +#if defined(HPUX10) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS) +#undef pthread_cond_timedwait +#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c)) +int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec *abstime); +#endif + +#if defined(HPUX10) +#define pthread_attr_getstacksize(A,B) my_pthread_attr_getstacksize(A,B) +void my_pthread_attr_getstacksize(pthread_attr_t *attrib, size_t *size); +#endif + +#if defined(HAVE_POSIX1003_4a_MUTEX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS) +#undef pthread_mutex_trylock +#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a)) +int my_pthread_mutex_trylock(pthread_mutex_t *mutex); +#endif + +#ifdef HAVE_SCHED_YIELD +#define pthread_yield() sched_yield() +#else +#if !defined(HAVE_PTHREAD_YIELD_ZERO_ARG) +/* no pthread_yield() available */ +#if defined(HAVE_PTHREAD_YIELD_NP) /* can be Mac OS X */ +#define pthread_yield() pthread_yield_np() +#elif defined(HAVE_THR_YIELD) +#define pthread_yield() thr_yield() +#endif //defined(HAVE_PTHREAD_YIELD_NP) +#endif //!defined(HAVE_PTHREAD_YIELD_ZERO_ARG) +#endif //HAVE_SCHED_YIELD + +size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize); + +/* + The defines set_timespec and set_timespec_nsec should be used + for calculating an absolute time at which + pthread_cond_timedwait should timeout +*/ +#define set_timespec(ABSTIME,SEC) set_timespec_nsec((ABSTIME),(SEC)*1000000000ULL) + +#ifndef set_timespec_nsec +#define set_timespec_nsec(ABSTIME,NSEC) \ + set_timespec_time_nsec((ABSTIME), my_hrtime_coarse().val*1000 + (NSEC)) +#endif /* !set_timespec_nsec */ + +/* adapt for two different flavors of struct timespec */ +#ifdef HAVE_TIMESPEC_TS_SEC +#define MY_tv_sec ts_sec +#define MY_tv_nsec ts_nsec +#else +#define MY_tv_sec tv_sec +#define MY_tv_nsec tv_nsec +#endif /* HAVE_TIMESPEC_TS_SEC */ + +/** + Compare two timespec structs. + + @retval 1 If TS1 ends after TS2. + + @retval 0 If TS1 is equal to TS2. + + @retval -1 If TS1 ends before TS2. +*/ +#ifndef cmp_timespec +#define cmp_timespec(TS1, TS2) \ + ((TS1.MY_tv_sec > TS2.MY_tv_sec || \ + (TS1.MY_tv_sec == TS2.MY_tv_sec && TS1.MY_tv_nsec > TS2.MY_tv_nsec)) ? 1 : \ + ((TS1.MY_tv_sec < TS2.MY_tv_sec || \ + (TS1.MY_tv_sec == TS2.MY_tv_sec && TS1.MY_tv_nsec < TS2.MY_tv_nsec)) ? -1 : 0)) +#endif /* !cmp_timespec */ + +#ifndef set_timespec_time_nsec +#define set_timespec_time_nsec(ABSTIME,NSEC) do { \ + ulonglong _now_= (NSEC); \ + (ABSTIME).MY_tv_sec= (time_t) (_now_ / 1000000000ULL); \ + (ABSTIME).MY_tv_nsec= (ulong) (_now_ % 1000000000UL); \ +} while(0) +#endif /* !set_timespec_time_nsec */ + +#ifdef MYSQL_CLIENT +#define _current_thd() NULL +#else +MYSQL_THD _current_thd(); +#endif + +/* safe_mutex adds checking to mutex for easier debugging */ +struct st_hash; +typedef struct st_safe_mutex_t +{ + pthread_mutex_t global,mutex; + const char *file, *name; + uint line,count; + myf create_flags, active_flags; + ulong id; + pthread_t thread; + struct st_hash *locked_mutex, *used_mutex; + struct st_safe_mutex_t *prev, *next; +#ifdef SAFE_MUTEX_DETECT_DESTROY + struct st_safe_mutex_info_t *info; /* to track destroying of mutexes */ +#endif +} safe_mutex_t; + +typedef struct st_safe_mutex_deadlock_t +{ + const char *file, *name; + safe_mutex_t *mutex; + uint line; + ulong count; + ulong id; + my_bool warning_only; +} safe_mutex_deadlock_t; + +#ifdef SAFE_MUTEX_DETECT_DESTROY +/* + Used to track the destroying of mutexes. This needs to be a separate + structure because the safe_mutex_t structure could be freed before + the mutexes are destroyed. +*/ + +typedef struct st_safe_mutex_info_t +{ + struct st_safe_mutex_info_t *next; + struct st_safe_mutex_info_t *prev; + const char *init_file; + uint32 init_line; +} safe_mutex_info_t; +#endif /* SAFE_MUTEX_DETECT_DESTROY */ + +int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr, + const char *name, const char *file, uint line); +int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, + uint line); +int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line); +int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line); +int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file, + uint line); +int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, + const struct timespec *abstime, + const char *file, uint line); +void safe_mutex_global_init(void); +void safe_mutex_end(FILE *file); +void safe_mutex_free_deadlock_data(safe_mutex_t *mp); + + /* Wrappers if safe mutex is actually used */ +#define MYF_TRY_LOCK 1 +#define MYF_NO_DEADLOCK_DETECTION 2 + +#ifdef SAFE_MUTEX +#define safe_mutex_is_owner(mp) ((mp)->count > 0 && \ + pthread_equal(pthread_self(), (mp)->thread)) +#define safe_mutex_assert_owner(mp) DBUG_ASSERT(safe_mutex_is_owner(mp)) +#define safe_mutex_assert_not_owner(mp) DBUG_ASSERT(!safe_mutex_is_owner(mp)) +#define safe_mutex_setflags(mp, F) do { (mp)->create_flags|= (F); } while (0) +#define my_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__) +#define my_cond_wait(A,B) safe_cond_wait((A), (B), __FILE__, __LINE__) +#else + +#define safe_mutex_is_owner(mp) (1) +#define safe_mutex_assert_owner(mp) do {} while (0) +#define safe_mutex_assert_not_owner(mp) do {} while (0) +#define safe_mutex_setflags(mp, F) do {} while (0) + +#define my_cond_timedwait(A,B,C) pthread_cond_timedwait((A),(B),(C)) +#define my_cond_wait(A,B) pthread_cond_wait((A), (B)) +#endif /* !SAFE_MUTEX */ + + /* READ-WRITE thread locking */ + +#if defined(USE_MUTEX_INSTEAD_OF_RW_LOCKS) +/* use these defs for simple mutex locking */ +#define rw_lock_t pthread_mutex_t +#define my_rwlock_init(A,B) pthread_mutex_init((A),(B)) +#define rw_rdlock(A) pthread_mutex_lock((A)) +#define rw_wrlock(A) pthread_mutex_lock((A)) +#define rw_tryrdlock(A) pthread_mutex_trylock((A)) +#define rw_trywrlock(A) pthread_mutex_trylock((A)) +#define rw_unlock(A) pthread_mutex_unlock((A)) +#define rwlock_destroy(A) pthread_mutex_destroy((A)) +#elif defined(HAVE_PTHREAD_RWLOCK_RDLOCK) +#define rw_lock_t pthread_rwlock_t +#define my_rwlock_init(A,B) pthread_rwlock_init((A),(B)) +#define rw_rdlock(A) pthread_rwlock_rdlock(A) +#define rw_wrlock(A) pthread_rwlock_wrlock(A) +#define rw_tryrdlock(A) pthread_rwlock_tryrdlock((A)) +#define rw_trywrlock(A) pthread_rwlock_trywrlock((A)) +#define rw_unlock(A) pthread_rwlock_unlock(A) +#define rwlock_destroy(A) pthread_rwlock_destroy(A) +#elif defined(HAVE_RWLOCK_INIT) +#ifdef HAVE_RWLOCK_T /* For example Solaris 2.6-> */ +#define rw_lock_t rwlock_t +#endif +#define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0) +#else +/* Use our own version of read/write locks */ +#define NEED_MY_RW_LOCK 1 +#define rw_lock_t my_rw_lock_t +#define my_rwlock_init(A,B) my_rw_init((A)) +#define rw_rdlock(A) my_rw_rdlock((A)) +#define rw_wrlock(A) my_rw_wrlock((A)) +#define rw_tryrdlock(A) my_rw_tryrdlock((A)) +#define rw_trywrlock(A) my_rw_trywrlock((A)) +#define rw_unlock(A) my_rw_unlock((A)) +#define rwlock_destroy(A) my_rw_destroy((A)) +#define rw_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A)) +#define rw_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A)) +#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */ + + +/** + Portable implementation of special type of read-write locks. + + These locks have two properties which are unusual for rwlocks: + 1) They "prefer readers" in the sense that they do not allow + situations in which rwlock is rd-locked and there is a + pending rd-lock which is blocked (e.g. due to pending + request for wr-lock). + This is a stronger guarantee than one which is provided for + PTHREAD_RWLOCK_PREFER_READER_NP rwlocks in Linux. + MDL subsystem deadlock detector relies on this property for + its correctness. + 2) They are optimized for uncontended wr-lock/unlock case. + This is a scenario in which they are most often used + within MDL subsystem. Optimizing for it gives significant + performance improvements in some of the tests involving many + connections. + + Another important requirement imposed on this type of rwlock + by the MDL subsystem is that it should be OK to destroy rwlock + object which is in unlocked state even though some threads might + have not yet fully left unlock operation for it (of course there + is an external guarantee that no thread will try to lock rwlock + which is destroyed). + Putting it another way the unlock operation should not access + rwlock data after changing its state to unlocked. + + TODO/FIXME: We should consider alleviating this requirement as + it blocks us from doing certain performance optimizations. +*/ + +typedef struct st_rw_pr_lock_t { + /** + Lock which protects the structure. + Also held for the duration of wr-lock. + */ + pthread_mutex_t lock; + /** + Condition variable which is used to wake-up + writers waiting for readers to go away. + */ + pthread_cond_t no_active_readers; + /** Number of active readers. */ + uint active_readers; + /** Number of writers waiting for readers to go away. */ + uint writers_waiting_readers; + /** Indicates whether there is an active writer. */ + my_bool active_writer; +#ifdef SAFE_MUTEX + /** Thread holding wr-lock (for debug purposes only). */ + pthread_t writer_thread; +#endif +} rw_pr_lock_t; + +extern int rw_pr_init(rw_pr_lock_t *); +extern int rw_pr_rdlock(rw_pr_lock_t *); +extern int rw_pr_wrlock(rw_pr_lock_t *); +extern int rw_pr_unlock(rw_pr_lock_t *); +extern int rw_pr_destroy(rw_pr_lock_t *); +#ifdef SAFE_MUTEX +#define rw_pr_lock_assert_write_owner(A) \ + DBUG_ASSERT((A)->active_writer && pthread_equal(pthread_self(), \ + (A)->writer_thread)) +#define rw_pr_lock_assert_not_write_owner(A) \ + DBUG_ASSERT(! (A)->active_writer || ! pthread_equal(pthread_self(), \ + (A)->writer_thread)) +#else +#define rw_pr_lock_assert_write_owner(A) +#define rw_pr_lock_assert_not_write_owner(A) +#endif /* SAFE_MUTEX */ + + +#ifdef NEED_MY_RW_LOCK + +#ifdef _WIN32 + +/** + Implementation of Windows rwlock. + + We use native (slim) rwlocks on Windows, which requires Win7 + or later. +*/ +typedef struct _my_rwlock_t +{ + SRWLOCK srwlock; /* native reader writer lock */ + BOOL have_exclusive_srwlock; /* used for unlock */ +} my_rw_lock_t; + + +#else /* _WIN32 */ + +/* + On systems which don't support native read/write locks we have + to use own implementation. +*/ +typedef struct st_my_rw_lock_t { + pthread_mutex_t lock; /* lock for structure */ + pthread_cond_t readers; /* waiting readers */ + pthread_cond_t writers; /* waiting writers */ + int state; /* -1:writer,0:free,>0:readers */ + int waiters; /* number of waiting writers */ +#ifdef SAFE_MUTEX + pthread_t write_thread; +#endif +} my_rw_lock_t; + +#endif /*! _WIN32 */ + +extern int my_rw_init(my_rw_lock_t *); +extern int my_rw_destroy(my_rw_lock_t *); +extern int my_rw_rdlock(my_rw_lock_t *); +extern int my_rw_wrlock(my_rw_lock_t *); +extern int my_rw_unlock(my_rw_lock_t *); +extern int my_rw_tryrdlock(my_rw_lock_t *); +extern int my_rw_trywrlock(my_rw_lock_t *); +#ifdef SAFE_MUTEX +#define my_rw_lock_assert_write_owner(A) \ + DBUG_ASSERT((A)->state == -1 && pthread_equal(pthread_self(), \ + (A)->write_thread)) +#define my_rw_lock_assert_not_write_owner(A) \ + DBUG_ASSERT((A)->state >= 0 || ! pthread_equal(pthread_self(), \ + (A)->write_thread)) +#else +#define my_rw_lock_assert_write_owner(A) +#define my_rw_lock_assert_not_write_owner(A) +#endif +#endif /* NEED_MY_RW_LOCK */ + + +#define GETHOSTBYADDR_BUFF_SIZE 2048 + +#ifndef HAVE_THR_SETCONCURRENCY +#define thr_setconcurrency(A) pthread_dummy(0) +#endif +#if !defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && ! defined(pthread_attr_setstacksize) +#define pthread_attr_setstacksize(A,B) pthread_dummy(0) +#endif + +/* Define mutex types, see my_thr_init.c */ +#define MY_MUTEX_INIT_SLOW NULL +#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +extern pthread_mutexattr_t my_fast_mutexattr; +#define MY_MUTEX_INIT_FAST &my_fast_mutexattr +#else +#define MY_MUTEX_INIT_FAST NULL +#endif +#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP +extern pthread_mutexattr_t my_errorcheck_mutexattr; +#define MY_MUTEX_INIT_ERRCHK &my_errorcheck_mutexattr +#else +#define MY_MUTEX_INIT_ERRCHK NULL +#endif + +#ifndef ESRCH +/* Define it to something */ +#define ESRCH 1 +#endif + +typedef uint64 my_thread_id; + +extern void my_threadattr_global_init(void); +extern my_bool my_thread_global_init(void); +extern void my_thread_global_reinit(void); +extern void my_thread_global_end(void); +extern my_bool my_thread_init(void); +extern void my_thread_end(void); +extern const char *my_thread_name(void); +extern my_thread_id my_thread_dbug_id(void); +extern int pthread_dummy(int); +extern void my_mutex_init(void); +extern void my_mutex_end(void); + +/* All thread specific variables are in the following struct */ + +#define THREAD_NAME_SIZE 10 +#ifndef DEFAULT_THREAD_STACK +/* + We need to have at least 256K stack to handle calls to myisamchk_init() + with the current number of keys and key parts. +*/ +#if defined(__SANITIZE_ADDRESS__) || defined(WITH_UBSAN) +#ifndef DBUG_OFF +#define DEFAULT_THREAD_STACK (1024*1024L) +#else +#define DEFAULT_THREAD_STACK (383*1024L) /* 392192 */ +#endif +#else +#define DEFAULT_THREAD_STACK (292*1024L) /* 299008 */ +#endif +#endif + +#define MY_PTHREAD_LOCK_READ 0 +#define MY_PTHREAD_LOCK_WRITE 1 + +#include <mysql/psi/mysql_thread.h> + +#define INSTRUMENT_ME 0 + +/* + Thread specific variables + + Aria key cache is using the following variables for keeping track of + state: + suspend, next, prev, keycache_link, keycache_file, suspend, lock_type + + MariaDB uses the following to + mutex, current_mutex, current_cond, abort +*/ + +struct st_my_thread_var +{ + int thr_errno; + mysql_cond_t suspend; + mysql_mutex_t mutex; + struct st_my_thread_var *next,**prev; + mysql_mutex_t * volatile current_mutex; + mysql_cond_t * volatile current_cond; + void *keycache_link; + void *keycache_file; + void *stack_ends_here; + safe_mutex_t *mutex_in_use; + pthread_t pthread_self; + my_thread_id id, dbug_id; + int volatile abort; + uint lock_type; /* used by conditional release the queue */ + my_bool init; +#ifndef DBUG_OFF + void *dbug; + char name[THREAD_NAME_SIZE+1]; +#endif +}; + +struct st_my_thread_var *_my_thread_var(void); +extern void **my_thread_var_dbug(void); +extern safe_mutex_t **my_thread_var_mutex_in_use(void); +extern uint my_thread_end_wait_time; +extern my_bool safe_mutex_deadlock_detector; +#define my_thread_var (_my_thread_var()) +#define my_errno my_thread_var->thr_errno +int set_mysys_var(struct st_my_thread_var *mysys_var); + + +/* + thread_safe_xxx functions are for critical statistic or counters. + The implementation is guaranteed to be thread safe, on all platforms. + Note that the calling code should *not* assume the counter is protected + by the mutex given, as the implementation of these helpers may change + to use my_atomic operations instead. +*/ + +#ifndef thread_safe_increment +#ifdef _WIN32 +#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V)) +#define thread_safe_decrement(V,L) InterlockedDecrement((long*) &(V)) +#else +#define thread_safe_increment(V,L) \ + (mysql_mutex_lock((L)), (V)++, mysql_mutex_unlock((L))) +#define thread_safe_decrement(V,L) \ + (mysql_mutex_lock((L)), (V)--, mysql_mutex_unlock((L))) +#endif +#endif + +#ifndef thread_safe_add +#ifdef _WIN32 +#define thread_safe_add(V,C,L) InterlockedExchangeAdd((long*) &(V),(C)) +#define thread_safe_sub(V,C,L) InterlockedExchangeAdd((long*) &(V),-(long) (C)) +#else +#define thread_safe_add(V,C,L) \ + (mysql_mutex_lock((L)), (V)+=(C), mysql_mutex_unlock((L))) +#define thread_safe_sub(V,C,L) \ + (mysql_mutex_lock((L)), (V)-=(C), mysql_mutex_unlock((L))) +#endif +#endif + + +/* + statistics_xxx functions are for non critical statistic, + maintained in global variables. + When compiling with SAFE_STATISTICS: + - race conditions can not occur. + - some locking occurs, which may cause performance degradation. + + When compiling without SAFE_STATISTICS: + - race conditions can occur, making the result slightly inaccurate. + - the lock given is not honored. +*/ +#ifdef SAFE_STATISTICS +#define statistic_increment(V,L) thread_safe_increment((V),(L)) +#define statistic_decrement(V,L) thread_safe_decrement((V),(L)) +#define statistic_add(V,C,L) thread_safe_add((V),(C),(L)) +#define statistic_sub(V,C,L) thread_safe_sub((V),(C),(L)) +#else +#define statistic_decrement(V,L) (V)-- +#define statistic_increment(V,L) (V)++ +#define statistic_add(V,C,L) (V)+=(C) +#define statistic_sub(V,C,L) (V)-=(C) +#endif /* SAFE_STATISTICS */ + +/* + No locking needed, the counter is owned by the thread +*/ +#define status_var_increment(V) (V)++ +#define status_var_decrement(V) (V)-- +#define status_var_add(V,C) (V)+=(C) +#define status_var_sub(V,C) (V)-=(C) + +#ifdef SAFE_MUTEX +#define mysql_mutex_record_order(A,B) \ + do { \ + mysql_mutex_lock(A); mysql_mutex_lock(B); \ + mysql_mutex_unlock(B); mysql_mutex_unlock(A); \ + } while(0) +#else +#define mysql_mutex_record_order(A,B) do { } while(0) +#endif + +/* At least Windows and NetBSD do not have this definition */ +#ifndef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 65536 +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _my_ptread_h */ diff --git a/include/my_rdtsc.h b/include/my_rdtsc.h new file mode 100644 index 00000000..8b9b0046 --- /dev/null +++ b/include/my_rdtsc.h @@ -0,0 +1,278 @@ +/* Copyright (c) 2008 MySQL AB, 2009 Sun Microsystems, Inc. + Copyright (c) 2019, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + rdtsc3 -- multi-platform timer code + pgulutzan@mysql.com, 2005-08-29 + modified 2008-11-02 +*/ + +#ifndef MY_RDTSC_H +#define MY_RDTSC_H + +# ifndef __has_builtin +# define __has_builtin(x) 0 /* Compatibility with non-clang compilers */ +# endif +# if __has_builtin(__builtin_readcyclecounter) +# elif defined _WIN32 +# include <intrin.h> +# elif defined __i386__ || defined __x86_64__ +# include <x86intrin.h> +# elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) +# include <ia64intrin.h> +# elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) +# include <sys/times.h> +# endif + +/** + Characteristics of a timer. +*/ +struct my_timer_unit_info +{ + /** Routine used for the timer. */ + ulonglong routine; + /** Overhead of the timer. */ + ulonglong overhead; + /** Frequency of the timer. */ + ulonglong frequency; + /** Resolution of the timer. */ + ulonglong resolution; +}; + +/** + Characteristics of all the supported timers. + @sa my_timer_init(). +*/ +struct my_timer_info +{ + /** Characteristics of the cycle timer. */ + struct my_timer_unit_info cycles; + /** Characteristics of the nanosecond timer. */ + struct my_timer_unit_info nanoseconds; + /** Characteristics of the microsecond timer. */ + struct my_timer_unit_info microseconds; + /** Characteristics of the millisecond timer. */ + struct my_timer_unit_info milliseconds; + /** Characteristics of the tick timer. */ + struct my_timer_unit_info ticks; +}; + +typedef struct my_timer_info MY_TIMER_INFO; + +#define MY_TIMER_ROUTINE_RDTSC 5 +#define MY_TIMER_ROUTINE_ASM_IA64 6 +#define MY_TIMER_ROUTINE_PPC_GET_TIMEBASE 7 +#define MY_TIMER_ROUTINE_GETHRTIME 9 +#define MY_TIMER_ROUTINE_READ_REAL_TIME 10 +#define MY_TIMER_ROUTINE_CLOCK_GETTIME 11 +#define MY_TIMER_ROUTINE_GETTIMEOFDAY 13 +#define MY_TIMER_ROUTINE_QUERYPERFORMANCECOUNTER 14 +#define MY_TIMER_ROUTINE_GETTICKCOUNT 15 +#define MY_TIMER_ROUTINE_TIME 16 +#define MY_TIMER_ROUTINE_TIMES 17 +#define MY_TIMER_ROUTINE_FTIME 18 +#define MY_TIMER_ROUTINE_ASM_GCC_SPARC64 23 +#define MY_TIMER_ROUTINE_ASM_GCC_SPARC32 24 +#define MY_TIMER_ROUTINE_MACH_ABSOLUTE_TIME 25 +#define MY_TIMER_ROUTINE_GETSYSTEMTIMEASFILETIME 26 +#define MY_TIMER_ROUTINE_ASM_S390 28 +#define MY_TIMER_ROUTINE_AARCH64 29 +#define MY_TIMER_ROUTINE_RISCV 30 + +C_MODE_START + +/** + A cycle timer. + + On clang we use __builtin_readcyclecounter(), except for AARCH64. + On other compilers: + + On IA-32 and AMD64, we use the RDTSC instruction. + On IA-64, we read the ar.itc register. + On SPARC, we read the tick register. + On POWER, we read the Time Base Register (which is not really a cycle count + but a separate counter with less than nanosecond resolution). + On IBM S/390 System z we use the STCK instruction. + On ARM, we probably should use the Generic Timer, but should figure out + how to ensure that it can be accessed. + On AARCH64, we use the generic timer base register. We override clang + implementation for aarch64 as it access a PMU register which is not + guaranteed to be active. + On RISC-V, we use the rdcycle instruction to read from mcycle register. + + Sadly, we have nothing for the Digital Alpha, MIPS, Motorola m68k, + HP PA-RISC or other non-mainstream (or obsolete) processors. + + TODO: consider C++11 std::chrono::high_resolution_clock. + + We fall back to gethrtime() where available. + + On the platforms that do not have a CYCLE timer, + "wait" events are initialized to use NANOSECOND instead of CYCLE + during performance_schema initialization (at the server startup). + + Linux performance monitor (see "man perf_event_open") can + provide cycle counter on the platforms that do not have + other kinds of cycle counters. But we don't use it so far. + + ARM notes + --------- + Userspace high precision timing on CNTVCT_EL0 requires that CNTKCTL_EL1 + is set to 1 for each CPU in privileged mode. + + During tests on ARMv7 Debian, perf_even_open() based cycle counter provided + too low frequency with too high overhead: + MariaDB [performance_schema]> SELECT * FROM performance_timers; + +-------------+-----------------+------------------+----------------+ + | TIMER_NAME | TIMER_FREQUENCY | TIMER_RESOLUTION | TIMER_OVERHEAD | + +-------------+-----------------+------------------+----------------+ + | CYCLE | 689368159 | 1 | 970 | + | NANOSECOND | 1000000000 | 1 | 308 | + | MICROSECOND | 1000000 | 1 | 417 | + | MILLISECOND | 1000 | 1000 | 407 | + | TICK | 127 | 1 | 612 | + +-------------+-----------------+------------------+----------------+ + Therefore, it was decided not to use perf_even_open() on ARM + (i.e. go without CYCLE and have "wait" events use NANOSECOND by default). + + @return the current timer value, in cycles. +*/ +static inline ulonglong my_timer_cycles(void) +{ +# if __has_builtin(__builtin_readcyclecounter) && !defined (__aarch64__) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_AARCH64 + return __builtin_readcyclecounter(); +# elif defined _M_IX86 || defined _M_X64 || defined __i386__ || defined __x86_64__ + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_RDTSC + return __rdtsc(); +#elif defined _M_ARM64 + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_AARCH64 + return _ReadStatusReg(ARM64_CNTVCT); +# elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_IA64 + return (ulonglong) __getReg(_IA64_REG_AR_ITC); /* (3116) */ +#elif defined(__GNUC__) && defined(__ia64__) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_IA64 + { + ulonglong result; + __asm __volatile__ ("mov %0=ar.itc" : "=r" (result)); + return result; + } +#elif defined __GNUC__ && defined __powerpc__ + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_PPC_GET_TIMEBASE + return __builtin_ppc_get_timebase(); +#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_GCC_SPARC64 + { + ulonglong result; + __asm __volatile__ ("rd %%tick,%0" : "=r" (result)); + return result; + } +#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_GCC_SPARC32 + { + union { + ulonglong wholeresult; + struct { + ulong high; + ulong low; + } splitresult; + } result; + __asm __volatile__ ("rd %%tick,%1; srlx %1,32,%0" : "=r" (result.splitresult.high), "=r" (result.splitresult.low)); + return result.wholeresult; + } +#elif defined(__GNUC__) && defined(__s390__) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_ASM_S390 + /* covers both s390 and s390x */ + { + ulonglong result; + __asm__ __volatile__ ("stck %0" : "=Q" (result) : : "cc"); + return result; + } +#elif defined(__GNUC__) && defined (__aarch64__) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_AARCH64 + { + ulonglong result; + __asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (result)); + return result; + } +#elif defined(__riscv) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_RISCV + /* Use RDCYCLE (and RDCYCLEH on riscv32) */ + { +# if __riscv_xlen == 32 + ulong result_lo, result_hi0, result_hi1; + /* Implemented in assembly because Clang insisted on branching. */ + __asm __volatile__( + "rdcycleh %0\n" + "rdcycle %1\n" + "rdcycleh %2\n" + "sub %0, %0, %2\n" + "seqz %0, %0\n" + "sub %0, zero, %0\n" + "and %1, %1, %0\n" + : "=r"(result_hi0), "=r"(result_lo), "=r"(result_hi1)); + return (static_cast<ulonglong>(result_hi1) << 32) | result_lo; +# else + ulonglong result; + __asm __volatile__("rdcycle %0" : "=r"(result)); + return result; + } +# endif +#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) + #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_GETHRTIME + /* gethrtime may appear as either cycle or nanosecond counter */ + return (ulonglong) gethrtime(); +#else + #define MY_TIMER_ROUTINE_CYCLES 0 + return 0; +#endif +} + +/** + A nanosecond timer. + @return the current timer value, in nanoseconds. +*/ +ulonglong my_timer_nanoseconds(void); + +/** + A microseconds timer. + @return the current timer value, in microseconds. +*/ +ulonglong my_timer_microseconds(void); + +/** + A millisecond timer. + @return the current timer value, in milliseconds. +*/ +ulonglong my_timer_milliseconds(void); + +/** + A ticks timer. + @return the current timer value, in ticks. +*/ +ulonglong my_timer_ticks(void); + +/** + Timer initialization function. + @param [out] mti the timer characteristics. +*/ +void my_timer_init(MY_TIMER_INFO *mti); + +C_MODE_END + +#endif + diff --git a/include/my_rnd.h b/include/my_rnd.h new file mode 100644 index 00000000..dc8efbd2 --- /dev/null +++ b/include/my_rnd.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2013 Monty Program Ab + + 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 or later 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_rnd_h +#define _my_rnd_h + +C_MODE_START + +struct my_rnd_struct { + unsigned long seed1,seed2,max_value; + double max_value_dbl; +}; + +void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2); +double my_rnd(struct my_rnd_struct *rand_st); + +C_MODE_END + +#endif /* _my_rnd_h */ diff --git a/include/my_service_manager.h b/include/my_service_manager.h new file mode 100644 index 00000000..498fc762 --- /dev/null +++ b/include/my_service_manager.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015 Daniel Black. 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, Fifth Floor, Boston, MA 02110-1335 USA +*/ + + +#ifndef MY_SERVICE_MANAGER_INCLUDED +#define MY_SERVICE_MANAGER_INCLUDED + +#if defined(HAVE_SYSTEMD) && !defined(EMBEDDED_LIBRARY) +/* + sd-daemon.h may include inttypes.h. Explicitly request format macros before + the first inclusion of inttypes.h. +*/ +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif // !defined(__STDC_FORMAT_MACROS) +#include <systemd/sd-daemon.h> +/** INTERVAL in seconds followed by printf style status */ +#define service_manager_extend_timeout(INTERVAL, FMTSTR, ...) \ + sd_notifyf(0, "STATUS=" FMTSTR "\nEXTEND_TIMEOUT_USEC=%u\n", ##__VA_ARGS__, INTERVAL * 1000000) +/* sd_listen_fds_with_names added v227 however RHEL/Centos7 has v219, fallback to sd_listen_fds */ +#ifndef HAVE_SYSTEMD_SD_LISTEN_FDS_WITH_NAMES +#define sd_listen_fds_with_names(FD, NAMES) sd_listen_fds(FD) +#endif + +#else +#define sd_listen_fds_with_names(FD, NAMES) (0) +#define sd_is_socket_unix(FD, TYPE, LISTENING, PATH, SIZE) (0) +#define sd_is_socket_inet(FD, FAMILY, TYPE, LISTENING, PORT) (0) +#define SD_LISTEN_FDS_START (0) +#define sd_notify(X, Y) +#define sd_notifyf(E, F, ...) +#ifdef _WIN32 + #define service_manager_extend_timeout(I, F, ...) \ + mysqld_win_extend_service_timeout(I) +#else + #define service_manager_extend_timeout(I, FMTSTR, ...) +#endif +#endif + +#endif /* MY_SERVICE_MANAGER_INCLUDED */ diff --git a/include/my_stack_alloc.h b/include/my_stack_alloc.h new file mode 100644 index 00000000..95e746d6 --- /dev/null +++ b/include/my_stack_alloc.h @@ -0,0 +1,92 @@ +/* Copyright 2019 MariaDB corporation AB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#ifndef _my_stack_alloc_h +#define _my_stack_alloc_h + +/* + Do allocation through alloca if there is enough stack available. + If not, use my_malloc() instead. + + The idea is that to be able to alloc as much as possible through the + stack. To ensure this, we have two different limits, on for big + blocks and one for small blocks. This will enable us to continue to + do allocation for small blocks even when there is less stack space + available. + This is for example used by Aria when traversing the b-tree and the code + needs to allocate one b-tree page and a few keys for each recursion. Even + if there is not space to allocate the b-tree pages on stack we can still + continue to allocate the keys. +*/ + +/* + Default suggested allocations +*/ + +/* Allocate big blocks as long as there is this much left */ +#define STACK_ALLOC_BIG_BLOCK 1024*64 + +/* Allocate small blocks as long as there is this much left */ +#define STACK_ALLOC_SMALL_BLOCK 1024*32 + +/* Allocate small blocks as long as there is this much left */ +#define STACK_ALLOC_SMALL_BLOCK_SIZE 4096 + +/* + Allocate a block on stack or through malloc. + The 'must_be_freed' variable will be set to 1 if malloc was called. + 'must_be_freed' must be a variable on the stack! +*/ + +#ifdef HAVE_ALLOCA +#define alloc_on_stack(stack_end, res, must_be_freed, size) \ +do \ +{ \ + size_t alloc_size= (size); \ + size_t stack_left= available_stack_size(&alloc_size, (stack_end)); \ + if (stack_left > alloc_size && \ + (STACK_ALLOC_BIG_BLOCK < stack_left - alloc_size || \ + ((STACK_ALLOC_SMALL_BLOCK < stack_left - alloc_size) && \ + (STACK_ALLOC_SMALL_BLOCK_SIZE <= alloc_size)))) \ + { \ + (must_be_freed)= 0; \ + (res)= alloca(size); \ + } \ + else \ + { \ + (must_be_freed)= 1; \ + (res)= my_malloc(PSI_INSTRUMENT_ME, size, MYF(MY_THREAD_SPECIFIC | MY_WME)); \ + } \ +} while(0) +#else +#define alloc_on_stack(stack_end, res, must_be_freed, size) \ + do { \ + (must_be_freed)= 1; \ + (res)= my_malloc(PSI_INSTRUMENT_ME, size, MYF(MY_THREAD_SPECIFIC | MY_WME)); \ + } while(0) +#endif /* HAVE_ALLOCA */ + + +/* + Free memory allocated by stack_alloc +*/ + +static inline void stack_alloc_free(void *res, my_bool must_be_freed) +{ + if (must_be_freed) + my_free(res); +} +#endif /* _my_stack_alloc_h */ diff --git a/include/my_stacktrace.h b/include/my_stacktrace.h new file mode 100644 index 00000000..7cfee0f7 --- /dev/null +++ b/include/my_stacktrace.h @@ -0,0 +1,109 @@ +/* + Copyright (c) 2001, 2011, Oracle and/or its affiliates. + Copyright (c) 2020, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_stacktrace_h_ +#define _my_stacktrace_h_ + +#ifdef TARGET_OS_LINUX +#if defined (__x86_64__) || defined (__i386__) || \ + (defined(__alpha__) && defined(__GNUC__)) +#define HAVE_STACKTRACE 1 +#endif +#elif defined(_WIN32) || defined(HAVE_PRINTSTACK) +#define HAVE_STACKTRACE 1 +#endif + +#if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD) +#undef HAVE_STACKTRACE +#define HAVE_STACKTRACE 1 +#endif + +#define HAVE_WRITE_CORE + +#if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS && HAVE_ABI_CXA_DEMANGLE && \ + HAVE_WEAK_SYMBOL +#define BACKTRACE_DEMANGLE 1 +#endif + +C_MODE_START + +#if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE) +void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack, + my_bool silent); +int my_safe_print_str(const char* val, size_t max_len); +void my_write_core(int sig); +# if BACKTRACE_DEMANGLE +char *my_demangle(const char *mangled_name, int *status); +# endif /* BACKTRACE_DEMANGLE */ +# ifdef _WIN32 +# define my_setup_stacktrace() +void my_set_exception_pointers(EXCEPTION_POINTERS *ep); +# else +void my_setup_stacktrace(void); +# endif /* _WIN32 */ +#else +# define my_setup_stacktrace() +#endif /* ! (defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)) */ + +#ifndef _WIN32 +#define MY_ADDR_RESOLVE_FORK +#endif + +#if defined(HAVE_BFD_H) || defined(MY_ADDR_RESOLVE_FORK) +#define HAVE_MY_ADDR_RESOLVE 1 +#endif + +typedef struct { + const char *file; + const char *func; + uint line; +} my_addr_loc; + +#ifdef HAVE_MY_ADDR_RESOLVE +int my_addr_resolve(void *ptr, my_addr_loc *loc); +const char *my_addr_resolve_init(); +#else +#define my_addr_resolve_init() (0) +#define my_addr_resolve(A,B) (1) +#endif + +#ifdef HAVE_WRITE_CORE +void my_write_core(int sig); +#endif + +/** + A (very) limited version of snprintf, which writes the result to STDERR. + @sa my_safe_snprintf + Implemented with simplicity, and async-signal-safety in mind. + @note Has an internal buffer capacity of 512 bytes, + which should suffice for our signal handling routines. +*/ +size_t my_safe_printf_stderr(const char* fmt, ...) + ATTRIBUTE_FORMAT(printf, 1, 2); + +/** + Writes up to count bytes from buffer to STDERR. + Implemented with simplicity, and async-signal-safety in mind. + @param buf Buffer containing data to be written. + @param count Number of bytes to write. + @returns Number of bytes written. +*/ +size_t my_write_stderr(const void *buf, size_t count); + +C_MODE_END + +#endif /* _my_stacktrace_h_ */ diff --git a/include/my_sys.h b/include/my_sys.h new file mode 100644 index 00000000..8316975c --- /dev/null +++ b/include/my_sys.h @@ -0,0 +1,1248 @@ +/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. + Copyright (c) 2010, 2022, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_sys_h +#define _my_sys_h + +#include <m_string.h> +#include <mysql/psi/mysql_memory.h> + +C_MODE_START + + +#include <my_valgrind.h> +#include <my_pthread.h> +#include <m_ctype.h> /* for CHARSET_INFO */ +#include <stdarg.h> +#include <typelib.h> +#include <my_alloca.h> +#include <mysql/plugin.h> +#include <mysql/service_my_print_error.h> + +#define MY_INIT(name) { my_progname= name; my_init(); } + +/** + Max length of an error message generated by mysys utilities. + Some mysys functions produce error messages. These mostly go + to stderr. + This constant defines the size of the buffer used to format + the message. It should be kept in sync with MYSQL_ERRMSG_SIZE, + since sometimes mysys errors are stored in the server diagnostics + area, and we would like to avoid unexpected truncation. +*/ +#define MYSYS_ERRMSG_SIZE (512) +#define MYSYS_STRERROR_SIZE (128) + +#define MY_FILE_ERROR ((size_t) -1) + + /* General bitmaps for my_func's */ +#define MY_FFNF 1U /* Fatal if file not found */ +#define MY_FNABP 2U /* Fatal if not all bytes read/written */ +#define MY_NABP 4U /* Error if not all bytes read/written */ +#define MY_FAE 8U /* Fatal if any error */ +#define MY_WME 16U /* Write message on error */ +#define MY_WAIT_IF_FULL 32U /* Wait and try again if disk full error */ +#define MY_IGNORE_BADFD 32U /* my_sync(): ignore 'bad descriptor' errors */ +#define MY_IGNORE_ENOENT 32U /* my_delete() ignores ENOENT (no such file) */ +#define MY_ENCRYPT 64U /* Encrypt IO_CACHE temporary files */ +#define MY_TEMPORARY 64U /* create_temp_file(): delete file at once */ +#define MY_NOSYMLINKS 512U /* my_open(): don't follow symlinks */ +#define MY_FULL_IO 512U /* my_read(): loop until I/O is complete */ +#define MY_DONT_CHECK_FILESIZE 128U /* Option to init_io_cache() */ +#define MY_LINK_WARNING 32U /* my_redel() gives warning if links */ +#define MY_COPYTIME 64U /* my_redel() copies time */ +#define MY_DELETE_OLD 256U /* my_create_with_symlink() */ +#define MY_RESOLVE_LINK 128U /* my_realpath(); Only resolve links */ +#define MY_HOLD_ORIGINAL_MODES 128U /* my_copy() holds to file modes */ +#define MY_REDEL_MAKE_BACKUP 256U +#define MY_SEEK_NOT_DONE 32U /* my_lock may have to do a seek */ +#define MY_SHORT_WAIT 64U /* my_lock() don't wait if can't lock */ +#define MY_FORCE_LOCK 128U /* use my_lock() even if disable_locking */ +#define MY_NO_WAIT 256U /* my_lock() don't wait at all */ +#define MY_NO_REGISTER 8196U /* my_open(), no malloc for file name */ +/* + If old_mode is UTF8_IS_UTF8MB3, then pass this flag. It mean utf8 is + alias for utf8mb3. Otherwise utf8 is alias for utf8mb4. +*/ +#define MY_UTF8_IS_UTF8MB3 1024U +/* + init_dynamic_array() has init buffer; Internal flag, not to be used by + caller. +*/ +#define MY_INIT_BUFFER_USED 256U +#define MY_ZEROFILL 32U /* my_malloc(), fill array with zero */ +#define MY_ALLOW_ZERO_PTR 64U /* my_realloc() ; zero ptr -> malloc */ +#define MY_FREE_ON_ERROR 128U /* my_realloc() ; Free old ptr on error */ +#define MY_DONT_OVERWRITE_FILE 2048U /* my_copy: Don't overwrite file */ +#define MY_THREADSAFE 2048U /* my_seek(): lock fd mutex */ +#define MY_SYNC 4096U /* my_copy(): sync dst file */ +#define MY_SYNC_DIR 32768U /* my_create/delete/rename: sync directory */ +#define MY_THREAD_SPECIFIC 0x10000U /* my_malloc(): thread specific */ +#define MY_ROOT_USE_MPROTECT 0x20000U /* init_alloc_root: read only segments */ +/* Tree that should delete things automatically */ +#define MY_TREE_WITH_DELETE 0x40000U + +#define MY_CHECK_ERROR 1U /* Params to my_end; Check open-close */ +#define MY_GIVE_INFO 2U /* Give time info about process*/ +#define MY_DONT_FREE_DBUG 4U /* Do not call DBUG_END() in my_end() */ + +#define ME_BELL 4U /* Ring bell then printing message */ +#define ME_ERROR_LOG 64 /**< write the error message to error log */ +#define ME_ERROR_LOG_ONLY 128 /**< write the error message to error log only */ +#define ME_NOTE 1024 /**< not error but just info */ +#define ME_WARNING 2048 /**< not error but just warning */ +#define ME_FATAL 4096 /**< fatal statement error */ + + /* Bits in last argument to fn_format */ +#define MY_REPLACE_DIR 1U /* replace dir in name with 'dir' */ +#define MY_REPLACE_EXT 2U /* replace extension with 'ext' */ +#define MY_UNPACK_FILENAME 4U /* Unpack name (~ -> home) */ +#define MY_PACK_FILENAME 8U /* Pack name (home -> ~) */ +#define MY_RESOLVE_SYMLINKS 16U /* Resolve all symbolic links */ +#define MY_RETURN_REAL_PATH 32U /* return full path for file */ +#define MY_SAFE_PATH 64U /* Return NULL if too long path */ +#define MY_RELATIVE_PATH 128U /* name is relative to 'dir' */ +#define MY_APPEND_EXT 256U /* add 'ext' as additional extension*/ + + + /* My seek flags */ +#define MY_SEEK_SET 0 +#define MY_SEEK_CUR 1 +#define MY_SEEK_END 2 + + /* Some constants */ +#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */ +#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */ +#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */ +#define DFLT_INIT_HITS 3 + + /* root_alloc flags */ +#define MY_KEEP_PREALLOC 1U +#define MY_MARK_BLOCKS_FREE 2U /* move used to free list and reuse them */ + + /* Internal error numbers (for assembler functions) */ +#define MY_ERRNO_EDOM 33 +#define MY_ERRNO_ERANGE 34 + + /* Bits for get_date timeflag */ +#define GETDATE_DATE_TIME 1U +#define GETDATE_SHORT_DATE 2U +#define GETDATE_HHMMSSTIME 4U +#define GETDATE_GMT 8U +#define GETDATE_FIXEDLENGTH 16U + +/* Extra length needed for filename if one calls my_create_backup_name */ +#define MY_BACKUP_NAME_EXTRA_LENGTH 17 + +char *guess_malloc_library(); + +/* If we have our own safemalloc (for debugging) */ +#if defined(SAFEMALLOC) +void sf_report_leaked_memory(my_thread_id id); +int sf_sanity(); +extern my_thread_id (*sf_malloc_dbug_id)(void); +#define SAFEMALLOC_REPORT_MEMORY(X) sf_report_leaked_memory(X) +#else +#define SAFEMALLOC_REPORT_MEMORY(X) do {} while(0) +#endif + +typedef void (*MALLOC_SIZE_CB) (long long size, my_bool is_thread_specific); +extern void set_malloc_size_cb(MALLOC_SIZE_CB func); +extern MALLOC_SIZE_CB update_malloc_size; + + /* defines when allocating data */ +extern void *my_malloc(PSI_memory_key key, size_t size, myf MyFlags); +extern void *my_multi_malloc(PSI_memory_key key, myf MyFlags, ...); +extern void *my_multi_malloc_large(PSI_memory_key key, myf MyFlags, ...); +extern void *my_realloc(PSI_memory_key key, void *ptr, size_t size, myf MyFlags); +extern void my_free(void *ptr); +extern void *my_memdup(PSI_memory_key key, const void *from,size_t length,myf MyFlags); +extern char *my_strdup(PSI_memory_key key, const char *from,myf MyFlags); +extern char *my_strndup(PSI_memory_key key, const char *from, size_t length, myf MyFlags); + +int my_init_large_pages(my_bool super_large_pages); +uchar *my_large_malloc(size_t *size, myf my_flags); +void my_large_free(void *ptr, size_t size); +void my_large_page_truncate(size_t *size); + +#ifdef _WIN32 +extern BOOL my_obtain_privilege(LPCSTR lpPrivilege); +#endif + +void my_init_atomic_write(void); +#ifdef __linux__ +my_bool my_test_if_atomic_write(File handle, int pagesize); +my_bool my_test_if_thinly_provisioned(File handle); +#else +# define my_test_if_atomic_write(A, B) 0 +# define my_test_if_thinly_provisioned(A) 0 +#endif /* __linux__ */ +extern my_bool my_may_have_atomic_write; + +#if defined(HAVE_ALLOCA) && !defined(HAVE_valgrind) +#define my_alloca(SZ) alloca((size_t) (SZ)) +#define my_afree(PTR) ((void)0) +#define MAX_ALLOCA_SZ 4096 +#define my_safe_alloca(size) (((size) <= MAX_ALLOCA_SZ) ? \ + my_alloca(size) : \ + my_malloc(PSI_NOT_INSTRUMENTED, (size), MYF(MY_THREAD_SPECIFIC|MY_WME))) +#define my_safe_afree(ptr, size) \ + do { if ((size) > MAX_ALLOCA_SZ) my_free(ptr); } while(0) +#else +#define my_alloca(SZ) my_malloc(PSI_NOT_INSTRUMENTED, SZ,MYF(MY_FAE)) +#define my_afree(PTR) my_free(PTR) +#define my_safe_alloca(size) my_alloca(size) +#define my_safe_afree(ptr, size) my_afree(ptr) +#endif /* HAVE_ALLOCA */ + +#ifndef errno /* did we already get it? */ +#ifdef HAVE_ERRNO_AS_DEFINE +#include <errno.h> /* errno is a define */ +#else +extern int errno; /* declare errno */ +#endif +#endif /* #ifndef errno */ +extern char *home_dir; /* Home directory for user */ +extern MYSQL_PLUGIN_IMPORT char *mysql_data_home; +extern const char *my_progname; /* program-name (printed in errors) */ +extern const char *my_progname_short; /* like above but without directory */ +extern char curr_dir[]; /* Current directory for user */ +extern void (*error_handler_hook)(uint my_err, const char *str,myf MyFlags); +extern void (*fatal_error_handler_hook)(uint my_err, const char *str, + myf MyFlags); +extern uint my_file_limit; +extern ulonglong my_thread_stack_size; +extern int sf_leaking_memory; /* set to 1 to disable memleak detection */ + +extern void (*proc_info_hook)(void *, const PSI_stage_info *, PSI_stage_info *, + const char *, const char *, const unsigned int); + +/* charsets */ +#define MY_ALL_CHARSETS_SIZE 4096 +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *default_charset_info; +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *all_charsets[MY_ALL_CHARSETS_SIZE]; +extern struct charset_info_st compiled_charsets[]; + +/* Collation properties and use statistics */ +extern my_bool my_collation_is_known_id(uint id); +extern ulonglong my_collation_statistics_get_use_count(uint id); +extern const char *my_collation_get_tailoring(uint id); + +/* statistics */ +extern ulong my_stream_opened, my_tmp_file_created; +extern ulong my_file_total_opened; +extern ulong my_sync_count; +extern uint mysys_usage_id; +extern int32 my_file_opened; +extern my_bool my_init_done, my_thr_key_mysys_exists; +extern my_bool my_assert; +extern my_bool my_assert_on_error; +extern myf my_global_flags; /* Set to MY_WME for more error messages */ + /* Point to current my_message() */ +extern void (*my_sigtstp_cleanup)(void), + /* Executed before jump to shell */ + (*my_sigtstp_restart)(void); + /* Executed when coming from shell */ +extern MYSQL_PLUGIN_IMPORT int my_umask; /* Default creation mask */ +extern int my_umask_dir, + my_recived_signals, /* Signals we have got */ + my_safe_to_handle_signal, /* Set when allowed to SIGTSTP */ + my_dont_interrupt; /* call remember_intr when set */ +#ifdef _WIN32 +extern SECURITY_ATTRIBUTES my_dir_security_attributes; +LPSECURITY_ATTRIBUTES my_win_file_secattr(); +#endif +extern MYSQL_PLUGIN_IMPORT my_bool my_use_symdir; + +extern ulong my_default_record_cache_size; +extern MYSQL_PLUGIN_IMPORT my_bool my_disable_locking; +extern my_bool my_disable_async_io, + my_disable_flush_key_blocks, my_disable_symlinks; +extern my_bool my_disable_sync, my_disable_copystat_in_redel; +extern char wild_many,wild_one,wild_prefix; +extern const char *charsets_dir; +extern size_t my_system_page_size; + +enum cache_type +{ + TYPE_NOT_SET= 0, READ_CACHE, WRITE_CACHE, + SEQ_READ_APPEND /* sequential read or append */, + READ_FIFO, READ_NET}; + +enum flush_type +{ + FLUSH_KEEP, /* flush block and keep it in the cache */ + FLUSH_RELEASE, /* flush block and remove it from the cache */ + FLUSH_IGNORE_CHANGED, /* remove block from the cache */ + /* + As my_disable_flush_pagecache_blocks is always 0, the following option + is strictly equivalent to FLUSH_KEEP + */ + FLUSH_FORCE_WRITE, + /** + @brief like FLUSH_KEEP but return immediately if file is already being + flushed (even partially) by another thread; only for page cache, + forbidden for key cache. + */ + FLUSH_KEEP_LAZY +}; + +typedef struct st_record_cache /* Used when caching records */ +{ + File file; + int rc_seek,error,inited; + uint rc_length,read_length,reclength; + my_off_t rc_record_pos,end_of_file; + uchar *rc_buff,*rc_buff2,*rc_pos,*rc_end,*rc_request_pos; + enum cache_type type; +} RECORD_CACHE; + +enum file_type +{ + UNOPEN = 0, FILE_BY_OPEN, FILE_BY_CREATE, STREAM_BY_FOPEN, STREAM_BY_FDOPEN, + FILE_BY_O_TMPFILE, FILE_BY_MKSTEMP, FILE_BY_DUP +}; + +struct st_my_file_info +{ + char *name; +#ifdef _WIN32 + HANDLE fhandle; /* win32 file handle */ + int oflag; /* open flags, e.g O_APPEND */ +#endif + enum file_type type; +}; + +extern struct st_my_file_info *my_file_info; + +/* Free function pointer */ +typedef void (*FREE_FUNC)(void *); + +typedef struct st_dynamic_array +{ + uchar *buffer; + size_t elements, max_element; + size_t alloc_increment; + size_t size_of_element; + PSI_memory_key m_psi_key; + myf malloc_flags; +} DYNAMIC_ARRAY; + +typedef struct st_my_tmpdir +{ + DYNAMIC_ARRAY full_list; + char **list; + size_t cur, max; + mysql_mutex_t mutex; +} MY_TMPDIR; + +typedef struct st_dynamic_string +{ + char *str; + size_t length,max_length,alloc_increment; +} DYNAMIC_STRING; + +struct st_io_cache; + +typedef struct st_io_cache_share +{ + mysql_mutex_t mutex; /* To sync on reads into buffer. */ + mysql_cond_t cond; /* To wait for signals. */ + mysql_cond_t cond_writer; /* For a synchronized writer. */ + /* Offset in file corresponding to the first byte of buffer. */ + my_off_t pos_in_file; + /* If a synchronized write cache is the source of the data. */ + struct st_io_cache *source_cache; + uchar *buffer; /* The read buffer. */ + uchar *read_end; /* Behind last valid byte of buffer. */ + int running_threads; /* threads not in lock. */ + int total_threads; /* threads sharing the cache. */ + int error; /* Last error. */ +#ifdef NOT_YET_IMPLEMENTED + /* whether the structure should be free'd */ + my_bool alloced; +#endif +} IO_CACHE_SHARE; + +typedef struct st_io_cache /* Used when caching files */ +{ + /* Offset in file corresponding to the first byte of uchar* buffer. */ + my_off_t pos_in_file; + /* + The offset of end of file for READ_CACHE and WRITE_CACHE. + For SEQ_READ_APPEND it the maximum of the actual end of file and + the position represented by read_end. + */ + my_off_t end_of_file; + /* Points to current read position in the buffer */ + uchar *read_pos; + /* the non-inclusive boundary in the buffer for the currently valid read */ + uchar *read_end; + uchar *buffer; /* The read buffer */ + /* Used in ASYNC_IO */ + uchar *request_pos; + + /* Only used in WRITE caches and in SEQ_READ_APPEND to buffer writes */ + uchar *write_buffer; + /* + Only used in SEQ_READ_APPEND, and points to the current read position + in the write buffer. Note that reads in SEQ_READ_APPEND caches can + happen from both read buffer (uchar* buffer) and write buffer + (uchar* write_buffer). + */ + uchar *append_read_pos; + /* Points to current write position in the write buffer */ + uchar *write_pos; + /* The non-inclusive boundary of the valid write area */ + uchar *write_end; + + /* + The lock is for append buffer used in SEQ_READ_APPEND cache + need mutex copying from append buffer to read buffer. + */ + mysql_mutex_t append_buffer_lock; + /* + The following is used when several threads are reading the + same file in parallel. They are synchronized on disk + accesses reading the cached part of the file asynchronously. + It should be set to NULL to disable the feature. Only + READ_CACHE mode is supported. + */ + IO_CACHE_SHARE *share; + + /* + A caller will use my_b_read() macro to read from the cache + if the data is already in cache, it will be simply copied with + memcpy() and internal variables will be accordingly updated with + no functions invoked. However, if the data is not fully in the cache, + my_b_read() will call read_function to fetch the data. read_function + must never be invoked directly. + */ + int (*read_function)(struct st_io_cache *,uchar *,size_t); + /* + Same idea as in the case of read_function, except my_b_write() needs to + be replaced with my_b_append() for a SEQ_READ_APPEND cache + */ + int (*write_function)(struct st_io_cache *,const uchar *,size_t); + /* + Specifies the type of the cache. Depending on the type of the cache + certain operations might not be available and yield unpredicatable + results. Details to be documented later + */ + enum cache_type type; + /* + Counts the number of times, when we were forced to use disk. We use it to + increase the binlog_cache_disk_use and binlog_stmt_cache_disk_use status + variables. + */ + ulong disk_writes; + char *file_name; /* if used with 'open_cached_file' */ + const char *dir; + char prefix[3]; + File file; /* file descriptor */ + + struct st_io_cache *next_file_user; + /* + seek_not_done is set by my_b_seek() to inform the upcoming read/write + operation that a seek needs to be preformed prior to the actual I/O + error is 0 if the cache operation was successful, -1 if there was a + "hard" error, and the actual number of I/O-ed bytes if the read/write was + partial. + */ + int seek_not_done,error; + /* length of the buffer used for storing un-encrypted data */ + size_t buffer_length; + /* read_length is the same as buffer_length except when we use async io */ + size_t read_length; + myf myflags; /* Flags used to my_read/my_write */ + /* + alloced_buffer is set to the size of the buffer allocated for the IO_CACHE. + Includes the overhead(storing key to encrypt and decrypt) for encryption. + Set to 0 if nothing is allocated. + Currently READ_NET is the only one that will use a buffer allocated + somewhere else + */ + size_t alloced_buffer; +} IO_CACHE; + +typedef int (*qsort2_cmp)(const void *, const void *, const void *); + +typedef void (*my_error_reporter)(enum loglevel level, const char *format, ...) + ATTRIBUTE_FORMAT_FPTR(printf, 2, 3); + +extern my_error_reporter my_charset_error_reporter; + +extern PSI_file_key key_file_io_cache; + +/* inline functions for mf_iocache */ + +extern int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock); +extern int _my_b_get(IO_CACHE *info); +extern int _my_b_read(IO_CACHE *info,uchar *Buffer,size_t Count); +extern int _my_b_write(IO_CACHE *info,const uchar *Buffer,size_t Count); + +/* Test if buffer is inited */ +static inline void my_b_clear(IO_CACHE *info) { info->buffer= 0; } +static inline int my_b_inited(IO_CACHE *info) { return MY_TEST(info->buffer); } +#define my_b_EOF INT_MIN + +static inline int my_b_read(IO_CACHE *info, uchar *Buffer, size_t Count) +{ + if (info->read_pos + Count <= info->read_end) + { + memcpy(Buffer, info->read_pos, Count); + info->read_pos+= Count; + return 0; + } + return _my_b_read(info, Buffer, Count); +} + +static inline int my_b_write(IO_CACHE *info, const uchar *Buffer, size_t Count) +{ + MEM_CHECK_DEFINED(Buffer, Count); + if (info->write_pos + Count <= info->write_end) + { + if (Count) + { + memcpy(info->write_pos, Buffer, Count); + info->write_pos+= Count; + } + return 0; + } + return _my_b_write(info, Buffer, Count); +} + +static inline int my_b_get(IO_CACHE *info) +{ + if (info->read_pos != info->read_end) + { + info->read_pos++; + return info->read_pos[-1]; + } + return _my_b_get(info); +} + +static inline my_bool my_b_write_byte(IO_CACHE *info, uchar chr) +{ + MEM_CHECK_DEFINED(&chr, 1); + if (info->write_pos >= info->write_end) + if (my_b_flush_io_cache(info, 1)) + return 1; + *info->write_pos++= chr; + return 0; +} + +/** + Fill buffer of the cache. + + @note It assumes that you have already used all characters in the CACHE, + independent of the read_pos value! + + @returns + 0 On error or EOF (info->error = -1 on error) + # Number of characters +*/ +static inline size_t my_b_fill(IO_CACHE *info) +{ + info->read_pos= info->read_end; + return _my_b_read(info,0,0) ? 0 : (size_t) (info->read_end - info->read_pos); +} + +static inline my_off_t my_b_tell(const IO_CACHE *info) +{ + if (info->type == WRITE_CACHE) { + return info->pos_in_file + (my_off_t)(info->write_pos - info->request_pos); + + } + return info->pos_in_file + (my_off_t) (info->read_pos - info->request_pos); +} + +static inline my_off_t my_b_write_tell(const IO_CACHE *info) +{ + return info->pos_in_file + (my_off_t) (info->write_pos - info->write_buffer); +} + +static inline uchar* my_b_get_buffer_start(const IO_CACHE *info) +{ + return info->request_pos; +} + +static inline size_t my_b_get_bytes_in_buffer(const IO_CACHE *info) +{ + return (size_t) (info->read_end - info->request_pos); +} + +static inline my_off_t my_b_get_pos_in_file(const IO_CACHE *info) +{ + return info->pos_in_file; +} + +static inline size_t my_b_bytes_in_cache(const IO_CACHE *info) +{ + if (info->type == WRITE_CACHE) { + return (size_t) (info->write_end - info->write_pos); + } + return (size_t) (info->read_end - info->read_pos); +} + +int my_b_copy_to_file (IO_CACHE *cache, FILE *file, size_t count); +int my_b_copy_all_to_file(IO_CACHE *cache, FILE *file); + +my_off_t my_b_append_tell(IO_CACHE* info); +my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */ +int my_b_pread(IO_CACHE *info, uchar *Buffer, size_t Count, my_off_t pos); + +typedef uint32 ha_checksum; + +extern int (*mysys_test_invalid_symlink)(const char *filename); +#include <my_alloc.h> + + /* Prototypes for mysys and my_func functions */ + +extern int my_copy(const char *from,const char *to,myf MyFlags); +extern int my_delete(const char *name,myf MyFlags); +extern int my_rmtree(const char *name, myf Myflags); +extern int my_getwd(char * buf,size_t size,myf MyFlags); +extern int my_setwd(const char *dir,myf MyFlags); +extern int my_lock(File fd,int op,my_off_t start, my_off_t length,myf MyFlags); +extern void *my_once_alloc(size_t Size,myf MyFlags); +extern void my_once_free(void); +extern char *my_once_strdup(const char *src,myf myflags); +extern void *my_once_memdup(const void *src, size_t len, myf myflags); +extern File my_open(const char *FileName,int Flags,myf MyFlags); +extern File my_register_filename(File fd, const char *FileName, + enum file_type type_of_file, + uint error_message_number, myf MyFlags); +extern File my_create(const char *FileName,int CreateFlags, + int AccessFlags, myf MyFlags); +extern int my_close(File Filedes,myf MyFlags); +extern int my_mkdir(const char *dir, int Flags, myf MyFlags); +extern int my_readlink(char *to, const char *filename, myf MyFlags); +extern int my_is_symlink(const char *filename); +extern int my_realpath(char *to, const char *filename, myf MyFlags); +extern File my_create_with_symlink(const char *linkname, const char *filename, + int createflags, int access_flags, + myf MyFlags); +extern int my_rename_with_symlink(const char *from,const char *to,myf MyFlags); +extern int my_symlink(const char *content, const char *linkname, myf MyFlags); +extern int my_handler_delete_with_symlink(const char *filename, myf sync_dir); + +extern size_t my_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags); +extern size_t my_pread(File Filedes,uchar *Buffer,size_t Count,my_off_t offset, + myf MyFlags); +extern int my_rename(const char *from,const char *to,myf MyFlags); +extern my_off_t my_seek(File fd,my_off_t pos,int whence,myf MyFlags); +extern my_off_t my_tell(File fd,myf MyFlags); +extern size_t my_write(File Filedes,const uchar *Buffer,size_t Count, + myf MyFlags); +extern size_t my_pwrite(File Filedes,const uchar *Buffer,size_t Count, + my_off_t offset,myf MyFlags); +extern size_t my_fread(FILE *stream,uchar *Buffer,size_t Count,myf MyFlags); +extern size_t my_fwrite(FILE *stream,const uchar *Buffer,size_t Count, + myf MyFlags); +extern my_off_t my_fseek(FILE *stream,my_off_t pos,int whence,myf MyFlags); +extern my_off_t my_ftell(FILE *stream,myf MyFlags); + +/* implemented in my_memmem.c */ +extern void *my_memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); + + +#ifdef _WIN32 +extern int my_access(const char *path, int amode); +#define my_check_user(A,B) (NULL) +#define my_set_user(A,B,C) (0) +#else +#define my_access access +struct passwd *my_check_user(const char *user, myf MyFlags); +int my_set_user(const char *user, struct passwd *user_info, myf MyFlags); +#endif + +extern int check_if_legal_filename(const char *path); +extern int check_if_legal_tablename(const char *path); + +#ifdef _WIN32 +extern my_bool is_filename_allowed(const char *name, size_t length, + my_bool allow_current_dir); +#else /* _WIN32 */ +# define is_filename_allowed(name, length, allow_cwd) (TRUE) +#endif /* _WIN32 */ + +#ifdef _WIN32 +/* Windows-only functions (CRT equivalents)*/ +extern HANDLE my_get_osfhandle(File fd); +extern File my_win_handle2File(HANDLE hFile); +extern void my_osmaperr(unsigned long last_error); +#endif + +extern void init_glob_errs(void); +extern const char** get_global_errmsgs(int nr); +extern void wait_for_free_space(const char *filename, int errors); +extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags); +extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags); +extern FILE *my_freopen(const char *path, const char *mode, FILE *stream); +extern int my_fclose(FILE *fd,myf MyFlags); +extern int my_vfprintf(FILE *stream, const char* format, va_list args); +extern const char* my_strerror(char *buf, size_t len, int nr); +extern int my_fprintf(FILE *stream, const char* format, ...); +extern File my_fileno(FILE *fd); +extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); +extern int my_chmod(const char *name, mode_t mode, myf my_flags); +extern const char *my_basename(const char *filename); +extern void thr_set_sync_wait_callback(void (*before_sync)(void), + void (*after_sync)(void)); +extern int my_sync(File fd, myf my_flags); +extern int my_sync_dir(const char *dir_name, myf my_flags); +extern int my_sync_dir_by_file(const char *file_name, myf my_flags); +extern const char *my_get_err_msg(uint nr); +extern int my_error_register(const char** (*get_errmsgs) (int nr), + uint first, uint last); +extern my_bool my_error_unregister(uint first, uint last); +extern void my_message(uint my_err, const char *str,myf MyFlags); +extern void my_message_stderr(uint my_err, const char *str, myf MyFlags); +extern my_bool my_init(void); +extern void my_end(int infoflag); +extern int my_redel(const char *from, const char *to, time_t backup_time_stamp, + myf MyFlags); +void my_create_backup_name(char *to, const char *from, + time_t backup_time_stamp); +extern int my_copystat(const char *from, const char *to, int MyFlags); +extern char * my_filename(File fd); + +extern my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist); +extern char *my_tmpdir(MY_TMPDIR *tmpdir); +extern void free_tmpdir(MY_TMPDIR *tmpdir); + +extern void my_remember_signal(int signal_number,sig_handler (*func)(int)); +extern size_t dirname_part(char * to,const char *name, size_t *to_res_length); +extern size_t dirname_length(const char *name); +#define base_name(A) (A+dirname_length(A)) +extern int test_if_hard_path(const char *dir_name); +extern my_bool has_path(const char *name); +extern char *convert_dirname(char *to, const char *from, const char *from_end); +extern void to_unix_path(char * name); +extern char * fn_ext(const char *name); +extern char * fn_ext2(const char *name); +extern char * fn_same(char * toname,const char *name,int flag); +extern char * fn_format(char * to,const char *name,const char *dir, + const char *form, uint flag); +extern size_t strlength(const char *str); +extern void pack_dirname(char * to,const char *from); +extern size_t normalize_dirname(char * to, const char *from); +extern size_t unpack_dirname(char * to,const char *from); +extern size_t cleanup_dirname(char * to,const char *from); +extern size_t system_filename(char * to,const char *from); +extern size_t unpack_filename(char * to,const char *from); +extern char * intern_filename(char * to,const char *from); +extern int pack_filename(char * to, const char *name, size_t max_length); +extern char * my_path(char * to,const char *progname, + const char *own_pathname_part); +extern char * my_load_path(char * to, const char *path, + const char *own_path_prefix); +extern int wild_compare(const char *str,const char *wildstr, + pbool str_is_pattern); +extern my_bool array_append_string_unique(const char *str, + const char **array, size_t size); +extern void get_date(char * to,int timeflag,time_t use_time); +extern void soundex(CHARSET_INFO *, char * out_pntr, char * in_pntr, + pbool remove_garbage); +extern int init_record_cache(RECORD_CACHE *info,size_t cachesize,File file, + size_t reclength,enum cache_type type, + pbool use_async_io); +extern int read_cache_record(RECORD_CACHE *info,uchar *to); +extern int end_record_cache(RECORD_CACHE *info); +extern int write_cache_record(RECORD_CACHE *info,my_off_t filepos, + const uchar *record,size_t length); +extern int flush_write_cache(RECORD_CACHE *info); +extern void handle_recived_signals(void); + +extern sig_handler my_set_alarm_variable(int signo); +extern my_bool radixsort_is_appliccable(uint n_items, size_t size_of_element); +extern void my_string_ptr_sort(uchar *base,uint items,size_t size); +extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements, + size_t size_of_element,uchar *buffer[]); +extern qsort_t my_qsort(void *base_ptr, size_t total_elems, size_t size, + qsort_cmp cmp); +extern qsort_t my_qsort2(void *base_ptr, size_t total_elems, size_t size, + qsort2_cmp cmp, void *cmp_argument); +extern qsort2_cmp get_ptr_compare(size_t); +void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos); +my_off_t my_get_ptr(uchar *ptr, size_t pack_length); +extern int init_io_cache(IO_CACHE *info,File file,size_t cachesize, + enum cache_type type,my_off_t seek_offset, + my_bool use_async_io, myf cache_myflags); +extern int init_io_cache_ext(IO_CACHE *info, File file, size_t cachesize, + enum cache_type type, my_off_t seek_offset, + pbool use_async_io, myf cache_myflags, + PSI_file_key file_key); +extern my_bool reinit_io_cache(IO_CACHE *info,enum cache_type type, + my_off_t seek_offset, my_bool use_async_io, + my_bool clear_cache); +extern void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, + IO_CACHE *write_cache, uint num_threads); + +extern int init_slave_io_cache(IO_CACHE *master, IO_CACHE *slave); +void end_slave_io_cache(IO_CACHE *cache); +void seek_io_cache(IO_CACHE *cache, my_off_t needed_offset); + +extern void remove_io_thread(IO_CACHE *info); +extern int my_b_append(IO_CACHE *info,const uchar *Buffer,size_t Count); +extern int my_b_safe_write(IO_CACHE *info,const uchar *Buffer,size_t Count); + +extern int my_block_write(IO_CACHE *info, const uchar *Buffer, + size_t Count, my_off_t pos); + +#define flush_io_cache(info) my_b_flush_io_cache((info),1) + +extern int end_io_cache(IO_CACHE *info); +extern void my_b_seek(IO_CACHE *info,my_off_t pos); +extern size_t my_b_gets(IO_CACHE *info, char *to, size_t max_length); +extern my_off_t my_b_filelength(IO_CACHE *info); +extern my_bool my_b_write_backtick_quote(IO_CACHE *info, const char *str, + size_t len); +extern my_bool my_b_printf(IO_CACHE *info, const char* fmt, ...); +extern size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list ap); +extern my_bool open_cached_file(IO_CACHE *cache,const char *dir, + const char *prefix, size_t cache_size, + myf cache_myflags); +extern my_bool real_open_cached_file(IO_CACHE *cache); +extern void close_cached_file(IO_CACHE *cache); +File create_temp_file(char *to, const char *dir, const char *pfx, + int mode, myf MyFlags); +#define my_init_dynamic_array(A,B,C,D,E,F) init_dynamic_array2(A,B,C,NULL,D,E,F) +#define my_init_dynamic_array2(A,B,C,D,E,F,G) init_dynamic_array2(A,B,C,D,E,F,G) +extern my_bool init_dynamic_array2(PSI_memory_key psi_key, DYNAMIC_ARRAY *array, + size_t element_size, void *init_buffer, + size_t init_alloc, size_t alloc_increment, + myf my_flags); +extern my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void* element); +extern void *alloc_dynamic(DYNAMIC_ARRAY *array); +extern void *pop_dynamic(DYNAMIC_ARRAY*); +extern my_bool set_dynamic(DYNAMIC_ARRAY *array, const void *element, + size_t array_index); +extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, size_t max_elements); +extern void get_dynamic(DYNAMIC_ARRAY *array, void *element, size_t array_index); +extern void delete_dynamic(DYNAMIC_ARRAY *array); +extern void delete_dynamic_element(DYNAMIC_ARRAY *array, size_t array_index); +extern void delete_dynamic_with_callback(DYNAMIC_ARRAY *array, FREE_FUNC f); +extern void freeze_size(DYNAMIC_ARRAY *array); +#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element) +#define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index)) +#define push_dynamic(A,B) insert_dynamic((A),(B)) +#define reset_dynamic(array) ((array)->elements= 0) +#define sort_dynamic(A,cmp) my_qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) + +extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, + size_t init_alloc,size_t alloc_increment); +extern my_bool dynstr_append(DYNAMIC_STRING *str, const char *append); +my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, + size_t length); +extern my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, + ...); +extern my_bool dynstr_append_quoted(DYNAMIC_STRING *str, + const char *append, size_t len, + char quote); +extern my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str); +extern my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size); +extern my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n); +extern void dynstr_free(DYNAMIC_STRING *str); +extern uint32 copy_and_convert_extended(char *to, uint32 to_length, + CHARSET_INFO *to_cs, + const char *from, uint32 from_length, + CHARSET_INFO *from_cs, uint *errors); +extern void dynstr_reassociate(DYNAMIC_STRING *str, char **res, size_t *length, + size_t *alloc_length); +extern uint32 copy_and_convert_extended(char *to, uint32 to_length, + CHARSET_INFO *to_cs, + const char *from, uint32 from_length, + CHARSET_INFO *from_cs, uint *errors); +#ifdef HAVE_MLOCK +extern void *my_malloc_lock(size_t length,myf flags); +extern void my_free_lock(void *ptr); +#else +#define my_malloc_lock(A,B) my_malloc(PSI_INSTRUMENT_ME, (A),(B)) +#define my_free_lock(A) my_free((A)) +#endif +#define alloc_root_inited(A) ((A)->min_malloc != 0) +#define clear_alloc_root(A) do { (A)->free= (A)->used= (A)->pre_alloc= 0; (A)->min_malloc=0;} while(0) +extern void init_alloc_root(PSI_memory_key key, MEM_ROOT *mem_root, + size_t block_size, size_t pre_alloc_size, + myf my_flags); +extern void *alloc_root(MEM_ROOT *mem_root, size_t Size); +extern void *multi_alloc_root(MEM_ROOT *mem_root, ...); +extern void free_root(MEM_ROOT *root, myf MyFLAGS); +extern void set_prealloc_root(MEM_ROOT *root, char *ptr); +extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, + size_t prealloc_size); +extern USED_MEM *get_last_memroot_block(MEM_ROOT* root); +extern void free_all_new_blocks(MEM_ROOT *root, USED_MEM *last_block); +extern void protect_root(MEM_ROOT *root, int prot); +extern char *strdup_root(MEM_ROOT *root,const char *str); +static inline char *safe_strdup_root(MEM_ROOT *root, const char *str) +{ + return str ? strdup_root(root, str) : 0; +} +extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len); +extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len); + +extern LEX_CSTRING safe_lexcstrdup_root(MEM_ROOT *root, const LEX_CSTRING str); +extern my_bool my_compress(uchar *, size_t *, size_t *); +extern my_bool my_uncompress(uchar *, size_t , size_t *); +extern uchar *my_compress_alloc(const uchar *packet, size_t *len, + size_t *complen); +extern void *my_az_allocator(void *dummy, unsigned int items, unsigned int size); +extern void my_az_free(void *dummy, void *address); +extern int my_compress_buffer(uchar *dest, size_t *destLen, + const uchar *source, size_t sourceLen); +extern int packfrm(const uchar *, size_t, uchar **, size_t *); +extern int unpackfrm(uchar **, size_t *, const uchar *); + +extern uint32 my_checksum(uint32, const void *, size_t); +extern uint32 my_crc32c(uint32, const void *, size_t); + +extern const char *my_crc32c_implementation(); + +#ifdef DBUG_ASSERT_EXISTS +extern void my_debug_put_break_here(void); +#else +#define my_debug_put_break_here() do {} while(0) +#endif + +extern void my_sleep(ulong m_seconds); +extern uint my_set_max_open_files(uint files); +void my_free_open_file_info(void); + +extern my_bool my_gethwaddr(uchar *to); +extern int my_getncpus(void); + +#define HRTIME_RESOLUTION 1000000ULL /* microseconds */ +typedef struct {ulonglong val;} my_hrtime_t; +void my_time_init(void); +extern my_hrtime_t my_hrtime(void); + +#ifdef _WIN32 +extern my_hrtime_t my_hrtime_coarse(); +#else +#define my_hrtime_coarse() my_hrtime() +#endif + +extern ulonglong my_interval_timer(void); +extern ulonglong my_getcputime(void); + +#define microsecond_interval_timer() (my_interval_timer()/1000) +#define hrtime_to_time(X) ((time_t)((X).val/HRTIME_RESOLUTION)) +#define hrtime_from_time(X) ((ulonglong)((X)*HRTIME_RESOLUTION)) +#define hrtime_to_double(X) ((X).val/(double)HRTIME_RESOLUTION) +#define hrtime_sec_part(X) ((ulong)((X).val % HRTIME_RESOLUTION)) +#define my_time(X) hrtime_to_time(my_hrtime_coarse()) + +/** + Make high resolution time from two parts. +*/ + +static inline my_hrtime_t make_hr_time(my_time_t time, ulong time_sec_part) +{ + my_hrtime_t res= {((ulonglong) time)*1000000 + time_sec_part}; + return res; +} + + +#if STACK_DIRECTION < 0 +#define available_stack_size(CUR,END) (long) ((char*)(CUR) - (char*)(END)) +#else +#define available_stack_size(CUR,END) (long) ((char*)(END) - (char*)(CUR)) +#endif + +#ifndef MAP_SYNC +#define MAP_SYNC 0x80000 +#endif +#ifndef MAP_SHARED_VALIDATE +#define MAP_SHARED_VALIDATE 0x03 +#endif + +#ifdef HAVE_SYS_MMAN_H +#ifndef MAP_NOSYNC +#define MAP_NOSYNC 0 +#endif +#ifndef MAP_NORESERVE +#define MAP_NORESERVE 0 /* For irix and AIX */ +#endif + +#ifdef HAVE_MMAP64 +#define my_mmap(a,b,c,d,e,f) mmap64(a,b,c,d,e,f) +#else +#define my_mmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f) +#endif +#define my_munmap(a,b) munmap((a),(b)) + +#else +/* not a complete set of mmap() flags, but only those that necessary */ +#define PROT_READ 1 +#define PROT_WRITE 2 +#define MAP_NORESERVE 0 +#define MAP_SHARED 0x0001 +#define MAP_PRIVATE 0x0002 +#define MAP_NOSYNC 0x0800 +#define MAP_FAILED ((void *)-1) +#define MS_SYNC 0x0000 + +#define HAVE_MMAP +void *my_mmap(void *, size_t, int, int, int, my_off_t); +int my_munmap(void *, size_t); +#endif + +#ifdef _WIN32 +extern FILE* my_win_popen(const char*, const char*); +extern int my_win_pclose(FILE*); +#define my_popen(A,B) my_win_popen(A,B) +#define my_pclose(A) my_win_pclose(A) +#else +#define my_popen(A,B) popen(A,B) +#define my_pclose(A) pclose(A) +#endif + +/* my_getpagesize */ +#ifdef HAVE_GETPAGESIZE +#define my_getpagesize() getpagesize() +#else +int my_getpagesize(void); +#endif + +int my_msync(int, void *, size_t, int); + +#define MY_UUID_SIZE 16 +#define MY_UUID_BARE_STRING_LENGTH (8+4+4+4+12) +#define MY_UUID_SEPARATORS 4 +#define MY_UUID_STRING_LENGTH (MY_UUID_BARE_STRING_LENGTH + MY_UUID_SEPARATORS) + +void my_uuid_init(ulong seed1, ulong seed2); +void my_uuid(uchar *guid); +void my_uuid_end(void); + +static inline void my_uuid2str(const uchar *guid, char *s, int with_separators) +{ + int i; + int mask= with_separators ? ((1 << 3) | (1 << 5) | (1 << 7) | (1 << 9)) : 0; + for (i=0; i < MY_UUID_SIZE; i++, mask >>= 1) + { + *s++= _dig_vec_lower[guid[i] >>4]; + *s++= _dig_vec_lower[guid[i] & 15]; + if (mask & 1) + *s++= '-'; + } +} + + +const char *my_dlerror(const char *dlpath); + +/* character sets */ +extern void my_charset_loader_init_mysys(MY_CHARSET_LOADER *loader); +extern uint get_charset_number(const char *cs_name, uint cs_flags, myf flags); +extern uint get_collation_number(const char *name,myf flags); +extern const char *get_charset_name(uint cs_number); + +extern CHARSET_INFO *get_charset(uint cs_number, myf flags); +extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags); +extern CHARSET_INFO *my_collation_get_by_name(MY_CHARSET_LOADER *loader, + const char *name, myf flags); +extern CHARSET_INFO *get_charset_by_csname(const char *cs_name, + uint cs_flags, myf my_flags); +extern CHARSET_INFO *my_charset_get_by_name(MY_CHARSET_LOADER *loader, + const char *name, + uint cs_flags, myf my_flags); +extern my_bool resolve_charset(const char *cs_name, + CHARSET_INFO *default_cs, + CHARSET_INFO **cs, + myf flags); +extern my_bool resolve_collation(const char *cl_name, + CHARSET_INFO *default_cl, + CHARSET_INFO **cl, + myf my_flags); +extern void free_charsets(void); +extern char *get_charsets_dir(char *buf); +static inline my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2) +{ + return (cs1->cs_name.str == cs2->cs_name.str); +} +extern my_bool init_compiled_charsets(myf flags); +extern void add_compiled_collation(struct charset_info_st *cs); +extern void add_compiled_extra_collation(struct charset_info_st *cs); +extern size_t escape_string_for_mysql(CHARSET_INFO *charset_info, + char *to, size_t to_length, + const char *from, size_t length, + my_bool *overflow); +extern char *my_get_tty_password(const char *opt_message); +#ifdef _WIN32 +#define BACKSLASH_MBTAIL +/* File system character set */ +extern CHARSET_INFO *fs_character_set(void); +extern int my_set_console_cp(const char *name); +#else +#define my_set_console_cp(A) do {} while (0) +#endif +extern const char *my_default_csname(void); +extern size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info, + char *to, size_t to_length, + const char *from, size_t length, + my_bool *overflow); + +extern void thd_increment_bytes_sent(void *thd, size_t length); +extern void thd_increment_bytes_received(void *thd, size_t length); +extern void thd_increment_net_big_packet_count(void *thd, size_t length); + +#include <mysql/psi/psi.h> + +#ifdef HAVE_PSI_INTERFACE +extern MYSQL_PLUGIN_IMPORT struct PSI_bootstrap *PSI_hook; +extern void set_psi_server(PSI *psi); +void my_init_mysys_psi_keys(void); +#endif + +struct st_mysql_file; +extern struct st_mysql_file *mysql_stdin; +C_MODE_END + + +#ifdef __cplusplus + +class Charset_loader_mysys: public MY_CHARSET_LOADER +{ +public: + Charset_loader_mysys() + { + my_charset_loader_init_mysys(this); + } + + /** + Get a CHARSET_INFO by a character set name. + + @param name Collation name + @param cs_flags e.g. MY_CS_PRIMARY, MY_CS_BINARY + @param my_flags mysys flags (MY_WME, MY_UTF8_IS_UTF8MB3) + @return + @retval NULL on error (e.g. not found) + @retval A CHARSET_INFO pointter on success + */ + CHARSET_INFO *get_charset(const char *cs_name, uint cs_flags, myf my_flags) + { + error[0]= '\0'; // Need to clear in case of the second call + return my_charset_get_by_name(this, cs_name, cs_flags, my_flags); + } + + /** + Get a CHARSET_INFO by an exact collation by name. + + @param name Collation name + @param my_flags e.g. the utf8 translation flag + @return + @retval NULL on error (e.g. not found) + @retval A CHARSET_INFO pointter on success + */ + CHARSET_INFO *get_exact_collation(const char *name, myf my_flags) + { + error[0]= '\0'; // Need to clear in case of the second call + return my_collation_get_by_name(this, name, my_flags); + } + + /** + Get a CHARSET_INFO by a context collation by name. + The returned pointer must be further resolved to a character set. + + @param name Collation name + @param utf8_flag The utf8 translation flag + @return + @retval NULL on error (e.g. not found) + @retval A CHARSET_INFO pointter on success + */ + CHARSET_INFO *get_context_collation(const char *name, myf my_flags) + { + return get_exact_collation_by_context_name(&my_charset_utf8mb4_general_ci, + name, my_flags); + } + + /** + Get an exact CHARSET_INFO by a contextually typed collation name. + + @param name Collation name + @param utf8_flag The utf8 translation flag + @return + @retval NULL on error (e.g. not found) + @retval A CHARSET_INFO pointer on success + */ + CHARSET_INFO *get_exact_collation_by_context_name(CHARSET_INFO *cs, + const char *name, + myf my_flags) + { + char tmp[MY_CS_COLLATION_NAME_SIZE]; + my_snprintf(tmp, sizeof(tmp), "%s_%s", cs->cs_name.str, name); + return get_exact_collation(tmp, my_flags); + } + + /* + Find a collation with binary comparison rules + */ + CHARSET_INFO *get_bin_collation(CHARSET_INFO *cs, myf my_flags) + { + /* + We don't need to handle old_mode=UTF8_IS_UTF8MB3 here, + This method assumes that "cs" points to a real character set name. + It can be either "utf8mb3" or "utf8mb4". It cannot be "utf8". + No thd->get_utf8_flag() flag passed to get_charset_by_csname(). + */ + DBUG_ASSERT(cs->cs_name.length !=4 || memcmp(cs->cs_name.str, "utf8", 4)); + /* + CREATE TABLE t1 (a CHAR(10) BINARY) + CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; + Nothing to do, we have the binary collation already. + */ + if (cs->state & MY_CS_BINSORT) + return cs; + + // CREATE TABLE t1 (a CHAR(10) BINARY) CHARACTER SET utf8mb4;/ + error[0]= '\0'; // Need in case of the second execution + return get_charset(cs->cs_name.str, MY_CS_BINSORT, my_flags); + } + + /* + Find the default collation in the given character set + */ + CHARSET_INFO *get_default_collation(CHARSET_INFO *cs, myf my_flags) + { + // See comments in find_bin_collation_or_error() + DBUG_ASSERT(cs->cs_name.length !=4 || memcmp(cs->cs_name.str, "utf8", 4)); + /* + CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT) CHARACTER SET utf8mb4; + Nothing to do, we have the default collation already. + */ + if (cs->state & MY_CS_PRIMARY) + return cs; + /* + CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT) + CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; + + Don't need to handle old_mode=UTF8_IS_UTF8MB3 here. + See comments in find_bin_collation_or_error. + */ + cs= get_charset(cs->cs_name.str, MY_CS_PRIMARY, my_flags); + DBUG_ASSERT(cs); + return cs; + } +}; + +#endif /*__cplusplus */ + + +#endif /* _my_sys_h */ diff --git a/include/my_time.h b/include/my_time.h new file mode 100644 index 00000000..9f3e61b9 --- /dev/null +++ b/include/my_time.h @@ -0,0 +1,285 @@ +/* + Copyright (c) 2004, 2011, Oracle and/or its affiliates. + Copyright (c) 2017, Monty Program Ab. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + This is a private header of sql-common library, containing + declarations for my_time.c +*/ + +#ifndef _my_time_h_ +#define _my_time_h_ +#include "mysql_time.h" +#include "my_decimal_limits.h" + +C_MODE_START + +extern MYSQL_PLUGIN_IMPORT ulonglong log_10_int[20]; +extern uchar days_in_month[]; + +#define MY_TIME_T_MAX LONG_MAX +#define MY_TIME_T_MIN LONG_MIN + +/* Time handling defaults */ +#define TIMESTAMP_MAX_YEAR 2038 +#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) +#define TIMESTAMP_MAX_VALUE INT_MAX32 +#define TIMESTAMP_MIN_VALUE 0 + +/* two-digit years < this are 20..; >= this are 19.. */ +#define YY_PART_YEAR 70 + +/* + check for valid times only if the range of time_t is greater than + the range of my_time_t +*/ +#if SIZEOF_TIME_T > 4 || defined(TIME_T_UNSIGNED) +# define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \ + ((x) <= TIMESTAMP_MAX_VALUE && \ + (x) >= TIMESTAMP_MIN_VALUE) +#else +# define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \ + ((x) >= TIMESTAMP_MIN_VALUE) +#endif + +/* Flags to str_to_datetime */ + +#define C_TIME_NO_ZERO_IN_DATE (1UL << 23) /* == MODE_NO_ZERO_IN_DATE */ +#define C_TIME_NO_ZERO_DATE (1UL << 24) /* == MODE_NO_ZERO_DATE */ +#define C_TIME_INVALID_DATES (1UL << 25) /* == MODE_INVALID_DATES */ + +#define MYSQL_TIME_WARN_TRUNCATED 1U +#define MYSQL_TIME_WARN_OUT_OF_RANGE 2U +#define MYSQL_TIME_WARN_EDOM 4U +#define MYSQL_TIME_WARN_ZERO_DATE 8U +#define MYSQL_TIME_NOTE_TRUNCATED 16U + +#define MYSQL_TIME_WARN_WARNINGS (MYSQL_TIME_WARN_TRUNCATED|\ + MYSQL_TIME_WARN_OUT_OF_RANGE|\ + MYSQL_TIME_WARN_EDOM|\ + MYSQL_TIME_WARN_ZERO_DATE) +#define MYSQL_TIME_WARN_NOTES (MYSQL_TIME_NOTE_TRUNCATED) + +#define MYSQL_TIME_WARN_HAVE_WARNINGS(x) MY_TEST((x) & MYSQL_TIME_WARN_WARNINGS) +#define MYSQL_TIME_WARN_HAVE_NOTES(x) MY_TEST((x) & MYSQL_TIME_WARN_NOTES) + +/* Useful constants */ +#define SECONDS_IN_24H 86400L + +/* Limits for the INTERVAL data type */ + + /* Number of hours between '0001-01-01 00h' and '9999-12-31 23h' */ +#define TIME_MAX_INTERVAL_HOUR 87649415 +#define TIME_MAX_INTERVAL_HOUR_CHAR_LENGTH 8 + +/* Number of full days between '0001-01-01' and '9999-12-31'*/ +#define TIME_MAX_INTERVAL_DAY 3652058 /*87649415/24*/ +#define TIME_MAX_INTERVAL_DAY_CHAR_LENGTH 7 + +/* Limits for the TIME data type */ +#define TIME_MAX_HOUR 838 +#define TIME_MAX_MINUTE 59 +#define TIME_MAX_SECOND 59 +#define TIME_MAX_SECOND_PART 999999 +#define TIME_SECOND_PART_FACTOR (TIME_MAX_SECOND_PART+1) +#define TIME_SECOND_PART_DIGITS 6 +#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND) +#define TIME_MAX_VALUE_SECONDS (TIME_MAX_HOUR * 3600L + \ + TIME_MAX_MINUTE * 60L + TIME_MAX_SECOND) + +/* + Structure to return status from + str_to_datetime(), str_to_time(). +*/ +typedef struct st_mysql_time_status +{ + int warnings; + uint precision; + uint nanoseconds; +} MYSQL_TIME_STATUS; + +static inline void my_time_status_init(MYSQL_TIME_STATUS *status) +{ + status->warnings= 0; + status->precision= 0; + status->nanoseconds= 0; +} + +my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, + ulonglong flags, int *was_cut); +my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *l_time, + ulong max_hour, MYSQL_TIME_STATUS *status); +my_bool str_to_datetime_or_date_or_time(const char *str, size_t length, + MYSQL_TIME *to, ulonglong flag, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour); +my_bool +str_to_datetime_or_date_or_interval_hhmmssff(const char *str, size_t length, + MYSQL_TIME *to, ulonglong flag, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour); +my_bool +str_to_datetime_or_date_or_interval_day(const char *str, size_t length, + MYSQL_TIME *to, ulonglong flag, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour); +my_bool str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *to, + ulonglong flags, MYSQL_TIME_STATUS *status); + +longlong number_to_datetime_or_date(longlong nr, ulong sec_part, + MYSQL_TIME *time_res, + ulonglong flags, int *was_cut); +int number_to_time_only(my_bool neg, ulonglong nr, ulong sec_part, + ulong max_hour, MYSQL_TIME *to, int *was_cut); + +ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *); +ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *); +ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *); +ulonglong TIME_to_ulonglong(const MYSQL_TIME *); +double TIME_to_double(const MYSQL_TIME *my_time); + +int check_time_range(struct st_mysql_time *my_time, uint dec, int *warning); +my_bool check_datetime_range(const MYSQL_TIME *ltime); + + +long calc_daynr(uint year,uint month,uint day); +uint calc_days_in_year(uint year); +uint year_2000_handling(uint year); + +void my_init_time(void); + + +/* + Function to check sanity of a TIMESTAMP value + + DESCRIPTION + Check if a given MYSQL_TIME value fits in TIMESTAMP range. + This function doesn't make precise check, but rather a rough + estimate. + + RETURN VALUES + TRUE The value seems sane + FALSE The MYSQL_TIME value is definitely out of range +*/ + +static inline my_bool validate_timestamp_range(const MYSQL_TIME *t) +{ + if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) || + (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) || + (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31))) + return FALSE; + + return TRUE; +} + +/* Can't include mysqld_error.h, it needs mysys to build, thus hardcode 2 error values here. */ +#ifndef ER_WARN_DATA_OUT_OF_RANGE +#define ER_WARN_DATA_OUT_OF_RANGE 1264 +#define ER_WARN_INVALID_TIMESTAMP 1299 +#endif + +my_time_t +my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, uint *error_code); + +void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type); + +/* + Required buffer length for my_time_to_str, my_date_to_str, + my_datetime_to_str and TIME_to_string functions. Note, that the + caller is still responsible to check that given TIME structure + has values in valid ranges, otherwise size of the buffer could + be not enough. We also rely on the fact that even wrong values + sent using binary protocol fit in this buffer. +*/ +#define MAX_DATE_STRING_REP_LENGTH 30 +#define AUTO_SEC_PART_DIGITS DECIMAL_NOT_SPECIFIED + +int my_interval_DDhhmmssff_to_str(const MYSQL_TIME *, char *to, uint digits); +int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint digits); +int my_date_to_str(const MYSQL_TIME *l_time, char *to); +int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits); +int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint digits); + +int my_timeval_to_str(const struct timeval *tm, char *to, uint dec); + +static inline longlong sec_part_shift(longlong second_part, uint digits) +{ + return second_part / (longlong)log_10_int[TIME_SECOND_PART_DIGITS - digits]; +} +static inline longlong sec_part_unshift(longlong second_part, uint digits) +{ + return second_part * (longlong)log_10_int[TIME_SECOND_PART_DIGITS - digits]; +} + +/* Date/time rounding and truncation functions */ +static inline long my_time_fraction_remainder(long nr, uint decimals) +{ + DBUG_ASSERT(decimals <= TIME_SECOND_PART_DIGITS); + return nr % (long) log_10_int[TIME_SECOND_PART_DIGITS - decimals]; +} +static inline void my_datetime_trunc(MYSQL_TIME *ltime, uint decimals) +{ + ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals); +} +static inline void my_time_trunc(MYSQL_TIME *ltime, uint decimals) +{ + ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals); + if (!ltime->second_part && ltime->neg && + !ltime->hour && !ltime->minute && !ltime->second) + ltime->neg= FALSE; +} +#ifdef _WIN32 +#define suseconds_t long +#endif +static inline void my_timeval_trunc(struct timeval *tv, uint decimals) +{ + tv->tv_usec-= (suseconds_t) my_time_fraction_remainder(tv->tv_usec, decimals); +} + + +#define hrtime_to_my_time(X) ((my_time_t)hrtime_to_time(X)) + +/* + Available interval types used in any statement. + + 'interval_type' must be sorted so that simple intervals comes first, + ie year, quarter, month, week, day, hour, etc. The order based on + interval size is also important and the intervals should be kept in a + large to smaller order. (get_interval_value() depends on this) + + Note: If you change the order of elements in this enum you should fix + order of elements in 'interval_type_to_name' and 'interval_names' + arrays + + See also interval_type_to_name, get_interval_value, interval_names, append_interval +*/ + +enum interval_type +{ + INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK, INTERVAL_DAY, + INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND, INTERVAL_MICROSECOND, + INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, + INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, + INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND, + INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND, INTERVAL_LAST +}; + +C_MODE_END + +#endif /* _my_time_h_ */ diff --git a/include/my_tree.h b/include/my_tree.h new file mode 100644 index 00000000..9bed28ef --- /dev/null +++ b/include/my_tree.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2000, 2016, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _tree_h +#define _tree_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "my_base.h" /* get 'enum ha_rkey_function' */ +#include "my_alloc.h" /* MEM_ROOT */ + +/* Worst case tree is half full. This gives use 2^(MAX_TREE_HEIGHT/2) leafs */ +#define MAX_TREE_HEIGHT 64 + +#define ELEMENT_KEY(tree,element)\ +(tree->offset_to_key ? (void*)((uchar*) element+tree->offset_to_key) :\ + *((void**) (element+1))) + +#define tree_set_pointer(element,ptr) *((uchar **) (element+1))=((uchar*) (ptr)) + +/* + A tree with its flag set to TREE_ONLY_DUPS behaves differently on inserting + an element that is not in the tree: + the element is not added at all, but instead tree_insert() returns a special + address TREE_ELEMENT_UNIQUE as an indication that the function has not failed + due to lack of memory. +*/ + +#define TREE_ELEMENT_UNIQUE ((TREE_ELEMENT *) 1) +#define TREE_NO_DUPS 1 +#define TREE_ONLY_DUPS 2 + +typedef enum { left_root_right, right_root_left } TREE_WALK; +typedef uint32 element_count; +typedef int (*tree_walk_action)(void *,element_count,void *); + +typedef enum { free_init, free_free, free_end } TREE_FREE; +typedef int (*tree_element_free)(void*, TREE_FREE, void *); + +typedef struct st_tree_element { + struct st_tree_element *left,*right; + uint32 count:31, + colour:1; /* black is marked as 1 */ +} TREE_ELEMENT; + +#define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs)) + +typedef struct st_tree { + TREE_ELEMENT *root; + TREE_ELEMENT **parents[MAX_TREE_HEIGHT]; + uint offset_to_key,elements_in_tree,size_of_element; + size_t memory_limit, allocated; + qsort_cmp2 compare; + void *custom_arg; + MEM_ROOT mem_root; + my_bool with_delete; + tree_element_free free; + myf my_flags; + uint flag; +} TREE; + + /* Functions on whole tree */ +void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, + int size, qsort_cmp2 compare, + tree_element_free free_element, void *custom_arg, + myf my_flags); +int delete_tree(TREE*, my_bool abort); +int reset_tree(TREE*); + + /* similar to delete tree, except we do not my_free() blocks in mem_root */ +#define is_tree_inited(tree) ((tree)->root != 0) + + /* Functions on leafs */ +TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size, + void *custom_arg); +void *tree_search(TREE *tree, void *key, void *custom_arg); +int tree_walk(TREE *tree,tree_walk_action action, + void *argument, TREE_WALK visit); +int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg); +void *tree_search_key(TREE *tree, const void *key, + TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, + enum ha_rkey_function flag, void *custom_arg); +void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents, + TREE_ELEMENT ***last_pos, int child_offs); +void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs, + int r_offs); +ha_rows tree_record_pos(TREE *tree, const void *key, + enum ha_rkey_function search_flag, void *custom_arg); +#define reset_free_element(tree) (tree)->free= 0 + +#define TREE_ELEMENT_EXTRA_SIZE (sizeof(TREE_ELEMENT) + sizeof(void*)) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/my_uctype.h b/include/my_uctype.h new file mode 100644 index 00000000..82949ffe --- /dev/null +++ b/include/my_uctype.h @@ -0,0 +1,1484 @@ +#ifndef MY_UCTYPE_INCLUDED +#define MY_UCTYPE_INCLUDED + +/* Copyright (c) 2006 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Unicode ctype data + Generated from UnicodeData-5.0.0d9.txt +*/ +static unsigned char uctype_page00[256]= +{ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, + 16, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 16, 16, 16, 16, 16, + 16, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 16, 16, 16, 16, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 32, 16, 16, + 16, 16, 20, 20, 16, 2, 16, 16, 16, 20, 2, 16, 20, 20, 20, 16, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_page01[256]= +{ + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, + 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 1, + 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, + 2, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2 +}; + +static unsigned char uctype_page02[256]= +{ + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, + 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 2, 2, 2, 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page03[256]= +{ + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 2, 2, 2, 2, 16, 0, + 0, 0, 0, 0, 16, 16, 1, 16, 1, 1, 1, 0, 1, 0, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 2, 2, 2, 2, 1, 2, 16, 1, 2, 1, 1, 2, 2, 1, 1, 1 +}; + +static unsigned char uctype_page04[256]= +{ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 16, 18, 18, 18, 18, 0, 18, 18, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 +}; + +static unsigned char uctype_page05[256]= +{ + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 16, 16, 16, 16, 16, 16, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 16, 16, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 16, 18, + 16, 18, 18, 16, 18, 18, 16, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 2, 2, 2, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page06[256]= +{ + 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, + 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 16, 0, 0, 16, 16, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 2, 2, + 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 16, 2, 18, 18, 18, 18, 18, 18, 18, 32, 18, 18, + 18, 18, 18, 18, 18, 2, 2, 18, 18, 16, 18, 18, 18, 18, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 16, 16, 2 +}; + +static unsigned char uctype_page07[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 32, + 2, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 2, 2, 16, 16, 16, 16, 2, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page09[256]= +{ + 0, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, + 2, 18, 18, 18, 18, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 18, 18, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, + 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 0, 0, 18, 18, 0, 0, 18, 18, 18, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 2, 2, 0, 2, + 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 16, 16, 20, 20, 20, 20, 20, 20, 16, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0A[256]= +{ + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, + 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 18, 0, 18, 18, + 18, 18, 18, 0, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 18, 18, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, + 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0B[256]= +{ + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, + 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 2, 2, 0, 2, + 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 16, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0, 2, 0, 2, 2, + 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, + 18, 18, 18, 0, 0, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0C[256]= +{ + 0, 18, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, + 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 18, 2, 18, 18, + 18, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 2, 2, 18, 18, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0D[256]= +{ + 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, 18, + 18, 18, 18, 18, 0, 0, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 18, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 18, 0, 0, 0, 0, 18, + 18, 18, 18, 18, 18, 0, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 18, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0E[256]= +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 18, 2, 2, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 16, + 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 16, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 0, 2, 0, 0, 2, 2, 0, 2, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, + 0, 2, 2, 2, 0, 2, 0, 2, 0, 0, 2, 2, 0, 2, 2, 2, + 2, 18, 2, 2, 18, 18, 18, 18, 18, 18, 0, 18, 18, 2, 0, 0, + 2, 2, 2, 2, 2, 0, 2, 0, 18, 18, 18, 18, 18, 18, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page0F[256]= +{ + 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 16, 16, 16, 16, 16, 16, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 16, 18, 16, 18, 16, 18, 16, 16, 16, 16, 18, 18, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 16, 18, 18, 2, 2, 2, 2, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 16, 16, + 16, 16, 16, 16, 16, 16, 18, 16, 16, 16, 16, 16, 16, 0, 0, 16, + 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page10[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 18, 18, 18, 18, + 18, 18, 18, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, + 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 0, 0, 0 +}; + +static unsigned char uctype_page11[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page12[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_page13[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 18, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page14[256]= +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_page16[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 7, 7, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page17[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 2, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 18, 18, 18, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 32, 32, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 16, 16, 16, 2, 16, 16, 16, 16, 2, 18, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page18[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 8, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page19[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, + 16, 0, 0, 0, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 2, 2, 2, 2, 2, 2, 2, 18, 18, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page1A[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 18, 18, 18, 18, 18, 0, 0, 16, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page1B[256]= +{ + 18, 18, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page1D[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18 +}; + +static unsigned char uctype_page1E[256]= +{ + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page1F[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 2, 16, + 16, 16, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 16, 16, + 2, 2, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 0, 16, 16, 16, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 16, 16, 16, + 0, 0, 2, 2, 2, 0, 2, 2, 1, 1, 1, 1, 1, 16, 16, 0 +}; + +static unsigned char uctype_page20[256]= +{ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 32, 32, 32, 32, 32, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 32, 32, 32, 32, 32, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, + 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, + 20, 2, 0, 0, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 2, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 0, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page21[256]= +{ + 16, 16, 1, 16, 16, 16, 16, 1, 16, 16, 2, 1, 1, 1, 2, 2, + 1, 1, 1, 2, 16, 1, 16, 16, 16, 1, 1, 1, 1, 1, 16, 16, + 16, 16, 16, 16, 1, 16, 1, 16, 1, 16, 1, 1, 1, 1, 16, 2, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 16, 16, 2, 2, 1, 1, + 16, 16, 16, 16, 16, 1, 2, 2, 2, 2, 16, 16, 16, 16, 2, 0, + 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page23[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page24[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 +}; + +static unsigned char uctype_page26[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page27[256]= +{ + 0, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 0, 16, + 16, 16, 16, 0, 0, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 16, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page2B[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page2C[256]= +{ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, + 0, 0, 0, 0, 2, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 2, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 20, 16, 16 +}; + +static unsigned char uctype_page2D[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page2E[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 16, 16, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_page2F[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0 +}; + +static unsigned char uctype_page30[256]= +{ + 8, 16, 16, 16, 16, 2, 2, 7, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 18, 18, 18, 18, 18, + 16, 2, 2, 2, 2, 2, 16, 16, 7, 7, 7, 2, 2, 16, 16, 16, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 0, 18, 18, 16, 16, 2, 2, 2, + 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2 +}; + +static unsigned char uctype_page31[256]= +{ + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_page32[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0 +}; + +static unsigned char uctype_page4D[256]= +{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static unsigned char uctype_page9F[256]= +{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageA4[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageA7[256]= +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageA8[256]= +{ + 2, 2, 18, 2, 2, 2, 18, 2, 2, 2, 2, 18, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 18, 18, 18, 18, 18, 16, 16, 16, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageD7[256]= +{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageD8[256]= +{ + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageDB[256]= +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 +}; + +static unsigned char uctype_pageDC[256]= +{ + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageDF[256]= +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 +}; + +static unsigned char uctype_pageE0[256]= +{ + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageF8[256]= +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 +}; + +static unsigned char uctype_pageFA[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned char uctype_pageFB[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 18, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 0, + 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static unsigned char uctype_pageFD[256]= +{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 0, 0 +}; + +static unsigned char uctype_pageFE[256]= +{ + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, + 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 32 +}; + +static unsigned char uctype_pageFF[256]= +{ + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, + 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, + 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, + 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 16, 16, 0, 0 +}; + +MY_UNI_CTYPE my_uni_ctype[256]={ + {0,uctype_page00}, + {0,uctype_page01}, + {0,uctype_page02}, + {0,uctype_page03}, + {0,uctype_page04}, + {0,uctype_page05}, + {0,uctype_page06}, + {0,uctype_page07}, + {0,NULL}, + {0,uctype_page09}, + {0,uctype_page0A}, + {0,uctype_page0B}, + {0,uctype_page0C}, + {0,uctype_page0D}, + {0,uctype_page0E}, + {0,uctype_page0F}, + {0,uctype_page10}, + {0,uctype_page11}, + {0,uctype_page12}, + {0,uctype_page13}, + {0,uctype_page14}, + {2,NULL}, + {0,uctype_page16}, + {0,uctype_page17}, + {0,uctype_page18}, + {0,uctype_page19}, + {0,uctype_page1A}, + {0,uctype_page1B}, + {0,NULL}, + {0,uctype_page1D}, + {0,uctype_page1E}, + {0,uctype_page1F}, + {0,uctype_page20}, + {0,uctype_page21}, + {16,NULL}, + {0,uctype_page23}, + {0,uctype_page24}, + {16,NULL}, + {0,uctype_page26}, + {0,uctype_page27}, + {16,NULL}, + {16,NULL}, + {16,NULL}, + {0,uctype_page2B}, + {0,uctype_page2C}, + {0,uctype_page2D}, + {0,uctype_page2E}, + {0,uctype_page2F}, + {0,uctype_page30}, + {0,uctype_page31}, + {0,uctype_page32}, + {16,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {0,uctype_page4D}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {0,uctype_page9F}, + {2,NULL}, + {2,NULL}, + {2,NULL}, + {2,NULL}, + {0,uctype_pageA4}, + {0,NULL}, + {0,NULL}, + {0,uctype_pageA7}, + {0,uctype_pageA8}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {3,NULL}, + {0,uctype_pageD7}, + {0,uctype_pageD8}, + {0,NULL}, + {0,NULL}, + {0,uctype_pageDB}, + {0,uctype_pageDC}, + {0,NULL}, + {0,NULL}, + {0,uctype_pageDF}, + {0,uctype_pageE0}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,NULL}, + {0,uctype_pageF8}, + {2,NULL}, + {0,uctype_pageFA}, + {0,uctype_pageFB}, + {2,NULL}, + {0,uctype_pageFD}, + {0,uctype_pageFE}, + {0,uctype_pageFF} +}; + + +#endif /* MY_UCTYPE_INCLUDED */ diff --git a/include/my_user.h b/include/my_user.h new file mode 100644 index 00000000..46a811d5 --- /dev/null +++ b/include/my_user.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2005-2007 MySQL AB + Use is subject to license terms + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + This is a header for libraries containing functions used in both server and + only some of clients (but not in libmysql)... +*/ + +#ifndef _my_user_h_ +#define _my_user_h_ + +C_MODE_START + +int parse_user(const char *user_id_str, size_t user_id_len, + char *user_name_str, size_t *user_name_len, + char *host_name_str, size_t *host_name_len); + +C_MODE_END + +#endif /* _my_user_h_ */ diff --git a/include/my_valgrind.h b/include/my_valgrind.h new file mode 100644 index 00000000..dfe2c3db --- /dev/null +++ b/include/my_valgrind.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2010, 2022, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MY_VALGRIND_INCLUDED +#define MY_VALGRIND_INCLUDED + +/* clang -> gcc */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif +#if __has_feature(address_sanitizer) +# define __SANITIZE_ADDRESS__ 1 +#endif + +#if __has_feature(memory_sanitizer) +# include <sanitizer/msan_interface.h> +# define HAVE_valgrind +# define HAVE_MEM_CHECK +# define MEM_UNDEFINED(a,len) __msan_allocated_memory(a,len) +# define MEM_MAKE_ADDRESSABLE(a,len) MEM_UNDEFINED(a,len) +# define MEM_MAKE_DEFINED(a,len) __msan_unpoison(a,len) +# define MEM_NOACCESS(a,len) ((void) 0) +# define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) +# define MEM_CHECK_DEFINED(a,len) __msan_check_mem_is_initialized(a,len) +# define MEM_GET_VBITS(a,b,len) __msan_copy_shadow(b,a,len) +# define MEM_SET_VBITS(a,b,len) __msan_copy_shadow(a,b,len) +# define REDZONE_SIZE 8 +# ifdef __linux__ +# define MSAN_STAT_WORKAROUND(st) MEM_MAKE_DEFINED(st, sizeof(*st)) +# else +# define MSAN_STAT_WORKAROUND(st) ((void) 0) +# endif +#elif defined(HAVE_VALGRIND_MEMCHECK_H) && defined(HAVE_valgrind) +# include <valgrind/memcheck.h> +# define HAVE_MEM_CHECK +# define MEM_UNDEFINED(a,len) VALGRIND_MAKE_MEM_UNDEFINED(a,len) +# define MEM_MAKE_ADDRESSABLE(a,len) MEM_UNDEFINED(a,len) +# define MEM_MAKE_DEFINED(a,len) VALGRIND_MAKE_MEM_DEFINED(a,len) +# define MEM_NOACCESS(a,len) VALGRIND_MAKE_MEM_NOACCESS(a,len) +# define MEM_CHECK_ADDRESSABLE(a,len) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,len) +# define MEM_CHECK_DEFINED(a,len) VALGRIND_CHECK_MEM_IS_DEFINED(a,len) +# define MEM_GET_VBITS(a,b,len) VALGRIND_GET_VBITS(a,b,len) +# define MEM_SET_VBITS(a,b,len) VALGRIND_SET_VBITS(a,b,len) +# define REDZONE_SIZE 8 +# define MSAN_STAT_WORKAROUND(st) ((void) 0) +#elif defined(__SANITIZE_ADDRESS__) && (!defined(_MSC_VER) || defined (__clang__)) +# include <sanitizer/asan_interface.h> +/* How to do manual poisoning: +https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */ +# define MEM_UNDEFINED(a,len) ((void) 0) +# define MEM_MAKE_ADDRESSABLE(a,len) ASAN_UNPOISON_MEMORY_REGION(a,len) +# define MEM_MAKE_DEFINED(a,len) ((void) 0) +# define MEM_NOACCESS(a,len) ASAN_POISON_MEMORY_REGION(a,len) +# define MEM_CHECK_ADDRESSABLE(a,len) \ + assert(!__asan_region_is_poisoned((void*) a,len)) +# define MEM_CHECK_DEFINED(a,len) ((void) 0) +# define MEM_GET_VBITS(a,b,len) ((void) 0) +# define MEM_SET_VBITS(a,b,len) ((void) 0) +# define MSAN_STAT_WORKAROUND(st) ((void) 0) +# define REDZONE_SIZE 8 +#else +# define MEM_UNDEFINED(a,len) ((void) 0) +# define MEM_MAKE_ADDRESSABLE(a,len) ((void) 0) +# define MEM_MAKE_DEFINED(a,len) ((void) 0) +# define MEM_NOACCESS(a,len) ((void) 0) +# define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) +# define MEM_CHECK_DEFINED(a,len) ((void) 0) +# define MEM_GET_VBITS(a,b,len) ((void) 0) +# define MEM_SET_VBITS(a,b,len) ((void) 0) +# define REDZONE_SIZE 0 +# define MSAN_STAT_WORKAROUND(st) ((void) 0) +#endif /* __has_feature(memory_sanitizer) */ + +#ifdef TRASH_FREED_MEMORY +/* + _TRASH_FILL() has to call MEM_MAKE_ADDRESSABLE() to cancel any effect of + TRASH_FREE(). + This can happen in the case one does + TRASH_ALLOC(A,B) ; TRASH_FREE(A,B) ; TRASH_ALLOC(A,B) + to reuse the same memory in an internal memory allocator like MEM_ROOT. + _TRASH_FILL() is an internal function and should not be used externally. +*/ +#define _TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_MAKE_ADDRESSABLE(A, trash_tmp); memset(A, C, trash_tmp); } while (0) +#else +#define _TRASH_FILL(A,B,C) do { MEM_UNDEFINED((A), (B)); } while (0) +#endif +/** Note that some memory became allocated and/or uninitialized. */ +#define TRASH_ALLOC(A,B) do { _TRASH_FILL(A,B,0xA5); MEM_MAKE_ADDRESSABLE(A,B); } while(0) +/** Note that some memory became freed. (Prohibit further access to it.) */ +#define TRASH_FREE(A,B) do { _TRASH_FILL(A,B,0x8F); MEM_NOACCESS(A,B); } while(0) + +#endif /* MY_VALGRIND_INCLUDED */ diff --git a/include/my_xml.h b/include/my_xml.h new file mode 100644 index 00000000..846448a0 --- /dev/null +++ b/include/my_xml.h @@ -0,0 +1,97 @@ +/* Copyright (c) 2000, 2002, 2003, 2005, 2007 MySQL AB + Use is subject to license terms + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + + +#ifndef _my_xml_h +#define _my_xml_h + +#ifdef __cplusplus +extern "C" { +#endif + + +#define MY_XML_OK 0 +#define MY_XML_ERROR 1 + +/* + A flag whether to use absolute tag names in call-back functions, + like "a", "a.b" and "a.b.c" (used in character set file parser), + or relative names like "a", "b" and "c". +*/ +#define MY_XML_FLAG_RELATIVE_NAMES 1 + +/* + A flag whether to skip normilization of text values before calling + call-back functions: i.e. skip leading/trailing spaces, + \r, \n, \t characters. +*/ +#define MY_XML_FLAG_SKIP_TEXT_NORMALIZATION 2 + +enum my_xml_node_type +{ + MY_XML_NODE_TAG, /* can have TAG, ATTR and TEXT children */ + MY_XML_NODE_ATTR, /* can have TEXT children */ + MY_XML_NODE_TEXT /* cannot have children */ +}; + +typedef struct xml_stack_st +{ + int flags; + enum my_xml_node_type current_node_type; + char errstr[128]; + + struct { + char static_buffer[128]; + char *buffer; + size_t buffer_size; + char *start; + char *end; + } attr; + + const char *beg; + const char *cur; + const char *end; + void *user_data; + int (*enter)(struct xml_stack_st *st,const char *val, size_t len); + int (*value)(struct xml_stack_st *st,const char *val, size_t len); + int (*leave_xml)(struct xml_stack_st *st,const char *val, size_t len); +} MY_XML_PARSER; + +void my_xml_parser_create(MY_XML_PARSER *st); +void my_xml_parser_free(MY_XML_PARSER *st); +int my_xml_parse(MY_XML_PARSER *st,const char *str, size_t len); + +void my_xml_set_value_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, + const char *, + size_t len)); +void my_xml_set_enter_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, + const char *, + size_t len)); +void my_xml_set_leave_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, + const char *, + size_t len)); +void my_xml_set_user_data(MY_XML_PARSER *st, void *); + +size_t my_xml_error_pos(MY_XML_PARSER *st); +uint my_xml_error_lineno(MY_XML_PARSER *st); + +const char *my_xml_error_string(MY_XML_PARSER *st); + +#ifdef __cplusplus +} +#endif + +#endif /* _my_xml_h */ diff --git a/include/myisam.h b/include/myisam.h new file mode 100644 index 00000000..c90026bf --- /dev/null +++ b/include/myisam.h @@ -0,0 +1,442 @@ +/* + Copyright (c) 2000, 2013, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* This file should be included when using myisam_functions */ + +#ifndef _myisam_h +#define _myisam_h +#ifdef __cplusplus +extern "C" { +#endif + +#include <my_base.h> +#include <m_ctype.h> +#include "keycache.h" +#include "my_compare.h" +#include <myisamchk.h> +#include <mysql/plugin.h> +#include <my_check_opt.h> +/* + Limit max keys according to HA_MAX_POSSIBLE_KEY; See myisamchk.h for details +*/ + +#if MAX_INDEXES > HA_MAX_POSSIBLE_KEY +#define MI_MAX_KEY HA_MAX_POSSIBLE_KEY /* Max allowed keys */ +#else +#define MI_MAX_KEY MAX_INDEXES /* Max allowed keys */ +#endif + +#define MI_MAX_POSSIBLE_KEY_BUFF HA_MAX_POSSIBLE_KEY_BUFF +/* + The following defines can be increased if necessary. + But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and MI_MAX_KEY_LENGTH. +*/ +#define MI_MAX_KEY_LENGTH 1000 /* Max length in bytes */ +#define MI_MAX_KEY_SEG 16 /* Max segments for key */ + +#define MI_NAME_IEXT ".MYI" +#define MI_NAME_DEXT ".MYD" + +/* Possible values for myisam_block_size (must be power of 2) */ +#define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */ +#define MI_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */ +#define MI_MAX_KEY_BLOCK_LENGTH 16384 + +/* + In the following macros '_keyno_' is 0 .. keys-1. + If there can be more keys than bits in the key_map, the highest bit + is for all upper keys. They cannot be switched individually. + This means that clearing of high keys is ignored, setting one high key + sets all high keys. +*/ +#define MI_KEYMAP_BITS (8 * SIZEOF_LONG_LONG) +#define MI_KEYMAP_HIGH_MASK (1ULL << (MI_KEYMAP_BITS - 1)) +#define mi_get_mask_all_keys_active(_keys_) \ + (((_keys_) < MI_KEYMAP_BITS) ? \ + ((1ULL << (_keys_)) - 1ULL) : \ + (~ 0ULL)) + +#if MI_MAX_KEY > MI_KEYMAP_BITS + +#define mi_is_key_active(_keymap_,_keyno_) \ + (((_keyno_) < MI_KEYMAP_BITS) ? \ + MY_TEST((_keymap_) & (1ULL << (_keyno_))) : \ + MY_TEST((_keymap_) & MI_KEYMAP_HIGH_MASK)) +#define mi_set_key_active(_keymap_,_keyno_) \ + (_keymap_)|= (((_keyno_) < MI_KEYMAP_BITS) ? \ + (1ULL << (_keyno_)) : \ + MI_KEYMAP_HIGH_MASK) +#define mi_clear_key_active(_keymap_,_keyno_) \ + (_keymap_)&= (((_keyno_) < MI_KEYMAP_BITS) ? \ + (~ (1ULL << (_keyno_))) : \ + (~ (0ULL)) /*ignore*/ ) + +#else + +#define mi_is_key_active(_keymap_,_keyno_) \ + MY_TEST((_keymap_) & (1ULL << (_keyno_))) +#define mi_set_key_active(_keymap_,_keyno_) \ + (_keymap_)|= (1ULL << (_keyno_)) +#define mi_clear_key_active(_keymap_,_keyno_) \ + (_keymap_)&= (~ (1ULL << (_keyno_))) + +#endif + +#define mi_is_any_key_active(_keymap_) \ + MY_TEST((_keymap_)) +#define mi_is_all_keys_active(_keymap_,_keys_) \ + ((_keymap_) == mi_get_mask_all_keys_active(_keys_)) +#define mi_set_all_keys_active(_keymap_,_keys_) \ + (_keymap_)= mi_get_mask_all_keys_active(_keys_) +#define mi_clear_all_keys_active(_keymap_) \ + (_keymap_)= 0 +#define mi_intersect_keys_active(_to_,_from_) \ + (_to_)&= (_from_) +#define mi_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \ + ((_keymap1_) & (_keymap2_) & \ + mi_get_mask_all_keys_active(_keys_)) +#define mi_copy_keys_active(_to_,_maxkeys_,_from_) \ + (_to_)= (mi_get_mask_all_keys_active(_maxkeys_) & \ + (_from_)) + + /* Param to/from mi_info */ + +typedef struct st_mi_isaminfo /* Struct from h_info */ +{ + ha_rows records; /* Records in database */ + ha_rows deleted; /* Deleted records in database */ + my_off_t recpos; /* Pos for last used record */ + my_off_t newrecpos; /* Pos if we write new record */ + my_off_t dupp_key_pos; /* Position to record with dupp key */ + my_off_t data_file_length, /* Length of data file */ + max_data_file_length, + index_file_length, + max_index_file_length, + delete_length; + ulong reclength; /* Recordlength */ + ulong mean_reclength; /* Mean recordlength (if packed) */ + ulonglong auto_increment; + ulonglong key_map; /* Which keys are used */ + char *data_file_name, *index_file_name; + uint keys; /* Number of keys in use */ + uint options; /* HA_OPTION_... used */ + int errkey, /* With key was dupplicated on err */ + sortkey; /* clustered by this key */ + File filenr; /* (uniq) filenr for datafile */ + time_t create_time; /* When table was created */ + time_t check_time; + time_t update_time; + uint reflength; + ulong record_offset; + ulong *rec_per_key; /* for sql optimizing */ +} MI_ISAMINFO; + + +typedef struct st_mi_create_info +{ + const char *index_file_name, *data_file_name; /* If using symlinks */ + ha_rows max_rows; + ha_rows reloc_rows; + ulonglong auto_increment; + ulonglong data_file_length; + ulonglong key_file_length; + uint old_options; + uint16 language; + my_bool with_auto_increment; +} MI_CREATE_INFO; + +struct st_myisam_info; /* For reference */ +struct st_mi_isam_share; +typedef struct st_myisam_info MI_INFO; +struct st_mi_s_param; + +typedef struct st_mi_keydef /* Key definition with open & info */ +{ + struct st_mi_isam_share *share; /* Pointer to base (set in mi_open) */ + uint16 keysegs; /* Number of key-segment */ + uint16 flag; /* NOSAME, PACK_USED */ + + uint8 key_alg; /* BTREE, RTREE */ + uint16 block_length; /* Length of keyblock (auto) */ + uint16 underflow_block_length; /* When to execute underflow */ + uint16 keylength; /* Tot length of keyparts (auto) */ + uint16 minlength; /* min length of (packed) key (auto) */ + uint16 maxlength; /* max length of (packed) key (auto) */ + uint16 block_size_index; /* block_size (auto) */ + uint32 version; /* For concurrent read/write */ + uint32 ftkey_nr; /* full-text index number */ + + HA_KEYSEG *seg,*end; + struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */ + int (*bin_search)(struct st_myisam_info *info,struct st_mi_keydef *keyinfo, + uchar *page,uchar *key, + uint key_len,uint comp_flag,uchar * *ret_pos, + uchar *buff, my_bool *was_last_key); + uint (*get_key)(struct st_mi_keydef *keyinfo,uint nod_flag,uchar * *page, + uchar *key); + int (*pack_key)(struct st_mi_keydef *keyinfo,uint nod_flag,uchar *next_key, + uchar *org_key, uchar *prev_key, uchar *key, + struct st_mi_s_param *s_temp); + void (*store_key)(struct st_mi_keydef *keyinfo, uchar *key_pos, + struct st_mi_s_param *s_temp); + int (*ck_insert)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen); + int (*ck_delete)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen); +} MI_KEYDEF; + + +#define MI_UNIQUE_HASH_LENGTH 4 + +typedef struct st_unique_def /* Segment definition of unique */ +{ + uint16 keysegs; /* Number of key-segment */ + uchar key; /* Mapped to which key */ + uint8 null_are_equal; + HA_KEYSEG *seg,*end; +} MI_UNIQUEDEF; + +typedef struct st_mi_decode_tree /* Decode huff-table */ +{ + uint16 *table; + uint quick_table_bits; + uchar *intervalls; +} MI_DECODE_TREE; + + +struct st_mi_bit_buff; + +/* + Note that null markers should always be first in a row ! + When creating a column, one should only specify: + type, length, null_bit and null_pos +*/ + +typedef struct st_columndef /* column information */ +{ + enum en_fieldtype type; + uint16 length; /* length of field */ + uint32 offset; /* Offset to position in row */ + uint8 null_bit; /* If column may be 0 */ + uint16 null_pos; /* position for null marker */ + +#ifndef NOT_PACKED_DATABASES + void (*unpack)(struct st_columndef *rec,struct st_mi_bit_buff *buff, + uchar *start,uchar *end); + enum en_fieldtype base_type; + uint space_length_bits,pack_type; + MI_DECODE_TREE *huff_tree; +#endif +} MI_COLUMNDEF; + +extern char * myisam_log_filename; /* Name of logfile */ +extern ulong myisam_block_size; +extern ulong myisam_concurrent_insert; +extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user; +extern my_off_t myisam_max_temp_length; +extern ulong myisam_data_pointer_size; + +/* usually used to check if a symlink points into the mysql data home */ +/* which is normally forbidden */ +extern int (*myisam_test_invalid_symlink)(const char *filename); +extern ulonglong myisam_mmap_size, myisam_mmap_used; +extern mysql_mutex_t THR_LOCK_myisam_mmap; + + /* Prototypes for myisam-functions */ + +extern int mi_close(struct st_myisam_info *file); +extern int mi_delete(struct st_myisam_info *file,const uchar *buff); +extern struct st_myisam_info *mi_open(const char *name,int mode, + uint wait_if_locked); +extern int mi_panic(enum ha_panic_function function); +extern int mi_rfirst(struct st_myisam_info *file,uchar *buf,int inx); +extern int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, + key_part_map keypart_map, enum ha_rkey_function search_flag); +extern int mi_rlast(struct st_myisam_info *file,uchar *buf,int inx); +extern int mi_rnext(struct st_myisam_info *file,uchar *buf,int inx); +extern int mi_rnext_same(struct st_myisam_info *info, uchar *buf); +extern int mi_rprev(struct st_myisam_info *file,uchar *buf,int inx); +extern int mi_rrnd(struct st_myisam_info *file,uchar *buf, my_off_t pos); +extern int mi_scan_init(struct st_myisam_info *file); +extern int mi_scan(struct st_myisam_info *file,uchar *buf); +extern int mi_rsame(struct st_myisam_info *file,uchar *record,int inx); +extern int mi_rsame_with_pos(struct st_myisam_info *file,uchar *record, + int inx, my_off_t pos); +extern int mi_update(struct st_myisam_info *file,const uchar *old, + const uchar *new_record); +extern int mi_write(struct st_myisam_info *file,const uchar *buff); +extern my_off_t mi_position(struct st_myisam_info *file); +extern int mi_status(struct st_myisam_info *info, MI_ISAMINFO *x, uint flag); +extern int mi_lock_database(struct st_myisam_info *file,int lock_type); +extern int mi_create(const char *name,uint keys,MI_KEYDEF *keydef, + uint columns, MI_COLUMNDEF *columndef, + uint uniques, MI_UNIQUEDEF *uniquedef, + MI_CREATE_INFO *create_info, uint flags); +extern int mi_delete_table(const char *name); +extern int mi_rename(const char *from, const char *to); +extern int mi_extra(struct st_myisam_info *file, + enum ha_extra_function function, + void *extra_arg); +extern int mi_reset(struct st_myisam_info *file); +extern ha_rows mi_records_in_range(MI_INFO *info,int inx, + const key_range *min_key, + const key_range *max_key, + page_range *pages); +extern int mi_log(int activate_log); +extern int mi_is_changed(struct st_myisam_info *info); +extern int mi_delete_all_rows(struct st_myisam_info *info); +extern ulong _mi_calc_blob_length(uint length , const uchar *pos); +extern uint mi_get_pointer_length(ulonglong file_length, uint def); +extern int mi_make_backup_of_index(struct st_myisam_info *info, + time_t backup_time, myf flags); +#define myisam_max_key_length() HA_MAX_KEY_LENGTH +#define myisam_max_key_segments() HA_MAX_KEY_SEG + +#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for mmap file */ +/* this is used to pass to mysql_myisamchk_table */ + +#define MYISAMCHK_REPAIR 1 /* equivalent to myisamchk -r */ +#define MYISAMCHK_VERIFY 2 /* Verify, run repair if failure */ + +typedef uint mi_bit_type; +typedef struct st_sort_key_blocks SORT_KEY_BLOCKS; +typedef struct st_sort_ftbuf SORT_FT_BUF; + +typedef struct st_mi_bit_buff +{ /* Used for packing of record */ + mi_bit_type current_byte; + uint bits; + uchar *pos, *end, *blob_pos, *blob_end; + uint error; +} MI_BIT_BUFF; + +typedef struct st_sort_info +{ + /* sync things */ + mysql_mutex_t mutex; + mysql_cond_t cond; + MI_INFO *info; + HA_CHECK *param; + uchar *buff; + SORT_KEY_BLOCKS *key_block, *key_block_end; + SORT_FT_BUF *ft_buf; + my_off_t filelength, dupp, buff_length; + ha_rows max_records; + uint current_key, total_keys; + volatile uint got_error; + uint threads_running; + myf myf_rw; + enum data_file_type new_data_file_type; +} MI_SORT_INFO; + +typedef struct st_mi_sort_param +{ + pthread_t thr; + IO_CACHE read_cache, tempfile, tempfile_for_exceptions; + DYNAMIC_ARRAY buffpek; + MI_BIT_BUFF bit_buff; /* For parallel repair of packrec. */ + + MI_KEYDEF *keyinfo; + MI_SORT_INFO *sort_info; + HA_KEYSEG *seg; + uchar **sort_keys; + uchar *rec_buff; + void *wordlist, *wordptr; + MEM_ROOT wordroot; + uchar *record; + MY_TMPDIR *tmpdir; + + /* + The next two are used to collect statistics, see update_key_parts for + description. + */ + ulonglong unique[HA_MAX_KEY_SEG+1]; + ulonglong notnull[HA_MAX_KEY_SEG+1]; + + my_off_t pos,max_pos,filepos,start_recpos; + uint key, key_length,real_key_length; + uint maxbuffers, find_length; + ulonglong sortbuff_size; + ha_rows keys; + my_bool fix_datafile, master; + my_bool calc_checksum; /* calculate table checksum */ + + int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *); + int (*key_read)(struct st_mi_sort_param *,void *); + int (*key_write)(struct st_mi_sort_param *, const void *); + void (*lock_in_memory)(HA_CHECK *); + int (*write_keys)(struct st_mi_sort_param *, uchar **, + ulonglong , struct st_buffpek *, IO_CACHE *); + my_off_t (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); + int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,uchar *, + uint, ulonglong); +} MI_SORT_PARAM; + +/* functions in mi_check */ +void myisamchk_init(HA_CHECK *param); +int chk_status(HA_CHECK *param, MI_INFO *info); +int chk_del(HA_CHECK *param, MI_INFO *info, ulonglong test_flag); +int chk_size(HA_CHECK *param, MI_INFO *info); +int chk_key(HA_CHECK *param, MI_INFO *info); +int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend); +int mi_repair(HA_CHECK *param, MI_INFO *info, char * name, int rep_quick); +int mi_sort_index(HA_CHECK *param, MI_INFO *info, char * name); +int mi_repair_by_sort(HA_CHECK *param, MI_INFO *info, + const char * name, int rep_quick); +int mi_repair_parallel(HA_CHECK *param, MI_INFO *info, + const char * name, int rep_quick); +int change_to_newfile(const char * filename, const char * old_ext, + const char * new_ext, time_t backup_time, myf myflags); +int lock_file(HA_CHECK *param, File file, my_off_t start, int lock_type, + const char *filetype, const char *filename); +void lock_memory(HA_CHECK *param); +void update_auto_increment_key(HA_CHECK *param, MI_INFO *info, + my_bool repair); +int update_state_info(HA_CHECK *param, MI_INFO *info,uint update); +void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part, + ulonglong *unique, ulonglong *notnull, + ulonglong records); +int filecopy(HA_CHECK *param, File to,File from,my_off_t start, + my_off_t length, const char *type); +int movepoint(MI_INFO *info,uchar *record,my_off_t oldpos, + my_off_t newpos, uint prot_key); +int write_data_suffix(MI_SORT_INFO *sort_info, my_bool fix_datafile); +int test_if_almost_full(MI_INFO *info); +int recreate_table(HA_CHECK *param, MI_INFO **org_info, char *filename); +void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); +my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map, + my_bool force); + +int mi_init_bulk_insert(MI_INFO *info, size_t cache_size, ha_rows rows); +void mi_flush_bulk_insert(MI_INFO *info, uint inx); +int mi_end_bulk_insert(MI_INFO *info, my_bool abort); +int mi_assign_to_key_cache(MI_INFO *info, ulonglong key_map, + KEY_CACHE *key_cache); +void mi_change_key_cache(KEY_CACHE *old_key_cache, + KEY_CACHE *new_key_cache); +int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves); + +int write_data_suffix(MI_SORT_INFO *sort_info, my_bool fix_datafile); +int flush_pending_blocks(MI_SORT_PARAM *param); +int sort_ft_buf_flush(MI_SORT_PARAM *sort_param); +int thr_write_keys(MI_SORT_PARAM *sort_param); +int sort_write_record(MI_SORT_PARAM *sort_param); +int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulonglong); +my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/myisamchk.h b/include/myisamchk.h new file mode 100644 index 00000000..c494c672 --- /dev/null +++ b/include/myisamchk.h @@ -0,0 +1,131 @@ +/* Copyright (C) 2006 MySQL AB + Copyright (c) 2017, MariaDB Corporation. + + 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; either version 2 of the License, or + (at your option) any later version. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Definitions needed for myisamchk/mariachk.c */ + +#ifndef _myisamchk_h +#define _myisamchk_h + +#include <my_stack_alloc.h> + +/* + Flags used by xxxxchk.c or/and ha_xxxx.cc that are NOT passed + to xxxcheck.c follows: +*/ + +#define TT_USEFRM 1U +#define TT_FOR_UPGRADE 2U +#define TT_FROM_MYSQL 4U + +/* Bits set in out_flag */ +#define O_NEW_DATA 2U +#define O_DATA_LOST 4U + +/* + MARIA/MYISAM supports several statistics collection + methods. Currently statistics collection method is not stored in + MARIA file and has to be specified for each table analyze/repair + operation in MI_CHECK::stats_method. +*/ + +typedef enum +{ + /* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */ + MI_STATS_METHOD_NULLS_NOT_EQUAL, + /* Treat NULLs as equal when collecting statistics (like 4.0 did) */ + MI_STATS_METHOD_NULLS_EQUAL, + /* Ignore NULLs - count only tuples without NULLs in the index components */ + MI_STATS_METHOD_IGNORE_NULLS +} enum_handler_stats_method; + +struct st_myisam_info; + +typedef struct st_handler_check_param +{ + char *isam_file_name; + MY_TMPDIR *tmpdir; + void *thd; + const char *db_name, *table_name, *op_name; + ulonglong auto_increment_value; + ulonglong max_data_file_length; + ulonglong keys_in_use; + ulonglong max_record_length; + /* + The next two are used to collect statistics, see update_key_parts for + description. + */ + ulonglong unique_count[HA_MAX_KEY_SEG + 1]; + ulonglong notnull_count[HA_MAX_KEY_SEG + 1]; + ulonglong max_allowed_lsn; + my_off_t search_after_block; + my_off_t new_file_pos, key_file_blocks; + my_off_t keydata, totaldata, key_blocks, start_check_pos; + my_off_t used, empty, splits, del_length, link_used, lost; + ha_rows total_records, total_deleted, records,del_blocks; + ha_rows full_page_count, tail_count; + ha_checksum record_checksum, glob_crc; + ha_checksum key_crc[HA_MAX_POSSIBLE_KEY]; + ha_checksum tmp_key_crc[HA_MAX_POSSIBLE_KEY]; + ha_checksum tmp_record_checksum; + ulonglong org_key_map; + ulonglong testflag; + + /* Following is used to check if rows are visible */ + ulonglong max_trid, max_found_trid; + ulonglong not_visible_rows_found; + ulonglong sort_buffer_length, orig_sort_buffer_length; + ulonglong use_buffers; /* Used as param to getopt() */ + size_t read_buffer_length, write_buffer_length, sort_key_blocks; + time_t backup_time; /* To sign backup files */ + ulong rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; + double new_rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; + uint out_flag, error_printed, verbose; + uint opt_sort_key, total_files, max_level; + uint key_cache_block_size, pagecache_block_size; + uint skip_lsn_error_count; + int tmpfile_createflag, err_count; + myf myf_rw; + uint16 language; + my_bool warning_printed, note_printed, wrong_trd_printed; + my_bool using_global_keycache, opt_lock_memory, opt_follow_links; + my_bool retry_repair, force_sort, calc_checksum, static_row_size; + char temp_filename[FN_REFLEN]; + IO_CACHE read_cache; + void **stack_end_ptr; + enum_handler_stats_method stats_method; + /* For reporting progress */ + uint stage, max_stage; + uint progress_counter; /* How often to call _report_progress() */ + ulonglong progress, max_progress; + + int (*fix_record)(struct st_myisam_info *info, uchar *record, int keynum); + + mysql_mutex_t print_msg_mutex; + my_bool need_print_msg_lock; + myf malloc_flags; +} HA_CHECK; + + +typedef struct st_buffpek { + my_off_t file_pos; /* Where we are in the sort file */ + uchar *base, *key; /* Key pointers */ + ha_rows count; /* Number of rows in table */ + ha_rows mem_count; /* Numbers of keys in memory */ + ha_rows max_keys; /* Max keys in buffert */ +} BUFFPEK; + +#endif /* _myisamchk_h */ diff --git a/include/myisammrg.h b/include/myisammrg.h new file mode 100644 index 00000000..b3bca218 --- /dev/null +++ b/include/myisammrg.h @@ -0,0 +1,129 @@ +/* Copyright (c) 2000-2002, 2004, 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* This file should be included when using merge_isam_functions */ + +#ifndef _myisammrg_h +#define _myisammrg_h +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _my_base_h +#include <my_base.h> +#endif +#ifndef _myisam_h +#include <myisam.h> +#endif + +#include <queues.h> + +#define MYRG_NAME_EXT ".MRG" +#define MYRG_NAME_TMPEXT ".MRG_TMP" + +/* In which table to INSERT rows */ +#define MERGE_INSERT_DISABLED 0 +#define MERGE_INSERT_TO_FIRST 1 +#define MERGE_INSERT_TO_LAST 2 + +extern TYPELIB merge_insert_method; + + /* Param to/from myrg_info */ + +typedef struct st_mymerge_info /* Struct from h_info */ +{ + ulonglong records; /* Records in database */ + ulonglong deleted; /* Deleted records in database */ + ulonglong recpos; /* Pos for last used record */ + ulonglong data_file_length; + ulonglong dupp_key_pos; /* Offset of the Duplicate key in the merge table */ + uint reclength; /* Recordlength */ + int errkey; /* With key was duplicated on err */ + uint options; /* HA_OPTION_... used */ + ulong *rec_per_key; /* for sql optimizing */ +} MYMERGE_INFO; + +typedef struct st_myrg_table_info +{ + struct st_myisam_info *table; + ulonglong file_offset; +} MYRG_TABLE; + +typedef struct st_myrg_info +{ + MYRG_TABLE *open_tables,*current_table,*end_table,*last_used_table; + ulonglong records; /* records in tables */ + ulonglong del; /* Removed records */ + ulonglong data_file_length; + ulong cache_size; + uint merge_insert_method; + uint tables,options,reclength,keys; + uint key_parts; + my_bool cache_in_use; + /* If MERGE children attached to parent. See top comment in ha_myisammrg.cc */ + my_bool children_attached; + LIST open_list; + QUEUE by_key; + ulong *rec_per_key_part; /* for sql optimizing */ + mysql_mutex_t mutex; +} MYRG_INFO; + + + /* Prototypes for merge-functions */ + +extern int myrg_close(MYRG_INFO *file); +extern int myrg_delete(MYRG_INFO *file,const uchar *buff); +extern MYRG_INFO *myrg_open(const char *name,int mode,int wait_if_locked); +extern MYRG_INFO *myrg_parent_open(const char *parent_name, + int (*callback)(void*, const char*), + void *callback_param); +extern int myrg_attach_children(MYRG_INFO *m_info, int handle_locking, + MI_INFO *(*callback)(void*), + void *callback_param, + my_bool *need_compat_check); +extern int myrg_detach_children(MYRG_INFO *m_info); +extern int myrg_panic(enum ha_panic_function function); +extern int myrg_rfirst(MYRG_INFO *file,uchar *buf,int inx); +extern int myrg_rlast(MYRG_INFO *file,uchar *buf,int inx); +extern int myrg_rnext(MYRG_INFO *file,uchar *buf,int inx); +extern int myrg_rprev(MYRG_INFO *file,uchar *buf,int inx); +extern int myrg_rnext_same(MYRG_INFO *file,uchar *buf); +extern int myrg_rkey(MYRG_INFO *info,uchar *buf,int inx, const uchar *key, + key_part_map keypart_map, enum ha_rkey_function search_flag); +extern int myrg_rrnd(MYRG_INFO *file,uchar *buf,ulonglong pos); +extern int myrg_rsame(MYRG_INFO *file,uchar *record,int inx); +extern int myrg_update(MYRG_INFO *file,const uchar *old, + const uchar *new_rec); +extern int myrg_write(MYRG_INFO *info,const uchar *rec); +extern int myrg_status(MYRG_INFO *file,MYMERGE_INFO *x,int flag); +extern int myrg_lock_database(MYRG_INFO *file,int lock_type); +extern int myrg_create(const char *name, const char **table_names, + uint insert_method, my_bool fix_names); +extern int myrg_extra(MYRG_INFO *file,enum ha_extra_function function, + void *extra_arg); +extern int myrg_reset(MYRG_INFO *info); +extern void myrg_extrafunc(MYRG_INFO *info,invalidator_by_filename inv); +extern ha_rows myrg_records_in_range(MYRG_INFO *info, int inx, + const key_range *min_key, + const key_range *max_key, + page_range *pages); +extern ha_rows myrg_records(MYRG_INFO *info); + +extern ulonglong myrg_position(MYRG_INFO *info); +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/myisampack.h b/include/myisampack.h new file mode 100644 index 00000000..f3c5fe71 --- /dev/null +++ b/include/myisampack.h @@ -0,0 +1,256 @@ +#ifndef MYISAMPACK_INCLUDED +#define MYISAMPACK_INCLUDED + +/* Copyright (c) 2000-2002, 2004 MySQL AB, 2009 Sun Microsystems, Inc. + Copyright (c) 2020, MariaDB Corporation. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Storing of values in high byte first order. + + integer keys and file pointers are stored with high byte first to get + better compression +*/ + +/* these two are for uniformity */ +#define mi_sint1korr(A) ((int8)(*A)) +#define mi_uint1korr(A) ((uint8)(*A)) + +#define mi_sint2korr(A) ((int16) (((int16) (((const uchar*) (A))[1])) |\ + ((int16) ((uint16) ((const uchar*) (A))[0]) << 8))) +#define mi_sint3korr(A) ((int32) (((((const uchar*) (A))[0]) & 128) ? \ + (((uint32) 255L << 24) | \ + (((uint32) ((const uchar*) (A))[0]) << 16) |\ + (((uint32) ((const uchar*) (A))[1]) << 8) | \ + ((uint32) ((const uchar*) (A))[2])) : \ + (((uint32) ((const uchar*) (A))[0]) << 16) |\ + (((uint32) ((const uchar*) (A))[1]) << 8) | \ + ((uint32) ((const uchar*) (A))[2]))) +#define mi_sint4korr(A) ((int32) (((uint32) (((const uchar*) (A))[3])) |\ + ((uint32) (((const uchar*) (A))[2]) << 8) |\ + ((uint32) (((const uchar*) (A))[1]) << 16) |\ + ((uint32) (((const uchar*) (A))[0]) << 24))) +#define mi_sint8korr(A) ((longlong) mi_uint8korr(A)) +#define mi_uint2korr(A) ((uint16) (((uint16) (((const uchar*) (A))[1])) |\ + ((uint16) (((const uchar*) (A))[0]) << 8))) +#define mi_uint3korr(A) ((uint32) (((uint32) (((const uchar*) (A))[2])) |\ + (((uint32) (((const uchar*) (A))[1])) << 8) |\ + (((uint32) (((const uchar*) (A))[0])) << 16))) +#define mi_uint4korr(A) ((uint32) (((uint32) (((const uchar*) (A))[3])) |\ + (((uint32) (((const uchar*) (A))[2])) << 8) |\ + (((uint32) (((const uchar*) (A))[1])) << 16) |\ + (((uint32) (((const uchar*) (A))[0])) << 24))) + +#ifndef HAVE_mi_uint5korr +#define mi_uint5korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[4])) |\ + (((uint32) (((const uchar*) (A))[3])) << 8) |\ + (((uint32) (((const uchar*) (A))[2])) << 16) |\ + (((uint32) (((const uchar*) (A))[1])) << 24)) |\ + (((ulonglong) (((const uchar*) (A))[0])) << 32)) +#endif /* HAVE_mi_uint5korr */ + +#ifndef HAVE_mi_uint6korr +#define mi_uint6korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[5])) |\ + (((uint32) (((const uchar*) (A))[4])) << 8) |\ + (((uint32) (((const uchar*) (A))[3])) << 16) |\ + (((uint32) (((const uchar*) (A))[2])) << 24)) |\ + (((ulonglong) (((uint32) (((const uchar*) (A))[1])) |\ + (((uint32) (((const uchar*) (A))[0]) << 8)))) <<\ + 32)) +#endif /* HAVE_mi_uint6korr */ + +#ifndef HAVE_mi_uint7korr +#define mi_uint7korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[6])) |\ + (((uint32) (((const uchar*) (A))[5])) << 8) |\ + (((uint32) (((const uchar*) (A))[4])) << 16) |\ + (((uint32) (((const uchar*) (A))[3])) << 24)) |\ + (((ulonglong) (((uint32) (((const uchar*) (A))[2])) |\ + (((uint32) (((const uchar*) (A))[1])) << 8) |\ + (((uint32) (((const uchar*) (A))[0])) << 16))) <<\ + 32)) +#endif /* HAVE_mi_uint7korr */ + +#ifndef HAVE_mi_uint8korr +#define mi_uint8korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[7])) |\ + (((uint32) (((const uchar*) (A))[6])) << 8) |\ + (((uint32) (((const uchar*) (A))[5])) << 16) |\ + (((uint32) (((const uchar*) (A))[4])) << 24)) |\ + (((ulonglong) (((uint32) (((const uchar*) (A))[3])) |\ + (((uint32) (((const uchar*) (A))[2])) << 8) |\ + (((uint32) (((const uchar*) (A))[1])) << 16) |\ + (((uint32) (((const uchar*) (A))[0])) << 24))) <<\ + 32)) +#endif /* HAVE_mi_uint8korr */ + +/* This one is for uniformity */ +#define mi_int1store(T,A) *((uchar*)(T))= (uchar) (A) + +#define mi_int2store(T,A) { uint def_temp= (uint) (A) ;\ + ((uchar*) (T))[1]= (uchar) (def_temp);\ + ((uchar*) (T))[0]= (uchar) (def_temp >> 8); } +#define mi_int3store(T,A) { /*lint -save -e734 */\ + ulong def_temp= (ulong) (A);\ + ((uchar*) (T))[2]= (uchar) (def_temp);\ + ((uchar*) (T))[1]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[0]= (uchar) (def_temp >> 16);\ + /*lint -restore */} +#define mi_int4store(T,A) { ulong def_temp= (ulong) (A);\ + ((uchar*) (T))[3]= (uchar) (def_temp);\ + ((uchar*) (T))[2]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[1]= (uchar) (def_temp >> 16);\ + ((uchar*) (T))[0]= (uchar) (def_temp >> 24); } +#define mi_int5store(T,A) { ulong def_temp= (ulong) (A),\ + def_temp2= (ulong) ((A) >> 32);\ + ((uchar*) (T))[4]= (uchar) (def_temp);\ + ((uchar*) (T))[3]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[2]= (uchar) (def_temp >> 16);\ + ((uchar*) (T))[1]= (uchar) (def_temp >> 24);\ + ((uchar*) (T))[0]= (uchar) (def_temp2); } +#define mi_int6store(T,A) { ulong def_temp= (ulong) (A),\ + def_temp2= (ulong) ((A) >> 32);\ + ((uchar*) (T))[5]= (uchar) (def_temp);\ + ((uchar*) (T))[4]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[3]= (uchar) (def_temp >> 16);\ + ((uchar*) (T))[2]= (uchar) (def_temp >> 24);\ + ((uchar*) (T))[1]= (uchar) (def_temp2);\ + ((uchar*) (T))[0]= (uchar) (def_temp2 >> 8); } +#define mi_int7store(T,A) { ulong def_temp= (ulong) (A),\ + def_temp2= (ulong) ((A) >> 32);\ + ((uchar*) (T))[6]= (uchar) (def_temp);\ + ((uchar*) (T))[5]= (uchar) (def_temp >> 8);\ + ((uchar*) (T))[4]= (uchar) (def_temp >> 16);\ + ((uchar*) (T))[3]= (uchar) (def_temp >> 24);\ + ((uchar*) (T))[2]= (uchar) (def_temp2);\ + ((uchar*) (T))[1]= (uchar) (def_temp2 >> 8);\ + ((uchar*) (T))[0]= (uchar) (def_temp2 >> 16); } +#define mi_int8store(T,A) { ulong def_temp3= (ulong) (A),\ + def_temp4= (ulong) ((A) >> 32);\ + mi_int4store((uchar*) (T) + 0, def_temp4);\ + mi_int4store((uchar*) (T) + 4, def_temp3); } + +#ifdef WORDS_BIGENDIAN + +#define mi_float4store(T,A) { ((uchar*) (T))[0]= ((uchar*) &A)[0];\ + ((uchar*) (T))[1]= ((uchar*) &A)[1];\ + ((uchar*) (T))[2]= ((uchar*) &A)[2];\ + ((uchar*) (T))[3]= ((uchar*) &A)[3]; } + +#define mi_float4get(V,M) { float def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[0];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[1]; \ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[3];\ + (V)= def_temp; } + +#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[0];\ + ((uchar*) (T))[1]= ((const uchar*) &V)[1];\ + ((uchar*) (T))[2]= ((const uchar*) &V)[2];\ + ((uchar*) (T))[3]= ((const uchar*) &V)[3];\ + ((uchar*) (T))[4]= ((const uchar*) &V)[4];\ + ((uchar*) (T))[5]= ((const uchar*) &V)[5];\ + ((uchar*) (T))[6]= ((const uchar*) &V)[6];\ + ((uchar*) (T))[7]= ((const uchar*) &V)[7]; } + +#define mi_float8get(V,M) { double def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[0];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[1];\ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[3];\ + ((uchar*) &def_temp)[4]= ((const uchar*) (M))[4];\ + ((uchar*) &def_temp)[5]= ((const uchar*) (M))[5];\ + ((uchar*) &def_temp)[6]= ((const uchar*) (M))[6];\ + ((uchar*) &def_temp)[7]= ((const uchar*) (M))[7]; \ + (V)= def_temp; } +#else + +#define mi_float4store(T,A) { ((uchar*) (T))[0]= ((const uchar*) &A)[3];\ + ((uchar*) (T))[1]= ((const uchar*) &A)[2];\ + ((uchar*) (T))[2]= ((const uchar*) &A)[1];\ + ((uchar*) (T))[3]= ((const uchar*) &A)[0]; } + +#define mi_float4get(V,M) { float def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[3];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[1];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[0];\ + (V)= def_temp; } + +#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) +#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[3];\ + ((uchar*) (T))[1]= ((const uchar*) &V)[2];\ + ((uchar*) (T))[2]= ((const uchar*) &V)[1];\ + ((uchar*) (T))[3]= ((const uchar*) &V)[0];\ + ((uchar*) (T))[4]= ((const uchar*) &V)[7];\ + ((uchar*) (T))[5]= ((const uchar*) &V)[6];\ + ((uchar*) (T))[6]= ((const uchar*) &V)[5];\ + ((uchar*) (T))[7]= ((const uchar*) &V)[4];} + +#define mi_float8get(V,M) { double def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[3];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[1];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[0];\ + ((uchar*) &def_temp)[4]= ((const uchar*) (M))[7];\ + ((uchar*) &def_temp)[5]= ((const uchar*) (M))[6];\ + ((uchar*) &def_temp)[6]= ((const uchar*) (M))[5];\ + ((uchar*) &def_temp)[7]= ((const uchar*) (M))[4];\ + (V)= def_temp; } + +#else +#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[7];\ + ((uchar*) (T))[1]= ((const uchar*) &V)[6];\ + ((uchar*) (T))[2]= ((const uchar*) &V)[5];\ + ((uchar*) (T))[3]= ((const uchar*) &V)[4];\ + ((uchar*) (T))[4]= ((const uchar*) &V)[3];\ + ((uchar*) (T))[5]= ((const uchar*) &V)[2];\ + ((uchar*) (T))[6]= ((const uchar*) &V)[1];\ + ((uchar*) (T))[7]= ((const uchar*) &V)[0];} + +#define mi_float8get(V,M) { double def_temp;\ + ((uchar*) &def_temp)[0]= ((const uchar*) (M))[7];\ + ((uchar*) &def_temp)[1]= ((const uchar*) (M))[6];\ + ((uchar*) &def_temp)[2]= ((const uchar*) (M))[5];\ + ((uchar*) &def_temp)[3]= ((const uchar*) (M))[4];\ + ((uchar*) &def_temp)[4]= ((const uchar*) (M))[3];\ + ((uchar*) &def_temp)[5]= ((const uchar*) (M))[2];\ + ((uchar*) &def_temp)[6]= ((const uchar*) (M))[1];\ + ((uchar*) &def_temp)[7]= ((const uchar*) (M))[0];\ + (V)= def_temp; } +#endif /* __FLOAT_WORD_ORDER */ +#endif /* WORDS_BIGENDIAN */ + +/* Fix to avoid warnings when sizeof(ha_rows) == sizeof(long) */ + +#ifdef BIG_TABLES +#define mi_rowstore(T,A) mi_int8store(T, A) +#define mi_rowkorr(T) mi_uint8korr(T) +#else +#define mi_rowstore(T,A) { mi_int4store(T, 0);\ + mi_int4store(((uchar*) (T) + 4), A); } +#define mi_rowkorr(T) mi_uint4korr((const uchar*) (T) + 4) +#endif + +#if SIZEOF_OFF_T > 4 +#define mi_sizestore(T,A) mi_int8store(T, A) +#define mi_sizekorr(T) mi_uint8korr(T) +#else +#define mi_sizestore(T,A) { if ((A) == HA_OFFSET_ERROR)\ + bfill((char*) (T), 8, 255);\ + else { mi_int4store((T), 0);\ + mi_int4store(((T) + 4), A); }} +#define mi_sizekorr(T) mi_uint4korr((const uchar*) (T) + 4) +#endif +#endif /* MYISAMPACK_INCLUDED */ diff --git a/include/mysql.h b/include/mysql.h new file mode 100644 index 00000000..a66dcc7b --- /dev/null +++ b/include/mysql.h @@ -0,0 +1,914 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2012, Monty Program Ab. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + This file defines the client API to MySQL and also the ABI of the + dynamically linked libmysqlclient. + + The ABI should never be changed in a released product of MySQL, + thus you need to take great care when changing the file. In case + the file is changed so the ABI is broken, you must also update + the SHARED_LIB_MAJOR_VERSION in cmake/mysql_version.cmake +*/ + +#ifndef _mysql_h +#define _mysql_h + +#ifdef _AIX /* large-file support will break without this */ +#include <standards.h> +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MY_GLOBAL_INCLUDED /* If not standard header */ +#ifndef MYSQL_ABI_CHECK +#include <sys/types.h> +#endif + +#ifndef MYSQL_PLUGIN_INCLUDED +typedef char my_bool; +#endif + +#if !defined(_WIN32) +#define STDCALL +#else +#define STDCALL __stdcall +#endif + +#ifndef my_socket_defined +#if defined (_WIN64) +#define my_socket unsigned long long +#elif defined (_WIN32) +#define my_socket unsigned int +#else +typedef int my_socket; +#endif /* _WIN64 */ +#endif /* my_socket_defined */ +#endif /* MY_GLOBAL_INCLUDED */ + +#include "mariadb_capi_rename.h" +#include "mysql_version.h" +#include "mysql_com.h" +#include "mysql_time.h" + +#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */ + +extern unsigned int mariadb_deinitialize_ssl; +extern unsigned int mysql_port; +extern char *mysql_unix_port; + +#define CLIENT_NET_READ_TIMEOUT (365*24*3600) /* Timeout on read */ +#define CLIENT_NET_WRITE_TIMEOUT (365*24*3600) /* Timeout on write */ + +#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG) +#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG) +#define IS_BLOB(n) ((n) & BLOB_FLAG) +/** + Returns true if the value is a number which does not need quotes for + the sql_lex.cc parser to parse correctly. +*/ +#define IS_NUM(t) (((t) <= MYSQL_TYPE_INT24 && (t) != MYSQL_TYPE_TIMESTAMP) || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL) +#define IS_LONGDATA(t) ((t) >= MYSQL_TYPE_TINY_BLOB && (t) <= MYSQL_TYPE_STRING) + + +typedef struct st_mysql_const_lex_string MARIADB_CONST_STRING; + + +typedef struct st_mysql_field { + char *name; /* Name of column */ + char *org_name; /* Original column name, if an alias */ + char *table; /* Table of column if column was a field */ + char *org_table; /* Org table name, if table was an alias */ + char *db; /* Database for table */ + char *catalog; /* Catalog for table */ + char *def; /* Default value (set by mysql_list_fields) */ + unsigned long length; /* Width of column (create length) */ + unsigned long max_length; /* Max width for selected set */ + unsigned int name_length; + unsigned int org_name_length; + unsigned int table_length; + unsigned int org_table_length; + unsigned int db_length; + unsigned int catalog_length; + unsigned int def_length; + unsigned int flags; /* Div flags */ + unsigned int decimals; /* Number of decimals in field */ + unsigned int charsetnr; /* Character set */ + enum enum_field_types type; /* Type of field. See mysql_com.h for types */ + void *extension; +} MYSQL_FIELD; + +typedef char **MYSQL_ROW; /* return data as array of strings */ +typedef unsigned int MYSQL_FIELD_OFFSET; /* offset to current field */ + +#ifndef MY_GLOBAL_INCLUDED +#if defined(NO_CLIENT_LONG_LONG) +typedef unsigned long my_ulonglong; +#elif defined (_WIN32) +typedef unsigned __int64 my_ulonglong; +#else +typedef unsigned long long my_ulonglong; +#endif +#endif + +#include "typelib.h" + +#define MYSQL_COUNT_ERROR (~(my_ulonglong) 0) + +/* backward compatibility define - to be removed eventually */ +#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED +#define WARN_PLUGIN_DELETE_BUILTIN ER_PLUGIN_DELETE_BUILTIN +#define ER_FK_DUP_NAME ER_DUP_CONSTRAINT_NAME +#define ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +#define ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN +#define ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN ER_WRONG_FK_OPTION_FOR_GENERATED_COLUMN +#define ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN +#define ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS ER_UNSUPPORTED_ENGINE_FOR_GENERATED_COLUMNS +#define ER_KEY_COLUMN_DOES_NOT_EXITS ER_KEY_COLUMN_DOES_NOT_EXIST +#define ER_DROP_PARTITION_NON_EXISTENT ER_PARTITION_DOES_NOT_EXIST + +typedef struct st_mysql_rows { + struct st_mysql_rows *next; /* list of rows */ + MYSQL_ROW data; + unsigned long length; +} MYSQL_ROWS; + +typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */ + +#include "my_alloc.h" + +typedef struct embedded_query_result EMBEDDED_QUERY_RESULT; +typedef struct st_mysql_data { + MYSQL_ROWS *data; + struct embedded_query_result *embedded_info; + MEM_ROOT alloc; + my_ulonglong rows; + unsigned int fields; + /* extra info for embedded library */ + void *extension; +} MYSQL_DATA; + +enum mysql_option +{ + MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE, + MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, + MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_LOCAL_INFILE, + MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT, + MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT, + MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, + MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, + MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, + MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, + MYSQL_OPT_BIND, + MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CERT, + MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CAPATH, MYSQL_OPT_SSL_CIPHER, + MYSQL_OPT_SSL_CRL, MYSQL_OPT_SSL_CRLPATH, + MYSQL_OPT_CONNECT_ATTR_RESET, MYSQL_OPT_CONNECT_ATTR_ADD, + MYSQL_OPT_CONNECT_ATTR_DELETE, + MYSQL_SERVER_PUBLIC_KEY, + MYSQL_ENABLE_CLEARTEXT_PLUGIN, + MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, + + /* MariaDB options */ + MYSQL_PROGRESS_CALLBACK=5999, + MYSQL_OPT_NONBLOCK, + MYSQL_OPT_USE_THREAD_SPECIFIC_MEMORY +}; + +/** + @todo remove the "extension", move st_mysql_options completely + out of mysql.h +*/ +struct st_mysql_options_extention; + +struct st_mysql_options { + unsigned int connect_timeout, read_timeout, write_timeout; + unsigned int port, protocol; + unsigned long client_flag; + char *host,*user,*password,*unix_socket,*db; + struct st_dynamic_array *init_commands; + char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name; + char *ssl_key; /* PEM key file */ + char *ssl_cert; /* PEM cert file */ + char *ssl_ca; /* PEM CA file */ + char *ssl_capath; /* PEM directory of CA-s? */ + char *ssl_cipher; /* cipher to use */ + char *shared_memory_base_name; + unsigned long max_allowed_packet; + my_bool use_ssl; /* if to use SSL or not */ + my_bool compress,named_pipe; + my_bool use_thread_specific_memory; + my_bool unused2; + my_bool unused3; + my_bool unused4; + enum mysql_option methods_to_use; + char *client_ip; + /* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */ + my_bool secure_auth; + /* 0 - never report, 1 - always report (default) */ + my_bool report_data_truncation; + + /* function pointers for local infile support */ + int (*local_infile_init)(void **, const char *, void *); + int (*local_infile_read)(void *, char *, unsigned int); + void (*local_infile_end)(void *); + int (*local_infile_error)(void *, char *, unsigned int); + void *local_infile_userdata; + struct st_mysql_options_extention *extension; +}; + +enum mysql_status +{ + MYSQL_STATUS_READY, MYSQL_STATUS_GET_RESULT, MYSQL_STATUS_USE_RESULT, + MYSQL_STATUS_STATEMENT_GET_RESULT +}; + +enum mysql_protocol_type +{ + MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET, + MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY +}; + +typedef struct character_set +{ + unsigned int number; /* character set number */ + unsigned int state; /* character set state */ + const char *csname; /* collation name */ + const char *name; /* character set name */ + const char *comment; /* comment */ + const char *dir; /* character set directory */ + unsigned int mbminlen; /* min. length for multibyte strings */ + unsigned int mbmaxlen; /* max. length for multibyte strings */ +} MY_CHARSET_INFO; + +struct st_mysql_methods; +struct st_mysql_stmt; + +typedef struct st_mysql +{ + NET net; /* Communication parameters */ + unsigned char *connector_fd; /* ConnectorFd for SSL */ + char *host,*user,*passwd,*unix_socket,*server_version,*host_info; + char *info, *db; + const struct charset_info_st *charset; + MYSQL_FIELD *fields; + MEM_ROOT field_alloc; + my_ulonglong affected_rows; + my_ulonglong insert_id; /* id if insert on table with NEXTNR */ + my_ulonglong extra_info; /* Not used */ + unsigned long thread_id; /* Id for connection in server */ + unsigned long packet_length; + unsigned int port; + unsigned long client_flag,server_capabilities; + unsigned int protocol_version; + unsigned int field_count; + unsigned int server_status; + unsigned int server_language; + unsigned int warning_count; + struct st_mysql_options options; + enum mysql_status status; + my_bool free_me; /* If free in mysql_close */ + my_bool reconnect; /* set to 1 if automatic reconnect */ + + /* session-wide random string */ + char scramble[SCRAMBLE_LENGTH+1]; + my_bool auto_local_infile; + void *unused2, *unused3, *unused4, *unused5; + + LIST *stmts; /* list of all statements */ + const struct st_mysql_methods *methods; + void *thd; + /* + Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag + from mysql_stmt_close if close had to cancel result set of this object. + */ + my_bool *unbuffered_fetch_owner; + /* needed for embedded server - no net buffer to store the 'info' */ + char *info_buffer; + void *extension; +} MYSQL; + + +typedef struct st_mysql_res { + my_ulonglong row_count; + MYSQL_FIELD *fields; + MYSQL_DATA *data; + MYSQL_ROWS *data_cursor; + unsigned long *lengths; /* column lengths of current row */ + MYSQL *handle; /* for unbuffered reads */ + const struct st_mysql_methods *methods; + MYSQL_ROW row; /* If unbuffered read */ + MYSQL_ROW current_row; /* buffer to current row */ + MEM_ROOT field_alloc; + unsigned int field_count, current_field; + my_bool eof; /* Used by mysql_fetch_row */ + /* mysql_stmt_close() had to cancel this result */ + my_bool unbuffered_fetch_cancelled; + void *extension; +} MYSQL_RES; + + +/* + We should not define MYSQL_CLIENT when the mysql.h is included + by the server or server plugins. + Now it is important only for the SQL service to work so we rely on + the MYSQL_SERVICE_SQL to check we're compiling the server/plugin + related file. +*/ + +#if !defined(MYSQL_SERVICE_SQL) && !defined(MYSQL_CLIENT) +#define MYSQL_CLIENT +#endif + + +typedef struct st_mysql_parameters +{ + unsigned long *p_max_allowed_packet; + unsigned long *p_net_buffer_length; + void *extension; +} MYSQL_PARAMETERS; + +/* + Flag bits, the asynchronous methods return a combination of these ORed + together to let the application know when to resume the suspended operation. +*/ + +/* + Wait for data to be available on socket to read. + mysql_get_socket_fd() will return socket descriptor. +*/ +#define MYSQL_WAIT_READ 1 +/* Wait for socket to be ready to write data. */ +#define MYSQL_WAIT_WRITE 2 +/* Wait for select() to mark exception on socket. */ +#define MYSQL_WAIT_EXCEPT 4 +/* + Wait until timeout occurs. Value of timeout can be obtained from + mysql_get_timeout_value(). +*/ +#define MYSQL_WAIT_TIMEOUT 8 + +#if !defined(MYSQL_SERVICE_SQL) +#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet) +#define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length) +#endif + +/* + Set up and bring down the server; to ensure that applications will + work when linked against either the standard client library or the + embedded server library, these functions should be called. +*/ +int STDCALL mysql_server_init(int argc, char **argv, char **groups); +void STDCALL mysql_server_end(void); + +/* + mysql_server_init/end need to be called when using libmysqld or + libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so + you don't need to call it explicitly; but you need to call + mysql_server_end() to free memory). The names are a bit misleading + (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general + names which suit well whether you're using libmysqld or libmysqlclient. We + intend to promote these aliases over the mysql_server* ones. +*/ +#define mysql_library_init mysql_server_init +#define mysql_library_end mysql_server_end + +MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void); + +/* + Set up and bring down a thread; these function should be called + for each thread in an application which opens at least one MySQL + connection. All uses of the connection(s) should be between these + function calls. +*/ +my_bool STDCALL mysql_thread_init(void); +void STDCALL mysql_thread_end(void); + +/* + Functions to get information from the MYSQL and MYSQL_RES structures + Should definitely be used if one uses shared libraries. +*/ + +my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res); +unsigned int STDCALL mysql_num_fields(MYSQL_RES *res); +my_bool STDCALL mysql_eof(MYSQL_RES *res); +MYSQL_FIELD *STDCALL mysql_fetch_field_direct(MYSQL_RES *res, + unsigned int fieldnr); +MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res); +MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res); +MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res); + + + + +int STDCALL mariadb_field_attr(MARIADB_CONST_STRING *attr, + const MYSQL_FIELD *field, + enum mariadb_field_attr_t type); + + +unsigned int STDCALL mysql_field_count(MYSQL *mysql); +my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql); +my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql); +unsigned int STDCALL mysql_errno(MYSQL *mysql); +const char * STDCALL mysql_error(MYSQL *mysql); +const char *STDCALL mysql_sqlstate(MYSQL *mysql); +unsigned int STDCALL mysql_warning_count(MYSQL *mysql); +const char * STDCALL mysql_info(MYSQL *mysql); +unsigned long STDCALL mysql_thread_id(MYSQL *mysql); +const char * STDCALL mysql_character_set_name(MYSQL *mysql); +int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname); +int STDCALL mysql_set_character_set_start(int *ret, MYSQL *mysql, + const char *csname); +int STDCALL mysql_set_character_set_cont(int *ret, MYSQL *mysql, + int status); + +MYSQL * STDCALL mysql_init(MYSQL *mysql); +my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, + const char *cert, const char *ca, + const char *capath, const char *cipher); +const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql); +my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, + const char *passwd, const char *db); +int STDCALL mysql_change_user_start(my_bool *ret, MYSQL *mysql, + const char *user, + const char *passwd, + const char *db); +int STDCALL mysql_change_user_cont(my_bool *ret, MYSQL *mysql, + int status); +MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, + const char *user, + const char *passwd, + const char *db, + unsigned int port, + const char *unix_socket, + unsigned long clientflag); +int STDCALL mysql_real_connect_start(MYSQL **ret, MYSQL *mysql, + const char *host, + const char *user, + const char *passwd, + const char *db, + unsigned int port, + const char *unix_socket, + unsigned long clientflag); +int STDCALL mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql, + int status); +int STDCALL mysql_select_db(MYSQL *mysql, const char *db); +int STDCALL mysql_select_db_start(int *ret, MYSQL *mysql, + const char *db); +int STDCALL mysql_select_db_cont(int *ret, MYSQL *mysql, + int status); +int STDCALL mysql_query(MYSQL *mysql, const char *q); +int STDCALL mysql_query_start(int *ret, MYSQL *mysql, + const char *q); +int STDCALL mysql_query_cont(int *ret, MYSQL *mysql, + int status); +int STDCALL mysql_send_query(MYSQL *mysql, const char *q, + unsigned long length); +int STDCALL mysql_send_query_start(int *ret, MYSQL *mysql, + const char *q, + unsigned long length); +int STDCALL mysql_send_query_cont(int *ret, MYSQL *mysql, + int status); +int STDCALL mysql_real_query(MYSQL *mysql, const char *q, + unsigned long length); +int STDCALL mysql_real_query_start(int *ret, MYSQL *mysql, + const char *q, + unsigned long length); +int STDCALL mysql_real_query_cont(int *ret, MYSQL *mysql, + int status); +MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql); +int STDCALL mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql); +int STDCALL mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); +MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql); + +void STDCALL mysql_get_character_set_info(MYSQL *mysql, + MY_CHARSET_INFO *charset); + +/* local infile support */ + +#define LOCAL_INFILE_ERROR_LEN 512 + +void +mysql_set_local_infile_handler(MYSQL *mysql, + int (*local_infile_init)(void **, const char *, + void *), + int (*local_infile_read)(void *, char *, + unsigned int), + void (*local_infile_end)(void *), + int (*local_infile_error)(void *, char*, + unsigned int), + void *); + +void +mysql_set_local_infile_default(MYSQL *mysql); + +int STDCALL mysql_shutdown(MYSQL *mysql, + enum mysql_enum_shutdown_level + shutdown_level); +int STDCALL mysql_shutdown_start(int *ret, MYSQL *mysql, + enum mysql_enum_shutdown_level + shutdown_level); +int STDCALL mysql_shutdown_cont(int *ret, MYSQL *mysql, + int status); +int STDCALL mysql_dump_debug_info(MYSQL *mysql); +int STDCALL mysql_dump_debug_info_start(int *ret, MYSQL *mysql); +int STDCALL mysql_dump_debug_info_cont(int *ret, MYSQL *mysql, + int status); +int STDCALL mysql_refresh(MYSQL *mysql, + unsigned int refresh_options); +int STDCALL mysql_refresh_start(int *ret, MYSQL *mysql, + unsigned int refresh_options); +int STDCALL mysql_refresh_cont(int *ret, MYSQL *mysql, int status); +int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid); +int STDCALL mysql_kill_start(int *ret, MYSQL *mysql, + unsigned long pid); +int STDCALL mysql_kill_cont(int *ret, MYSQL *mysql, int status); +int STDCALL mysql_set_server_option(MYSQL *mysql, + enum enum_mysql_set_option + option); +int STDCALL mysql_set_server_option_start(int *ret, MYSQL *mysql, + enum enum_mysql_set_option + option); +int STDCALL mysql_set_server_option_cont(int *ret, MYSQL *mysql, + int status); +int STDCALL mysql_ping(MYSQL *mysql); +int STDCALL mysql_ping_start(int *ret, MYSQL *mysql); +int STDCALL mysql_ping_cont(int *ret, MYSQL *mysql, int status); +const char * STDCALL mysql_stat(MYSQL *mysql); +int STDCALL mysql_stat_start(const char **ret, MYSQL *mysql); +int STDCALL mysql_stat_cont(const char **ret, MYSQL *mysql, + int status); +const char * STDCALL mysql_get_server_info(MYSQL *mysql); +const char * STDCALL mysql_get_server_name(MYSQL *mysql); +const char * STDCALL mysql_get_client_info(void); +unsigned long STDCALL mysql_get_client_version(void); +const char * STDCALL mysql_get_host_info(MYSQL *mysql); +unsigned long STDCALL mysql_get_server_version(MYSQL *mysql); +unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql); +MYSQL_RES * STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild); +int STDCALL mysql_list_dbs_start(MYSQL_RES **ret, MYSQL *mysql, + const char *wild); +int STDCALL mysql_list_dbs_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); +MYSQL_RES * STDCALL mysql_list_tables(MYSQL *mysql,const char *wild); +int STDCALL mysql_list_tables_start(MYSQL_RES **ret, MYSQL *mysql, + const char *wild); +int STDCALL mysql_list_tables_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); +MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql); +int STDCALL mysql_list_processes_start(MYSQL_RES **ret, + MYSQL *mysql); +int STDCALL mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); +int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option, + const void *arg); +int STDCALL mysql_options4(MYSQL *mysql,enum mysql_option option, + const void *arg1, const void *arg2); +void STDCALL mysql_free_result(MYSQL_RES *result); +int STDCALL mysql_free_result_start(MYSQL_RES *result); +int STDCALL mysql_free_result_cont(MYSQL_RES *result, int status); +void STDCALL mysql_data_seek(MYSQL_RES *result, + my_ulonglong offset); +MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result, + MYSQL_ROW_OFFSET offset); +MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result, + MYSQL_FIELD_OFFSET offset); +MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); +int STDCALL mysql_fetch_row_start(MYSQL_ROW *ret, + MYSQL_RES *result); +int STDCALL mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result, + int status); +unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); +MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); +MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, + const char *wild); +int STDCALL mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql, + const char *table, + const char *wild); +int STDCALL mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); +unsigned long STDCALL mysql_escape_string(char *to,const char *from, + unsigned long from_length); +unsigned long STDCALL mysql_hex_string(char *to,const char *from, + unsigned long from_length); +unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, + char *to,const char *from, + unsigned long length); +void STDCALL mysql_debug(const char *debug); +void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); +unsigned int STDCALL mysql_thread_safe(void); +my_bool STDCALL mysql_embedded(void); +my_bool STDCALL mariadb_connection(MYSQL *mysql); +my_bool STDCALL mysql_read_query_result(MYSQL *mysql); +int STDCALL mysql_read_query_result_start(my_bool *ret, + MYSQL *mysql); +int STDCALL mysql_read_query_result_cont(my_bool *ret, + MYSQL *mysql, int status); + + +/* + The following definitions are added for the enhanced + client-server protocol +*/ + +/* statement state */ +enum enum_mysql_stmt_state +{ + MYSQL_STMT_INIT_DONE= 1, MYSQL_STMT_PREPARE_DONE, MYSQL_STMT_EXECUTE_DONE, + MYSQL_STMT_FETCH_DONE +}; + + +/* + This structure is used to define bind information, and + internally by the client library. + Public members with their descriptions are listed below + (conventionally `On input' refers to the binds given to + mysql_stmt_bind_param, `On output' refers to the binds given + to mysql_stmt_bind_result): + + buffer_type - One of the MYSQL_* types, used to describe + the host language type of buffer. + On output: if column type is different from + buffer_type, column value is automatically converted + to buffer_type before it is stored in the buffer. + buffer - On input: points to the buffer with input data. + On output: points to the buffer capable to store + output data. + The type of memory pointed by buffer must correspond + to buffer_type. See the correspondence table in + the comment to mysql_stmt_bind_param. + + The two above members are mandatory for any kind of bind. + + buffer_length - the length of the buffer. You don't have to set + it for any fixed length buffer: float, double, + int, etc. It must be set however for variable-length + types, such as BLOBs or STRINGs. + + length - On input: in case when lengths of input values + are different for each execute, you can set this to + point at a variable containing value length. This + way the value length can be different in each execute. + If length is not NULL, buffer_length is not used. + Note, length can even point at buffer_length if + you keep bind structures around while fetching: + this way you can change buffer_length before + each execution, everything will work ok. + On output: if length is set, mysql_stmt_fetch will + write column length into it. + + is_null - On input: points to a boolean variable that should + be set to TRUE for NULL values. + This member is useful only if your data may be + NULL in some but not all cases. + If your data is never NULL, is_null should be set to 0. + If your data is always NULL, set buffer_type + to MYSQL_TYPE_NULL, and is_null will not be used. + + is_unsigned - On input: used to signify that values provided for one + of numeric types are unsigned. + On output describes signedness of the output buffer. + If, taking into account is_unsigned flag, column data + is out of range of the output buffer, data for this column + is regarded truncated. Note that this has no correspondence + to the sign of result set column, if you need to find it out + use mysql_stmt_result_metadata. + error - where to write a truncation error if it is present. + possible error value is: + 0 no truncation + 1 value is out of range or buffer is too small + + Please note that MYSQL_BIND also has internals members. +*/ + +typedef struct st_mysql_bind +{ + unsigned long *length; /* output length pointer */ + my_bool *is_null; /* Pointer to null indicator */ + void *buffer; /* buffer to get/put data */ + /* set this if you want to track data truncations happened during fetch */ + my_bool *error; + unsigned char *row_ptr; /* for the current data position */ + void (*store_param_func)(NET *net, struct st_mysql_bind *param); + void (*fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *, + unsigned char **row); + void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *, + unsigned char **row); + /* output buffer length, must be set when fetching str/binary */ + unsigned long buffer_length; + unsigned long offset; /* offset position for char/binary fetch */ + unsigned long length_value; /* Used if length is 0 */ + unsigned int param_number; /* For null count and error messages */ + unsigned int pack_length; /* Internal length for packed data */ + enum enum_field_types buffer_type; /* buffer type */ + my_bool error_value; /* used if error is 0 */ + my_bool is_unsigned; /* set if integer type is unsigned */ + my_bool long_data_used; /* If used with mysql_send_long_data */ + my_bool is_null_value; /* Used if is_null is 0 */ + void *extension; +} MYSQL_BIND; + + +struct st_mysql_stmt_extension; + +/* statement handler */ +typedef struct st_mysql_stmt +{ + MEM_ROOT mem_root; /* root allocations */ + LIST list; /* list to keep track of all stmts */ + MYSQL *mysql; /* connection handle */ + MYSQL_BIND *params; /* input parameters */ + MYSQL_BIND *bind; /* output parameters */ + MYSQL_FIELD *fields; /* result set metadata */ + MYSQL_DATA result; /* cached result set */ + MYSQL_ROWS *data_cursor; /* current row in cached result */ + /* + mysql_stmt_fetch() calls this function to fetch one row (it's different + for buffered, unbuffered and cursor fetch). + */ + int (*read_row_func)(struct st_mysql_stmt *stmt, + unsigned char **row); + /* copy of mysql->affected_rows after statement execution */ + my_ulonglong affected_rows; + my_ulonglong insert_id; /* copy of mysql->insert_id */ + unsigned long stmt_id; /* Id for prepared statement */ + unsigned long flags; /* i.e. type of cursor to open */ + unsigned long prefetch_rows; /* number of rows per one COM_FETCH */ + /* + Copied from mysql->server_status after execute/fetch to know + server-side cursor status for this statement. + */ + unsigned int server_status; + unsigned int last_errno; /* error code */ + unsigned int param_count; /* input parameter count */ + unsigned int field_count; /* number of columns in result set */ + enum enum_mysql_stmt_state state; /* statement state */ + char last_error[MYSQL_ERRMSG_SIZE]; /* error message */ + char sqlstate[SQLSTATE_LENGTH+1]; + /* Types of input parameters should be sent to server */ + my_bool send_types_to_server; + my_bool bind_param_done; /* input buffers were supplied */ + unsigned char bind_result_done; /* output buffers were supplied */ + /* mysql_stmt_close() had to cancel this result */ + my_bool unbuffered_fetch_cancelled; + /* + Is set to true if we need to calculate field->max_length for + metadata fields when doing mysql_stmt_store_result. + */ + my_bool update_max_length; + struct st_mysql_stmt_extension *extension; +} MYSQL_STMT; + +enum enum_stmt_attr_type +{ + /* + When doing mysql_stmt_store_result calculate max_length attribute + of statement metadata. This is to be consistent with the old API, + where this was done automatically. + In the new API we do that only by request because it slows down + mysql_stmt_store_result sufficiently. + */ + STMT_ATTR_UPDATE_MAX_LENGTH, + /* + unsigned long with combination of cursor flags (read only, for update, + etc) + */ + STMT_ATTR_CURSOR_TYPE, + /* + Amount of rows to retrieve from server per one fetch if using cursors. + Accepts unsigned long attribute in the range 1 - ulong_max + */ + STMT_ATTR_PREFETCH_ROWS +}; + +MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql); +int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, + unsigned long length); +int STDCALL mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt, + const char *query, unsigned long length); +int STDCALL mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int status); +int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int status); +int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int status); +int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, + unsigned int column, + unsigned long offset); +int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt, + int status); +unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt); +my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, + enum enum_stmt_attr_type attr_type, + const void *attr); +my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, + enum enum_stmt_attr_type attr_type, + void *attr); +my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); +int STDCALL mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT * stmt, int status); +my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt); +int STDCALL mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT * stmt); +int STDCALL mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int status); +my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt, + int status); +my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, + unsigned int param_number, + const char *data, + unsigned long length); +int STDCALL mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt, + unsigned int param_number, + const char *data, + unsigned long len); +int STDCALL mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, + int status); +MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt); +MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt); +unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); +const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); +const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt); +MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt, + MYSQL_ROW_OFFSET offset); +MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt); +void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset); +my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt); +my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt); +my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt); +unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt); + +my_bool STDCALL mysql_commit(MYSQL * mysql); +int STDCALL mysql_commit_start(my_bool *ret, MYSQL * mysql); +int STDCALL mysql_commit_cont(my_bool *ret, MYSQL * mysql, int status); +my_bool STDCALL mysql_rollback(MYSQL * mysql); +int STDCALL mysql_rollback_start(my_bool *ret, MYSQL * mysql); +int STDCALL mysql_rollback_cont(my_bool *ret, MYSQL * mysql, int status); +my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode); +int STDCALL mysql_autocommit_start(my_bool *ret, MYSQL * mysql, + my_bool auto_mode); +int STDCALL mysql_autocommit_cont(my_bool *ret, MYSQL * mysql, int status); +my_bool STDCALL mysql_more_results(MYSQL *mysql); +int STDCALL mysql_next_result(MYSQL *mysql); +int STDCALL mysql_next_result_start(int *ret, MYSQL *mysql); +int STDCALL mysql_next_result_cont(int *ret, MYSQL *mysql, int status); +int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_next_result_start(int *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_next_result_cont(int *ret, MYSQL_STMT *stmt, int status); +void STDCALL mysql_close_slow_part(MYSQL *mysql); +void STDCALL mysql_close(MYSQL *sock); +int STDCALL mysql_close_start(MYSQL *sock); +int STDCALL mysql_close_cont(MYSQL *sock, int status); +my_socket STDCALL mysql_get_socket(const MYSQL *mysql); +unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql); +unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql); + +/******************************************************************** + mysql_net_ functions - low-level API to MySQL protocol +*********************************************************************/ +unsigned long STDCALL mysql_net_read_packet(MYSQL *mysql); +unsigned long STDCALL mysql_net_field_length(unsigned char **packet); + +/* status return codes */ +#define MYSQL_NO_DATA 100 +#define MYSQL_DATA_TRUNCATED 101 + +#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT) + +#ifdef USE_OLD_FUNCTIONS +MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host, + const char *user, const char *passwd); +int STDCALL mysql_create_db(MYSQL *mysql, const char *DB); +int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); +#endif +#define HAVE_MYSQL_REAL_CONNECT + +#ifdef __cplusplus +} +#endif + +#endif /* _mysql_h */ diff --git a/include/mysql/auth_dialog_client.h b/include/mysql/auth_dialog_client.h new file mode 100644 index 00000000..f1ad3e69 --- /dev/null +++ b/include/mysql/auth_dialog_client.h @@ -0,0 +1,56 @@ +#ifndef MYSQL_AUTH_DIALOG_CLIENT_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Definitions needed to use Dialog client authentication plugin +*/ + +struct st_mysql; + +#define MYSQL_AUTH_DIALOG_CLIENT_INCLUDED + +/** + type of the mysql_authentication_dialog_ask function + + @param mysql mysql + @param type type of the input + 1 - ordinary string input + 2 - password string + @param prompt prompt + @param buf a buffer to store the use input + @param buf_len the length of the buffer + + @retval a pointer to the user input string. + It may be equal to 'buf' or to 'mysql->password'. + In all other cases it is assumed to be an allocated + string, and the "dialog" plugin will free() it. +*/ +typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql, + int type, const char *prompt, char *buf, int buf_len); + +/** + first byte of the question string is the question "type". + It can be an "ordinary" or a "password" question. + The last bit set marks a last question in the authentication exchange. +*/ +#define ORDINARY_QUESTION "\2" +#define LAST_QUESTION "\3" +#define PASSWORD_QUESTION "\4" +#define LAST_PASSWORD "\5" + +#endif diff --git a/include/mysql/client_plugin.h b/include/mysql/client_plugin.h new file mode 100644 index 00000000..990cecc9 --- /dev/null +++ b/include/mysql/client_plugin.h @@ -0,0 +1,188 @@ +#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + Copyright (c) 2010, 2011, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + MySQL Client Plugin API + + This file defines the API for plugins that work on the client side +*/ +#define MYSQL_CLIENT_PLUGIN_INCLUDED + +/* + On Windows, exports from DLL need to be declared + Also, plugin needs to be declared as extern "C" because MSVC + unlike other compilers, uses C++ mangling for variables not only + for functions. +*/ +#undef MYSQL_PLUGIN_EXPORT +#if defined(_MSC_VER) + #define MYSQL_PLUGIN_EXPORT_C __declspec(dllexport) +#else /*_MSC_VER */ + #define MYSQL_PLUGIN_EXPORT_C +#endif +#ifdef __cplusplus +#define MYSQL_PLUGIN_EXPORT extern "C" MYSQL_PLUGIN_EXPORT_C +#define C_MODE_START extern "C" { +#define C_MODE_END } +#else +#define MYSQL_PLUGIN_EXPORT MYSQL_PLUGIN_EXPORT_C +#define C_MODE_START +#define C_MODE_END +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#include <stdlib.h> +#endif + +/* known plugin types */ +#define MYSQL_CLIENT_reserved1 0 +#define MYSQL_CLIENT_reserved2 1 +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 + +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100 + +#define MYSQL_CLIENT_MAX_PLUGINS 3 + +#define mysql_declare_client_plugin(X) \ + C_MODE_START MYSQL_PLUGIN_EXPORT_C \ + struct st_mysql_client_plugin_ ## X \ + _mysql_client_plugin_declaration_ = { \ + MYSQL_CLIENT_ ## X ## _PLUGIN, \ + MYSQL_CLIENT_ ## X ## _PLUGIN_INTERFACE_VERSION, +#define mysql_end_client_plugin }; C_MODE_END + +/* generic plugin header structure */ +#define MYSQL_CLIENT_PLUGIN_HEADER \ + int type; \ + unsigned int interface_version; \ + const char *name; \ + const char *author; \ + const char *desc; \ + unsigned int version[3]; \ + const char *license; \ + void *mysql_api; \ + int (*init)(char *, size_t, int, va_list); \ + int (*deinit)(); \ + int (*options)(const char *option, const void *); + +struct st_mysql_client_plugin +{ + MYSQL_CLIENT_PLUGIN_HEADER +}; + +struct st_mysql; + +/******** authentication plugin specific declarations *********/ +#include <mysql/plugin_auth_common.h> + +struct st_mysql_client_plugin_AUTHENTICATION +{ + MYSQL_CLIENT_PLUGIN_HEADER + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); +}; + +#include <mysql/auth_dialog_client.h> + +/******** using plugins ************/ + +/** + loads a plugin and initializes it + + @param mysql MYSQL structure. + @param name a name of the plugin to load + @param type type of plugin that should be loaded, -1 to disable type check + @param argc number of arguments to pass to the plugin initialization + function + @param ... arguments for the plugin initialization function + + @retval + a pointer to the loaded plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, + int argc, ...); + +/** + loads a plugin and initializes it, taking va_list as an argument + + This is the same as mysql_load_plugin, but take va_list instead of + a list of arguments. + + @param mysql MYSQL structure. + @param name a name of the plugin to load + @param type type of plugin that should be loaded, -1 to disable type check + @param argc number of arguments to pass to the plugin initialization + function + @param args arguments for the plugin initialization function + + @retval + a pointer to the loaded plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, + int argc, va_list args); + +/** + finds an already loaded plugin by name, or loads it, if necessary + + @param mysql MYSQL structure. + @param name a name of the plugin to load + @param type type of plugin that should be loaded + + @retval + a pointer to the plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); + +/** + adds a plugin structure to the list of loaded plugins + + This is useful if an application has the necessary functionality + (for example, a special load data handler) statically linked into + the application binary. It can use this function to register the plugin + directly, avoiding the need to factor it out into a shared object. + + @param mysql MYSQL structure. It is only used for error reporting + @param plugin an st_mysql_client_plugin structure to register + + @retval + a pointer to the plugin, or NULL in case of a failure +*/ +struct st_mysql_client_plugin * +mysql_client_register_plugin(struct st_mysql *mysql, + struct st_mysql_client_plugin *plugin); + +/** + set plugin options + + Can be used to set extra options and affect behavior for a plugin. + This function may be called multiple times to set several options + + @param plugin an st_mysql_client_plugin structure + @param option a string which specifies the option to set + @param value value for the option. + + @retval 0 on success, 1 in case of failure +**/ +int mysql_plugin_options(struct st_mysql_client_plugin *plugin, + const char *option, const void *value); +#endif + diff --git a/include/mysql/client_plugin.h.pp b/include/mysql/client_plugin.h.pp new file mode 100644 index 00000000..b6ba9cf0 --- /dev/null +++ b/include/mysql/client_plugin.h.pp @@ -0,0 +1,41 @@ +struct st_mysql_client_plugin +{ + int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(); int (*options)(const char *option, const void *); +}; +struct st_mysql; +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; +} MYSQL_PLUGIN_VIO_INFO; +typedef struct st_plugin_vio +{ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); +} MYSQL_PLUGIN_VIO; +struct st_mysql_client_plugin_AUTHENTICATION +{ + int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(); int (*options)(const char *option, const void *); + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); +}; +struct st_mysql; +typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql, + int type, const char *prompt, char *buf, int buf_len); +struct st_mysql_client_plugin * +mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, + int argc, ...); +struct st_mysql_client_plugin * +mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, + int argc, va_list args); +struct st_mysql_client_plugin * +mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); +struct st_mysql_client_plugin * +mysql_client_register_plugin(struct st_mysql *mysql, + struct st_mysql_client_plugin *plugin); +int mysql_plugin_options(struct st_mysql_client_plugin *plugin, + const char *option, const void *value); diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h new file mode 100644 index 00000000..14c75251 --- /dev/null +++ b/include/mysql/plugin.h @@ -0,0 +1,794 @@ +/* Copyright (c) 2005, 2013, Oracle and/or its affiliates + Copyright (C) 2009, 2017, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_PLUGIN_INCLUDED +#define MYSQL_PLUGIN_INCLUDED + +/* + On Windows, exports from DLL need to be declared + Also, plugin needs to be declared as extern "C" because MSVC + unlike other compilers, uses C++ mangling for variables not only + for functions. +*/ +#ifdef MYSQL_DYNAMIC_PLUGIN + #ifdef _MSC_VER + #define MYSQL_DLLEXPORT _declspec(dllexport) + #else + #define MYSQL_DLLEXPORT + #endif +#else + #define MYSQL_DLLEXPORT +#endif + +#ifdef __cplusplus + #define MYSQL_PLUGIN_EXPORT extern "C" MYSQL_DLLEXPORT +#else + #define MYSQL_PLUGIN_EXPORT MYSQL_DLLEXPORT +#endif + +#ifdef __cplusplus +class THD; +class Item; +#define MYSQL_THD THD* +#else +#define MYSQL_THD void* +#endif + +typedef char my_bool; +typedef void * MYSQL_PLUGIN; + +#include <mysql/services.h> + +#define MYSQL_XIDDATASIZE 128 +/** + struct st_mysql_xid is binary compatible with the XID structure as + in the X/Open CAE Specification, Distributed Transaction Processing: + The XA Specification, X/Open Company Ltd., 1991. + http://www.opengroup.org/bookstore/catalog/c193.htm + + @see XID in sql/handler.h +*/ +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[MYSQL_XIDDATASIZE]; /* Not \0-terminated */ +}; +typedef struct st_mysql_xid MYSQL_XID; + +/************************************************************************* + Plugin API. Common for all plugin types. +*/ + +/* MySQL plugin interface version */ +#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104 + +/* MariaDB plugin interface version */ +#define MARIA_PLUGIN_INTERFACE_VERSION 0x010f + +/* + The allowable types of plugins +*/ +#define MYSQL_UDF_PLUGIN 0 /* not implemented */ +#define MYSQL_STORAGE_ENGINE_PLUGIN 1 +#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */ +#define MYSQL_DAEMON_PLUGIN 3 +#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 +#define MYSQL_AUDIT_PLUGIN 5 +#define MYSQL_REPLICATION_PLUGIN 6 +#define MYSQL_AUTHENTICATION_PLUGIN 7 +#define MYSQL_MAX_PLUGIN_TYPE_NUM 12 /* The number of plugin types */ + +/* MariaDB plugin types */ +#define MariaDB_PASSWORD_VALIDATION_PLUGIN 8 +#define MariaDB_ENCRYPTION_PLUGIN 9 +#define MariaDB_DATA_TYPE_PLUGIN 10 +#define MariaDB_FUNCTION_PLUGIN 11 + +/* We use the following strings to define licenses for plugins */ +#define PLUGIN_LICENSE_PROPRIETARY 0 +#define PLUGIN_LICENSE_GPL 1 +#define PLUGIN_LICENSE_BSD 2 + +#define PLUGIN_LICENSE_PROPRIETARY_STRING "PROPRIETARY" +#define PLUGIN_LICENSE_GPL_STRING "GPL" +#define PLUGIN_LICENSE_BSD_STRING "BSD" + +/* definitions of code maturity for plugins */ +#define MariaDB_PLUGIN_MATURITY_UNKNOWN 0 +#define MariaDB_PLUGIN_MATURITY_EXPERIMENTAL 1 +#define MariaDB_PLUGIN_MATURITY_ALPHA 2 +#define MariaDB_PLUGIN_MATURITY_BETA 3 +#define MariaDB_PLUGIN_MATURITY_GAMMA 4 +#define MariaDB_PLUGIN_MATURITY_STABLE 5 + +/* + Macros for beginning and ending plugin declarations. Between + mysql_declare_plugin and mysql_declare_plugin_end there should + be a st_mysql_plugin struct for each plugin to be declared. +*/ + + +#ifndef MYSQL_DYNAMIC_PLUGIN +#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \ +int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \ +int PSIZE= sizeof(struct st_mysql_plugin); \ +struct st_mysql_plugin DECLS[]= { + +#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \ +MYSQL_PLUGIN_EXPORT int VERSION; \ +int VERSION= MARIA_PLUGIN_INTERFACE_VERSION; \ +MYSQL_PLUGIN_EXPORT int PSIZE; \ +int PSIZE= sizeof(struct st_maria_plugin); \ +MYSQL_PLUGIN_EXPORT struct st_maria_plugin DECLS[]; \ +struct st_maria_plugin DECLS[]= { +#else + +#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \ +MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_; \ +int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \ +MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_; \ +int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \ +MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]; \ +struct st_mysql_plugin _mysql_plugin_declarations_[]= { + +#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \ +MYSQL_PLUGIN_EXPORT int _maria_plugin_interface_version_; \ +int _maria_plugin_interface_version_= MARIA_PLUGIN_INTERFACE_VERSION; \ +MYSQL_PLUGIN_EXPORT int _maria_sizeof_struct_st_plugin_; \ +int _maria_sizeof_struct_st_plugin_= sizeof(struct st_maria_plugin); \ +MYSQL_PLUGIN_EXPORT struct st_maria_plugin _maria_plugin_declarations_[]; \ +struct st_maria_plugin _maria_plugin_declarations_[]= { + +#endif + +#define mysql_declare_plugin(NAME) \ +__MYSQL_DECLARE_PLUGIN(NAME, \ + builtin_ ## NAME ## _plugin_interface_version, \ + builtin_ ## NAME ## _sizeof_struct_st_plugin, \ + builtin_ ## NAME ## _plugin) + +#define maria_declare_plugin(NAME) \ +MARIA_DECLARE_PLUGIN__(NAME, \ + builtin_maria_ ## NAME ## _plugin_interface_version, \ + builtin_maria_ ## NAME ## _sizeof_struct_st_plugin, \ + builtin_maria_ ## NAME ## _plugin) + +#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}} +#define maria_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}} + +/* + declarations for SHOW STATUS support in plugins +*/ +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; + +/* backward compatibility mapping. */ +#define SHOW_INT SHOW_UINT +#define SHOW_LONG SHOW_ULONG +#define SHOW_LONGLONG SHOW_ULONGLONG + +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; + +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; + +struct system_status_var; + +#define SHOW_VAR_FUNC_BUFF_SIZE (256 * sizeof(void*)) +typedef int (*mysql_show_var_func)(MYSQL_THD, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); + + +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; + + +/* + Constants for plugin flags. + */ + +#define PLUGIN_OPT_NO_INSTALL 1UL /* Not dynamically loadable */ +#define PLUGIN_OPT_NO_UNINSTALL 2UL /* Not dynamically unloadable */ + + +/* + declarations for server variables and command line options +*/ + + +#define PLUGIN_VAR_BOOL 0x0001 +#define PLUGIN_VAR_INT 0x0002 +#define PLUGIN_VAR_LONG 0x0003 +#define PLUGIN_VAR_LONGLONG 0x0004 +#define PLUGIN_VAR_STR 0x0005 +#define PLUGIN_VAR_ENUM 0x0006 +#define PLUGIN_VAR_SET 0x0007 +#define PLUGIN_VAR_DOUBLE 0x0008 +#define PLUGIN_VAR_UNSIGNED 0x0080 +#define PLUGIN_VAR_THDLOCAL 0x0100 /* Variable is per-connection */ +#define PLUGIN_VAR_READONLY 0x0200 /* Server variable is read only */ +#define PLUGIN_VAR_NOSYSVAR 0x0400 /* Not a server variable */ +#define PLUGIN_VAR_NOCMDOPT 0x0800 /* Not a command line option */ +#define PLUGIN_VAR_NOCMDARG 0x1000 /* No argument for cmd line */ +#define PLUGIN_VAR_RQCMDARG 0x0000 /* Argument required for cmd line */ +#define PLUGIN_VAR_OPCMDARG 0x2000 /* Argument optional for cmd line */ +#define PLUGIN_VAR_DEPRECATED 0x4000 /* Server variable is deprecated */ +#define PLUGIN_VAR_MEMALLOC 0x8000 /* String needs memory allocated */ + +struct st_mysql_sys_var; +struct st_mysql_value; + +/* + SYNOPSIS + (*mysql_var_check_func)() + thd thread handle + var dynamic variable being altered + save pointer to temporary storage + value user provided value + RETURN + 0 user provided value is OK and the update func may be called. + any other value indicates error. + + This function should parse the user provided value and store in the + provided temporary storage any data as required by the update func. + There is sufficient space in the temporary storage to store a double. + Note that the update func may not be called if any other error occurs + so any memory allocated should be thread-local so that it may be freed + automatically at the end of the statement. +*/ + +typedef int (*mysql_var_check_func)(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); + +/* + SYNOPSIS + (*mysql_var_update_func)() + thd thread handle + var dynamic variable being altered + var_ptr pointer to dynamic variable + save pointer to temporary storage + RETURN + NONE + + This function should use the validated value stored in the temporary store + and persist it in the provided pointer to the dynamic variable. + For example, strings may require memory to be allocated. +*/ +typedef void (*mysql_var_update_func)(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); + + +/* the following declarations are for internal use only */ + + +#define PLUGIN_VAR_MASK \ + (PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR | \ + PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_NOCMDARG | \ + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_RQCMDARG | \ + PLUGIN_VAR_DEPRECATED | PLUGIN_VAR_MEMALLOC) + +#define MYSQL_PLUGIN_VAR_HEADER \ + int flags; \ + const char *name; \ + const char *comment; \ + mysql_var_check_func check; \ + mysql_var_update_func update + +#define MYSQL_SYSVAR_NAME(name) mysql_sysvar_ ## name +#define MYSQL_SYSVAR(name) \ + ((struct st_mysql_sys_var *)&(MYSQL_SYSVAR_NAME(name))) + +/* + for global variables, the value pointer is the first + element after the header, the default value is the second. + for thread variables, the value offset is the first + element after the header, the default value is the second. +*/ + + +#define DECLARE_MYSQL_SYSVAR_BASIC(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + type *value; \ + const type def_val; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_SYSVAR_CONST_BASIC(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + const type *value; \ + const type def_val; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_SYSVAR_SIMPLE(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + type *value; type def_val; \ + type min_val; type max_val; \ + type blk_sz; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_SYSVAR_TYPELIB(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + type *value; type def_val; \ + TYPELIB *typelib; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_THDVAR_FUNC(type) \ + type *(*resolve)(MYSQL_THD thd, int offset) + +#define DECLARE_MYSQL_THDVAR_BASIC(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + const type def_val; \ + DECLARE_THDVAR_FUNC(type); \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_THDVAR_SIMPLE(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + type def_val; type min_val; \ + type max_val; type blk_sz; \ + DECLARE_THDVAR_FUNC(type); \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_THDVAR_TYPELIB(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + const type def_val; \ + DECLARE_THDVAR_FUNC(type); \ + TYPELIB *typelib; \ +} MYSQL_SYSVAR_NAME(name) + + +/* + the following declarations are for use by plugin implementors +*/ + +#define MYSQL_SYSVAR_BOOL(name, varname, opt, comment, check, update, def) \ +DECLARE_MYSQL_SYSVAR_BASIC(name, char) = { \ + PLUGIN_VAR_BOOL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def} + +#define MYSQL_SYSVAR_STR(name, varname, opt, comment, check, update, def) \ +DECLARE_MYSQL_SYSVAR_BASIC(name, char *) = { \ + PLUGIN_VAR_STR | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def} + +#define MYSQL_SYSVAR_CONST_STR(name, varname, opt, comment, check, update, def) \ +DECLARE_MYSQL_SYSVAR_CONST_BASIC(name, char *) = { \ + PLUGIN_VAR_STR | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def} + +#define MYSQL_SYSVAR_INT(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, int) = { \ + PLUGIN_VAR_INT | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_UINT(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, unsigned int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_LONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, long) = { \ + PLUGIN_VAR_LONG | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_ULONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, unsigned long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_LONGLONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, long long) = { \ + PLUGIN_VAR_LONGLONG | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_ULONGLONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, unsigned long long) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_UINT64_T(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, uint64_t) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#ifdef _WIN64 +#define MYSQL_SYSVAR_SIZE_T(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, size_t) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } +#else +#define MYSQL_SYSVAR_SIZE_T(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, size_t) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } +#endif + +#define MYSQL_SYSVAR_ENUM(name, varname, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_SYSVAR_TYPELIB(name, unsigned long) = { \ + PLUGIN_VAR_ENUM | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, typelib } + +#define MYSQL_SYSVAR_SET(name, varname, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_SYSVAR_TYPELIB(name, unsigned long long) = { \ + PLUGIN_VAR_SET | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, typelib } + +#define MYSQL_SYSVAR_DOUBLE(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, double) = { \ + PLUGIN_VAR_DOUBLE | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_THDVAR_BOOL(name, opt, comment, check, update, def) \ +DECLARE_MYSQL_THDVAR_BASIC(name, char) = { \ + PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL} + +#define MYSQL_THDVAR_STR(name, opt, comment, check, update, def) \ +DECLARE_MYSQL_THDVAR_BASIC(name, char *) = { \ + PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL} + +#define MYSQL_THDVAR_INT(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_UINT(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, unsigned int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_LONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ULONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, unsigned long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_LONGLONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, long long) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ULONGLONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, unsigned long long) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ENUM(name, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_THDVAR_TYPELIB(name, unsigned long) = { \ + PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL, typelib } + +#define MYSQL_THDVAR_SET(name, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_THDVAR_TYPELIB(name, unsigned long long) = { \ + PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL, typelib } + +#define MYSQL_THDVAR_DOUBLE(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, double) = { \ + PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +/* accessor macros */ + +#define SYSVAR(name) \ + (*(MYSQL_SYSVAR_NAME(name).value)) + +/* when thd == null, result points to global value */ +#define THDVAR(thd, name) \ + (*(MYSQL_SYSVAR_NAME(name).resolve(thd, MYSQL_SYSVAR_NAME(name).offset))) + + +/* + Plugin description structure. +*/ + +struct st_mysql_plugin +{ + int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + void *info; /* pointer to type-specific plugin descriptor */ + const char *name; /* plugin name */ + const char *author; /* plugin author (for I_S.PLUGINS) */ + const char *descr; /* general descriptive text (for I_S.PLUGINS) */ + int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ + int (*init)(void *); /* the function to invoke when plugin is loaded */ + int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ + unsigned int version; /* plugin version (for I_S.PLUGINS) */ + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; /* reserved for dependency checking */ + unsigned long flags; /* flags for plugin */ +}; + +/* + MariaDB extension for plugins declaration structure. + + It also copy current MySQL plugin fields to have more independency + in plugins extension +*/ + +struct st_maria_plugin +{ + int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + void *info; /* pointer to type-specific plugin descriptor */ + const char *name; /* plugin name */ + const char *author; /* plugin author (for SHOW PLUGINS) */ + const char *descr; /* general descriptive text (for SHOW PLUGINS ) */ + int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ + int (*init)(void *); /* the function to invoke when plugin is loaded */ + int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ + unsigned int version; /* plugin version (for SHOW PLUGINS) */ + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; /* plugin version string */ + unsigned int maturity; /* MariaDB_PLUGIN_MATURITY_XXX */ +}; + +/************************************************************************* + API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN) +*/ +#include "plugin_ftparser.h" + +/************************************************************************* + API for Storage Engine plugin. (MYSQL_DAEMON_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_DAEMON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/* + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_daemon +{ + int interface_version; +}; + + +/************************************************************************* + API for I_S plugin. (MYSQL_INFORMATION_SCHEMA_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/* + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_information_schema +{ + int interface_version; +}; + + +/************************************************************************* + API for Storage Engine plugin. (MYSQL_STORAGE_ENGINE_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_HANDLERTON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/* + The real API is in the sql/handler.h + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_storage_engine +{ + int interface_version; +}; + +struct handlerton; + + +/* + API for Replication plugin. (MYSQL_REPLICATION_PLUGIN) +*/ + #define MYSQL_REPLICATION_INTERFACE_VERSION 0x0200 + + /** + Replication plugin descriptor + */ + struct Mysql_replication { + int interface_version; + }; + +/************************************************************************* + st_mysql_value struct for reading values from mysqld. + Used by server variables framework to parse user-provided values. + Will be used for arguments when implementing UDFs. + + Note that val_str() returns a string in temporary memory + that will be freed at the end of statement. Copy the string + if you need it to persist. +*/ + +#define MYSQL_VALUE_TYPE_STRING 0 +#define MYSQL_VALUE_TYPE_REAL 1 +#define MYSQL_VALUE_TYPE_INT 2 + +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; + + +/************************************************************************* + Miscellaneous functions for plugin implementors +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +int thd_in_lock_tables(const MYSQL_THD thd); +int thd_tablespace_op(const MYSQL_THD thd); +long long thd_test_options(const MYSQL_THD thd, long long test_options); +int thd_sql_command(const MYSQL_THD thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const MYSQL_THD thd); +void thd_storage_lock_wait(MYSQL_THD thd, long long value); +int thd_tx_isolation(const MYSQL_THD thd); +int thd_tx_is_read_only(const MYSQL_THD thd); +/** + Create a temporary file. + + @details + The temporary file is created in a location specified by the mysql + server configuration (--tmpdir option). The caller does not need to + delete the file, it will be deleted automatically. + + @param prefix prefix for temporary file name + @retval -1 error + @retval >= 0 a file handle that can be passed to dup or my_close +*/ +int mysql_tmpfile(const char *prefix); + +/** + Return the thread id of a user thread + + @param thd user thread connection handle + @return thread id +*/ +unsigned long thd_get_thread_id(const MYSQL_THD thd); + +/** + Get the XID for this connection's transaction + + @param thd user thread connection handle + @param xid location where identifier is stored +*/ +void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid); + +/** + Invalidate the query cache for a given table. + + @param thd user thread connection handle + @param key databasename\\0tablename\\0 + @param key_length length of key in bytes, including the NUL bytes + @param using_trx flag: TRUE if using transactions, FALSE otherwise +*/ +void mysql_query_cache_invalidate4(MYSQL_THD thd, + const char *key, unsigned int key_length, + int using_trx); + + +/** + Provide a handler data getter to simplify coding +*/ +void *thd_get_ha_data(const MYSQL_THD thd, const struct handlerton *hton); + + +/** + Provide a handler data setter to simplify coding + + @details + Set ha_data pointer (storage engine per-connection information). + + To avoid unclean deactivation (uninstall) of storage engine plugin + in the middle of transaction, additional storage engine plugin + lock is acquired. + + If ha_data is not null and storage engine plugin was not locked + by thd_set_ha_data() in this connection before, storage engine + plugin gets locked. + + If ha_data is null and storage engine plugin was locked by + thd_set_ha_data() in this connection before, storage engine + plugin lock gets released. + + If handlerton::close_connection() didn't reset ha_data, server does + it immediately after calling handlerton::close_connection(). +*/ +void thd_set_ha_data(MYSQL_THD thd, const struct handlerton *hton, + const void *ha_data); + + +/** + Signal that the first part of handler commit is finished, and that the + committed transaction is now visible and has fixed commit ordering with + respect to other transactions. The commit need _not_ be durable yet, and + typically will not be when this call makes sense. + + This call is optional, if the storage engine does not call it the upper + layer will after the handler commit() method is done. However, the storage + engine may choose to call it itself to increase the possibility for group + commit. + + In-order parallel replication uses this to apply different transaction in + parallel, but delay the commits of later transactions until earlier + transactions have committed first, thus achieving increased performance on + multi-core systems while still preserving full transaction consistency. + + The storage engine can call this from within the commit() method, typically + after the commit record has been written to the transaction log, but before + the log has been fsync()'ed. This will allow the next replicated transaction + to proceed to commit before the first one has done fsync() or similar. Thus, + it becomes possible for multiple sequential replicated transactions to share + a single fsync() inside the engine in group commit. + + Note that this method should _not_ be called from within the commit_ordered() + method, or any other place in the storage engine. When commit_ordered() is + used (typically when binlog is enabled), the transaction coordinator takes + care of this and makes group commit in the storage engine possible without + any other action needed on the part of the storage engine. This function + thd_wakeup_subsequent_commits() is only needed when no transaction + coordinator is used, meaning a single storage engine and no binary log. +*/ +void thd_wakeup_subsequent_commits(MYSQL_THD thd, int wakeup_error); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/plugin_audit.h b/include/mysql/plugin_audit.h new file mode 100644 index 00000000..bfa6621b --- /dev/null +++ b/include/mysql/plugin_audit.h @@ -0,0 +1,181 @@ +/* Copyright (c) 2007, 2013, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_audit_h +#define _my_audit_h + +/************************************************************************* + API for Audit plugin. (MYSQL_AUDIT_PLUGIN) +*/ + +#include "plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MYSQL_AUDIT_CLASS_MASK_SIZE 1 + +#define MYSQL_AUDIT_INTERFACE_VERSION 0x0302 + + +/************************************************************************* + AUDIT CLASS : GENERAL + + LOG events occurs before emitting to the general query log. + ERROR events occur before transmitting errors to the user. + RESULT events occur after transmitting a resultset to the user. + STATUS events occur after transmitting a resultset or errors + to the user. +*/ + +#define MYSQL_AUDIT_GENERAL_CLASS 0 +#define MYSQL_AUDIT_GENERAL_CLASSMASK (1 << MYSQL_AUDIT_GENERAL_CLASS) +#define MYSQL_AUDIT_GENERAL_LOG 0 +#define MYSQL_AUDIT_GENERAL_ERROR 1 +#define MYSQL_AUDIT_GENERAL_RESULT 2 +#define MYSQL_AUDIT_GENERAL_STATUS 3 +#define MYSQL_AUDIT_GENERAL_WARNING 4 + +struct mysql_event_general +{ + unsigned int event_subclass; + int general_error_code; + unsigned long general_thread_id; + const char *general_user; + unsigned int general_user_length; + const char *general_command; + unsigned int general_command_length; + const char *general_query; + unsigned int general_query_length; + const struct charset_info_st *general_charset; + unsigned long long general_time; + unsigned long long general_rows; + /* Added in version 0x302 */ + unsigned long long query_id; + MYSQL_CONST_LEX_STRING database; +}; + + +/* + AUDIT CLASS : CONNECTION + + CONNECT occurs after authentication phase is completed. + DISCONNECT occurs after connection is terminated. + CHANGE_USER occurs after COM_CHANGE_USER RPC is completed. +*/ + +#define MYSQL_AUDIT_CONNECTION_CLASS 1 +#define MYSQL_AUDIT_CONNECTION_CLASSMASK (1 << MYSQL_AUDIT_CONNECTION_CLASS) +#define MYSQL_AUDIT_CONNECTION_CONNECT 0 +#define MYSQL_AUDIT_CONNECTION_DISCONNECT 1 +#define MYSQL_AUDIT_CONNECTION_CHANGE_USER 2 + +struct mysql_event_connection +{ + unsigned int event_subclass; + int status; + unsigned long thread_id; + const char *user; + unsigned int user_length; + const char *priv_user; + unsigned int priv_user_length; + const char *external_user; + unsigned int external_user_length; + const char *proxy_user; + unsigned int proxy_user_length; + const char *host; + unsigned int host_length; + const char *ip; + unsigned int ip_length; + MYSQL_CONST_LEX_STRING database; +}; + +/* + AUDIT CLASS : TABLE + + LOCK occurs when a connection "locks" (this does not necessarily mean a table + lock and also happens for row-locking engines) the table at the beginning of + a statement. This event is generated at the beginning of every statement for + every affected table, unless there's a LOCK TABLES statement in effect (in + which case it is generated once for LOCK TABLES and then is suppressed until + the tables are unlocked). + + CREATE/DROP/RENAME occur when a table is created, dropped, or renamed. +*/ + +#define MYSQL_AUDIT_TABLE_CLASS 15 +#define MYSQL_AUDIT_TABLE_CLASSMASK (1 << MYSQL_AUDIT_TABLE_CLASS) +#define MYSQL_AUDIT_TABLE_LOCK 0 +#define MYSQL_AUDIT_TABLE_CREATE 1 +#define MYSQL_AUDIT_TABLE_DROP 2 +#define MYSQL_AUDIT_TABLE_RENAME 3 +#define MYSQL_AUDIT_TABLE_ALTER 4 + +struct mysql_event_table +{ + unsigned int event_subclass; + unsigned long thread_id; + const char *user; + const char *priv_user; + const char *priv_host; + const char *external_user; + const char *proxy_user; + const char *host; + const char *ip; + MYSQL_CONST_LEX_STRING database; + MYSQL_CONST_LEX_STRING table; + /* for MYSQL_AUDIT_TABLE_RENAME */ + MYSQL_CONST_LEX_STRING new_database; + MYSQL_CONST_LEX_STRING new_table; + /* for MYSQL_AUDIT_TABLE_LOCK, true if read-only, false if read/write */ + int read_only; + /* Added in version 0x302 */ + unsigned long long query_id; +}; + +/************************************************************************* + Here we define the descriptor structure, that is referred from + st_mysql_plugin. + + release_thd() event occurs when the event class consumer is to be + disassociated from the specified THD. This would typically occur + before some operation which may require sleeping - such as when + waiting for the next query from the client. + + event_notify() is invoked whenever an event occurs which is of any + class for which the plugin has interest. The second argument + indicates the specific event class and the third argument is data + as required for that class. + + class_mask is an array of bits used to indicate what event classes + that this plugin wants to receive. +*/ + +struct st_mysql_audit +{ + int interface_version; + void (*release_thd)(MYSQL_THD); + void (*event_notify)(MYSQL_THD, unsigned int, const void *); + unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp new file mode 100644 index 00000000..a01e4ff8 --- /dev/null +++ b/include/mysql/plugin_audit.h.pp @@ -0,0 +1,725 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +extern "C" { +struct mysql_event_general +{ + unsigned int event_subclass; + int general_error_code; + unsigned long general_thread_id; + const char *general_user; + unsigned int general_user_length; + const char *general_command; + unsigned int general_command_length; + const char *general_query; + unsigned int general_query_length; + const struct charset_info_st *general_charset; + unsigned long long general_time; + unsigned long long general_rows; + unsigned long long query_id; + MYSQL_CONST_LEX_STRING database; +}; +struct mysql_event_connection +{ + unsigned int event_subclass; + int status; + unsigned long thread_id; + const char *user; + unsigned int user_length; + const char *priv_user; + unsigned int priv_user_length; + const char *external_user; + unsigned int external_user_length; + const char *proxy_user; + unsigned int proxy_user_length; + const char *host; + unsigned int host_length; + const char *ip; + unsigned int ip_length; + MYSQL_CONST_LEX_STRING database; +}; +struct mysql_event_table +{ + unsigned int event_subclass; + unsigned long thread_id; + const char *user; + const char *priv_user; + const char *priv_host; + const char *external_user; + const char *proxy_user; + const char *host; + const char *ip; + MYSQL_CONST_LEX_STRING database; + MYSQL_CONST_LEX_STRING table; + MYSQL_CONST_LEX_STRING new_database; + MYSQL_CONST_LEX_STRING new_table; + int read_only; + unsigned long long query_id; +}; +struct st_mysql_audit +{ + int interface_version; + void (*release_thd)(THD*); + void (*event_notify)(THD*, unsigned int, const void *); + unsigned long class_mask[1]; +}; +} diff --git a/include/mysql/plugin_auth.h b/include/mysql/plugin_auth.h new file mode 100644 index 00000000..3827db33 --- /dev/null +++ b/include/mysql/plugin_auth.h @@ -0,0 +1,183 @@ +#ifndef MYSQL_PLUGIN_AUTH_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + Copyright (c) 2010, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Authentication Plugin API. + + This file defines the API for server authentication plugins. +*/ + +#define MYSQL_PLUGIN_AUTH_INCLUDED + +#include <mysql/plugin.h> + +#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0202 + +#include <mysql/plugin_auth_common.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* defines for MYSQL_SERVER_AUTH_INFO.password_used */ + +#define PASSWORD_USED_NO 0 +#define PASSWORD_USED_YES 1 +#define PASSWORD_USED_NO_MENTION 2 + + +/** + Provides server plugin access to authentication information +*/ +typedef struct st_mysql_server_auth_info +{ + /** + User name as sent by the client and shown in USER(). + NULL if the client packet with the user name was not received yet. + */ + const char *user_name; + + /** + Length of user_name + */ + unsigned int user_name_length; + + /** + A corresponding column value from the mysql.user table for the + matching account name or the preprocessed value, if preprocess_hash + method is not NULL + */ + const char *auth_string; + + /** + Length of auth_string + */ + unsigned long auth_string_length; + + /** + Matching account name as found in the mysql.user table. + A plugin can override it with another name that will be + used by MySQL for authorization, and shown in CURRENT_USER() + */ + char authenticated_as[MYSQL_USERNAME_LENGTH+1]; + + + /** + The unique user name that was used by the plugin to authenticate. + Not used by the server. + Available through the @@EXTERNAL_USER variable. + */ + char external_user[MYSQL_USERNAME_LENGTH+1]; + + /** + This only affects the "Authentication failed. Password used: %s" + error message. has the following values : + 0 : %s will be NO. + 1 : %s will be YES. + 2 : there will be no %s. + Set it as appropriate or ignore at will. + */ + int password_used; + + /** + Set to the name of the connected client host, if it can be resolved, + or to its IP address otherwise. + */ + const char *host_or_ip; + + /** + Length of host_or_ip + */ + unsigned int host_or_ip_length; + + /** + Current THD pointer (to use with various services) + */ + MYSQL_THD thd; + +} MYSQL_SERVER_AUTH_INFO; + +/** + Server authentication plugin descriptor +*/ +struct st_mysql_auth +{ + int interface_version; /**< version plugin uses */ + /** + A plugin that a client must use for authentication with this server + plugin. Can be NULL to mean "any plugin". + */ + const char *client_auth_plugin; + /** + Function provided by the plugin which should perform authentication (using + the vio functions if necessary) and return 0 if successful. The plugin can + also fill the info.authenticated_as field if a different username should be + used for authorization. + */ + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); + /** + Create a password hash (or digest) out of a plain-text password + + Used in SET PASSWORD, GRANT, and CREATE USER to convert user specified + plain-text password into a value that will be stored in mysql.user table. + + @see preprocess_hash + + @param password plain-text password + @param password_length plain-text password length + @param hash the digest will be stored there + @param hash_length in: hash buffer size + out: the actual length of the hash + + @return 0 for ok, 1 for error + + Can be NULL, in this case one will not be able to use SET PASSWORD or + PASSWORD('...') in GRANT, CREATE USER, ALTER USER. + */ + int (*hash_password)(const char *password, size_t password_length, + char *hash, size_t *hash_length); + + /** + Prepare the password hash for authentication. + + Password hash is stored in the authentication_string column of the + mysql.user table in a text form. If a plugin needs to preprocess the + value somehow before the authentication (e.g. convert from hex or base64 + to binary), it can do it in this method. This way the conversion + will happen only once, not for every authentication attempt. + + The value written to the out buffer will be cached and later made + available to the authenticate_user() method in the + MYSQL_SERVER_AUTH_INFO::auth_string[] buffer. + + @return 0 for ok, 1 for error + + Can be NULL, in this case the mysql.user.authentication_string value will + be given to the authenticate_user() method as is, unconverted. + */ + int (*preprocess_hash)(const char *hash, size_t hash_length, + unsigned char *out, size_t *out_length); +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp new file mode 100644 index 00000000..1844f7b7 --- /dev/null +++ b/include/mysql/plugin_auth.h.pp @@ -0,0 +1,702 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; +} MYSQL_PLUGIN_VIO_INFO; +typedef struct st_plugin_vio +{ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); +} MYSQL_PLUGIN_VIO; +extern "C" { +typedef struct st_mysql_server_auth_info +{ + const char *user_name; + unsigned int user_name_length; + const char *auth_string; + unsigned long auth_string_length; + char authenticated_as[512 +1]; + char external_user[512 +1]; + int password_used; + const char *host_or_ip; + unsigned int host_or_ip_length; + THD* thd; +} MYSQL_SERVER_AUTH_INFO; +struct st_mysql_auth +{ + int interface_version; + const char *client_auth_plugin; + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); + int (*hash_password)(const char *password, size_t password_length, + char *hash, size_t *hash_length); + int (*preprocess_hash)(const char *hash, size_t hash_length, + unsigned char *out, size_t *out_length); +}; +} diff --git a/include/mysql/plugin_auth_common.h b/include/mysql/plugin_auth_common.h new file mode 100644 index 00000000..8edd7128 --- /dev/null +++ b/include/mysql/plugin_auth_common.h @@ -0,0 +1,131 @@ +#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + Copyright (c) 2010, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef _WIN32 +#include <windows.h> +#endif + +/** + @file + + This file defines constants and data structures that are the same for + both client- and server-side authentication plugins. +*/ +#define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED + +/** the max allowed length for a user name */ +#define MYSQL_USERNAME_LENGTH 512 + +/** + return values of the plugin authenticate_user() method. +*/ + + /** + Authentication failed, plugin internal error. + An error occurred in the authentication plugin itself. + These errors are reported in table performance_schema.host_cache, + column COUNT_AUTH_PLUGIN_ERRORS. +*/ +#define CR_AUTH_PLUGIN_ERROR 3 +/** + Authentication failed, client server handshake. + An error occurred during the client server handshake. + These errors are reported in table performance_schema.host_cache, + column COUNT_HANDSHAKE_ERRORS. +*/ +#define CR_AUTH_HANDSHAKE 2 +/** + Authentication failed, user credentials. + For example, wrong passwords. + These errors are reported in table performance_schema.host_cache, + column COUNT_AUTHENTICATION_ERRORS. +*/ +#define CR_AUTH_USER_CREDENTIALS 1 +/** + Authentication failed. Additionally, all other CR_xxx values + (libmysql error code) can be used too. + + The client plugin may set the error code and the error message directly + in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error + code was returned, an error message in the MYSQL structure will be + overwritten. If CR_ERROR is returned without setting the error in MYSQL, + CR_UNKNOWN_ERROR will be user. +*/ +#define CR_ERROR 0 +/** + Authentication (client part) was successful. It does not mean that the + authentication as a whole was successful, usually it only means + that the client was able to send the user name and the password to the + server. If CR_OK is returned, the libmysql reads the next packet expecting + it to be one of OK, ERROR, or CHANGE_PLUGIN packets. +*/ +#define CR_OK -1 +/** + Authentication was successful. + It means that the client has done its part successfully and also that + a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN). + In this case, libmysql will not read a packet from the server, + but it will use the data at mysql->net.read_pos. + + A plugin may return this value if the number of roundtrips in the + authentication protocol is not known in advance, and the client plugin + needs to read one packet more to determine if the authentication is finished + or not. +*/ +#define CR_OK_HANDSHAKE_COMPLETE -2 + +typedef struct st_plugin_vio_info +{ + enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; + int socket; /**< it's set, if the protocol is SOCKET or TCP */ +#ifdef _WIN32 + HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */ +#endif +} MYSQL_PLUGIN_VIO_INFO; + +/** + Provides plugin access to communication channel +*/ +typedef struct st_plugin_vio +{ + /** + Plugin provides a pointer reference and this function sets it to the + contents of any incoming packet. Returns the packet length, or -1 if + the plugin should terminate. + */ + int (*read_packet)(struct st_plugin_vio *vio, + unsigned char **buf); + + /** + Plugin provides a buffer with data and the length and this + function sends it as a packet. Returns 0 on success, 1 on failure. + */ + int (*write_packet)(struct st_plugin_vio *vio, + const unsigned char *packet, + int packet_len); + + /** + Fills in a st_plugin_vio_info structure, providing the information + about the connection. + */ + void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); + +} MYSQL_PLUGIN_VIO; + +#endif + diff --git a/include/mysql/plugin_data_type.h b/include/mysql/plugin_data_type.h new file mode 100644 index 00000000..77aa9fb2 --- /dev/null +++ b/include/mysql/plugin_data_type.h @@ -0,0 +1,49 @@ +#ifndef MARIADB_PLUGIN_DATA_TYPE_INCLUDED +#define MARIADB_PLUGIN_DATA_TYPE_INCLUDED +/* Copyright (C) 2019, Alexander Barkov and MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Data Type Plugin API. + + This file defines the API for server plugins that manage data types. +*/ + +#ifdef __cplusplus + +#include <mysql/plugin.h> + +/* + API for data type plugins. (MariaDB_DATA_TYPE_PLUGIN) +*/ +#define MariaDB_DATA_TYPE_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + + +struct st_mariadb_data_type +{ + int interface_version; + class Type_handler *type_handler; +}; + + +/** + Data type plugin descriptor +*/ + +#endif /* __cplusplus */ + +#endif /* MARIADB_PLUGIN_DATA_TYPE_INCLUDED */ diff --git a/include/mysql/plugin_data_type.h.pp b/include/mysql/plugin_data_type.h.pp new file mode 100644 index 00000000..80b5a863 --- /dev/null +++ b/include/mysql/plugin_data_type.h.pp @@ -0,0 +1,667 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +struct st_mariadb_data_type +{ + int interface_version; + class Type_handler *type_handler; +}; diff --git a/include/mysql/plugin_encryption.h b/include/mysql/plugin_encryption.h new file mode 100644 index 00000000..3c574aa4 --- /dev/null +++ b/include/mysql/plugin_encryption.h @@ -0,0 +1,126 @@ +#ifndef MYSQL_PLUGIN_ENCRYPTION_INCLUDED +/* Copyright (C) 2014, 2015 Sergei Golubchik and MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Encryption Plugin API. + + This file defines the API for server plugins that manage encryption + keys for MariaDB on-disk data encryption. +*/ + +#define MYSQL_PLUGIN_ENCRYPTION_INCLUDED + +#include <mysql/plugin.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MariaDB_ENCRYPTION_INTERFACE_VERSION 0x0300 + +/** + Encryption plugin descriptor +*/ +struct st_mariadb_encryption +{ + int interface_version; /**< version plugin uses */ + + /*********** KEY MANAGEMENT ********************************************/ + + /** + function returning latest key version for a given key id + + @return a version or ENCRYPTION_KEY_VERSION_INVALID to indicate an error. + */ + unsigned int (*get_latest_key_version)(unsigned int key_id); + + /** + function returning a key for a key version + + @param version the requested key version + @param key the key will be stored there. Can be NULL - + in which case no key will be returned + @param key_length in: key buffer size + out: the actual length of the key + + This method can be used to query the key length - the required + buffer size - by passing key==NULL. + + If the buffer size is less than the key length the content of the + key buffer is undefined (the plugin is free to partially fill it with + the key data or leave it untouched). + + @return 0 on success, or + ENCRYPTION_KEY_VERSION_INVALID, ENCRYPTION_KEY_BUFFER_TOO_SMALL + or any other non-zero number for errors + */ + unsigned int (*get_key)(unsigned int key_id, unsigned int version, + unsigned char *key, unsigned int *key_length); + + /*********** ENCRYPTION ************************************************/ + /* + the caller uses encryption as follows: + 1. create the encryption context object of the crypt_ctx_size() bytes. + 2. initialize it with crypt_ctx_init(). + 3. repeat crypt_ctx_update() until there are no more data to encrypt. + 4. write the remaining output bytes and destroy the context object + with crypt_ctx_finish(). + */ + + /** + returns the size of the encryption context object in bytes + */ + unsigned int (*crypt_ctx_size)(unsigned int key_id, unsigned int key_version); + /** + initializes the encryption context object. + */ + int (*crypt_ctx_init)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + /** + processes (encrypts or decrypts) a chunk of data + + writes the output to th dst buffer. note that it might write + more bytes that were in the input. or less. or none at all. + */ + int (*crypt_ctx_update)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + /** + writes the remaining output bytes and destroys the encryption context + + crypt_ctx_update might've cached part of the output in the context, + this method will flush these data out. + */ + int (*crypt_ctx_finish)(void *ctx, unsigned char* dst, unsigned int* dlen); + /** + returns the length of the encrypted data + + it returns the exact length, given only the source length. + which means, this API only supports encryption algorithms where + the length of the encrypted data only depends on the length of the + input (a.k.a. compression is not supported). + */ + unsigned int (*encrypted_length)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp new file mode 100644 index 00000000..ac5798b1 --- /dev/null +++ b/include/mysql/plugin_encryption.h.pp @@ -0,0 +1,680 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +extern "C" { +struct st_mariadb_encryption +{ + int interface_version; + unsigned int (*get_latest_key_version)(unsigned int key_id); + unsigned int (*get_key)(unsigned int key_id, unsigned int version, + unsigned char *key, unsigned int *key_length); + unsigned int (*crypt_ctx_size)(unsigned int key_id, unsigned int key_version); + int (*crypt_ctx_init)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*crypt_ctx_update)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*crypt_ctx_finish)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encrypted_length)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +} diff --git a/include/mysql/plugin_ftparser.h b/include/mysql/plugin_ftparser.h new file mode 100644 index 00000000..511b34bb --- /dev/null +++ b/include/mysql/plugin_ftparser.h @@ -0,0 +1,222 @@ +/* Copyright (c) 2005 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _my_plugin_ftparser_h +#define _my_plugin_ftparser_h +#include "plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************* + API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN) +*/ + +#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0100 + +/* Parsing modes. Set in MYSQL_FTPARSER_PARAM::mode */ +enum enum_ftparser_mode +{ +/* + Fast and simple mode. This mode is used for indexing, and natural + language queries. + + The parser is expected to return only those words that go into the + index. Stopwords or too short/long words should not be returned. The + 'boolean_info' argument of mysql_add_word() does not have to be set. +*/ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + +/* + Parse with stopwords mode. This mode is used in boolean searches for + "phrase matching." + + The parser is not allowed to ignore words in this mode. Every word + should be returned, including stopwords and words that are too short + or long. The 'boolean_info' argument of mysql_add_word() does not + have to be set. +*/ + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + +/* + Parse in boolean mode. This mode is used to parse a boolean query string. + + The parser should provide a valid MYSQL_FTPARSER_BOOLEAN_INFO + structure in the 'boolean_info' argument to mysql_add_word(). + Usually that means that the parser should recognize boolean operators + in the parsing stream and set appropriate fields in + MYSQL_FTPARSER_BOOLEAN_INFO structure accordingly. As for + MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored. + Instead, use FT_TOKEN_STOPWORD for the token type of such a word. +*/ + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; + +/* + Token types for boolean mode searching (used for the type member of + MYSQL_FTPARSER_BOOLEAN_INFO struct) + + FT_TOKEN_EOF: End of data. + FT_TOKEN_WORD: Regular word. + FT_TOKEN_LEFT_PAREN: Left parenthesis (start of group/sub-expression). + FT_TOKEN_RIGHT_PAREN: Right parenthesis (end of group/sub-expression). + FT_TOKEN_STOPWORD: Stopword. +*/ + +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; + +/* + This structure is used in boolean search mode only. It conveys + boolean-mode metadata to the MySQL search engine for every word in + the search query. A valid instance of this structure must be filled + in by the plugin parser and passed as an argument in the call to + mysql_add_word (the callback function in the MYSQL_FTPARSER_PARAM + structure) when a query is parsed in boolean mode. + + type: The token type. Should be one of the enum_ft_token_type values. + + yesno: Whether the word must be present for a match to occur: + >0 Must be present + <0 Must not be present + 0 Neither; the word is optional but its presence increases the relevance + With the default settings of the ft_boolean_syntax system variable, + >0 corresponds to the '+' operator, <0 corresponds to the '-' operator, + and 0 means neither operator was used. + + weight_adjust: A weighting factor that determines how much a match + for the word counts. Positive values increase, negative - decrease the + relative word's importance in the query. + + wasign: The sign of the word's weight in the query. If it's non-negative + the match for the word will increase document relevance, if it's + negative - decrease (the word becomes a "noise word", the less of it the + better). + + trunc: Corresponds to the '*' operator in the default setting of the + ft_boolean_syntax system variable. +*/ + +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + /* These are parser state and must be removed. */ + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; + +/* + The following flag means that buffer with a string (document, word) + may be overwritten by the caller before the end of the parsing (that is + before st_mysql_ftparser::deinit() call). If one needs the string + to survive between two successive calls of the parsing function, she + needs to save a copy of it. The flag may be set by MySQL before calling + st_mysql_ftparser::parse(), or it may be set by a plugin before calling + st_mysql_ftparser_param::mysql_parse() or + st_mysql_ftparser_param::mysql_add_word(). +*/ +#define MYSQL_FTFLAGS_NEED_COPY 1 + +/* + An argument of the full-text parser plugin. This structure is + filled in by MySQL server and passed to the parsing function of the + plugin as an in/out parameter. + + mysql_parse: A pointer to the built-in parser implementation of the + server. It's set by the server and can be used by the parser plugin + to invoke the MySQL default parser. If plugin's role is to extract + textual data from .doc, .pdf or .xml content, it might extract + plaintext from the content, and then pass the text to the default + MySQL parser to be parsed. + + mysql_add_word: A server callback to add a new word. When parsing + a document, the server sets this to point at a function that adds + the word to MySQL full-text index. When parsing a search query, + this function will add the new word to the list of words to search + for. The boolean_info argument can be NULL for all cases except + when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO. A plugin can replace this + callback to post-process every parsed word before passing it to the original + mysql_add_word function. + + ftparser_state: A generic pointer. The plugin can set it to point + to information to be used internally for its own purposes. + + mysql_ftparam: This is set by the server. It is used by MySQL functions + called via mysql_parse() and mysql_add_word() callback. The plugin + should not modify it. + + cs: Information about the character set of the document or query string. + + doc: A pointer to the document or query string to be parsed. + + length: Length of the document or query string, in bytes. + + flags: See MYSQL_FTFLAGS_* constants above. + + mode: The parsing mode. With boolean operators, with stopwords, or + nothing. See enum_ftparser_mode above. +*/ + +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; + +/* + Full-text parser descriptor. + + interface_version is, e.g., MYSQL_FTPARSER_INTERFACE_VERSION. + The parsing, initialization, and deinitialization functions are + invoked per SQL statement for which the parser is used. +*/ + +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp new file mode 100644 index 00000000..919c9aae --- /dev/null +++ b/include/mysql/plugin_ftparser.h.pp @@ -0,0 +1,662 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} diff --git a/include/mysql/plugin_function.h b/include/mysql/plugin_function.h new file mode 100644 index 00000000..117acd43 --- /dev/null +++ b/include/mysql/plugin_function.h @@ -0,0 +1,54 @@ +#ifndef MARIADB_PLUGIN_FUNCTION_INCLUDED +#define MARIADB_PLUGIN_FUNCTION_INCLUDED +/* Copyright (C) 2019, Alexander Barkov and MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Function Plugin API. + + This file defines the API for server plugins that manage functions. +*/ + +#ifdef __cplusplus + +#include <mysql/plugin.h> + +/* + API for function plugins. (MariaDB_FUNCTION_PLUGIN) +*/ +#define MariaDB_FUNCTION_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + + +class Plugin_function +{ + int m_interface_version; + Create_func *m_builder; +public: + Plugin_function(Create_func *builder) + :m_interface_version(MariaDB_FUNCTION_INTERFACE_VERSION), + m_builder(builder) + { } + Create_func *create_func() + { + return m_builder; + } +}; + + +#endif /* __cplusplus */ + +#endif /* MARIADB_PLUGIN_FUNCTION_INCLUDED */ diff --git a/include/mysql/plugin_function.h.pp b/include/mysql/plugin_function.h.pp new file mode 100644 index 00000000..f5b22dbd --- /dev/null +++ b/include/mysql/plugin_function.h.pp @@ -0,0 +1,676 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +class Plugin_function +{ + int m_interface_version; + Create_func *m_builder; +public: + Plugin_function(Create_func *builder) + :m_interface_version((MYSQL_VERSION_ID << 8)), + m_builder(builder) + { } + Create_func *create_func() + { + return m_builder; + } +}; diff --git a/include/mysql/plugin_password_validation.h b/include/mysql/plugin_password_validation.h new file mode 100644 index 00000000..94d6c639 --- /dev/null +++ b/include/mysql/plugin_password_validation.h @@ -0,0 +1,55 @@ +#ifndef MYSQL_PLUGIN_PASSWORD_VALIDATION_INCLUDED +/* Copyright (C) 2014 Sergei Golubchik and MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Password Validation Plugin API. + + This file defines the API for server password validation plugins. +*/ + +#define MYSQL_PLUGIN_PASSWORD_VALIDATION_INCLUDED + +#include <mysql/plugin.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MariaDB_PASSWORD_VALIDATION_INTERFACE_VERSION 0x0101 + +/** + Password validation plugin descriptor +*/ +struct st_mariadb_password_validation +{ + int interface_version; /**< version plugin uses */ + /** + Function provided by the plugin which should perform password validation + and return 0 if the password has passed the validation. + */ + int (*validate_password)(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password, + const MYSQL_CONST_LEX_STRING *hostname); +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp new file mode 100644 index 00000000..115cbf26 --- /dev/null +++ b/include/mysql/plugin_password_validation.h.pp @@ -0,0 +1,671 @@ +class THD; +class Item; +typedef char my_bool; +typedef void * MYSQL_PLUGIN; +extern "C" { +extern "C" { +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; +int my_base64_needed_encoded_length(int length_of_data); +int my_base64_encode_max_arg_length(void); +int my_base64_needed_decoded_length(int length_of_encoded_data); +int my_base64_decode_max_arg_length(); +int my_base64_encode(const void *src, size_t src_len, char *dst); +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} +extern "C" { +extern void (*debug_sync_C_callback_ptr)(THD*, const char *, size_t); +} +extern "C" { +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; +extern struct encryption_service_st encryption_handler; +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0); +} +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0); +} +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) + return res1; + res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} +} +extern "C" { +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[16]; +}; +struct st_encryption_scheme { + unsigned char iv[16]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + void (*locker)(struct st_encryption_scheme *self, int release); +}; +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} +extern "C" { +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, + THD_ABORT_ASAP=100, +}; +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const THD*); +} *thd_kill_statement_service; +enum thd_kill_levels thd_kill_level(const THD*); +} +extern "C" { +typedef struct logger_handle_st LOGGER_HANDLE; +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +} +extern "C" { +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); +} +extern "C" { +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +}; +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +} +extern "C" { +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +} +extern "C" { +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); +} +extern "C" { +extern struct progress_report_service_st { + void (*thd_progress_init_func)(THD* thd, unsigned int max_stage); + void (*thd_progress_report_func)(THD* thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(THD* thd); + void (*thd_progress_end_func)(THD* thd); + const char *(*set_thd_proc_info_func)(THD*, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; +void thd_progress_init(THD* thd, unsigned int max_stage); +void thd_progress_report(THD* thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(THD* thd); +void thd_progress_end(THD* thd); +const char *set_thd_proc_info(THD*, const char * info, const char *func, + const char *file, unsigned int line); +} +extern "C" { +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); +} +extern "C" { +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); +} +extern "C" { +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(THD*, size_t); + void *(*thd_calloc_func)(THD*, size_t); + char *(*thd_strdup_func)(THD*, const char *); + char *(*thd_strmake_func)(THD*, const char *, size_t); + void *(*thd_memdup_func)(THD*, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(THD*, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; +void *thd_alloc(THD* thd, size_t size); +void *thd_calloc(THD* thd, size_t size); +char *thd_strdup(THD* thd, const char *str); +char *thd_strmake(THD* thd, const char *str, size_t size); +void *thd_memdup(THD* thd, const void* str, size_t size); +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(THD* thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); +} +extern "C" { +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const THD* thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; +void thd_get_autoinc(const THD* thd, + unsigned long* off, unsigned long* inc); +} +extern "C" { +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const THD* thd); + unsigned int (*thd_get_error_number_func)(const THD* thd); + unsigned long (*thd_get_error_row_func)(const THD* thd); + void (*thd_inc_error_row_func)(THD* thd); + char *(*thd_get_error_context_description_func)(THD* thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; +const char *thd_get_error_message(const THD* thd); +unsigned int thd_get_error_number(const THD* thd); +unsigned long thd_get_error_row(const THD* thd); +void thd_inc_error_row(THD* thd); +char *thd_get_error_context_description(THD* thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +} +extern "C" { +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(THD* thd); + void (*thd_c_r_p_ptr)(THD* thd, char *to, size_t length); +} *thd_rnd_service; +double thd_rnd(THD* thd); +void thd_create_random_password(THD* thd, char *to, size_t length); +} +extern "C" { +typedef int MYSQL_THD_KEY_T; +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(THD* thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(THD* thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; +int thd_key_create(MYSQL_THD_KEY_T *key); +void thd_key_delete(MYSQL_THD_KEY_T *key); +void* thd_getspecific(THD* thd, MYSQL_THD_KEY_T key); +int thd_setspecific(THD* thd, MYSQL_THD_KEY_T key, void *value); +} +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern "C" { +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(THD* thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(THD* thd, MYSQL_TIME *ltime, my_time_t t); +} +extern "C" { +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(THD*, int); + void (*thd_wait_end_func)(THD*); +} *thd_wait_service; +void thd_wait_begin(THD* thd, int wait_type); +void thd_wait_end(THD* thd); +} +extern "C" { +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); +} +extern "C" { +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); +} +} +struct st_mysql_xid { + long formatID; + long gtrid_length; + long bqual_length; + char data[128]; +}; +typedef struct st_mysql_xid MYSQL_XID; +enum enum_mysql_show_type +{ + SHOW_UNDEF, SHOW_BOOL, SHOW_UINT, SHOW_ULONG, + SHOW_ULONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, + SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE, + SHOW_SINT, SHOW_SLONG, SHOW_SLONGLONG, SHOW_SIMPLE_FUNC, + SHOW_SIZE_T, SHOW_always_last +}; +enum enum_var_type +{ + SHOW_OPT_DEFAULT= 0, SHOW_OPT_SESSION, SHOW_OPT_GLOBAL +}; +struct st_mysql_show_var { + const char *name; + void *value; + enum enum_mysql_show_type type; +}; +struct system_status_var; +typedef int (*mysql_show_var_func)(THD*, struct st_mysql_show_var*, void *, struct system_status_var *status_var, enum enum_var_type); +static inline +struct st_mysql_show_var SHOW_FUNC_ENTRY(const char *name, + mysql_show_var_func func_arg) +{ + struct st_mysql_show_var tmp; + tmp.name= name; + tmp.value= (void*) func_arg; + tmp.type= SHOW_FUNC; + return tmp; +}; +struct st_mysql_sys_var; +struct st_mysql_value; +typedef int (*mysql_var_check_func)(THD* thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(THD* thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save); +struct st_mysql_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + void * __reserved1; + unsigned long flags; +}; +struct st_maria_plugin +{ + int type; + void *info; + const char *name; + const char *author; + const char *descr; + int license; + int (*init)(void *); + int (*deinit)(void *); + unsigned int version; + struct st_mysql_show_var *status_vars; + struct st_mysql_sys_var **system_vars; + const char *version_info; + unsigned int maturity; +}; +extern "C" { +enum enum_ftparser_mode +{ + MYSQL_FTPARSER_SIMPLE_MODE= 0, + MYSQL_FTPARSER_WITH_STOPWORDS= 1, + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; +enum enum_ft_token_type +{ + FT_TOKEN_EOF= 0, + FT_TOKEN_WORD= 1, + FT_TOKEN_LEFT_PAREN= 2, + FT_TOKEN_RIGHT_PAREN= 3, + FT_TOKEN_STOPWORD= 4 +}; +typedef struct st_mysql_ftparser_boolean_info +{ + enum enum_ft_token_type type; + int yesno; + int weight_adjust; + char wasign; + char trunc; + char prev; + char *quot; +} MYSQL_FTPARSER_BOOLEAN_INFO; +typedef struct st_mysql_ftparser_param +{ + int (*mysql_parse)(struct st_mysql_ftparser_param *, + const char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + const char *word, int word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); + void *ftparser_state; + void *mysql_ftparam; + const struct charset_info_st *cs; + const char *doc; + int length; + unsigned int flags; + enum enum_ftparser_mode mode; +} MYSQL_FTPARSER_PARAM; +struct st_mysql_ftparser +{ + int interface_version; + int (*parse)(MYSQL_FTPARSER_PARAM *param); + int (*init)(MYSQL_FTPARSER_PARAM *param); + int (*deinit)(MYSQL_FTPARSER_PARAM *param); +}; +} +struct st_mysql_daemon +{ + int interface_version; +}; +struct st_mysql_information_schema +{ + int interface_version; +}; +struct st_mysql_storage_engine +{ + int interface_version; +}; +struct handlerton; + struct Mysql_replication { + int interface_version; + }; +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, double *realbuf); + int (*val_int)(struct st_mysql_value *, long long *intbuf); + int (*is_unsigned)(struct st_mysql_value *); +}; +extern "C" { +int thd_in_lock_tables(const THD* thd); +int thd_tablespace_op(const THD* thd); +long long thd_test_options(const THD* thd, long long test_options); +int thd_sql_command(const THD* thd); +struct DDL_options_st; +struct DDL_options_st *thd_ddl_options(const THD* thd); +void thd_storage_lock_wait(THD* thd, long long value); +int thd_tx_isolation(const THD* thd); +int thd_tx_is_read_only(const THD* thd); +int mysql_tmpfile(const char *prefix); +unsigned long thd_get_thread_id(const THD* thd); +void thd_get_xid(const THD* thd, MYSQL_XID *xid); +void mysql_query_cache_invalidate4(THD* thd, + const char *key, unsigned int key_length, + int using_trx); +void *thd_get_ha_data(const THD* thd, const struct handlerton *hton); +void thd_set_ha_data(THD* thd, const struct handlerton *hton, + const void *ha_data); +void thd_wakeup_subsequent_commits(THD* thd, int wakeup_error); +} +extern "C" { +struct st_mariadb_password_validation +{ + int interface_version; + int (*validate_password)(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password, + const MYSQL_CONST_LEX_STRING *hostname); +}; +} diff --git a/include/mysql/psi/mysql_file.h b/include/mysql/psi/mysql_file.h new file mode 100644 index 00000000..fd3b29cc --- /dev/null +++ b/include/mysql/psi/mysql_file.h @@ -0,0 +1,1454 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_FILE_H +#define MYSQL_FILE_H + +/* For strlen() */ +#include <string.h> +/* For MY_STAT */ +#include <my_dir.h> +/* For my_chsize */ +#include <my_sys.h> + +/** + @file mysql/psi/mysql_file.h + Instrumentation helpers for mysys file io. + This header file provides the necessary declarations + to use the mysys file API with the performance schema instrumentation. + In some compilers (SunStudio), 'static inline' functions, when declared + but not used, are not optimized away (because they are unused) by default, + so that including a static inline function from a header file does + create unwanted dependencies, causing unresolved symbols at link time. + Other compilers, like gcc, optimize these dependencies by default. + + Since the instrumented APIs declared here are wrapper on top + of mysys file io APIs, including mysql/psi/mysql_file.h assumes that + the dependency on my_sys already exists. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_FILE_CALL +#define PSI_FILE_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup File_instrumentation File Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_file_register(P1, P2, P3) + File registration. +*/ +#define mysql_file_register(P1, P2, P3) \ + inline_mysql_file_register(P1, P2, P3) + +/** + @def mysql_file_fgets(P1, P2, F) + Instrumented fgets. + @c mysql_file_fgets is a replacement for @c fgets. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fgets(P1, P2, F) \ + inline_mysql_file_fgets(__FILE__, __LINE__, P1, P2, F) +#else + #define mysql_file_fgets(P1, P2, F) \ + inline_mysql_file_fgets(P1, P2, F) +#endif + +/** + @def mysql_file_fgetc(F) + Instrumented fgetc. + @c mysql_file_fgetc is a replacement for @c fgetc. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fgetc(F) inline_mysql_file_fgetc(__FILE__, __LINE__, F) +#else + #define mysql_file_fgetc(F) inline_mysql_file_fgetc(F) +#endif + +/** + @def mysql_file_fputs(P1, F) + Instrumented fputs. + @c mysql_file_fputs is a replacement for @c fputs. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fputs(P1, F) \ + inline_mysql_file_fputs(__FILE__, __LINE__, P1, F) +#else + #define mysql_file_fputs(P1, F)\ + inline_mysql_file_fputs(P1, F) +#endif + +/** + @def mysql_file_fputc(P1, F) + Instrumented fputc. + @c mysql_file_fputc is a replacement for @c fputc. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fputc(P1, F) \ + inline_mysql_file_fputc(__FILE__, __LINE__, P1, F) +#else + #define mysql_file_fputc(P1, F) \ + inline_mysql_file_fputc(P1, F) +#endif + +/** + @def mysql_file_fprintf + Instrumented fprintf. + @c mysql_file_fprintf is a replacement for @c fprintf. +*/ +#define mysql_file_fprintf inline_mysql_file_fprintf + +/** + @def mysql_file_vfprintf(F, P1, P2) + Instrumented vfprintf. + @c mysql_file_vfprintf is a replacement for @c vfprintf. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_vfprintf(F, P1, P2) \ + inline_mysql_file_vfprintf(__FILE__, __LINE__, F, P1, P2) +#else + #define mysql_file_vfprintf(F, P1, P2) \ + inline_mysql_file_vfprintf(F, P1, P2) +#endif + +/** + @def mysql_file_fflush(F, P1, P2) + Instrumented fflush. + @c mysql_file_fflush is a replacement for @c fflush. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fflush(F) \ + inline_mysql_file_fflush(__FILE__, __LINE__, F) +#else + #define mysql_file_fflush(F) \ + inline_mysql_file_fflush(F) +#endif + +/** + @def mysql_file_feof(F) + Instrumented feof. + @c mysql_file_feof is a replacement for @c feof. +*/ +#define mysql_file_feof(F) inline_mysql_file_feof(F) + +/** + @def mysql_file_fstat(FN, S, FL) + Instrumented fstat. + @c mysql_file_fstat is a replacement for @c my_fstat. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fstat(FN, S, FL) \ + inline_mysql_file_fstat(__FILE__, __LINE__, FN, S, FL) +#else + #define mysql_file_fstat(FN, S, FL) \ + inline_mysql_file_fstat(FN, S, FL) +#endif + +/** + @def mysql_file_stat(K, FN, S, FL) + Instrumented stat. + @c mysql_file_stat is a replacement for @c my_stat. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_stat(K, FN, S, FL) \ + inline_mysql_file_stat(K, __FILE__, __LINE__, FN, S, FL) +#else + #define mysql_file_stat(K, FN, S, FL) \ + inline_mysql_file_stat(FN, S, FL) +#endif + +/** + @def mysql_file_chsize(F, P1, P2, P3) + Instrumented chsize. + @c mysql_file_chsize is a replacement for @c my_chsize. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_chsize(F, P1, P2, P3) \ + inline_mysql_file_chsize(__FILE__, __LINE__, F, P1, P2, P3) +#else + #define mysql_file_chsize(F, P1, P2, P3) \ + inline_mysql_file_chsize(F, P1, P2, P3) +#endif + +/** + @def mysql_file_fopen(K, N, F1, F2) + Instrumented fopen. + @c mysql_file_fopen is a replacement for @c my_fopen. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fopen(K, N, F1, F2) \ + inline_mysql_file_fopen(K, __FILE__, __LINE__, N, F1, F2) +#else + #define mysql_file_fopen(K, N, F1, F2) \ + inline_mysql_file_fopen(N, F1, F2) +#endif + +/** + @def mysql_file_fclose(FD, FL) + Instrumented fclose. + @c mysql_file_fclose is a replacement for @c my_fclose. + Without the instrumentation, this call will have the same behavior as the + undocumented and possibly platform specific my_fclose(NULL, ...) behavior. + With the instrumentation, mysql_fclose(NULL, ...) will safely return 0, + which is an extension compared to my_fclose and is therefore compliant. + mysql_fclose is on purpose *not* implementing + @code assert(file != NULL) @endcode, + since doing so could introduce regressions. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fclose(FD, FL) \ + inline_mysql_file_fclose(__FILE__, __LINE__, FD, FL) +#else + #define mysql_file_fclose(FD, FL) \ + inline_mysql_file_fclose(FD, FL) +#endif + +/** + @def mysql_file_fread(FD, P1, P2, P3) + Instrumented fread. + @c mysql_file_fread is a replacement for @c my_fread. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fread(FD, P1, P2, P3) \ + inline_mysql_file_fread(__FILE__, __LINE__, FD, P1, P2, P3) +#else + #define mysql_file_fread(FD, P1, P2, P3) \ + inline_mysql_file_fread(FD, P1, P2, P3) +#endif + +/** + @def mysql_file_fwrite(FD, P1, P2, P3) + Instrumented fwrite. + @c mysql_file_fwrite is a replacement for @c my_fwrite. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fwrite(FD, P1, P2, P3) \ + inline_mysql_file_fwrite(__FILE__, __LINE__, FD, P1, P2, P3) +#else + #define mysql_file_fwrite(FD, P1, P2, P3) \ + inline_mysql_file_fwrite(FD, P1, P2, P3) +#endif + +/** + @def mysql_file_fseek(FD, P, W, F) + Instrumented fseek. + @c mysql_file_fseek is a replacement for @c my_fseek. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_fseek(FD, P, W, F) \ + inline_mysql_file_fseek(__FILE__, __LINE__, FD, P, W, F) +#else + #define mysql_file_fseek(FD, P, W, F) \ + inline_mysql_file_fseek(FD, P, W, F) +#endif + +/** + @def mysql_file_ftell(FD, F) + Instrumented ftell. + @c mysql_file_ftell is a replacement for @c my_ftell. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_ftell(FD, F) \ + inline_mysql_file_ftell(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_ftell(FD, F) \ + inline_mysql_file_ftell(FD, F) +#endif + +/** + @def mysql_file_create(K, N, F1, F2, F3) + Instrumented create. + @c mysql_file_create is a replacement for @c my_create. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_create(K, N, F1, F2, F3) \ + inline_mysql_file_create(K, __FILE__, __LINE__, N, F1, F2, F3) +#else + #define mysql_file_create(K, N, F1, F2, F3) \ + inline_mysql_file_create(N, F1, F2, F3) +#endif + +/** + @def mysql_file_create_temp(K, T, D, P, M, F) + Instrumented create_temp_file. + @c mysql_file_create_temp is a replacement for @c create_temp_file. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_create_temp(K, T, D, P, M, F) \ + inline_mysql_file_create_temp(K, __FILE__, __LINE__, T, D, P, M, F) +#else + #define mysql_file_create_temp(K, T, D, P, M, F) \ + inline_mysql_file_create_temp(T, D, P, M, F) +#endif + +/** + @def mysql_file_open(K, N, F1, F2) + Instrumented open. + @c mysql_file_open is a replacement for @c my_open. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_open(K, N, F1, F2) \ + inline_mysql_file_open(K, __FILE__, __LINE__, N, F1, F2) +#else + #define mysql_file_open(K, N, F1, F2) \ + inline_mysql_file_open(N, F1, F2) +#endif + +/** + @def mysql_file_close(FD, F) + Instrumented close. + @c mysql_file_close is a replacement for @c my_close. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_close(FD, F) \ + inline_mysql_file_close(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_close(FD, F) \ + inline_mysql_file_close(FD, F) +#endif + +/** + @def mysql_file_read(FD, B, S, F) + Instrumented read. + @c mysql_read is a replacement for @c my_read. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_read(FD, B, S, F) \ + inline_mysql_file_read(__FILE__, __LINE__, FD, B, S, F) +#else + #define mysql_file_read(FD, B, S, F) \ + inline_mysql_file_read(FD, B, S, F) +#endif + +/** + @def mysql_file_write(FD, B, S, F) + Instrumented write. + @c mysql_file_write is a replacement for @c my_write. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_write(FD, B, S, F) \ + inline_mysql_file_write(__FILE__, __LINE__, FD, B, S, F) +#else + #define mysql_file_write(FD, B, S, F) \ + inline_mysql_file_write(FD, B, S, F) +#endif + +/** + @def mysql_file_pread(FD, B, S, O, F) + Instrumented pread. + @c mysql_pread is a replacement for @c my_pread. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_pread(FD, B, S, O, F) \ + inline_mysql_file_pread(__FILE__, __LINE__, FD, B, S, O, F) +#else + #define mysql_file_pread(FD, B, S, O, F) \ + inline_mysql_file_pread(FD, B, S, O, F) +#endif + +/** + @def mysql_file_pwrite(FD, B, S, O, F) + Instrumented pwrite. + @c mysql_file_pwrite is a replacement for @c my_pwrite. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_pwrite(FD, B, S, O, F) \ + inline_mysql_file_pwrite(__FILE__, __LINE__, FD, B, S, O, F) +#else + #define mysql_file_pwrite(FD, B, S, O, F) \ + inline_mysql_file_pwrite(FD, B, S, O, F) +#endif + +/** + @def mysql_file_seek(FD, P, W, F) + Instrumented seek. + @c mysql_file_seek is a replacement for @c my_seek. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_seek(FD, P, W, F) \ + inline_mysql_file_seek(__FILE__, __LINE__, FD, P, W, F) +#else + #define mysql_file_seek(FD, P, W, F) \ + inline_mysql_file_seek(FD, P, W, F) +#endif + +/** + @def mysql_file_tell(FD, F) + Instrumented tell. + @c mysql_file_tell is a replacement for @c my_tell. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_tell(FD, F) \ + inline_mysql_file_tell(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_tell(FD, F) \ + inline_mysql_file_tell(FD, F) +#endif + +/** + @def mysql_file_delete(K, P1, P2) + Instrumented delete. + @c mysql_file_delete is a replacement for @c my_delete. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_delete(K, P1, P2) \ + inline_mysql_file_delete(K, __FILE__, __LINE__, P1, P2) +#else + #define mysql_file_delete(K, P1, P2) \ + inline_mysql_file_delete(P1, P2) +#endif + +/** + @def mysql_file_rename(K, P1, P2, P3) + Instrumented rename. + @c mysql_file_rename is a replacement for @c my_rename. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_rename(K, P1, P2, P3) \ + inline_mysql_file_rename(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_rename(K, P1, P2, P3) \ + inline_mysql_file_rename(P1, P2, P3) +#endif + +/** + @def mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) + Instrumented create with symbolic link. + @c mysql_file_create_with_symlink is a replacement + for @c my_create_with_symlink. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) \ + inline_mysql_file_create_with_symlink(K, __FILE__, __LINE__, \ + P1, P2, P3, P4, P5) +#else + #define mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) \ + inline_mysql_file_create_with_symlink(P1, P2, P3, P4, P5) +#endif + +/** + @def mysql_file_delete_with_symlink(K, P1, P2, P3) + Instrumented delete with symbolic link. + @c mysql_file_delete_with_symlink is a replacement + for @c my_handler_delete_with_symlink. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_delete_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_delete_with_symlink(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_delete_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_delete_with_symlink(P1, P2, P3) +#endif + +/** + @def mysql_file_rename_with_symlink(K, P1, P2, P3) + Instrumented rename with symbolic link. + @c mysql_file_rename_with_symlink is a replacement + for @c my_rename_with_symlink. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_rename_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_rename_with_symlink(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_rename_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_rename_with_symlink(P1, P2, P3) +#endif + +/** + @def mysql_file_sync(P1, P2) + Instrumented file sync. + @c mysql_file_sync is a replacement for @c my_sync. +*/ +#ifdef HAVE_PSI_FILE_INTERFACE + #define mysql_file_sync(P1, P2) \ + inline_mysql_file_sync(__FILE__, __LINE__, P1, P2) +#else + #define mysql_file_sync(P1, P2) \ + inline_mysql_file_sync(P1, P2) +#endif + +/** + An instrumented FILE structure. + @sa MYSQL_FILE +*/ +struct st_mysql_file +{ + /** The real file. */ + FILE *m_file; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c MYSQL_FILE interface. + */ + struct PSI_file *m_psi; +}; + +/** + Type of an instrumented file. + @c MYSQL_FILE is a drop-in replacement for @c FILE. + @sa mysql_file_open +*/ +typedef struct st_mysql_file MYSQL_FILE; + +static inline void inline_mysql_file_register( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *category, + PSI_file_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_FILE_CALL(register_file)(category, info, count); +#endif +} + +static inline char * +inline_mysql_file_fgets( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + char *str, int size, MYSQL_FILE *file) +{ + char *result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_READ); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) size, src_file, src_line); + result= fgets(str, size, file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, result ? strlen(result) : 0); + return result; + } + } +#endif + + result= fgets(str, size, file->m_file); + return result; +} + +static inline int +inline_mysql_file_fgetc( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_READ); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line); + result= fgetc(file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 1); + return result; + } + } +#endif + + result= fgetc(file->m_file); + return result; +} + +static inline int +inline_mysql_file_fputs( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + const char *str, MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + bytes= str ? strlen(str) : 0; + PSI_FILE_CALL(start_file_wait)(locker, bytes, src_file, src_line); + result= fputs(str, file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, bytes); + return result; + } + } +#endif + + result= fputs(str, file->m_file); + return result; +} + +static inline int +inline_mysql_file_fputc( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + char c, MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line); + result= fputc(c, file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 1); + return result; + } + } +#endif + + result= fputc(c, file->m_file); + return result; +} + +static inline int +inline_mysql_file_fprintf(MYSQL_FILE *file, const char *format, ...) +{ + /* + TODO: figure out how to pass src_file and src_line from the caller. + */ + int result; + va_list args; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, __FILE__, __LINE__); + va_start(args, format); + result= vfprintf(file->m_file, format, args); + va_end(args); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) result); + return result; + } + } +#endif + + va_start(args, format); + result= vfprintf(file->m_file, format, args); + va_end(args); + return result; +} + +static inline int +inline_mysql_file_vfprintf( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, const char *format, va_list args) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker) (&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= vfprintf(file->m_file, format, args); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) result); + return result; + } + } +#endif + + result= vfprintf(file->m_file, format, args); + return result; +} + +static inline int +inline_mysql_file_fflush( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_FLUSH); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= fflush(file->m_file); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } + } +#endif + + result= fflush(file->m_file); + return result; +} + +static inline int inline_mysql_file_feof(MYSQL_FILE *file) +{ + /* Not instrumented, there is no wait involved */ + return feof(file->m_file); +} + +static inline int +inline_mysql_file_fstat( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + int filenr, MY_STAT *stat_area, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, filenr, PSI_FILE_FSTAT); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_fstat(filenr, stat_area, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } +#endif + + result= my_fstat(filenr, stat_area, flags); + return result; +} + +static inline MY_STAT * +inline_mysql_file_stat( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *path, MY_STAT *stat_area, myf flags) +{ + MY_STAT *result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_STAT, path, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + result= my_stat(path, stat_area, flags); + PSI_FILE_CALL(end_file_open_wait)(locker, result); + return result; + } +#endif + + result= my_stat(path, stat_area, flags); + return result; +} + +static inline int +inline_mysql_file_chsize( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, my_off_t newlength, int filler, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_CHSIZE); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) newlength, src_file, + src_line); + result= my_chsize(file, newlength, filler, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) newlength); + return result; + } +#endif + + result= my_chsize(file, newlength, filler, flags); + return result; +} + +static inline MYSQL_FILE* +inline_mysql_file_fopen( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int flags, myf myFlags) +{ + MYSQL_FILE *that; + that= (MYSQL_FILE*) my_malloc(PSI_NOT_INSTRUMENTED, + sizeof(MYSQL_FILE), MYF(MY_WME)); + if (likely(that != NULL)) + { +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_STREAM_OPEN, + filename, that); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + that->m_file= my_fopen(filename, flags, myFlags); + that->m_psi= PSI_FILE_CALL(end_file_open_wait)(locker, that->m_file); + if (unlikely(that->m_file == NULL)) + { + my_free(that); + return NULL; + } + return that; + } +#endif + + that->m_psi= NULL; + that->m_file= my_fopen(filename, flags, myFlags); + if (unlikely(that->m_file == NULL)) + { + my_free(that); + return NULL; + } + } + return that; +} + +static inline int +inline_mysql_file_fclose( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, myf flags) +{ + int result= 0; + if (likely(file != NULL)) + { +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, + PSI_FILE_STREAM_CLOSE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); + result= my_fclose(file->m_file, flags); + PSI_FILE_CALL(end_file_close_wait)(locker, result); + my_free(file); + return result; + } + } +#endif + + result= my_fclose(file->m_file, flags); + my_free(file); + } + return result; +} + +static inline size_t +inline_mysql_file_fread( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_read; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_READ); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_fread(file->m_file, buffer, count, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_read); + return result; + } + } +#endif + + result= my_fread(file->m_file, buffer, count, flags); + return result; +} + +static inline size_t +inline_mysql_file_fwrite( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, const uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_written; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_fwrite(file->m_file, buffer, count, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_written); + return result; + } + } +#endif + + result= my_fwrite(file->m_file, buffer, count, flags); + return result; +} + +static inline my_off_t +inline_mysql_file_fseek( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, my_off_t pos, int whence, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_SEEK); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_fseek(file->m_file, pos, whence, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } + } +#endif + + result= my_fseek(file->m_file, pos, whence, flags); + return result; +} + +static inline my_off_t +inline_mysql_file_ftell( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + if (psi_likely(file->m_psi)) + { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_stream_locker)(&state, file->m_psi, PSI_FILE_TELL); + if (likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_ftell(file->m_file, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } + } +#endif + + result= my_ftell(file->m_file, flags); + return result; +} + +static inline File +inline_mysql_file_create( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int create_flags, int access_flags, myf myFlags) +{ + File file; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_CREATE, filename, + &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + file= my_create(filename, create_flags, access_flags, myFlags); + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); + return file; + } +#endif + + file= my_create(filename, create_flags, access_flags, myFlags); + return file; +} + +static inline File +inline_mysql_file_create_temp( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + char *to, const char *dir, const char *pfx, int mode, myf myFlags) +{ + File file; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker) + (&state, key, PSI_FILE_CREATE, NULL, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + /* The file name is generated by create_temp_file(). */ + file= create_temp_file(to, dir, pfx, mode, myFlags); + PSI_FILE_CALL(end_temp_file_open_wait_and_bind_to_descriptor)(locker, file, (const char*)to); + return file; + } +#endif + + file= create_temp_file(to, dir, pfx, mode, myFlags); + return file; +} + +static inline File +inline_mysql_file_open( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int flags, myf myFlags) +{ + File file; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_OPEN, filename, + &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + file= my_open(filename, flags, myFlags); + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); + return file; + } +#endif + + file= my_open(filename, flags, myFlags); + return file; +} + +static inline int +inline_mysql_file_close( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_CLOSE); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); + result= my_close(file, flags); + PSI_FILE_CALL(end_file_close_wait)(locker, result); + return result; + } +#endif + + result= my_close(file, flags); + return result; +} + +static inline size_t +inline_mysql_file_read( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_read; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_READ); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_read(file, buffer, count, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_read); + return result; + } +#endif + + result= my_read(file, buffer, count, flags); + return result; +} + +static inline size_t +inline_mysql_file_write( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, const uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_written; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_WRITE); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_write(file, buffer, count, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_written); + return result; + } +#endif + + result= my_write(file, buffer, count, flags); + return result; +} + +static inline size_t +inline_mysql_file_pread( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, uchar *buffer, size_t count, my_off_t offset, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_read; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_READ); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_pread(file, buffer, count, offset, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_read); + return result; + } +#endif + + result= my_pread(file, buffer, count, offset, flags); + return result; +} + +static inline size_t +inline_mysql_file_pwrite( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, const uchar *buffer, size_t count, my_off_t offset, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + size_t bytes_written; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_WRITE); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); + result= my_pwrite(file, buffer, count, offset, flags); + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_FILE_CALL(end_file_wait)(locker, bytes_written); + return result; + } +#endif + + result= my_pwrite(file, buffer, count, offset, flags); + return result; +} + +static inline my_off_t +inline_mysql_file_seek( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, my_off_t pos, int whence, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_SEEK); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_seek(file, pos, whence, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } +#endif + + result= my_seek(file, pos, whence, flags); + return result; +} + +static inline my_off_t +inline_mysql_file_tell( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File file, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_TELL); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_tell(file, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } +#endif + + result= my_tell(file, flags); + return result; +} + +static inline int +inline_mysql_file_delete( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *name, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE, name, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); + result= my_delete(name, flags); + PSI_FILE_CALL(end_file_close_wait)(locker, result); + return result; + } +#endif + + result= my_delete(name, flags); + return result; +} + +static inline int +inline_mysql_file_rename( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *from, const char *to, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker) + (&state, key, PSI_FILE_RENAME, from, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_rename(from, to, flags); + PSI_FILE_CALL(end_file_rename_wait)(locker, from, to, result); + return result; + } +#endif + + result= my_rename(from, to, flags); + return result; +} + + +static inline File +inline_mysql_file_create_with_symlink( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *linkname, const char *filename, int create_flags, + int access_flags, myf flags) +{ + File file; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_CREATE, filename, + &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); + file= my_create_with_symlink(linkname, filename, create_flags, access_flags, + flags); + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); + return file; + } +#endif + + file= my_create_with_symlink(linkname, filename, create_flags, access_flags, + flags); + return file; +} + + +static inline int +inline_mysql_file_delete_with_symlink( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *name, const char *ext, myf flags) +{ + int result; + char buf[FN_REFLEN]; + char *fullname= fn_format(buf, name, "", ext, MY_UNPACK_FILENAME | MY_APPEND_EXT); +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE, fullname, + &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); + result= my_handler_delete_with_symlink(fullname, flags); + PSI_FILE_CALL(end_file_close_wait)(locker, result); + return result; + } +#endif + + result= my_handler_delete_with_symlink(fullname, flags); + return result; +} + + +static inline int +inline_mysql_file_rename_with_symlink( +#ifdef HAVE_PSI_FILE_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *from, const char *to, myf flags) +{ + int result; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_name_locker) + (&state, key, PSI_FILE_RENAME, from, &locker); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_rename_with_symlink(from, to, flags); + PSI_FILE_CALL(end_file_rename_wait)(locker, from, to, result); + return result; + } +#endif + + result= my_rename_with_symlink(from, to, flags); + return result; +} + +static inline int +inline_mysql_file_sync( +#ifdef HAVE_PSI_FILE_INTERFACE + const char *src_file, uint src_line, +#endif + File fd, myf flags) +{ + int result= 0; +#ifdef HAVE_PSI_FILE_INTERFACE + struct PSI_file_locker *locker; + PSI_file_locker_state state; + locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)(&state, fd, PSI_FILE_SYNC); + if (psi_likely(locker != NULL)) + { + PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); + result= my_sync(fd, flags); + PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); + return result; + } +#endif + + result= my_sync(fd, flags); + return result; +} + +/** @} (end of group File_instrumentation) */ + +#endif diff --git a/include/mysql/psi/mysql_idle.h b/include/mysql/psi/mysql_idle.h new file mode 100644 index 00000000..dc7f5180 --- /dev/null +++ b/include/mysql/psi/mysql_idle.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2011, 2023, Oracle and/or its affiliates + Copyright (c) 2017, 2019, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_IDLE_H +#define MYSQL_IDLE_H + +/** + @file mysql/psi/mysql_idle.h + Instrumentation helpers for idle waits. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_IDLE_CALL +#define PSI_IDLE_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Idle_instrumentation Idle Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def MYSQL_START_IDLE_WAIT + Instrumentation helper for table io_waits. + This instrumentation marks the start of a wait event. + @param LOCKER the locker + @param STATE the locker state + @sa MYSQL_END_IDLE_WAIT. +*/ +#ifdef HAVE_PSI_IDLE_INTERFACE + #define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \ + LOCKER= inline_mysql_start_idle_wait(STATE, __FILE__, __LINE__) +#else + #define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \ + do {} while (0) +#endif + +/** + @def MYSQL_END_IDLE_WAIT + Instrumentation helper for idle waits. + This instrumentation marks the end of a wait event. + @param LOCKER the locker + @sa MYSQL_START_IDLE_WAIT. +*/ +#ifdef HAVE_PSI_IDLE_INTERFACE + #define MYSQL_END_IDLE_WAIT(LOCKER) \ + inline_mysql_end_idle_wait(LOCKER) +#else + #define MYSQL_END_IDLE_WAIT(LOCKER) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_IDLE_INTERFACE +/** + Instrumentation calls for MYSQL_START_IDLE_WAIT. + @sa MYSQL_END_IDLE_WAIT. +*/ +static inline struct PSI_idle_locker * +inline_mysql_start_idle_wait(PSI_idle_locker_state *state, + const char *src_file, uint src_line) +{ + struct PSI_idle_locker *locker; + locker= PSI_IDLE_CALL(start_idle_wait)(state, src_file, src_line); + return locker; +} + +/** + Instrumentation calls for MYSQL_END_IDLE_WAIT. + @sa MYSQL_START_IDLE_WAIT. +*/ +static inline void +inline_mysql_end_idle_wait(struct PSI_idle_locker *locker) +{ + if (psi_likely(locker != NULL)) + PSI_IDLE_CALL(end_idle_wait)(locker); +} +#endif + +/** @} (end of group Idle_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_mdl.h b/include/mysql/psi/mysql_mdl.h new file mode 100644 index 00000000..8721a191 --- /dev/null +++ b/include/mysql/psi/mysql_mdl.h @@ -0,0 +1,143 @@ +/* Copyright (c) 2012, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_MDL_H +#define MYSQL_MDL_H + +/** + @file mysql/psi/mysql_mdl.h + Instrumentation helpers for metadata locks. +*/ + +#include "mysql/psi/psi.h" + +#ifdef HAVE_PSI_METADATA_INTERFACE + +#ifndef PSI_METADATA_CALL +#define PSI_METADATA_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#define PSI_CALL_start_metadata_wait(A,B,C,D) PSI_METADATA_CALL(start_metadata_wait)(A,B,C,D) +#define PSI_CALL_end_metadata_wait(A,B) PSI_METADATA_CALL(end_metadata_wait)(A,B) +#define PSI_CALL_create_metadata_lock(A,B,C,D,E,F,G) PSI_METADATA_CALL(create_metadata_lock)(A,B,C,D,E,F,G) +#define PSI_CALL_set_metadata_lock_status(A,B) PSI_METADATA_CALL(set_metadata_lock_status)(A,B) +#define PSI_CALL_destroy_metadata_lock(A) PSI_METADATA_CALL(destroy_metadata_lock)(A) +#else +#define PSI_CALL_start_metadata_wait(A,B,C,D) 0 +#define PSI_CALL_end_metadata_wait(A,B) do { } while(0) +#define PSI_CALL_create_metadata_lock(A,B,C,D,E,F,G) 0 +#define PSI_CALL_set_metadata_lock_status(A,B) do {} while(0) +#define PSI_CALL_destroy_metadata_lock(A) do {} while(0) +#endif + +/** + @defgroup Thread_instrumentation Metadata Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_mdl_create(K, M, A) + Instrumented metadata lock creation. + @param I Metadata lock identity + @param K Metadata key + @param T Metadata lock type + @param D Metadata lock duration + @param S Metadata lock status + @param F request source file + @param L request source line +*/ + +#ifdef HAVE_PSI_METADATA_INTERFACE + #define mysql_mdl_create(I, K, T, D, S, F, L) \ + inline_mysql_mdl_create(I, K, T, D, S, F, L) +#else + #define mysql_mdl_create(I, K, T, D, S, F, L) NULL +#endif + +#ifdef HAVE_PSI_METADATA_INTERFACE + #define mysql_mdl_set_status(L, S) \ + inline_mysql_mdl_set_status(L, S) +#else + #define mysql_mdl_set_status(L, S) \ + do {} while (0) +#endif + + +/** + @def mysql_mdl_destroy(M) + Instrumented metadata lock destruction. + @param M Metadata lock +*/ +#ifdef HAVE_PSI_METADATA_INTERFACE + #define mysql_mdl_destroy(M) \ + inline_mysql_mdl_destroy(M, __FILE__, __LINE__) +#else + #define mysql_mdl_destroy(M) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_METADATA_INTERFACE + +static inline PSI_metadata_lock * +inline_mysql_mdl_create(void *identity, + const MDL_key *mdl_key, + enum_mdl_type mdl_type, + enum_mdl_duration mdl_duration, + MDL_ticket::enum_psi_status mdl_status, + const char *src_file, uint src_line) +{ + PSI_metadata_lock *result; + + /* static_cast: Fit a round C++ enum peg into a square C int hole ... */ + result= PSI_METADATA_CALL(create_metadata_lock) + (identity, + mdl_key, + static_cast<opaque_mdl_type> (mdl_type), + static_cast<opaque_mdl_duration> (mdl_duration), + static_cast<opaque_mdl_status> (mdl_status), + src_file, src_line); + + return result; +} + +static inline void inline_mysql_mdl_set_status( + PSI_metadata_lock *psi, + MDL_ticket::enum_psi_status mdl_status) +{ + if (psi != NULL) + PSI_METADATA_CALL(set_metadata_lock_status)(psi, mdl_status); +} + +static inline void inline_mysql_mdl_destroy( + PSI_metadata_lock *psi, + const char *src_file, uint src_line) +{ + if (psi != NULL) + PSI_METADATA_CALL(destroy_metadata_lock)(psi); +} +#endif /* HAVE_PSI_METADATA_INTERFACE */ + +/** @} (end of group Metadata_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_memory.h b/include/mysql/psi/mysql_memory.h new file mode 100644 index 00000000..7f54b00d --- /dev/null +++ b/include/mysql/psi/mysql_memory.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2012, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_MEMORY_H +#define MYSQL_MEMORY_H + +/** + @file mysql/psi/mysql_memory.h + Instrumentation helpers for memory allocation. +*/ + +#include "mysql/psi/psi.h" + +#ifdef HAVE_PSI_MEMORY_INTERFACE +#define PSI_CALL_memory_alloc(A1,A2,A3) PSI_MEMORY_CALL(memory_alloc)(A1,A2,A3) +#define PSI_CALL_memory_free(A1,A2,A3) PSI_MEMORY_CALL(memory_free)(A1,A2,A3) +#define PSI_CALL_memory_realloc(A1,A2,A3,A4) PSI_MEMORY_CALL(memory_realloc)(A1,A2,A3,A4) +#define PSI_CALL_register_memory(A1,A2,A3) PSI_MEMORY_CALL(register_memory)(A1,A2,A3) +#else +#define PSI_CALL_memory_alloc(A1,A2,A3) 0 +#define PSI_CALL_memory_free(A1,A2,A3) do { } while(0) +#define PSI_CALL_memory_realloc(A1,A2,A3,A4) 0 +#define PSI_CALL_register_memory(A1,A2,A3) do { } while(0) +#endif + +#ifndef PSI_MEMORY_CALL +#define PSI_MEMORY_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Memory_instrumentation Memory Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_memory_register(P1, P2, P3) + Memory registration. +*/ +#define mysql_memory_register(P1, P2, P3) \ + inline_mysql_memory_register(P1, P2, P3) + +static inline void inline_mysql_memory_register( +#ifdef HAVE_PSI_MEMORY_INTERFACE + const char *category, + PSI_memory_info *info, + int count) +#else + const char *category __attribute__((unused)), + void *info __attribute__((unused)), + int count __attribute__((unused))) +#endif +{ + PSI_CALL_register_memory(category, info, count); +} + +/** @} (end of group Memory_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_ps.h b/include/mysql/psi/mysql_ps.h new file mode 100644 index 00000000..89f34ef6 --- /dev/null +++ b/include/mysql/psi/mysql_ps.h @@ -0,0 +1,108 @@ +/* Copyright (c) 2014, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef MYSQL_PS_H +#define MYSQL_PS_H + +/** + @file mysql/psi/mysql_ps.h + Instrumentation helpers for prepared statements. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_PS_CALL +#define PSI_PS_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifdef HAVE_PSI_PS_INTERFACE + #define MYSQL_CREATE_PS(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH) \ + inline_mysql_create_prepared_stmt(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH) + #define MYSQL_EXECUTE_PS(LOCKER, PREPARED_STMT) \ + inline_mysql_execute_prepared_stmt(LOCKER, PREPARED_STMT) + #define MYSQL_DESTROY_PS(PREPARED_STMT) \ + inline_mysql_destroy_prepared_stmt(PREPARED_STMT) + #define MYSQL_REPREPARE_PS(PREPARED_STMT) \ + inline_mysql_reprepare_prepared_stmt(PREPARED_STMT) + #define MYSQL_SET_PS_TEXT(PREPARED_STMT, SQLTEXT, SQLTEXT_LENGTH) \ + inline_mysql_set_prepared_stmt_text(PREPARED_STMT, SQLTEXT, SQLTEXT_LENGTH) +#else + #define MYSQL_CREATE_PS(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH) \ + NULL + #define MYSQL_EXECUTE_PS(LOCKER, PREPARED_STMT) \ + do {} while (0) + #define MYSQL_DESTROY_PS(PREPARED_STMT) \ + do {} while (0) + #define MYSQL_REPREPARE_PS(PREPARED_STMT) \ + do {} while (0) + #define MYSQL_SET_PS_TEXT(PREPARED_STMT, SQLTEXT, SQLTEXT_LENGTH) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_PS_INTERFACE +static inline struct PSI_prepared_stmt* +inline_mysql_create_prepared_stmt(void *identity, uint stmt_id, + PSI_statement_locker *locker, + const char *stmt_name, size_t stmt_name_length) +{ + if (locker == NULL) + return NULL; + return PSI_PS_CALL(create_prepared_stmt)(identity, stmt_id, + locker, + stmt_name, stmt_name_length); +} + +static inline void +inline_mysql_execute_prepared_stmt(PSI_statement_locker *locker, + PSI_prepared_stmt* prepared_stmt) +{ + if (prepared_stmt != NULL && locker != NULL) + PSI_PS_CALL(execute_prepared_stmt)(locker, prepared_stmt); +} + +static inline void +inline_mysql_destroy_prepared_stmt(PSI_prepared_stmt *prepared_stmt) +{ + if (prepared_stmt != NULL) + PSI_PS_CALL(destroy_prepared_stmt)(prepared_stmt); +} + +static inline void +inline_mysql_reprepare_prepared_stmt(PSI_prepared_stmt *prepared_stmt) +{ + if (prepared_stmt != NULL) + PSI_PS_CALL(reprepare_prepared_stmt)(prepared_stmt); +} + +static inline void +inline_mysql_set_prepared_stmt_text(PSI_prepared_stmt *prepared_stmt, + const char *text, + uint text_len) +{ + if (prepared_stmt != NULL) + { + PSI_PS_CALL(set_prepared_stmt_text)(prepared_stmt, text, text_len); + } +} +#endif + +#endif diff --git a/include/mysql/psi/mysql_socket.h b/include/mysql/psi/mysql_socket.h new file mode 100644 index 00000000..95cb02a5 --- /dev/null +++ b/include/mysql/psi/mysql_socket.h @@ -0,0 +1,1353 @@ +/* Copyright (c) 2010, 2023, Oracle and/or its affiliates. + Copyright (c) 2017, MariaDB Corporation. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2.0, +as published by the Free Software Foundation. + +This program is also distributed with certain software (including +but not limited to OpenSSL) that is licensed under separate terms, +as designated in a particular file or component or in included license +documentation. The authors of MySQL hereby grant you an additional +permission to link the program and your derivative works with the +separately licensed software that they have included with MySQL. + +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, version 2.0, 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 St, Fifth Floor, Boston, MA +02110-1335 USA +*/ + +#ifndef MYSQL_SOCKET_H +#define MYSQL_SOCKET_H + +/* For MY_STAT */ +#include <my_dir.h> +/* For my_chsize */ +#include <my_sys.h> +/* For socket api */ +#ifdef _WIN32 + #include <ws2def.h> + #include <winsock2.h> + #include <MSWSock.h> + #define SOCKBUF_T char +#else + #include <netinet/in.h> + #define SOCKBUF_T void +#endif +/** + @file mysql/psi/mysql_socket.h +[...] +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_SOCKET_CALL +#define PSI_SOCKET_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Socket_instrumentation Socket Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_socket_register(P1, P2, P3) + Socket registration. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_register(P1, P2, P3) \ + inline_mysql_socket_register(P1, P2, P3) +#else + #define mysql_socket_register(P1, P2, P3) \ + do {} while (0) +#endif + +/** An instrumented socket. */ +struct st_mysql_socket +{ + /** The real socket descriptor. */ + my_socket fd; + + /** Is this a Unix-domain socket? */ + char is_unix_domain_socket; + + /** Is this a socket opened for the extra port? */ + char is_extra_port; + + /** Address family of the socket. (See sa_family from struct sockaddr). */ + unsigned short address_family; + + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c MYSQL_SOCKET interface. + */ + struct PSI_socket *m_psi; +}; + +/** + An instrumented socket. + @c MYSQL_SOCKET is a replacement for @c my_socket. +*/ +typedef struct st_mysql_socket MYSQL_SOCKET; + + +/** + @def MYSQL_INVALID_SOCKET + MYSQL_SOCKET initial value. +*/ +//MYSQL_SOCKET MYSQL_INVALID_SOCKET= {INVALID_SOCKET, NULL}; +#define MYSQL_INVALID_SOCKET mysql_socket_invalid() + +/** + MYSQL_SOCKET helper. Initialize instrumented socket. + @sa mysql_socket_getfd + @sa mysql_socket_setfd +*/ +static inline MYSQL_SOCKET +mysql_socket_invalid() +{ + MYSQL_SOCKET mysql_socket= {INVALID_SOCKET, 0, 0, 0, NULL}; + return mysql_socket; +} + +/** + Set socket descriptor and address. + @param socket nstrumented socket + @param addr unformatted socket address + @param addr_len length of socket address +*/ + +static inline void +mysql_socket_set_address( +#ifdef HAVE_PSI_SOCKET_INTERFACE + MYSQL_SOCKET socket, + const struct sockaddr *addr, + socklen_t addr_len +#else + MYSQL_SOCKET socket __attribute__ ((unused)), + const struct sockaddr *addr __attribute__ ((unused)), + socklen_t addr_len __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (socket.m_psi != NULL) + PSI_SOCKET_CALL(set_socket_info)(socket.m_psi, NULL, addr, addr_len); +#endif +} + +/** + Set socket descriptor and address. + @param socket instrumented socket +*/ +static inline void +mysql_socket_set_thread_owner( +#ifdef HAVE_PSI_SOCKET_INTERFACE +MYSQL_SOCKET socket +#else +MYSQL_SOCKET socket __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (socket.m_psi != NULL) + PSI_SOCKET_CALL(set_socket_thread_owner)(socket.m_psi); +#endif +} + +/** + MYSQL_SOCKET helper. Get socket descriptor. + @param mysql_socket Instrumented socket + @sa mysql_socket_getfd +*/ +static inline my_socket +mysql_socket_getfd(MYSQL_SOCKET mysql_socket) +{ + return mysql_socket.fd; +} + +/** + MYSQL_SOCKET helper. Set socket descriptor. + @param mysql_socket Instrumented socket + @param fd Socket descriptor + @sa mysql_socket_setfd +*/ +static inline void +mysql_socket_setfd(MYSQL_SOCKET *mysql_socket, my_socket fd) +{ + if (likely(mysql_socket != NULL)) + mysql_socket->fd= fd; +} + +/** + @def MYSQL_SOCKET_WAIT_VARIABLES + Instrumentation helper for socket waits. + This instrumentation declares local variables. + Do not use a ';' after this macro + @param LOCKER locker + @param STATE locker state + @sa MYSQL_START_SOCKET_WAIT. + @sa MYSQL_END_SOCKET_WAIT. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE) \ + struct PSI_socket_locker* LOCKER; \ + PSI_socket_locker_state STATE; +#else + #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE) +#endif + +/** + @def MYSQL_START_SOCKET_WAIT + Instrumentation helper for socket waits. + This instrumentation marks the start of a wait event. + @param LOCKER locker + @param STATE locker state + @param SOCKET instrumented socket + @param OP The socket operation to be performed + @param COUNT bytes to be written/read + @sa MYSQL_END_SOCKET_WAIT. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \ + LOCKER= inline_mysql_start_socket_wait(STATE, SOCKET, OP, COUNT,\ + __FILE__, __LINE__) +#else + #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \ + do {} while (0) +#endif + +/** + @def MYSQL_END_SOCKET_WAIT + Instrumentation helper for socket waits. + This instrumentation marks the end of a wait event. + @param LOCKER locker + @param COUNT actual bytes written/read, or -1 + @sa MYSQL_START_SOCKET_WAIT. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \ + inline_mysql_end_socket_wait(LOCKER, COUNT) +#else + #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \ + do {} while (0) +#endif + +/** + @def MYSQL_SOCKET_SET_STATE + Set the state (IDLE, ACTIVE) of an instrumented socket. + @param SOCKET the instrumented socket + @param STATE the new state + @sa PSI_socket_state +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \ + inline_mysql_socket_set_state(SOCKET, STATE) +#else + #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_SOCKET_INTERFACE +/** + Instrumentation calls for MYSQL_START_SOCKET_WAIT. + @sa MYSQL_START_SOCKET_WAIT. +*/ +static inline struct PSI_socket_locker* +inline_mysql_start_socket_wait(PSI_socket_locker_state *state, + MYSQL_SOCKET mysql_socket, + enum PSI_socket_operation op, + size_t byte_count, + const char *src_file, uint src_line) +{ + struct PSI_socket_locker *locker; + if (psi_likely(mysql_socket.m_psi != NULL)) + { + locker= PSI_SOCKET_CALL(start_socket_wait) + (state, mysql_socket.m_psi, op, byte_count, src_file, src_line); + } + else + locker= NULL; + return locker; +} + +/** + Instrumentation calls for MYSQL_END_SOCKET_WAIT. + @sa MYSQL_END_SOCKET_WAIT. +*/ +static inline void +inline_mysql_end_socket_wait(struct PSI_socket_locker *locker, size_t byte_count) +{ + if (psi_likely(locker != NULL)) + PSI_SOCKET_CALL(end_socket_wait)(locker, byte_count); +} + +/** + Set the state (IDLE, ACTIVE) of an instrumented socket. + @param socket the instrumented socket + @param state the new state + @sa PSI_socket_state +*/ +static inline void +inline_mysql_socket_set_state(MYSQL_SOCKET socket, enum PSI_socket_state state) +{ + if (socket.m_psi != NULL) + PSI_SOCKET_CALL(set_socket_state)(socket.m_psi, state); +} +#endif /* HAVE_PSI_SOCKET_INTERFACE */ + +/** + @def mysql_socket_fd(K, F) + Create a socket. + @c mysql_socket_fd is a replacement for @c socket. + @param K PSI_socket_key for this instrumented socket + @param F File descriptor +*/ + +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_fd(K, F) \ + inline_mysql_socket_fd(K, F) +#else + #define mysql_socket_fd(K, F) \ + inline_mysql_socket_fd(F) +#endif + +/** + @def mysql_socket_socket(K, D, T, P) + Create a socket. + @c mysql_socket_socket is a replacement for @c socket. + @param K PSI_socket_key for this instrumented socket + @param D Socket domain + @param T Protocol type + @param P Transport protocol +*/ + +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_socket(K, D, T, P) \ + inline_mysql_socket_socket(K, D, T, P) +#else + #define mysql_socket_socket(K, D, T, P) \ + inline_mysql_socket_socket(D, T, P) +#endif + +/** + @def mysql_socket_bind(FD, AP, L) + Bind a socket to a local port number and IP address + @c mysql_socket_bind is a replacement for @c bind. + @param FD Instrumented socket descriptor returned by socket() + @param AP Pointer to local port number and IP address in sockaddr structure + @param L Length of sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_bind(FD, AP, L) \ + inline_mysql_socket_bind(__FILE__, __LINE__, FD, AP, L) +#else + #define mysql_socket_bind(FD, AP, L) \ + inline_mysql_socket_bind(FD, AP, L) +#endif + +/** + @def mysql_socket_getsockname(FD, AP, LP) + Return port number and IP address of the local host + @c mysql_socket_getsockname is a replacement for @c getsockname. + @param FD Instrumented socket descriptor returned by socket() + @param AP Pointer to returned address of local host in @c sockaddr structure + @param LP Pointer to length of @c sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_getsockname(FD, AP, LP) \ + inline_mysql_socket_getsockname(__FILE__, __LINE__, FD, AP, LP) +#else + #define mysql_socket_getsockname(FD, AP, LP) \ + inline_mysql_socket_getsockname(FD, AP, LP) +#endif + +/** + @def mysql_socket_connect(FD, AP, L) + Establish a connection to a remote host. + @c mysql_socket_connect is a replacement for @c connect. + @param FD Instrumented socket descriptor returned by socket() + @param AP Pointer to target address in sockaddr structure + @param L Length of sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_connect(FD, AP, L) \ + inline_mysql_socket_connect(__FILE__, __LINE__, FD, AP, L) +#else + #define mysql_socket_connect(FD, AP, L) \ + inline_mysql_socket_connect(FD, AP, L) +#endif + +/** + @def mysql_socket_getpeername(FD, AP, LP) + Get port number and IP address of remote host that a socket is connected to. + @c mysql_socket_getpeername is a replacement for @c getpeername. + @param FD Instrumented socket descriptor returned by socket() or accept() + @param AP Pointer to returned address of remote host in sockaddr structure + @param LP Pointer to length of sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_getpeername(FD, AP, LP) \ + inline_mysql_socket_getpeername(__FILE__, __LINE__, FD, AP, LP) +#else + #define mysql_socket_getpeername(FD, AP, LP) \ + inline_mysql_socket_getpeername(FD, AP, LP) +#endif + +/** + @def mysql_socket_send(FD, B, N, FL) + Send data from the buffer, B, to a connected socket. + @c mysql_socket_send is a replacement for @c send. + @param FD Instrumented socket descriptor returned by socket() or accept() + @param B Buffer to send + @param N Number of bytes to send + @param FL Control flags +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_send(FD, B, N, FL) \ + inline_mysql_socket_send(__FILE__, __LINE__, FD, B, N, FL) +#else + #define mysql_socket_send(FD, B, N, FL) \ + inline_mysql_socket_send(FD, B, N, FL) +#endif + +/** + @def mysql_socket_recv(FD, B, N, FL) + Receive data from a connected socket. + @c mysql_socket_recv is a replacement for @c recv. + @param FD Instrumented socket descriptor returned by socket() or accept() + @param B Buffer to receive to + @param N Maximum bytes to receive + @param FL Control flags +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_recv(FD, B, N, FL) \ + inline_mysql_socket_recv(__FILE__, __LINE__, FD, B, N, FL) +#else + #define mysql_socket_recv(FD, B, N, FL) \ + inline_mysql_socket_recv(FD, B, N, FL) +#endif + +/** + @def mysql_socket_sendto(FD, B, N, FL, AP, L) + Send data to a socket at the specified address. + @c mysql_socket_sendto is a replacement for @c sendto. + @param FD Instrumented socket descriptor returned by socket() + @param B Buffer to send + @param N Number of bytes to send + @param FL Control flags + @param AP Pointer to destination sockaddr structure + @param L Size of sockaddr structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_sendto(FD, B, N, FL, AP, L) \ + inline_mysql_socket_sendto(__FILE__, __LINE__, FD, B, N, FL, AP, L) +#else + #define mysql_socket_sendto(FD, B, N, FL, AP, L) \ + inline_mysql_socket_sendto(FD, B, N, FL, AP, L) +#endif + +/** + @def mysql_socket_recvfrom(FD, B, N, FL, AP, L) + Receive data from a socket and return source address information + @c mysql_socket_recvfrom is a replacement for @c recvfrom. + @param FD Instrumented socket descriptor returned by socket() + @param B Buffer to receive to + @param N Maximum bytes to receive + @param FL Control flags + @param AP Pointer to source address in sockaddr_storage structure + @param LP Size of sockaddr_storage structure +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \ + inline_mysql_socket_recvfrom(__FILE__, __LINE__, FD, B, N, FL, AP, LP) +#else + #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \ + inline_mysql_socket_recvfrom(FD, B, N, FL, AP, LP) +#endif + +/** + @def mysql_socket_getsockopt(FD, LV, ON, OP, OL) + Get a socket option for the specified socket. + @c mysql_socket_getsockopt is a replacement for @c getsockopt. + @param FD Instrumented socket descriptor returned by socket() + @param LV Protocol level + @param ON Option to query + @param OP Buffer which will contain the value for the requested option + @param OL Pointer to length of OP +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \ + inline_mysql_socket_getsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL) +#else + #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \ + inline_mysql_socket_getsockopt(FD, LV, ON, OP, OL) +#endif + +/** + @def mysql_socket_setsockopt(FD, LV, ON, OP, OL) + Set a socket option for the specified socket. + @c mysql_socket_setsockopt is a replacement for @c setsockopt. + @param FD Instrumented socket descriptor returned by socket() + @param LV Protocol level + @param ON Option to modify + @param OP Buffer containing the value for the specified option + @param OL Pointer to length of OP +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \ + inline_mysql_socket_setsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL) +#else + #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \ + inline_mysql_socket_setsockopt(FD, LV, ON, OP, OL) +#endif + +/** + @def mysql_sock_set_nonblocking + Set socket to non-blocking. + @param FD instrumented socket descriptor +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_sock_set_nonblocking(FD) \ + inline_mysql_sock_set_nonblocking(__FILE__, __LINE__, FD) +#else + #define mysql_sock_set_nonblocking(FD) \ + inline_mysql_sock_set_nonblocking(FD) +#endif + +/** + @def mysql_socket_listen(FD, N) + Set socket state to listen for an incoming connection. + @c mysql_socket_listen is a replacement for @c listen. + @param FD Instrumented socket descriptor, bound and connected + @param N Maximum number of pending connections allowed. +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_listen(FD, N) \ + inline_mysql_socket_listen(__FILE__, __LINE__, FD, N) +#else + #define mysql_socket_listen(FD, N) \ + inline_mysql_socket_listen(FD, N) +#endif + +/** + @def mysql_socket_accept(K, FD, AP, LP) + Accept a connection from any remote host; TCP only. + @c mysql_socket_accept is a replacement for @c accept. + @param K PSI_socket_key for this instrumented socket + @param FD Instrumented socket descriptor, bound and placed in a listen state + @param AP Pointer to sockaddr structure with returned IP address and port of connected host + @param LP Pointer to length of valid information in AP +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_accept(K, FD, AP, LP) \ + inline_mysql_socket_accept(__FILE__, __LINE__, K, FD, AP, LP) +#else + #define mysql_socket_accept(K, FD, AP, LP) \ + inline_mysql_socket_accept(FD, AP, LP) +#endif + +/** + @def mysql_socket_close(FD) + Close a socket and sever any connections. + @c mysql_socket_close is a replacement for @c close. + @param FD Instrumented socket descriptor returned by socket() or accept() +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_close(FD) \ + inline_mysql_socket_close(__FILE__, __LINE__, FD) +#else + #define mysql_socket_close(FD) \ + inline_mysql_socket_close(FD) +#endif + +/** + @def mysql_socket_shutdown(FD, H) + Disable receives and/or sends on a socket. + @c mysql_socket_shutdown is a replacement for @c shutdown. + @param FD Instrumented socket descriptor returned by socket() or accept() + @param H Specifies which operations to shutdown +*/ +#ifdef HAVE_PSI_SOCKET_INTERFACE + #define mysql_socket_shutdown(FD, H) \ + inline_mysql_socket_shutdown(__FILE__, __LINE__, FD, H) +#else + #define mysql_socket_shutdown(FD, H) \ + inline_mysql_socket_shutdown(FD, H) +#endif + +#ifdef HAVE_PSI_SOCKET_INTERFACE +static inline void inline_mysql_socket_register( + const char *category, + PSI_socket_info *info, + int count) +{ + PSI_SOCKET_CALL(register_socket)(category, info, count); +} +#endif + +/** mysql_socket_fd */ + +static inline MYSQL_SOCKET +inline_mysql_socket_fd +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + PSI_socket_key key, +#endif + int fd) +{ + MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET; + mysql_socket.fd= fd; + + DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET); +#ifdef HAVE_PSI_SOCKET_INTERFACE + mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket) + (key, (const my_socket*)&mysql_socket.fd, NULL, 0); +#endif + /** + Currently systemd socket activation is the user of this + function. Its API (man sd_listen_fds) says FD_CLOSE_EXEC + is already called. If there becomes another user, we + can call it again without detriment. + + If needed later: + #if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + (void) fcntl(mysql_socket.fd, F_SETFD, FD_CLOEXEC); + #endif + */ + + return mysql_socket; +} + +/** mysql_socket_socket */ + +static inline MYSQL_SOCKET +inline_mysql_socket_socket +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + PSI_socket_key key, +#endif + int domain, int type, int protocol) +{ + MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET; + mysql_socket.fd= socket(domain, type | SOCK_CLOEXEC, protocol); + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (likely(mysql_socket.fd != INVALID_SOCKET)) + { + mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket) + (key, (const my_socket*)&mysql_socket.fd, NULL, 0); + } +#endif + + /* SOCK_CLOEXEC isn't always a number - can't preprocessor compare */ +#if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) && !defined(HAVE_SOCK_CLOEXEC) + (void) fcntl(mysql_socket.fd, F_SETFD, FD_CLOEXEC); +#endif + + return mysql_socket; +} + +/** mysql_socket_bind */ + +static inline int +inline_mysql_socket_bind +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, size_t len) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker_state state; + PSI_socket_locker *locker; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= bind(mysql_socket.fd, addr, (int)len); + + /* Instrumentation end */ + if (result == 0) + PSI_SOCKET_CALL(set_socket_info)(mysql_socket.m_psi, NULL, addr, (socklen_t)len); + + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= bind(mysql_socket.fd, addr, (int)len); + return result; +} + +/** mysql_socket_getsockname */ + +static inline int +inline_mysql_socket_getsockname +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= getsockname(mysql_socket.fd, addr, len); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= getsockname(mysql_socket.fd, addr, len); + + return result; +} + +/** mysql_socket_connect */ + +static inline int +inline_mysql_socket_connect +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, socklen_t len) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= connect(mysql_socket.fd, addr, len); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= connect(mysql_socket.fd, addr, len); + + return result; +} + +/** mysql_socket_getpeername */ + +static inline int +inline_mysql_socket_getpeername +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= getpeername(mysql_socket.fd, addr, len); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= getpeername(mysql_socket.fd, addr, len); + + return result; +} + +/** mysql_socket_send */ + +static inline ssize_t +inline_mysql_socket_send +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags) +{ + ssize_t result; + DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET); +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line); + + /* Instrumented code */ + result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags); + + /* Instrumentation end */ + if (locker != NULL) + { + size_t bytes_written= (result > 0) ? (size_t) result : 0; + PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written); + } + + return result; + } +#endif + + /* Non instrumented code */ + result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags); + + return result; +} + +/** mysql_socket_recv */ + +static inline ssize_t +inline_mysql_socket_recv +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags) +{ + ssize_t result; + DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET); +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags); + + /* Instrumentation end */ + if (locker != NULL) + { + size_t bytes_read= (result > 0) ? (size_t) result : 0; + PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read); + } + + return result; + } +#endif + + /* Non instrumented code */ + result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags); + + return result; +} + +/** mysql_socket_sendto */ + +static inline ssize_t +inline_mysql_socket_sendto +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags, const struct sockaddr *addr, socklen_t addr_len) +{ + ssize_t result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line); + + /* Instrumented code */ + result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); + + /* Instrumentation end */ + if (locker != NULL) + { + size_t bytes_written = (result > 0) ? (size_t) result : 0; + PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written); + } + + return result; + } +#endif + + /* Non instrumented code */ + result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); + + return result; +} + +/** mysql_socket_recvfrom */ + +static inline ssize_t +inline_mysql_socket_recvfrom +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags, + struct sockaddr *addr, socklen_t *addr_len) +{ + ssize_t result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); + + /* Instrumentation end */ + if (locker != NULL) + { + size_t bytes_read= (result > 0) ? (size_t) result : 0; + PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read); + } + + return result; + } +#endif + + /* Non instrumented code */ + result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); + + return result; +} + +/** mysql_socket_getsockopt */ + +static inline int +inline_mysql_socket_getsockopt +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, int level, int optname, SOCKBUF_T *optval, socklen_t *optlen) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= getsockopt(mysql_socket.fd, level, optname, optval, optlen); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= getsockopt(mysql_socket.fd, level, optname, optval, optlen); + + return result; +} + +/** mysql_socket_setsockopt */ + +static inline int +inline_mysql_socket_setsockopt +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, int level, int optname, const SOCKBUF_T *optval, + socklen_t optlen) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= setsockopt(mysql_socket.fd, level, optname, optval, optlen); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= setsockopt(mysql_socket.fd, level, optname, optval, optlen); + + return result; +} + +/** set_socket_nonblock */ +static inline int +set_socket_nonblock(my_socket fd) +{ + int ret= 0; +#ifdef _WIN32 + { + u_long nonblocking= 1; + ret= ioctlsocket(fd, FIONBIO, &nonblocking); + } +#else + { + int fd_flags; + fd_flags= fcntl(fd, F_GETFL, 0); + if (fd_flags < 0) + return errno; +#if defined(O_NONBLOCK) + fd_flags |= O_NONBLOCK; +#elif defined(O_NDELAY) + fd_flags |= O_NDELAY; +#elif defined(O_FNDELAY) + fd_flags |= O_FNDELAY; +#else +#error "No definition of non-blocking flag found." +#endif /* O_NONBLOCK */ + if (fcntl(fd, F_SETFL, fd_flags) == -1) + ret= errno; + } +#endif /* _WIN32 */ + return ret; +} + +/** mysql_socket_set_nonblocking */ + +static inline int +inline_mysql_sock_set_nonblocking +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket +) +{ + int result= 0; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (mysql_socket.m_psi) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, + (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= set_socket_nonblock(mysql_socket.fd); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= set_socket_nonblock(mysql_socket.fd); + + return result; +} + +/** mysql_socket_listen */ + +static inline int +inline_mysql_socket_listen +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, int backlog) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= listen(mysql_socket.fd, backlog); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ + result= listen(mysql_socket.fd, backlog); + + return result; +} + +/** mysql_socket_accept */ + +static inline MYSQL_SOCKET +inline_mysql_socket_accept +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, PSI_socket_key key, +#endif + MYSQL_SOCKET socket_listen, struct sockaddr *addr, socklen_t *addr_len) +{ +#ifdef FD_CLOEXEC + int flags __attribute__ ((unused)); +#endif + + MYSQL_SOCKET socket_accept; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (socket_listen.m_psi != NULL) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, socket_listen.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); + + /* Instrumented code */ +#ifdef HAVE_ACCEPT4 + socket_accept.fd= accept4(socket_listen.fd, addr, addr_len, SOCK_CLOEXEC); +#else + socket_accept.fd= accept(socket_listen.fd, addr, addr_len); +#ifdef FD_CLOEXEC + if (socket_accept.fd != INVALID_SOCKET) + { + flags= fcntl(socket_accept.fd, F_GETFD); + if (flags != -1) + { + flags |= FD_CLOEXEC; + fcntl(socket_accept.fd, F_SETFD, flags); + } + } +#endif +#endif + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + } + else +#endif + { + /* Non instrumented code */ +#ifdef HAVE_ACCEPT4 + socket_accept.fd= accept4(socket_listen.fd, addr, addr_len, SOCK_CLOEXEC); +#else + socket_accept.fd= accept(socket_listen.fd, addr, addr_len); +#ifdef FD_CLOEXEC + if (socket_accept.fd != INVALID_SOCKET) + { + flags= fcntl(socket_accept.fd, F_GETFD); + if (flags != -1) + { + flags |= FD_CLOEXEC; + fcntl(socket_accept.fd, F_SETFD, flags); + } + } +#endif +#endif + } + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (likely(socket_accept.fd != INVALID_SOCKET)) + { + /* Initialize the instrument with the new socket descriptor and address */ + socket_accept.m_psi= PSI_SOCKET_CALL(init_socket) + (key, (const my_socket*)&socket_accept.fd, addr, *addr_len); + } +#endif + + return socket_accept; +} + +/** mysql_socket_close */ + +static inline int +inline_mysql_socket_close +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket) +{ + int result; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + /* Instrumentation start */ + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_CLOSE, (size_t)0, src_file, src_line); + + /* Instrumented code */ + result= closesocket(mysql_socket.fd); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + /* Remove the instrumentation for this socket. */ + if (mysql_socket.m_psi != NULL) + PSI_SOCKET_CALL(destroy_socket)(mysql_socket.m_psi); + + return result; + } +#endif + + /* Non instrumented code */ + result= closesocket(mysql_socket.fd); + + return result; +} + +/** mysql_socket_shutdown */ + +static inline int +inline_mysql_socket_shutdown +( +#ifdef HAVE_PSI_SOCKET_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_SOCKET mysql_socket, int how) +{ + int result; + +#ifdef _WIN32 + static LPFN_DISCONNECTEX DisconnectEx = NULL; + if (DisconnectEx == NULL) + { + DWORD dwBytesReturned; + GUID guidDisconnectEx = WSAID_DISCONNECTEX; + WSAIoctl(mysql_socket.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, + &guidDisconnectEx, sizeof(GUID), + &DisconnectEx, sizeof(DisconnectEx), + &dwBytesReturned, NULL, NULL); + } +#endif + +/* Instrumentation start */ +#ifdef HAVE_PSI_SOCKET_INTERFACE + if (psi_likely(mysql_socket.m_psi != NULL)) + { + PSI_socket_locker *locker; + PSI_socket_locker_state state; + locker= PSI_SOCKET_CALL(start_socket_wait) + (&state, mysql_socket.m_psi, PSI_SOCKET_SHUTDOWN, (size_t)0, src_file, src_line); + + /* Instrumented code */ +#ifdef _WIN32 + if (DisconnectEx) + result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL, + (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1; + else +#endif + result= shutdown(mysql_socket.fd, how); + + /* Instrumentation end */ + if (locker != NULL) + PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); + + return result; + } +#endif + + /* Non instrumented code */ +#ifdef _WIN32 + if (DisconnectEx) + result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL, + (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1; + else +#endif + result= shutdown(mysql_socket.fd, how); + + return result; +} + +/** @} (end of group Socket_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_sp.h b/include/mysql/psi/mysql_sp.h new file mode 100644 index 00000000..c2524745 --- /dev/null +++ b/include/mysql/psi/mysql_sp.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2013, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef MYSQL_SP_H +#define MYSQL_SP_H + +/** + @file mysql/psi/mysql_sp.h + Instrumentation helpers for stored programs. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_SP_CALL +#define PSI_SP_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifdef HAVE_PSI_SP_INTERFACE + #define MYSQL_START_SP(STATE, SP_SHARE) \ + inline_mysql_start_sp(STATE, SP_SHARE) +#else + #define MYSQL_START_SP(STATE, SP_SHARE) \ + NULL +#endif + + +#ifdef HAVE_PSI_SP_INTERFACE + #define MYSQL_END_SP(LOCKER) \ + inline_mysql_end_sp(LOCKER) +#else + #define MYSQL_END_SP(LOCKER) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_SP_INTERFACE + #define MYSQL_DROP_SP(OT, SN, SNL, ON, ONL) \ + inline_mysql_drop_sp(OT, SN, SNL, ON, ONL) +#else + #define MYSQL_DROP_SP(OT, SN, SNL, ON, ONL) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_SP_INTERFACE + #define MYSQL_GET_SP_SHARE(OT, SN, SNL, ON, ONL) \ + inline_mysql_get_sp_share(OT, SN, SNL, ON, ONL) +#else + #define MYSQL_GET_SP_SHARE(OT, SN, SNL, ON, ONL) \ + NULL +#endif + +#ifdef HAVE_PSI_SP_INTERFACE +static inline struct PSI_sp_locker* +inline_mysql_start_sp(PSI_sp_locker_state *state, PSI_sp_share *sp_share) +{ + return PSI_SP_CALL(start_sp)(state, sp_share); +} + +static inline void inline_mysql_end_sp(PSI_sp_locker *locker) +{ + if (likely(locker != NULL)) + PSI_SP_CALL(end_sp)(locker); +} + +static inline void +inline_mysql_drop_sp(uint sp_type, + const char* schema_name, uint shcema_name_length, + const char* object_name, uint object_name_length) +{ + PSI_SP_CALL(drop_sp)(sp_type, + schema_name, shcema_name_length, + object_name, object_name_length); +} + +static inline PSI_sp_share* +inline_mysql_get_sp_share(uint sp_type, + const char* schema_name, uint shcema_name_length, + const char* object_name, uint object_name_length) +{ + return PSI_SP_CALL(get_sp_share)(sp_type, + schema_name, shcema_name_length, + object_name, object_name_length); +} +#endif + +#endif diff --git a/include/mysql/psi/mysql_stage.h b/include/mysql/psi/mysql_stage.h new file mode 100644 index 00000000..b6bc5ce3 --- /dev/null +++ b/include/mysql/psi/mysql_stage.h @@ -0,0 +1,205 @@ +/* Copyright (c) 2010, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_STAGE_H +#define MYSQL_STAGE_H + +/** + @file mysql/psi/mysql_stage.h + Instrumentation helpers for stages. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_STAGE_CALL +#define PSI_STAGE_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Stage_instrumentation Stage Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_stage_register(P1, P2, P3) + Stage registration. +*/ +#ifdef HAVE_PSI_STAGE_INTERFACE +#define mysql_stage_register(P1, P2, P3) \ + inline_mysql_stage_register(P1, P2, P3) +#else +#define mysql_stage_register(P1, P2, P3) \ + do {} while (0) +#endif + +/** + @def MYSQL_SET_STAGE + Set the current stage. + Use this API when the file and line + is passed from the caller. + @param K the stage key + @param F the source file name + @param L the source file line + @return the current stage progress +*/ +#ifdef HAVE_PSI_STAGE_INTERFACE + #define MYSQL_SET_STAGE(K, F, L) \ + inline_mysql_set_stage(K, F, L) +#else + #define MYSQL_SET_STAGE(K, F, L) \ + NULL +#endif + +/** + @def mysql_set_stage + Set the current stage. + @param K the stage key + @return the current stage progress +*/ +#ifdef HAVE_PSI_STAGE_INTERFACE + #define mysql_set_stage(K) \ + inline_mysql_set_stage(K, __FILE__, __LINE__) +#else + #define mysql_set_stage(K) \ + NULL +#endif + +/** + @def mysql_end_stage + End the last stage +*/ +#ifdef HAVE_PSI_STAGE_INTERFACE + #define mysql_end_stage() \ + inline_mysql_end_stage() +#else + #define mysql_end_stage() \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void inline_mysql_stage_register( + const char *category, PSI_stage_info **info, int count) +{ + PSI_STAGE_CALL(register_stage)(category, info, count); +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline PSI_stage_progress* +inline_mysql_set_stage(PSI_stage_key key, + const char *src_file, int src_line) +{ + return PSI_STAGE_CALL(start_stage)(key, src_file, src_line); +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void +inline_mysql_end_stage() +{ + PSI_STAGE_CALL(end_stage)(); +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +#define mysql_stage_set_work_completed(P1, P2) \ + inline_mysql_stage_set_work_completed(P1, P2) + +#define mysql_stage_get_work_completed(P1) \ + inline_mysql_stage_get_work_completed(P1) +#else +#define mysql_stage_set_work_completed(P1, P2) \ + do {} while (0) + +#define mysql_stage_get_work_completed(P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +#define mysql_stage_inc_work_completed(P1, P2) \ + inline_mysql_stage_inc_work_completed(P1, P2) +#else +#define mysql_stage_inc_work_completed(P1, P2) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +#define mysql_stage_set_work_estimated(P1, P2) \ + inline_mysql_stage_set_work_estimated(P1, P2) + +#define mysql_stage_get_work_estimated(P1) \ + inline_mysql_stage_get_work_estimated(P1) +#else +#define mysql_stage_set_work_estimated(P1, P2) \ + do {} while (0) + +#define mysql_stage_get_work_estimated(P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void +inline_mysql_stage_set_work_completed(PSI_stage_progress *progress, + ulonglong val) +{ + if (progress != NULL) + progress->m_work_completed= val; +} + +static inline ulonglong +inline_mysql_stage_get_work_completed(PSI_stage_progress *progress) +{ + return progress->m_work_completed; +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void +inline_mysql_stage_inc_work_completed(PSI_stage_progress *progress, + ulonglong val) +{ + if (progress != NULL) + progress->m_work_completed+= val; +} +#endif + +#ifdef HAVE_PSI_STAGE_INTERFACE +static inline void +inline_mysql_stage_set_work_estimated(PSI_stage_progress *progress, + ulonglong val) +{ + if (progress != NULL) + progress->m_work_estimated= val; +} + +static inline ulonglong +inline_mysql_stage_get_work_estimated(PSI_stage_progress *progress) +{ + return progress->m_work_estimated; +} +#endif + +/** @} (end of group Stage_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_statement.h b/include/mysql/psi/mysql_statement.h new file mode 100644 index 00000000..544bba67 --- /dev/null +++ b/include/mysql/psi/mysql_statement.h @@ -0,0 +1,243 @@ +/* Copyright (c) 2010, 2023, Oracle and/or its affiliates. + Copyright (c) 2017, 2019, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_STATEMENT_H +#define MYSQL_STATEMENT_H + +/** + @file mysql/psi/mysql_statement.h + Instrumentation helpers for statements. +*/ + +#include "mysql/psi/psi.h" + +class Diagnostics_area; +typedef const struct charset_info_st CHARSET_INFO; + +#ifndef PSI_STATEMENT_CALL +#define PSI_STATEMENT_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifndef PSI_DIGEST_CALL +#define PSI_DIGEST_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Statement_instrumentation Statement Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_statement_register(P1, P2, P3) + Statement registration. +*/ +#ifdef HAVE_PSI_STATEMENT_INTERFACE +#define mysql_statement_register(P1, P2, P3) \ + inline_mysql_statement_register(P1, P2, P3) +#else +#define mysql_statement_register(P1, P2, P3) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE + #define MYSQL_DIGEST_START(LOCKER) \ + inline_mysql_digest_start(LOCKER) +#else + #define MYSQL_DIGEST_START(LOCKER) \ + NULL +#endif + +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE + #define MYSQL_DIGEST_END(LOCKER, DIGEST) \ + inline_mysql_digest_end(LOCKER, DIGEST) +#else + #define MYSQL_DIGEST_END(LOCKER, DIGEST) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS, SPS) \ + inline_mysql_start_statement(STATE, K, DB, DB_LEN, CS, SPS, __FILE__, __LINE__) +#else + #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS, SPS) \ + NULL +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_REFINE_STATEMENT(LOCKER, K) \ + inline_mysql_refine_statement(LOCKER, K) +#else + #define MYSQL_REFINE_STATEMENT(LOCKER, K) \ + NULL +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_SET_STATEMENT_TEXT(LOCKER, P1, P2) \ + inline_mysql_set_statement_text(LOCKER, P1, P2) +#else + #define MYSQL_SET_STATEMENT_TEXT(LOCKER, P1, P2) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_SET_STATEMENT_LOCK_TIME(LOCKER, P1) \ + inline_mysql_set_statement_lock_time(LOCKER, P1) +#else + #define MYSQL_SET_STATEMENT_LOCK_TIME(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_SET_STATEMENT_ROWS_SENT(LOCKER, P1) \ + inline_mysql_set_statement_rows_sent(LOCKER, P1) +#else + #define MYSQL_SET_STATEMENT_ROWS_SENT(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_SET_STATEMENT_ROWS_EXAMINED(LOCKER, P1) \ + inline_mysql_set_statement_rows_examined(LOCKER, P1) +#else + #define MYSQL_SET_STATEMENT_ROWS_EXAMINED(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + #define MYSQL_END_STATEMENT(LOCKER, DA) \ + inline_mysql_end_statement(LOCKER, DA) +#else + #define MYSQL_END_STATEMENT(LOCKER, DA) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_STATEMENT_INTERFACE +static inline void inline_mysql_statement_register( + const char *category, PSI_statement_info *info, int count) +{ + PSI_STATEMENT_CALL(register_statement)(category, info, count); +} + +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE +static inline struct PSI_digest_locker * +inline_mysql_digest_start(PSI_statement_locker *locker) +{ + PSI_digest_locker* digest_locker= NULL; + + if (psi_likely(locker != NULL)) + digest_locker= PSI_DIGEST_CALL(digest_start)(locker); + return digest_locker; +} +#endif + +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE +static inline void +inline_mysql_digest_end(PSI_digest_locker *locker, const sql_digest_storage *digest) +{ + if (psi_likely(locker != NULL)) + PSI_DIGEST_CALL(digest_end)(locker, digest); +} +#endif + +static inline struct PSI_statement_locker * +inline_mysql_start_statement(PSI_statement_locker_state *state, + PSI_statement_key key, + const char *db, size_t db_len, + CHARSET_INFO *charset, + PSI_sp_share *sp_share, + const char *src_file, uint src_line) +{ + PSI_statement_locker *locker; + locker= PSI_STATEMENT_CALL(get_thread_statement_locker)(state, key, charset, + sp_share); + if (psi_likely(locker != NULL)) + PSI_STATEMENT_CALL(start_statement)(locker, db, (uint)db_len, src_file, src_line); + return locker; +} + +static inline struct PSI_statement_locker * +inline_mysql_refine_statement(PSI_statement_locker *locker, + PSI_statement_key key) +{ + if (psi_likely(locker != NULL)) + { + locker= PSI_STATEMENT_CALL(refine_statement)(locker, key); + } + return locker; +} + +static inline void +inline_mysql_set_statement_text(PSI_statement_locker *locker, + const char *text, uint text_len) +{ + if (psi_likely(locker != NULL)) + { + PSI_STATEMENT_CALL(set_statement_text)(locker, text, text_len); + } +} + +static inline void +inline_mysql_set_statement_lock_time(PSI_statement_locker *locker, + ulonglong count) +{ + if (psi_likely(locker != NULL)) + { + PSI_STATEMENT_CALL(set_statement_lock_time)(locker, count); + } +} + +static inline void +inline_mysql_set_statement_rows_sent(PSI_statement_locker *locker, + ulonglong count) +{ + if (psi_likely(locker != NULL)) + { + PSI_STATEMENT_CALL(set_statement_rows_sent)(locker, count); + } +} + +static inline void +inline_mysql_set_statement_rows_examined(PSI_statement_locker *locker, + ulonglong count) +{ + if (psi_likely(locker != NULL)) + { + PSI_STATEMENT_CALL(set_statement_rows_examined)(locker, count); + } +} + +static inline void +inline_mysql_end_statement(struct PSI_statement_locker *locker, + Diagnostics_area *stmt_da) +{ + PSI_STAGE_CALL(end_stage)(); + if (psi_likely(locker != NULL)) + PSI_STATEMENT_CALL(end_statement)(locker, stmt_da); +} +#endif + +/** @} (end of group Statement_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_table.h b/include/mysql/psi/mysql_table.h new file mode 100644 index 00000000..317627a6 --- /dev/null +++ b/include/mysql/psi/mysql_table.h @@ -0,0 +1,172 @@ +/* Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, 2019, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_TABLE_H +#define MYSQL_TABLE_H + +/** + @file mysql/psi/mysql_table.h + Instrumentation helpers for table io. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_TABLE_CALL +#define PSI_TABLE_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Table_instrumentation Table Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +#ifdef HAVE_PSI_TABLE_INTERFACE +#define MYSQL_UNBIND_TABLE(handler) (handler)->unbind_psi() + +#define PSI_CALL_unbind_table PSI_TABLE_CALL(unbind_table) +#define PSI_CALL_rebind_table PSI_TABLE_CALL(rebind_table) +#define PSI_CALL_open_table PSI_TABLE_CALL(open_table) +#define PSI_CALL_close_table PSI_TABLE_CALL(close_table) +#define PSI_CALL_get_table_share PSI_TABLE_CALL(get_table_share) +#define PSI_CALL_release_table_share PSI_TABLE_CALL(release_table_share) +#define PSI_CALL_drop_table_share PSI_TABLE_CALL(drop_table_share) +#else +#define MYSQL_UNBIND_TABLE(handler) do { } while(0) + +#define PSI_CALL_unbind_table(A1) do { } while(0) +#define PSI_CALL_rebind_table(A1,A2,A3) NULL +#define PSI_CALL_close_table(A1,A2) do { } while(0) +#define PSI_CALL_open_table(A1,A2) NULL +#define PSI_CALL_get_table_share(A1,A2) NULL +#define PSI_CALL_release_table_share(A1) do { } while(0) +#define PSI_CALL_drop_table_share(A1,A2,A3,A4,A5) do { } while(0) +#endif + +/** + @def MYSQL_TABLE_WAIT_VARIABLES + Instrumentation helper for table waits. + This instrumentation declares local variables. + Do not use a ';' after this macro + @param LOCKER the locker + @param STATE the locker state + @sa MYSQL_START_TABLE_IO_WAIT. + @sa MYSQL_END_TABLE_IO_WAIT. + @sa MYSQL_START_TABLE_LOCK_WAIT. + @sa MYSQL_END_TABLE_LOCK_WAIT. +*/ +#ifdef HAVE_PSI_TABLE_INTERFACE + #define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) \ + struct PSI_table_locker* LOCKER; \ + PSI_table_locker_state STATE; +#else + #define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) +#endif + +/** + @def MYSQL_START_TABLE_LOCK_WAIT + Instrumentation helper for table lock waits. + This instrumentation marks the start of a wait event. + @param LOCKER the locker + @param STATE the locker state + @param PSI the instrumented table + @param OP the table operation to be performed + @param FLAGS per table operation flags. + @sa MYSQL_END_TABLE_LOCK_WAIT. +*/ +#ifdef HAVE_PSI_TABLE_INTERFACE + #define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \ + LOCKER= inline_mysql_start_table_lock_wait(STATE, PSI, \ + OP, FLAGS, __FILE__, __LINE__) +#else + #define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \ + do {} while (0) +#endif + +/** + @def MYSQL_END_TABLE_LOCK_WAIT + Instrumentation helper for table lock waits. + This instrumentation marks the end of a wait event. + @param LOCKER the locker + @sa MYSQL_START_TABLE_LOCK_WAIT. +*/ +#ifdef HAVE_PSI_TABLE_INTERFACE + #define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \ + inline_mysql_end_table_lock_wait(LOCKER) +#else + #define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TABLE_INTERFACE + #define MYSQL_UNLOCK_TABLE(T) \ + inline_mysql_unlock_table(T) +#else + #define MYSQL_UNLOCK_TABLE(T) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TABLE_INTERFACE +/** + Instrumentation calls for MYSQL_START_TABLE_LOCK_WAIT. + @sa MYSQL_END_TABLE_LOCK_WAIT. +*/ +static inline struct PSI_table_locker * +inline_mysql_start_table_lock_wait(PSI_table_locker_state *state, + struct PSI_table *psi, + enum PSI_table_lock_operation op, + ulong flags, const char *src_file, uint src_line) +{ + if (psi_likely(psi != NULL)) + { + struct PSI_table_locker *locker; + locker= PSI_TABLE_CALL(start_table_lock_wait) + (state, psi, op, flags, src_file, src_line); + return locker; + } + return NULL; +} + +/** + Instrumentation calls for MYSQL_END_TABLE_LOCK_WAIT. + @sa MYSQL_START_TABLE_LOCK_WAIT. +*/ +static inline void +inline_mysql_end_table_lock_wait(struct PSI_table_locker *locker) +{ + if (psi_likely(locker != NULL)) + PSI_TABLE_CALL(end_table_lock_wait)(locker); +} + +static inline void +inline_mysql_unlock_table(struct PSI_table *table) +{ + if (table != NULL) + PSI_TABLE_CALL(unlock_table)(table); +} +#endif + +/** @} (end of group Table_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_thread.h b/include/mysql/psi/mysql_thread.h new file mode 100644 index 00000000..11cf3548 --- /dev/null +++ b/include/mysql/psi/mysql_thread.h @@ -0,0 +1,1172 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + Copyright (c) 2020, 2021, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_THREAD_H +#define MYSQL_THREAD_H + +/** + @file mysql/psi/mysql_thread.h + Instrumentation helpers for mysys threads, mutexes, + read write locks and conditions. + This header file provides the necessary declarations + to use the mysys thread API with the performance schema instrumentation. + In some compilers (SunStudio), 'static inline' functions, when declared + but not used, are not optimized away (because they are unused) by default, + so that including a static inline function from a header file does + create unwanted dependencies, causing unresolved symbols at link time. + Other compilers, like gcc, optimize these dependencies by default. + + Since the instrumented APIs declared here are wrapper on top + of my_pthread / safemutex / etc APIs, + including mysql/psi/mysql_thread.h assumes that + the dependency on my_pthread and safemutex already exists. +*/ +/* + Note: there are several orthogonal dimensions here. + + Dimension 1: Instrumentation + HAVE_PSI_INTERFACE is defined when the instrumentation is compiled in. + This may happen both in debug or production builds. + + Dimension 2: Debug + SAFE_MUTEX is defined when debug is compiled in. + This may happen both with and without instrumentation. + + Dimension 3: Platform + Mutexes are implemented with one of: + - the pthread library + - fast mutexes + - window apis + This is implemented by various macro definitions in my_pthread.h + + This causes complexity with '#ifdef'-ery that can't be avoided. +*/ + +#include "mysql/psi/psi.h" +#ifdef MYSQL_SERVER +#ifndef MYSQL_DYNAMIC_PLUGIN +#include "pfs_thread_provider.h" +#endif +#endif + +#ifndef PSI_MUTEX_CALL +#define PSI_MUTEX_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifndef PSI_RWLOCK_CALL +#define PSI_RWLOCK_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifndef PSI_COND_CALL +#define PSI_COND_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +#ifndef PSI_THREAD_CALL +#define PSI_THREAD_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Thread_instrumentation Thread Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +#ifdef HAVE_PSI_THREAD_INTERFACE +#define PSI_CALL_delete_current_thread PSI_THREAD_CALL(delete_current_thread) +#define PSI_CALL_get_thread PSI_THREAD_CALL(get_thread) +#define PSI_CALL_new_thread PSI_THREAD_CALL(new_thread) +#define PSI_CALL_register_thread PSI_THREAD_CALL(register_thread) +#define PSI_CALL_set_thread PSI_THREAD_CALL(set_thread) +#define PSI_CALL_set_thread_THD PSI_THREAD_CALL(set_thread_THD) +#define PSI_CALL_set_thread_connect_attrs PSI_THREAD_CALL(set_thread_connect_attrs) +#define PSI_CALL_set_thread_db PSI_THREAD_CALL(set_thread_db) +#define PSI_CALL_set_thread_id PSI_THREAD_CALL(set_thread_id) +#define PSI_CALL_set_thread_os_id PSI_THREAD_CALL(set_thread_os_id) +#define PSI_CALL_set_thread_info PSI_THREAD_CALL(set_thread_info) +#define PSI_CALL_set_thread_start_time PSI_THREAD_CALL(set_thread_start_time) +#define PSI_CALL_set_thread_account PSI_THREAD_CALL(set_thread_account) +#define PSI_CALL_spawn_thread PSI_THREAD_CALL(spawn_thread) +#define PSI_CALL_set_connection_type PSI_THREAD_CALL(set_connection_type) +#else +#define PSI_CALL_delete_current_thread() do { } while(0) +#define PSI_CALL_get_thread() NULL +#define PSI_CALL_new_thread(A1,A2,A3) NULL +#define PSI_CALL_register_thread(A1,A2,A3) do { } while(0) +#define PSI_CALL_set_thread(A1) do { } while(0) +#define PSI_CALL_set_thread_THD(A1,A2) do { } while(0) +#define PSI_CALL_set_thread_connect_attrs(A1,A2,A3) 0 +#define PSI_CALL_set_thread_db(A1,A2) do { } while(0) +#define PSI_CALL_set_thread_id(A1,A2) do { } while(0) +#define PSI_CALL_set_thread_os_id(A1) do { } while(0) +#define PSI_CALL_set_thread_info(A1, A2) do { } while(0) +#define PSI_CALL_set_thread_start_time(A1) do { } while(0) +#define PSI_CALL_set_thread_account(A1, A2, A3, A4) do { } while(0) +#define PSI_CALL_spawn_thread(A1, A2, A3, A4, A5) 0 +#define PSI_CALL_set_connection_type(A) do { } while(0) +#endif + + +/** + An instrumented mutex structure. + @sa mysql_mutex_t +*/ +struct st_mysql_mutex +{ + /** The real mutex. */ +#ifdef SAFE_MUTEX + safe_mutex_t m_mutex; +#else + pthread_mutex_t m_mutex; +#endif + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_mutex_t interface. + */ + struct PSI_mutex *m_psi; +}; + +/** + Type of an instrumented mutex. + @c mysql_mutex_t is a drop-in replacement for @c pthread_mutex_t. + @sa mysql_mutex_assert_owner + @sa mysql_mutex_assert_not_owner + @sa mysql_mutex_init + @sa mysql_mutex_lock + @sa mysql_mutex_unlock + @sa mysql_mutex_destroy +*/ +typedef struct st_mysql_mutex mysql_mutex_t; + +/** + An instrumented rwlock structure. + @sa mysql_rwlock_t +*/ +struct st_mysql_rwlock +{ + /** The real rwlock */ + rw_lock_t m_rwlock; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_rwlock_t interface. + */ + struct PSI_rwlock *m_psi; +}; + +/** + An instrumented prlock structure. + @sa mysql_prlock_t +*/ +struct st_mysql_prlock +{ + /** The real prlock */ + rw_pr_lock_t m_prlock; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_rwlock_t interface. + */ + struct PSI_rwlock *m_psi; +}; + +/** + Type of an instrumented rwlock. + @c mysql_rwlock_t is a drop-in replacement for @c pthread_rwlock_t. + @sa mysql_rwlock_init + @sa mysql_rwlock_rdlock + @sa mysql_rwlock_tryrdlock + @sa mysql_rwlock_wrlock + @sa mysql_rwlock_trywrlock + @sa mysql_rwlock_unlock + @sa mysql_rwlock_destroy +*/ +typedef struct st_mysql_rwlock mysql_rwlock_t; + +/** + Type of an instrumented prlock. + A prlock is a read write lock that 'prefers readers' (pr). + @c mysql_prlock_t is a drop-in replacement for @c rw_pr_lock_t. + @sa mysql_prlock_init + @sa mysql_prlock_rdlock + @sa mysql_prlock_wrlock + @sa mysql_prlock_unlock + @sa mysql_prlock_destroy +*/ +typedef struct st_mysql_prlock mysql_prlock_t; + +/** + An instrumented cond structure. + @sa mysql_cond_t +*/ +struct st_mysql_cond +{ + /** The real condition */ + pthread_cond_t m_cond; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_cond_t interface. + */ + struct PSI_cond *m_psi; +}; + +/** + Type of an instrumented condition. + @c mysql_cond_t is a drop-in replacement for @c pthread_cond_t. + @sa mysql_cond_init + @sa mysql_cond_wait + @sa mysql_cond_timedwait + @sa mysql_cond_signal + @sa mysql_cond_broadcast + @sa mysql_cond_destroy +*/ +typedef struct st_mysql_cond mysql_cond_t; + +/* + Consider the following code: + static inline void foo() { bar(); } + when foo() is never called. + + With gcc, foo() is a local static function, so the dependencies + are optimized away at compile time, and there is no dependency on bar(). + With other compilers (HP, Sun Studio), the function foo() implementation + is compiled, and bar() needs to be present to link. + + Due to the existing header dependencies in MySQL code, this header file + is sometime used when it is not needed, which in turn cause link failures + on some platforms. + The proper fix would be to cut these extra dependencies in the calling code. + DISABLE_MYSQL_THREAD_H is a work around to limit dependencies. + DISABLE_MYSQL_PRLOCK_H is similar, and is used to disable specifically + the prlock wrappers. +*/ +#ifndef DISABLE_MYSQL_THREAD_H + +#define mysql_mutex_is_owner(M) safe_mutex_is_owner(&(M)->m_mutex) +/** + @def mysql_mutex_assert_owner(M) + Wrapper, to use safe_mutex_assert_owner with instrumented mutexes. + @c mysql_mutex_assert_owner is a drop-in replacement + for @c safe_mutex_assert_owner. +*/ +#define mysql_mutex_assert_owner(M) \ + safe_mutex_assert_owner(&(M)->m_mutex) + +/** + @def mysql_mutex_assert_not_owner(M) + Wrapper, to use safe_mutex_assert_not_owner with instrumented mutexes. + @c mysql_mutex_assert_not_owner is a drop-in replacement + for @c safe_mutex_assert_not_owner. +*/ +#define mysql_mutex_assert_not_owner(M) \ + safe_mutex_assert_not_owner(&(M)->m_mutex) + +#define mysql_mutex_setflags(M, F) \ + safe_mutex_setflags(&(M)->m_mutex, (F)) + +/** + @def mysql_prlock_assert_write_owner(M) + Drop-in replacement + for @c rw_pr_lock_assert_write_owner. +*/ +#define mysql_prlock_assert_write_owner(M) \ + rw_pr_lock_assert_write_owner(&(M)->m_prlock) + +/** + @def mysql_prlock_assert_not_write_owner(M) + Drop-in replacement + for @c rw_pr_lock_assert_not_write_owner. +*/ +#define mysql_prlock_assert_not_write_owner(M) \ + rw_pr_lock_assert_not_write_owner(&(M)->m_prlock) + +/** + @def mysql_mutex_register(P1, P2, P3) + Mutex registration. +*/ +#define mysql_mutex_register(P1, P2, P3) \ + inline_mysql_mutex_register(P1, P2, P3) + +/** + @def mysql_mutex_init(K, M, A) + Instrumented mutex_init. + @c mysql_mutex_init is a replacement for @c pthread_mutex_init. + @param K The PSI_mutex_key for this instrumented mutex + @param M The mutex to initialize + @param A Mutex attributes +*/ + +#ifdef HAVE_PSI_MUTEX_INTERFACE + #ifdef SAFE_MUTEX + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(K, M, A, #M, __FILE__, __LINE__) + #else + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(K, M, A) + #endif +#else + #ifdef SAFE_MUTEX + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(M, A, #M, __FILE__, __LINE__) + #else + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(M, A) + #endif +#endif + +/** + @def mysql_mutex_destroy(M) + Instrumented mutex_destroy. + @c mysql_mutex_destroy is a drop-in replacement + for @c pthread_mutex_destroy. +*/ +#ifdef SAFE_MUTEX + #define mysql_mutex_destroy(M) \ + inline_mysql_mutex_destroy(M, __FILE__, __LINE__) +#else + #define mysql_mutex_destroy(M) \ + inline_mysql_mutex_destroy(M) +#endif + +/** + @def mysql_mutex_lock(M) + Instrumented mutex_lock. + @c mysql_mutex_lock is a drop-in replacement for @c pthread_mutex_lock. + @param M The mutex to lock +*/ + +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) + #define mysql_mutex_lock(M) \ + inline_mysql_mutex_lock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_lock(M) \ + inline_mysql_mutex_lock(M) +#endif + +/** + @def mysql_mutex_trylock(M) + Instrumented mutex_lock. + @c mysql_mutex_trylock is a drop-in replacement + for @c pthread_mutex_trylock. +*/ + +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) + #define mysql_mutex_trylock(M) \ + inline_mysql_mutex_trylock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_trylock(M) \ + inline_mysql_mutex_trylock(M) +#endif + +/** + @def mysql_mutex_unlock(M) + Instrumented mutex_unlock. + @c mysql_mutex_unlock is a drop-in replacement for @c pthread_mutex_unlock. +*/ +#ifdef SAFE_MUTEX + #define mysql_mutex_unlock(M) \ + inline_mysql_mutex_unlock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_unlock(M) \ + inline_mysql_mutex_unlock(M) +#endif + +/** + @def mysql_rwlock_register(P1, P2, P3) + Rwlock registration. +*/ +#define mysql_rwlock_register(P1, P2, P3) \ + inline_mysql_rwlock_register(P1, P2, P3) + +/** + @def mysql_rwlock_init(K, RW) + Instrumented rwlock_init. + @c mysql_rwlock_init is a replacement for @c pthread_rwlock_init. + Note that pthread_rwlockattr_t is not supported in MySQL. + @param K The PSI_rwlock_key for this instrumented rwlock + @param RW The rwlock to initialize +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(K, RW) +#else + #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(RW) +#endif + +/** + @def mysql_prlock_init(K, RW) + Instrumented rw_pr_init. + @c mysql_prlock_init is a replacement for @c rw_pr_init. + @param K The PSI_rwlock_key for this instrumented prlock + @param RW The prlock to initialize +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_prlock_init(K, RW) inline_mysql_prlock_init(K, RW) +#else + #define mysql_prlock_init(K, RW) inline_mysql_prlock_init(RW) +#endif + +/** + @def mysql_rwlock_destroy(RW) + Instrumented rwlock_destroy. + @c mysql_rwlock_destroy is a drop-in replacement + for @c pthread_rwlock_destroy. +*/ +#define mysql_rwlock_destroy(RW) inline_mysql_rwlock_destroy(RW) + +/** + @def mysql_prlock_destroy(RW) + Instrumented rw_pr_destroy. + @c mysql_prlock_destroy is a drop-in replacement + for @c rw_pr_destroy. +*/ +#define mysql_prlock_destroy(RW) inline_mysql_prlock_destroy(RW) + +/** + @def mysql_rwlock_rdlock(RW) + Instrumented rwlock_rdlock. + @c mysql_rwlock_rdlock is a drop-in replacement + for @c pthread_rwlock_rdlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_rdlock(RW) \ + inline_mysql_rwlock_rdlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_rdlock(RW) \ + inline_mysql_rwlock_rdlock(RW) +#endif + +/** + @def mysql_prlock_rdlock(RW) + Instrumented rw_pr_rdlock. + @c mysql_prlock_rdlock is a drop-in replacement + for @c rw_pr_rdlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_prlock_rdlock(RW) \ + inline_mysql_prlock_rdlock(RW, __FILE__, __LINE__) +#else + #define mysql_prlock_rdlock(RW) \ + inline_mysql_prlock_rdlock(RW) +#endif + +/** + @def mysql_rwlock_wrlock(RW) + Instrumented rwlock_wrlock. + @c mysql_rwlock_wrlock is a drop-in replacement + for @c pthread_rwlock_wrlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_wrlock(RW) \ + inline_mysql_rwlock_wrlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_wrlock(RW) \ + inline_mysql_rwlock_wrlock(RW) +#endif + +/** + @def mysql_prlock_wrlock(RW) + Instrumented rw_pr_wrlock. + @c mysql_prlock_wrlock is a drop-in replacement + for @c rw_pr_wrlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_prlock_wrlock(RW) \ + inline_mysql_prlock_wrlock(RW, __FILE__, __LINE__) +#else + #define mysql_prlock_wrlock(RW) \ + inline_mysql_prlock_wrlock(RW) +#endif + +/** + @def mysql_rwlock_tryrdlock(RW) + Instrumented rwlock_tryrdlock. + @c mysql_rwlock_tryrdlock is a drop-in replacement + for @c pthread_rwlock_tryrdlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_tryrdlock(RW) \ + inline_mysql_rwlock_tryrdlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_tryrdlock(RW) \ + inline_mysql_rwlock_tryrdlock(RW) +#endif + +/** + @def mysql_rwlock_trywrlock(RW) + Instrumented rwlock_trywrlock. + @c mysql_rwlock_trywrlock is a drop-in replacement + for @c pthread_rwlock_trywrlock. +*/ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + #define mysql_rwlock_trywrlock(RW) \ + inline_mysql_rwlock_trywrlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_trywrlock(RW) \ + inline_mysql_rwlock_trywrlock(RW) +#endif + +/** + @def mysql_rwlock_unlock(RW) + Instrumented rwlock_unlock. + @c mysql_rwlock_unlock is a drop-in replacement + for @c pthread_rwlock_unlock. +*/ +#define mysql_rwlock_unlock(RW) inline_mysql_rwlock_unlock(RW) + +/** + @def mysql_prlock_unlock(RW) + Instrumented rw_pr_unlock. + @c mysql_prlock_unlock is a drop-in replacement + for @c rw_pr_unlock. +*/ +#define mysql_prlock_unlock(RW) inline_mysql_prlock_unlock(RW) + +/** + @def mysql_cond_register(P1, P2, P3) + Cond registration. +*/ +#define mysql_cond_register(P1, P2, P3) \ + inline_mysql_cond_register(P1, P2, P3) + +/** + @def mysql_cond_init(K, C, A) + Instrumented cond_init. + @c mysql_cond_init is a replacement for @c pthread_cond_init. + @param C The cond to initialize + @param K The PSI_cond_key for this instrumented cond + @param A Condition attributes +*/ +#ifdef HAVE_PSI_COND_INTERFACE + #define mysql_cond_init(K, C, A) inline_mysql_cond_init(K, C, A) +#else + #define mysql_cond_init(K, C, A) inline_mysql_cond_init(C, A) +#endif + +/** + @def mysql_cond_destroy(C) + Instrumented cond_destroy. + @c mysql_cond_destroy is a drop-in replacement for @c pthread_cond_destroy. +*/ +#define mysql_cond_destroy(C) inline_mysql_cond_destroy(C) + +/** + @def mysql_cond_wait(C) + Instrumented cond_wait. + @c mysql_cond_wait is a drop-in replacement for @c pthread_cond_wait. +*/ +#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) + #define mysql_cond_wait(C, M) \ + inline_mysql_cond_wait(C, M, __FILE__, __LINE__) +#else + #define mysql_cond_wait(C, M) \ + inline_mysql_cond_wait(C, M) +#endif + +/** + @def mysql_cond_timedwait(C, M, W) + Instrumented cond_timedwait. + @c mysql_cond_timedwait is a drop-in replacement + for @c pthread_cond_timedwait. +*/ +#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) + #define mysql_cond_timedwait(C, M, W) \ + inline_mysql_cond_timedwait(C, M, W, __FILE__, __LINE__) +#else + #define mysql_cond_timedwait(C, M, W) \ + inline_mysql_cond_timedwait(C, M, W) +#endif + +/** + @def mysql_cond_signal(C) + Instrumented cond_signal. + @c mysql_cond_signal is a drop-in replacement for @c pthread_cond_signal. +*/ +#define mysql_cond_signal(C) inline_mysql_cond_signal(C) + +/** + @def mysql_cond_broadcast(C) + Instrumented cond_broadcast. + @c mysql_cond_broadcast is a drop-in replacement + for @c pthread_cond_broadcast. +*/ +#define mysql_cond_broadcast(C) inline_mysql_cond_broadcast(C) + +/** + @def mysql_thread_register(P1, P2, P3) + Thread registration. +*/ +#define mysql_thread_register(P1, P2, P3) \ + inline_mysql_thread_register(P1, P2, P3) + +/** + @def mysql_thread_create(K, P1, P2, P3, P4) + Instrumented pthread_create. + This function creates both the thread instrumentation and a thread. + @c mysql_thread_create is a replacement for @c pthread_create. + The parameter P4 (or, if it is NULL, P1) will be used as the + instrumented thread "identity". + Providing a P1 / P4 parameter with a different value for each call + will on average improve performances, since this thread identity value + is used internally to randomize access to data and prevent contention. + This is optional, and the improvement is not guaranteed, only statistical. + @param K The PSI_thread_key for this instrumented thread + @param P1 pthread_create parameter 1 + @param P2 pthread_create parameter 2 + @param P3 pthread_create parameter 3 + @param P4 pthread_create parameter 4 +*/ +#ifdef HAVE_PSI_THREAD_INTERFACE + #define mysql_thread_create(K, P1, P2, P3, P4) \ + inline_mysql_thread_create(K, P1, P2, P3, P4) +#else + #define mysql_thread_create(K, P1, P2, P3, P4) \ + pthread_create(P1, P2, P3, P4) +#endif + +/** + @def mysql_thread_set_psi_id(I) + Set the thread identifier for the instrumentation. + @param I The thread identifier +*/ +#ifdef HAVE_PSI_THREAD_INTERFACE + #define mysql_thread_set_psi_id(I) inline_mysql_thread_set_psi_id(I) +#else + #define mysql_thread_set_psi_id(I) do {} while (0) +#endif + +/** + @def mysql_thread_set_psi_THD(T) + Set the thread sql session for the instrumentation. + @param I The thread identifier +*/ +#ifdef HAVE_PSI_THREAD_INTERFACE + #define mysql_thread_set_psi_THD(T) inline_mysql_thread_set_psi_THD(T) +#else + #define mysql_thread_set_psi_THD(T) do {} while (0) +#endif + +static inline void inline_mysql_mutex_register( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char *category, + PSI_mutex_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + PSI_MUTEX_CALL(register_mutex)(category, info, count); +#endif +} + +static inline int inline_mysql_mutex_init( +#ifdef HAVE_PSI_MUTEX_INTERFACE + PSI_mutex_key key, +#endif + mysql_mutex_t *that, + const pthread_mutexattr_t *attr +#ifdef SAFE_MUTEX + , const char *src_name, const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + that->m_psi= PSI_MUTEX_CALL(init_mutex)(key, &that->m_mutex); +#else + that->m_psi= NULL; +#endif +#ifdef SAFE_MUTEX + return safe_mutex_init(&that->m_mutex, attr, src_name, src_file, src_line); +#else + return pthread_mutex_init(&that->m_mutex, attr); +#endif +} + +static inline int inline_mysql_mutex_destroy( + mysql_mutex_t *that +#ifdef SAFE_MUTEX + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + if (that->m_psi != NULL) + { + PSI_MUTEX_CALL(destroy_mutex)(that->m_psi); + that->m_psi= NULL; + } +#endif +#ifdef SAFE_MUTEX + return safe_mutex_destroy(&that->m_mutex, src_file, src_line); +#else + return pthread_mutex_destroy(&that->m_mutex); +#endif +} + +#ifdef HAVE_PSI_MUTEX_INTERFACE +ATTRIBUTE_COLD int psi_mutex_lock(mysql_mutex_t *that, + const char *file, uint line); +ATTRIBUTE_COLD int psi_mutex_trylock(mysql_mutex_t *that, + const char *file, uint line); +#endif + +static inline int inline_mysql_mutex_lock( + mysql_mutex_t *that +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_mutex_lock(that, src_file, src_line); +#endif + /* Non instrumented code */ +#ifdef SAFE_MUTEX + return safe_mutex_lock(&that->m_mutex, FALSE, src_file, src_line); +#else + return pthread_mutex_lock(&that->m_mutex); +#endif +} + +static inline int inline_mysql_mutex_trylock( + mysql_mutex_t *that +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_MUTEX_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_mutex_trylock(that, src_file, src_line); +#endif + /* Non instrumented code */ +#ifdef SAFE_MUTEX + return safe_mutex_lock(&that->m_mutex, TRUE, src_file, src_line); +#else + return pthread_mutex_trylock(&that->m_mutex); +#endif +} + +static inline int inline_mysql_mutex_unlock( + mysql_mutex_t *that +#ifdef SAFE_MUTEX + , const char *src_file, uint src_line +#endif + ) +{ + int result; + +#ifdef HAVE_PSI_MUTEX_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_MUTEX_CALL(unlock_mutex)(that->m_psi); +#endif + +#ifdef SAFE_MUTEX + result= safe_mutex_unlock(&that->m_mutex, src_file, src_line); +#else + result= pthread_mutex_unlock(&that->m_mutex); +#endif + + return result; +} + +static inline void inline_mysql_rwlock_register( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char *category, + PSI_rwlock_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + PSI_RWLOCK_CALL(register_rwlock)(category, info, count); +#endif +} + +static inline int inline_mysql_rwlock_init( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + PSI_rwlock_key key, +#endif + mysql_rwlock_t *that) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_rwlock); +#else + that->m_psi= NULL; +#endif + /* + pthread_rwlockattr_t is not used in MySQL. + */ + return my_rwlock_init(&that->m_rwlock, NULL); +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_init( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + PSI_rwlock_key key, +#endif + mysql_prlock_t *that) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_prlock); +#else + that->m_psi= NULL; +#endif + return rw_pr_init(&that->m_prlock); +} +#endif + +static inline int inline_mysql_rwlock_destroy( + mysql_rwlock_t *that) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + { + PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi); + that->m_psi= NULL; + } +#endif + return rwlock_destroy(&that->m_rwlock); +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_destroy( + mysql_prlock_t *that) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + { + PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi); + that->m_psi= NULL; + } +#endif + return rw_pr_destroy(&that->m_prlock); +} +#endif + +#ifdef HAVE_PSI_RWLOCK_INTERFACE +ATTRIBUTE_COLD +int psi_rwlock_rdlock(mysql_rwlock_t *that, const char *file, uint line); +ATTRIBUTE_COLD +int psi_rwlock_tryrdlock(mysql_rwlock_t *that, const char *file, uint line); +ATTRIBUTE_COLD +int psi_rwlock_wrlock(mysql_rwlock_t *that, const char *file, uint line); +ATTRIBUTE_COLD +int psi_rwlock_trywrlock(mysql_rwlock_t *that, const char *file, uint line); +# ifndef DISABLE_MYSQL_PRLOCK_H +ATTRIBUTE_COLD +int psi_prlock_rdlock(mysql_prlock_t *that, const char *file, uint line); +ATTRIBUTE_COLD +int psi_prlock_wrlock(mysql_prlock_t *that, const char *file, uint line); +# endif +#endif + +static inline int inline_mysql_rwlock_rdlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_rwlock_rdlock(that, src_file, src_line); +#endif + return rw_rdlock(&that->m_rwlock); +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_rdlock( + mysql_prlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_prlock_rdlock(that, src_file, src_line); +#endif + return rw_pr_rdlock(&that->m_prlock); +} +#endif + +static inline int inline_mysql_rwlock_wrlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_rwlock_wrlock(that, src_file, src_line); +#endif + return rw_wrlock(&that->m_rwlock); +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_wrlock( + mysql_prlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_prlock_wrlock(that, src_file, src_line); +#endif + return rw_pr_wrlock(&that->m_prlock); +} +#endif + +static inline int inline_mysql_rwlock_tryrdlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_rwlock_tryrdlock(that, src_file, src_line); +#endif + return rw_tryrdlock(&that->m_rwlock); +} + +static inline int inline_mysql_rwlock_trywrlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_rwlock_trywrlock(that, src_file, src_line); +#endif + return rw_trywrlock(&that->m_rwlock); +} + +static inline int inline_mysql_rwlock_unlock( + mysql_rwlock_t *that) +{ + int result; +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi); +#endif + result= rw_unlock(&that->m_rwlock); + return result; +} + +#ifndef DISABLE_MYSQL_PRLOCK_H +static inline int inline_mysql_prlock_unlock( + mysql_prlock_t *that) +{ + int result; +#ifdef HAVE_PSI_RWLOCK_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi); +#endif + result= rw_pr_unlock(&that->m_prlock); + return result; +} +#endif + +static inline void inline_mysql_cond_register( +#ifdef HAVE_PSI_COND_INTERFACE + const char *category, + PSI_cond_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_COND_INTERFACE + PSI_COND_CALL(register_cond)(category, info, count); +#endif +} + +static inline int inline_mysql_cond_init( +#ifdef HAVE_PSI_COND_INTERFACE + PSI_cond_key key, +#endif + mysql_cond_t *that, + const pthread_condattr_t *attr) +{ +#ifdef HAVE_PSI_COND_INTERFACE + that->m_psi= PSI_COND_CALL(init_cond)(key, &that->m_cond); +#else + that->m_psi= NULL; +#endif + return pthread_cond_init(&that->m_cond, attr); +} + +static inline int inline_mysql_cond_destroy( + mysql_cond_t *that) +{ +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + { + PSI_COND_CALL(destroy_cond)(that->m_psi); + that->m_psi= NULL; + } +#endif + return pthread_cond_destroy(&that->m_cond); +} + +#ifdef HAVE_PSI_COND_INTERFACE +ATTRIBUTE_COLD int psi_cond_wait(mysql_cond_t *that, mysql_mutex_t *mutex, + const char *file, uint line); +ATTRIBUTE_COLD int psi_cond_timedwait(mysql_cond_t *that, mysql_mutex_t *mutex, + const struct timespec *abstime, + const char *file, uint line); +#endif + +static inline int inline_mysql_cond_wait( + mysql_cond_t *that, + mysql_mutex_t *mutex +#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_cond_wait(that, mutex, src_file, src_line); +#endif + return my_cond_wait(&that->m_cond, &mutex->m_mutex); +} + +static inline int inline_mysql_cond_timedwait( + mysql_cond_t *that, + mysql_mutex_t *mutex, + const struct timespec *abstime +#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + return psi_cond_timedwait(that, mutex, abstime, src_file, src_line); +#endif + return my_cond_timedwait(&that->m_cond, &mutex->m_mutex, abstime); +} + +static inline int inline_mysql_cond_signal( + mysql_cond_t *that) +{ + int result; +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_COND_CALL(signal_cond)(that->m_psi); +#endif + result= pthread_cond_signal(&that->m_cond); + return result; +} + +static inline int inline_mysql_cond_broadcast( + mysql_cond_t *that) +{ + int result; +#ifdef HAVE_PSI_COND_INTERFACE + if (psi_likely(that->m_psi != NULL)) + PSI_COND_CALL(broadcast_cond)(that->m_psi); +#endif + result= pthread_cond_broadcast(&that->m_cond); + return result; +} + +static inline void inline_mysql_thread_register( +#ifdef HAVE_PSI_THREAD_INTERFACE + const char *category, + PSI_thread_info *info, + int count +#else + const char *category __attribute__ ((unused)), + void *info __attribute__ ((unused)), + int count __attribute__ ((unused)) +#endif +) +{ +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_THREAD_CALL(register_thread)(category, info, count); +#endif +} + +#ifdef HAVE_PSI_THREAD_INTERFACE +static inline int inline_mysql_thread_create( + PSI_thread_key key, + pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg) +{ + int result; + result= PSI_THREAD_CALL(spawn_thread)(key, thread, attr, start_routine, arg); + return result; +} + +static inline void inline_mysql_thread_set_psi_id(my_thread_id id) +{ + struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)(); + PSI_THREAD_CALL(set_thread_id)(psi, id); +} + +#ifdef __cplusplus +class THD; +static inline void inline_mysql_thread_set_psi_THD(THD *thd) +{ + struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)(); + PSI_THREAD_CALL(set_thread_THD)(psi, thd); +} +#endif /* __cplusplus */ + +static inline void mysql_thread_set_peer_port(uint port __attribute__ ((unused))) { +#ifdef HAVE_PSI_THREAD_INTERFACE + struct PSI_thread *psi = PSI_THREAD_CALL(get_thread)(); + PSI_THREAD_CALL(set_thread_peer_port)(psi, port); +#endif +} + +#endif + +#endif /* DISABLE_MYSQL_THREAD_H */ + +/** @} (end of group Thread_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_transaction.h b/include/mysql/psi/mysql_transaction.h new file mode 100644 index 00000000..a4444804 --- /dev/null +++ b/include/mysql/psi/mysql_transaction.h @@ -0,0 +1,220 @@ +/* Copyright (c) 2013, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef MYSQL_TRANSACTION_H +#define MYSQL_TRANSACTION_H + +/** + @file mysql/psi/mysql_transaction.h + Instrumentation helpers for transactions. +*/ + +#include "mysql/psi/psi.h" + +#ifndef PSI_TRANSACTION_CALL +#define PSI_TRANSACTION_CALL(M) PSI_DYNAMIC_CALL(M) +#endif + +/** + @defgroup Transaction_instrumentation Transaction Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_START_TRANSACTION(STATE, XID, TRXID, ISO, RO, AC) \ + inline_mysql_start_transaction(STATE, XID, TRXID, ISO, RO, AC, __FILE__, __LINE__) +#else + #define MYSQL_START_TRANSACTION(STATE, XID, TRXID, ISO, RO, AC) \ + 0 +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_SET_TRANSACTION_GTID(LOCKER, P1, P2) \ + inline_mysql_set_transaction_gtid(LOCKER, P1, P2) +#else + #define MYSQL_SET_TRANSACTION_GTID(LOCKER, P1, P2) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_SET_TRANSACTION_XID(LOCKER, P1, P2) \ + inline_mysql_set_transaction_xid(LOCKER, P1, P2) +#else + #define MYSQL_SET_TRANSACTION_XID(LOCKER, P1, P2) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_SET_TRANSACTION_XA_STATE(LOCKER, P1) \ + inline_mysql_set_transaction_xa_state(LOCKER, P1) +#else + #define MYSQL_SET_TRANSACTION_XA_STATE(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_SET_TRANSACTION_TRXID(LOCKER, P1) \ + inline_mysql_set_transaction_trxid(LOCKER, P1) +#else + #define MYSQL_SET_TRANSACTION_TRXID(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_INC_TRANSACTION_SAVEPOINTS(LOCKER, P1) \ + inline_mysql_inc_transaction_savepoints(LOCKER, P1) +#else + #define MYSQL_INC_TRANSACTION_SAVEPOINTS(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(LOCKER, P1) \ + inline_mysql_inc_transaction_rollback_to_savepoint(LOCKER, P1) +#else + #define MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(LOCKER, P1) \ + inline_mysql_inc_transaction_release_savepoint(LOCKER, P1) +#else + #define MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(LOCKER, P1) \ + do {} while (0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_ROLLBACK_TRANSACTION(LOCKER) \ + inline_mysql_rollback_transaction(LOCKER) +#else + #define MYSQL_ROLLBACK_TRANSACTION(LOCKER) \ + do { } while(0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE + #define MYSQL_COMMIT_TRANSACTION(LOCKER) \ + inline_mysql_commit_transaction(LOCKER) +#else + #define MYSQL_COMMIT_TRANSACTION(LOCKER) \ + do { } while(0) +#endif + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE +static inline struct PSI_transaction_locker * +inline_mysql_start_transaction(PSI_transaction_locker_state *state, + const void *xid, + ulonglong trxid, + int isolation_level, + my_bool read_only, + my_bool autocommit, + const char *src_file, int src_line) +{ + PSI_transaction_locker *locker; + locker= PSI_TRANSACTION_CALL(get_thread_transaction_locker)(state, + xid, trxid, + isolation_level, + read_only, + autocommit); + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(start_transaction)(locker, src_file, src_line); + return locker; +} + +static inline void +inline_mysql_set_transaction_gtid(PSI_transaction_locker *locker, + const void *sid, + const void *gtid_spec) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(set_transaction_gtid)(locker, sid, gtid_spec); +} + +static inline void +inline_mysql_set_transaction_xid(PSI_transaction_locker *locker, + const void *xid, + int xa_state) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(set_transaction_xid)(locker, xid, xa_state); +} + +static inline void +inline_mysql_set_transaction_xa_state(PSI_transaction_locker *locker, + int xa_state) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(set_transaction_xa_state)(locker, xa_state); +} + +static inline void +inline_mysql_set_transaction_trxid(PSI_transaction_locker *locker, + const ulonglong *trxid) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(set_transaction_trxid)(locker, trxid); +} + +static inline void +inline_mysql_inc_transaction_savepoints(PSI_transaction_locker *locker, + ulong count) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(inc_transaction_savepoints)(locker, count); +} + +static inline void +inline_mysql_inc_transaction_rollback_to_savepoint(PSI_transaction_locker *locker, + ulong count) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(inc_transaction_rollback_to_savepoint)(locker, count); +} + +static inline void +inline_mysql_inc_transaction_release_savepoint(PSI_transaction_locker *locker, + ulong count) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(inc_transaction_release_savepoint)(locker, count); +} + +static inline void +inline_mysql_rollback_transaction(struct PSI_transaction_locker *locker) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(end_transaction)(locker, false); +} + +static inline void +inline_mysql_commit_transaction(struct PSI_transaction_locker *locker) +{ + if (likely(locker != NULL)) + PSI_TRANSACTION_CALL(end_transaction)(locker, true); +} +#endif + +/** @} (end of group Transaction_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/psi.h b/include/mysql/psi/psi.h new file mode 100644 index 00000000..702d31fa --- /dev/null +++ b/include/mysql/psi/psi.h @@ -0,0 +1,3039 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H +#define MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H + +#ifndef MY_GLOBAL_INCLUDED +/* + Make sure a .c or .cc file contains an include to my_global.h first. + When this include is missing, all the #ifdef HAVE_XXX have no effect, + and the resulting binary won't build, or won't link, + or will crash at runtime + since various structures will have different binary definitions. +*/ +#error "You must include my_global.h in the code for the build to be correct." +#endif + +/* + If PSI_ON_BY_DFAULT is defined, assume PSI will be enabled by default and + optimize jumps testing for PSI this case. If not, optimize the binary for + that PSI is not enabled +*/ + +#ifdef PSI_ON_BY_DEFAULT +#define psi_likely(A) likely(A) +#define psi_unlikely(A) unlikely(A) +#else +#define psi_likely(A) unlikely(A) +#define psi_unlikely(A) likely(A) +#endif + +#include "psi_base.h" +#include "psi_memory.h" + +#ifdef _WIN32 +typedef struct thread_attr pthread_attr_t; +typedef DWORD pthread_t; +typedef DWORD pthread_key_t; +#endif + +/* + MAINTAINER: + The following pattern: + typedef struct XYZ XYZ; + is not needed in C++, but required for C. +*/ + +C_MODE_START + +/** @sa MDL_key. */ +struct MDL_key; +typedef struct MDL_key MDL_key; + +/** @sa enum_mdl_type. */ +typedef int opaque_mdl_type; + +/** @sa enum_mdl_duration. */ +typedef int opaque_mdl_duration; + +/** @sa MDL_wait::enum_wait_status. */ +typedef int opaque_mdl_status; + +/** @sa enum_vio_type. */ +typedef int opaque_vio_type; + +struct TABLE_SHARE; + +struct sql_digest_storage; + +#ifdef __cplusplus + class THD; +#else + /* + Phony declaration when compiling C code. + This is ok, because the C code will never have a THD anyway. + */ + struct opaque_THD + { + int dummy; + }; + typedef struct opaque_THD THD; +#endif + +/** + @file mysql/psi/psi.h + Performance schema instrumentation interface. + + @defgroup Instrumentation_interface Instrumentation Interface + @ingroup Performance_schema + @{ +*/ + +/** + Interface for an instrumented mutex. + This is an opaque structure. +*/ +struct PSI_mutex; +typedef struct PSI_mutex PSI_mutex; + +/** + Interface for an instrumented rwlock. + This is an opaque structure. +*/ +struct PSI_rwlock; +typedef struct PSI_rwlock PSI_rwlock; + +/** + Interface for an instrumented condition. + This is an opaque structure. +*/ +struct PSI_cond; +typedef struct PSI_cond PSI_cond; + +/** + Interface for an instrumented table share. + This is an opaque structure. +*/ +struct PSI_table_share; +typedef struct PSI_table_share PSI_table_share; + +/** + Interface for an instrumented table handle. + This is an opaque structure. +*/ +struct PSI_table; +typedef struct PSI_table PSI_table; + +/** + Interface for an instrumented thread. + This is an opaque structure. +*/ +struct PSI_thread; +typedef struct PSI_thread PSI_thread; + +/** + Interface for an instrumented file handle. + This is an opaque structure. +*/ +struct PSI_file; +typedef struct PSI_file PSI_file; + +/** + Interface for an instrumented socket descriptor. + This is an opaque structure. +*/ +struct PSI_socket; +typedef struct PSI_socket PSI_socket; + +/** + Interface for an instrumented prepared statement. + This is an opaque structure. +*/ +struct PSI_prepared_stmt; +typedef struct PSI_prepared_stmt PSI_prepared_stmt; + +/** + Interface for an instrumented table operation. + This is an opaque structure. +*/ +struct PSI_table_locker; +typedef struct PSI_table_locker PSI_table_locker; + +/** + Interface for an instrumented statement. + This is an opaque structure. +*/ +struct PSI_statement_locker; +typedef struct PSI_statement_locker PSI_statement_locker; + +/** + Interface for an instrumented transaction. + This is an opaque structure. +*/ +struct PSI_transaction_locker; +typedef struct PSI_transaction_locker PSI_transaction_locker; + +/** + Interface for an instrumented idle operation. + This is an opaque structure. +*/ +struct PSI_idle_locker; +typedef struct PSI_idle_locker PSI_idle_locker; + +/** + Interface for an instrumented statement digest operation. + This is an opaque structure. +*/ +struct PSI_digest_locker; +typedef struct PSI_digest_locker PSI_digest_locker; + +/** + Interface for an instrumented stored procedure share. + This is an opaque structure. +*/ +struct PSI_sp_share; +typedef struct PSI_sp_share PSI_sp_share; + +/** + Interface for an instrumented stored program. + This is an opaque structure. +*/ +struct PSI_sp_locker; +typedef struct PSI_sp_locker PSI_sp_locker; + +/** + Interface for an instrumented metadata lock. + This is an opaque structure. +*/ +struct PSI_metadata_lock; +typedef struct PSI_metadata_lock PSI_metadata_lock; + +/** + Interface for an instrumented stage progress. + This is a public structure, for efficiency. +*/ +struct PSI_stage_progress +{ + ulonglong m_work_completed; + ulonglong m_work_estimated; +}; +typedef struct PSI_stage_progress PSI_stage_progress; + +/** IO operation performed on an instrumented table. */ +enum PSI_table_io_operation +{ + /** Row fetch. */ + PSI_TABLE_FETCH_ROW= 0, + /** Row write. */ + PSI_TABLE_WRITE_ROW= 1, + /** Row update. */ + PSI_TABLE_UPDATE_ROW= 2, + /** Row delete. */ + PSI_TABLE_DELETE_ROW= 3 +}; +typedef enum PSI_table_io_operation PSI_table_io_operation; + +/** + State data storage for @c start_table_io_wait_v1_t, + @c start_table_lock_wait_v1_t. + This structure provide temporary storage to a table locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_table_io_wait_v1_t + @sa start_table_lock_wait_v1_t +*/ +struct PSI_table_locker_state +{ + /** Internal state. */ + uint m_flags; + /** Current io operation. */ + enum PSI_table_io_operation m_io_operation; + /** Current table handle. */ + struct PSI_table *m_table; + /** Current table share. */ + struct PSI_table_share *m_table_share; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; + /** + Implementation specific. + For table io, the table io index. + For table lock, the lock type. + */ + uint m_index; +}; +typedef struct PSI_table_locker_state PSI_table_locker_state; + +/** Entry point for the performance schema interface. */ +struct PSI_bootstrap +{ + /** + ABI interface finder. + Calling this method with an interface version number returns either + an instance of the ABI for this version, or NULL. + @param version the interface version number to find + @return a versioned interface (PSI_v1, PSI_v2 or PSI) + @sa PSI_VERSION_1 + @sa PSI_v1 + @sa PSI_VERSION_2 + @sa PSI_v2 + @sa PSI_CURRENT_VERSION + @sa PSI + */ + void* (*get_interface)(int version); +}; +typedef struct PSI_bootstrap PSI_bootstrap; + +#ifdef HAVE_PSI_INTERFACE + +#ifdef DISABLE_ALL_PSI + +#ifndef DISABLE_PSI_THREAD +#define DISABLE_PSI_THREAD +#endif + +#ifndef DISABLE_PSI_MUTEX +#define DISABLE_PSI_MUTEX +#endif + +#ifndef DISABLE_PSI_RWLOCK +#define DISABLE_PSI_RWLOCK +#endif + +#ifndef DISABLE_PSI_COND +#define DISABLE_PSI_COND +#endif + +#ifndef DISABLE_PSI_FILE +#define DISABLE_PSI_FILE +#endif + +#ifndef DISABLE_PSI_TABLE +#define DISABLE_PSI_TABLE +#endif + +#ifndef DISABLE_PSI_SOCKET +#define DISABLE_PSI_SOCKET +#endif + +#ifndef DISABLE_PSI_STAGE +#define DISABLE_PSI_STAGE +#endif + +#ifndef DISABLE_PSI_STATEMENT +#define DISABLE_PSI_STATEMENT +#endif + +#ifndef DISABLE_PSI_SP +#define DISABLE_PSI_SP +#endif + +#ifndef DISABLE_PSI_IDLE +#define DISABLE_PSI_IDLE +#endif + +#ifndef DISABLE_PSI_STATEMENT_DIGEST +#define DISABLE_PSI_STATEMENT_DIGEST +#endif + +#ifndef DISABLE_PSI_METADATA +#define DISABLE_PSI_METADATA +#endif + +#ifndef DISABLE_PSI_MEMORY +#define DISABLE_PSI_MEMORY +#endif + +#ifndef DISABLE_PSI_TRANSACTION +#define DISABLE_PSI_TRANSACTION +#endif + +#ifndef DISABLE_PSI_SP +#define DISABLE_PSI_SP +#endif + +#ifndef DISABLE_PSI_PS +#define DISABLE_PSI_PS +#endif + +#endif + +/** + @def DISABLE_PSI_MUTEX + Compiling option to disable the mutex instrumentation. + This option is mostly intended to be used during development, + when doing special builds with only a subset of the performance schema instrumentation, + for code analysis / profiling / performance tuning of a specific instrumentation alone. + @sa DISABLE_PSI_RWLOCK + @sa DISABLE_PSI_COND + @sa DISABLE_PSI_FILE + @sa DISABLE_PSI_THREAD + @sa DISABLE_PSI_TABLE + @sa DISABLE_PSI_STAGE + @sa DISABLE_PSI_STATEMENT + @sa DISABLE_PSI_SP + @sa DISABLE_PSI_STATEMENT_DIGEST + @sa DISABLE_PSI_SOCKET + @sa DISABLE_PSI_MEMORY + @sa DISABLE_PSI_IDLE + @sa DISABLE_PSI_METADATA + @sa DISABLE PSI_TRANSACTION +*/ + +#ifndef DISABLE_PSI_MUTEX +#define HAVE_PSI_MUTEX_INTERFACE +#endif + +/** + @def DISABLE_PSI_RWLOCK + Compiling option to disable the rwlock instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_RWLOCK +#define HAVE_PSI_RWLOCK_INTERFACE +#endif + +/** + @def DISABLE_PSI_COND + Compiling option to disable the cond instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_COND +#define HAVE_PSI_COND_INTERFACE +#endif + +/** + @def DISABLE_PSI_FILE + Compiling option to disable the file instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_FILE +#define HAVE_PSI_FILE_INTERFACE +#endif + +/** + @def DISABLE_PSI_THREAD + Compiling option to disable the thread instrumentation. + @sa DISABLE_PSI_MUTEX +*/ +#ifndef DISABLE_PSI_THREAD +#define HAVE_PSI_THREAD_INTERFACE +#endif + +/** + @def DISABLE_PSI_TABLE + Compiling option to disable the table instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_TABLE +#define HAVE_PSI_TABLE_INTERFACE +#endif + +/** + @def DISABLE_PSI_STAGE + Compiling option to disable the stage instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_STAGE +#define HAVE_PSI_STAGE_INTERFACE +#endif + +/** + @def DISABLE_PSI_STATEMENT + Compiling option to disable the statement instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_STATEMENT +#define HAVE_PSI_STATEMENT_INTERFACE +#endif + +/** + @def DISABLE_PSI_SP + Compiling option to disable the stored program instrumentation. + @sa DISABLE_PSI_MUTEX +*/ +#ifndef DISABLE_PSI_SP +#define HAVE_PSI_SP_INTERFACE +#endif + +/** + @def DISABLE_PSI_PS + Compiling option to disable the prepared statement instrumentation. + @sa DISABLE_PSI_MUTEX +*/ +#ifndef DISABLE_PSI_STATEMENT +#ifndef DISABLE_PSI_PS +#define HAVE_PSI_PS_INTERFACE +#endif +#endif + +/** + @def DISABLE_PSI_STATEMENT_DIGEST + Compiling option to disable the statement digest instrumentation. +*/ + +#ifndef DISABLE_PSI_STATEMENT +#ifndef DISABLE_PSI_STATEMENT_DIGEST +#define HAVE_PSI_STATEMENT_DIGEST_INTERFACE +#endif +#endif + +/** + @def DISABLE_PSI_TRANSACTION + Compiling option to disable the transaction instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_TRANSACTION +#define HAVE_PSI_TRANSACTION_INTERFACE +#endif + +/** + @def DISABLE_PSI_SOCKET + Compiling option to disable the statement instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_SOCKET +#define HAVE_PSI_SOCKET_INTERFACE +#endif + +/** + @def DISABLE_PSI_MEMORY + Compiling option to disable the memory instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_MEMORY +#define HAVE_PSI_MEMORY_INTERFACE +#endif + +/** + @def DISABLE_PSI_IDLE + Compiling option to disable the idle instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_IDLE +#define HAVE_PSI_IDLE_INTERFACE +#endif + +/** + @def DISABLE_PSI_METADATA + Compiling option to disable the metadata instrumentation. + @sa DISABLE_PSI_MUTEX +*/ + +#ifndef DISABLE_PSI_METADATA +#define HAVE_PSI_METADATA_INTERFACE +#endif + +/** + @def PSI_VERSION_1 + Performance Schema Interface number for version 1. + This version is supported. +*/ +#define PSI_VERSION_1 1 + +/** + @def PSI_VERSION_2 + Performance Schema Interface number for version 2. + This version is not implemented, it's a placeholder. +*/ +#define PSI_VERSION_2 2 + +/** + @def PSI_CURRENT_VERSION + Performance Schema Interface number for the most recent version. + The most current version is @c PSI_VERSION_1 +*/ +#define PSI_CURRENT_VERSION 1 + +#ifndef USE_PSI_2 +#ifndef USE_PSI_1 +#define USE_PSI_1 +#endif +#endif + +/** + Interface for an instrumented mutex operation. + This is an opaque structure. +*/ +struct PSI_mutex_locker; +typedef struct PSI_mutex_locker PSI_mutex_locker; + +/** + Interface for an instrumented rwlock operation. + This is an opaque structure. +*/ +struct PSI_rwlock_locker; +typedef struct PSI_rwlock_locker PSI_rwlock_locker; + +/** + Interface for an instrumented condition operation. + This is an opaque structure. +*/ +struct PSI_cond_locker; +typedef struct PSI_cond_locker PSI_cond_locker; + +/** + Interface for an instrumented file operation. + This is an opaque structure. +*/ +struct PSI_file_locker; +typedef struct PSI_file_locker PSI_file_locker; + +/** + Interface for an instrumented socket operation. + This is an opaque structure. +*/ +struct PSI_socket_locker; +typedef struct PSI_socket_locker PSI_socket_locker; + +/** + Interface for an instrumented MDL operation. + This is an opaque structure. +*/ +struct PSI_metadata_locker; +typedef struct PSI_metadata_locker PSI_metadata_locker; + +/** Operation performed on an instrumented mutex. */ +enum PSI_mutex_operation +{ + /** Lock. */ + PSI_MUTEX_LOCK= 0, + /** Lock attempt. */ + PSI_MUTEX_TRYLOCK= 1 +}; +typedef enum PSI_mutex_operation PSI_mutex_operation; + +/** + Operation performed on an instrumented rwlock. + For basic READ / WRITE lock, + operations are "READ" or "WRITE". + For SX-locks, operations are "SHARED", "SHARED-EXCLUSIVE" or "EXCLUSIVE". +*/ +enum PSI_rwlock_operation +{ + /** Read lock. */ + PSI_RWLOCK_READLOCK= 0, + /** Write lock. */ + PSI_RWLOCK_WRITELOCK= 1, + /** Read lock attempt. */ + PSI_RWLOCK_TRYREADLOCK= 2, + /** Write lock attempt. */ + PSI_RWLOCK_TRYWRITELOCK= 3, + + /** Shared lock. */ + PSI_RWLOCK_SHAREDLOCK= 4, + /** Shared Exclusive lock. */ + PSI_RWLOCK_SHAREDEXCLUSIVELOCK= 5, + /** Exclusive lock. */ + PSI_RWLOCK_EXCLUSIVELOCK= 6, + /** Shared lock attempt. */ + PSI_RWLOCK_TRYSHAREDLOCK= 7, + /** Shared Exclusive lock attempt. */ + PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK= 8, + /** Exclusive lock attempt. */ + PSI_RWLOCK_TRYEXCLUSIVELOCK= 9 + +}; +typedef enum PSI_rwlock_operation PSI_rwlock_operation; + +/** Operation performed on an instrumented condition. */ +enum PSI_cond_operation +{ + /** Wait. */ + PSI_COND_WAIT= 0, + /** Wait, with timeout. */ + PSI_COND_TIMEDWAIT= 1 +}; +typedef enum PSI_cond_operation PSI_cond_operation; + +/** Operation performed on an instrumented file. */ +enum PSI_file_operation +{ + /** File creation, as in @c create(). */ + PSI_FILE_CREATE= 0, + /** Temporary file creation, as in @c create_temp_file(). */ + PSI_FILE_CREATE_TMP= 1, + /** File open, as in @c open(). */ + PSI_FILE_OPEN= 2, + /** File open, as in @c fopen(). */ + PSI_FILE_STREAM_OPEN= 3, + /** File close, as in @c close(). */ + PSI_FILE_CLOSE= 4, + /** File close, as in @c fclose(). */ + PSI_FILE_STREAM_CLOSE= 5, + /** + Generic file read, such as @c fgets(), @c fgetc(), @c fread(), @c read(), + @c pread(). + */ + PSI_FILE_READ= 6, + /** + Generic file write, such as @c fputs(), @c fputc(), @c fprintf(), + @c vfprintf(), @c fwrite(), @c write(), @c pwrite(). + */ + PSI_FILE_WRITE= 7, + /** Generic file seek, such as @c fseek() or @c seek(). */ + PSI_FILE_SEEK= 8, + /** Generic file tell, such as @c ftell() or @c tell(). */ + PSI_FILE_TELL= 9, + /** File flush, as in @c fflush(). */ + PSI_FILE_FLUSH= 10, + /** File stat, as in @c stat(). */ + PSI_FILE_STAT= 11, + /** File stat, as in @c fstat(). */ + PSI_FILE_FSTAT= 12, + /** File chsize, as in @c my_chsize(). */ + PSI_FILE_CHSIZE= 13, + /** File delete, such as @c my_delete() or @c my_handler_delete_with_symlink(). */ + PSI_FILE_DELETE= 14, + /** File rename, such as @c my_rename() or @c my_rename_with_symlink(). */ + PSI_FILE_RENAME= 15, + /** File sync, as in @c fsync() or @c my_sync(). */ + PSI_FILE_SYNC= 16 +}; +typedef enum PSI_file_operation PSI_file_operation; + +/** Lock operation performed on an instrumented table. */ +enum PSI_table_lock_operation +{ + /** Table lock, in the server layer. */ + PSI_TABLE_LOCK= 0, + /** Table lock, in the storage engine layer. */ + PSI_TABLE_EXTERNAL_LOCK= 1 +}; +typedef enum PSI_table_lock_operation PSI_table_lock_operation; + +/** State of an instrumented socket. */ +enum PSI_socket_state +{ + /** Idle, waiting for the next command. */ + PSI_SOCKET_STATE_IDLE= 1, + /** Active, executing a command. */ + PSI_SOCKET_STATE_ACTIVE= 2 +}; +typedef enum PSI_socket_state PSI_socket_state; + +/** Operation performed on an instrumented socket. */ +enum PSI_socket_operation +{ + /** Socket creation, as in @c socket() or @c socketpair(). */ + PSI_SOCKET_CREATE= 0, + /** Socket connection, as in @c connect(), @c listen() and @c accept(). */ + PSI_SOCKET_CONNECT= 1, + /** Socket bind, as in @c bind(), @c getsockname() and @c getpeername(). */ + PSI_SOCKET_BIND= 2, + /** Socket close, as in @c shutdown(). */ + PSI_SOCKET_CLOSE= 3, + /** Socket send, @c send(). */ + PSI_SOCKET_SEND= 4, + /** Socket receive, @c recv(). */ + PSI_SOCKET_RECV= 5, + /** Socket send, @c sendto(). */ + PSI_SOCKET_SENDTO= 6, + /** Socket receive, @c recvfrom). */ + PSI_SOCKET_RECVFROM= 7, + /** Socket send, @c sendmsg(). */ + PSI_SOCKET_SENDMSG= 8, + /** Socket receive, @c recvmsg(). */ + PSI_SOCKET_RECVMSG= 9, + /** Socket seek, such as @c fseek() or @c seek(). */ + PSI_SOCKET_SEEK= 10, + /** Socket options, as in @c getsockopt() and @c setsockopt(). */ + PSI_SOCKET_OPT= 11, + /** Socket status, as in @c sockatmark() and @c isfdtype(). */ + PSI_SOCKET_STAT= 12, + /** Socket shutdown, as in @c shutdown(). */ + PSI_SOCKET_SHUTDOWN= 13, + /** Socket select, as in @c select() and @c poll(). */ + PSI_SOCKET_SELECT= 14 +}; +typedef enum PSI_socket_operation PSI_socket_operation; + +#endif +/** + Instrumented mutex key. + To instrument a mutex, a mutex key must be obtained using @c register_mutex. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_mutex_key; + +/** + Instrumented rwlock key. + To instrument a rwlock, a rwlock key must be obtained + using @c register_rwlock. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_rwlock_key; + +/** + Instrumented cond key. + To instrument a condition, a condition key must be obtained + using @c register_cond. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_cond_key; + +/** + Instrumented thread key. + To instrument a thread, a thread key must be obtained + using @c register_thread. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_thread_key; + +/** + Instrumented file key. + To instrument a file, a file key must be obtained using @c register_file. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_file_key; + +/** + Instrumented stage key. + To instrument a stage, a stage key must be obtained using @c register_stage. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_stage_key; + +/** + Instrumented statement key. + To instrument a statement, a statement key must be obtained using @c register_statement. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_statement_key; + +/** + Instrumented socket key. + To instrument a socket, a socket key must be obtained using @c register_socket. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_socket_key; + +#ifdef HAVE_PSI_1 + +/** + @defgroup Group_PSI_v1 Application Binary Interface, version 1 + @ingroup Instrumentation_interface + @{ +*/ + +/** + Mutex information. + @since PSI_VERSION_1 + This structure is used to register an instrumented mutex. +*/ +struct PSI_mutex_info_v1 +{ + /** + Pointer to the key assigned to the registered mutex. + */ + PSI_mutex_key *m_key; + /** + The name of the mutex to register. + */ + const char *m_name; + /** + The flags of the mutex to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_mutex_info_v1 PSI_mutex_info_v1; + +/** + Rwlock information. + @since PSI_VERSION_1 + This structure is used to register an instrumented rwlock. +*/ +struct PSI_rwlock_info_v1 +{ + /** + Pointer to the key assigned to the registered rwlock. + */ + PSI_rwlock_key *m_key; + /** + The name of the rwlock to register. + */ + const char *m_name; + /** + The flags of the rwlock to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info_v1; + +/** + Condition information. + @since PSI_VERSION_1 + This structure is used to register an instrumented cond. +*/ +struct PSI_cond_info_v1 +{ + /** + Pointer to the key assigned to the registered cond. + */ + PSI_cond_key *m_key; + /** + The name of the cond to register. + */ + const char *m_name; + /** + The flags of the cond to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_cond_info_v1 PSI_cond_info_v1; + +/** + Thread instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented thread. +*/ +struct PSI_thread_info_v1 +{ + /** + Pointer to the key assigned to the registered thread. + */ + PSI_thread_key *m_key; + /** + The name of the thread instrument to register. + */ + const char *m_name; + /** + The flags of the thread to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_thread_info_v1 PSI_thread_info_v1; + +/** + File instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented file. +*/ +struct PSI_file_info_v1 +{ + /** + Pointer to the key assigned to the registered file. + */ + PSI_file_key *m_key; + /** + The name of the file instrument to register. + */ + const char *m_name; + /** + The flags of the file instrument to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_file_info_v1 PSI_file_info_v1; + +/** + Stage instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented stage. +*/ +struct PSI_stage_info_v1 +{ + /** The registered stage key. */ + PSI_stage_key m_key; + /** The name of the stage instrument to register. */ + const char *m_name; + /** The flags of the stage instrument to register. */ + int m_flags; +}; +typedef struct PSI_stage_info_v1 PSI_stage_info_v1; + +/** + Statement instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented statement. +*/ +struct PSI_statement_info_v1 +{ + /** The registered statement key. */ + PSI_statement_key m_key; + /** The name of the statement instrument to register. */ + const char *m_name; + /** The flags of the statement instrument to register. */ + int m_flags; +}; +typedef struct PSI_statement_info_v1 PSI_statement_info_v1; + +/** + Socket instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented socket. +*/ +struct PSI_socket_info_v1 +{ + /** + Pointer to the key assigned to the registered socket. + */ + PSI_socket_key *m_key; + /** + The name of the socket instrument to register. + */ + const char *m_name; + /** + The flags of the socket instrument to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_socket_info_v1 PSI_socket_info_v1; + +/** + State data storage for @c start_idle_wait_v1_t. + This structure provide temporary storage to an idle locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_idle_wait_v1_t. +*/ +struct PSI_idle_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state_v1; + +/** + State data storage for @c start_mutex_wait_v1_t. + This structure provide temporary storage to a mutex locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_mutex_wait_v1_t +*/ +struct PSI_mutex_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current operation. */ + enum PSI_mutex_operation m_operation; + /** Current mutex. */ + struct PSI_mutex *m_mutex; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state_v1; + +/** + State data storage for @c start_rwlock_rdwait_v1_t, @c start_rwlock_wrwait_v1_t. + This structure provide temporary storage to a rwlock locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_rwlock_rdwait_v1_t + @sa start_rwlock_wrwait_v1_t +*/ +struct PSI_rwlock_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current operation. */ + enum PSI_rwlock_operation m_operation; + /** Current rwlock. */ + struct PSI_rwlock *m_rwlock; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state_v1; + +/** + State data storage for @c start_cond_wait_v1_t. + This structure provide temporary storage to a condition locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_cond_wait_v1_t +*/ +struct PSI_cond_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current operation. */ + enum PSI_cond_operation m_operation; + /** Current condition. */ + struct PSI_cond *m_cond; + /** Current mutex. */ + struct PSI_mutex *m_mutex; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state_v1; + +/** + State data storage for @c get_thread_file_name_locker_v1_t. + This structure provide temporary storage to a file locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa get_thread_file_name_locker_v1_t + @sa get_thread_file_stream_locker_v1_t + @sa get_thread_file_descriptor_locker_v1_t +*/ +struct PSI_file_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current operation. */ + enum PSI_file_operation m_operation; + /** Current file. */ + struct PSI_file *m_file; + /** Current file name. */ + const char *m_name; + /** Current file class. */ + void *m_class; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Operation number of bytes. */ + size_t m_number_of_bytes; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_file_locker_state_v1 PSI_file_locker_state_v1; + +/** + State data storage for @c start_metadata_wait_v1_t. + This structure provide temporary storage to a metadata locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_metadata_wait_v1_t +*/ +struct PSI_metadata_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current metadata lock. */ + struct PSI_metadata_lock *m_metadata_lock; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state_v1; + +/* Duplicate of NAME_LEN, to avoid dependency on mysql_com.h */ +#define PSI_SCHEMA_NAME_LEN (64 * 3) + +/** + State data storage for @c get_thread_statement_locker_v1_t, + @c get_thread_statement_locker_v1_t. + This structure provide temporary storage to a statement locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa get_thread_statement_locker_v1_t +*/ +struct PSI_statement_locker_state_v1 +{ + /** Discarded flag. */ + my_bool m_discarded; + /** In prepare flag. */ + my_bool m_in_prepare; + /** Metric, no index used flag. */ + uchar m_no_index_used; + /** Metric, no good index used flag. */ + uchar m_no_good_index_used; + /** Internal state. */ + uint m_flags; + /** Instrumentation class. */ + void *m_class; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_statement; + /** Locked time. */ + ulonglong m_lock_time; + /** Rows sent. */ + ulonglong m_rows_sent; + /** Rows examined. */ + ulonglong m_rows_examined; + /** Metric, temporary tables created on disk. */ + ulong m_created_tmp_disk_tables; + /** Metric, temporary tables created. */ + ulong m_created_tmp_tables; + /** Metric, number of select full join. */ + ulong m_select_full_join; + /** Metric, number of select full range join. */ + ulong m_select_full_range_join; + /** Metric, number of select range. */ + ulong m_select_range; + /** Metric, number of select range check. */ + ulong m_select_range_check; + /** Metric, number of select scan. */ + ulong m_select_scan; + /** Metric, number of sort merge passes. */ + ulong m_sort_merge_passes; + /** Metric, number of sort merge. */ + ulong m_sort_range; + /** Metric, number of sort rows. */ + ulong m_sort_rows; + /** Metric, number of sort scans. */ + ulong m_sort_scan; + /** Statement digest. */ + const struct sql_digest_storage *m_digest; + /** Current schema name. */ + char m_schema_name[PSI_SCHEMA_NAME_LEN]; + /** Length in bytes of @c m_schema_name. */ + uint m_schema_name_length; + /** Statement character set number. */ + uint m_cs_number; + PSI_sp_share *m_parent_sp_share; + PSI_prepared_stmt *m_parent_prepared_stmt; +}; +typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state_v1; + +/** + State data storage for @c get_thread_transaction_locker_v1_t, + @c get_thread_transaction_locker_v1_t. + This structure provide temporary storage to a transaction locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa get_thread_transaction_locker_v1_t +*/ +struct PSI_transaction_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Instrumentation class. */ + void *m_class; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Internal data. */ + void *m_transaction; + /** True if read-only transaction, false if read-write. */ + my_bool m_read_only; + /** True if transaction is autocommit. */ + my_bool m_autocommit; + /** Number of statements. */ + ulong m_statement_count; + /** Total number of savepoints. */ + ulong m_savepoint_count; + /** Number of rollback_to_savepoint. */ + ulong m_rollback_to_savepoint_count; + /** Number of release_savepoint. */ + ulong m_release_savepoint_count; +}; + +typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state_v1; + +/** + State data storage for @c start_socket_wait_v1_t. + This structure provide temporary storage to a socket locker. + The content of this structure is considered opaque, + the fields are only hints of what an implementation + of the psi interface can use. + This memory is provided by the instrumented code for performance reasons. + @sa start_socket_wait_v1_t +*/ +struct PSI_socket_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current socket. */ + struct PSI_socket *m_socket; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Operation number of bytes. */ + size_t m_number_of_bytes; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Current operation. */ + enum PSI_socket_operation m_operation; + /** Source file. */ + const char* m_src_file; + /** Source line number. */ + int m_src_line; + /** Internal data. */ + void *m_wait; +}; +typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state_v1; + +struct PSI_sp_locker_state_v1 +{ + /** Internal state. */ + uint m_flags; + /** Current thread. */ + struct PSI_thread *m_thread; + /** Timer start. */ + ulonglong m_timer_start; + /** Timer function. */ + ulonglong (*m_timer)(void); + /** Stored Procedure share. */ + PSI_sp_share* m_sp_share; +}; +typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state_v1; + +/* Using typedef to make reuse between PSI_v1 and PSI_v2 easier later. */ + +/** + Mutex registration API. + @param category a category name (typically a plugin name) + @param info an array of mutex info to register + @param count the size of the info array +*/ +typedef void (*register_mutex_v1_t) + (const char *category, struct PSI_mutex_info_v1 *info, int count); + +/** + Rwlock registration API. + @param category a category name (typically a plugin name) + @param info an array of rwlock info to register + @param count the size of the info array +*/ +typedef void (*register_rwlock_v1_t) + (const char *category, struct PSI_rwlock_info_v1 *info, int count); + +/** + Cond registration API. + @param category a category name (typically a plugin name) + @param info an array of cond info to register + @param count the size of the info array +*/ +typedef void (*register_cond_v1_t) + (const char *category, struct PSI_cond_info_v1 *info, int count); + +/** + Thread registration API. + @param category a category name (typically a plugin name) + @param info an array of thread info to register + @param count the size of the info array +*/ +typedef void (*register_thread_v1_t) + (const char *category, struct PSI_thread_info_v1 *info, int count); + +/** + File registration API. + @param category a category name (typically a plugin name) + @param info an array of file info to register + @param count the size of the info array +*/ +typedef void (*register_file_v1_t) + (const char *category, struct PSI_file_info_v1 *info, int count); + +/** + Stage registration API. + @param category a category name + @param info an array of stage info to register + @param count the size of the info array +*/ +typedef void (*register_stage_v1_t) + (const char *category, struct PSI_stage_info_v1 **info, int count); + +/** + Statement registration API. + @param category a category name + @param info an array of stage info to register + @param count the size of the info array +*/ +typedef void (*register_statement_v1_t) + (const char *category, struct PSI_statement_info_v1 *info, int count); + +/** + Socket registration API. + @param category a category name (typically a plugin name) + @param info an array of socket info to register + @param count the size of the info array +*/ +typedef void (*register_socket_v1_t) + (const char *category, struct PSI_socket_info_v1 *info, int count); + +/** + Mutex instrumentation initialisation API. + @param key the registered mutex key + @param identity the address of the mutex itself + @return an instrumented mutex +*/ +typedef struct PSI_mutex* (*init_mutex_v1_t) + (PSI_mutex_key key, void *identity); + +/** + Mutex instrumentation destruction API. + @param mutex the mutex to destroy +*/ +typedef void (*destroy_mutex_v1_t)(struct PSI_mutex *mutex); + +/** + Rwlock instrumentation initialisation API. + @param key the registered rwlock key + @param identity the address of the rwlock itself + @return an instrumented rwlock +*/ +typedef struct PSI_rwlock* (*init_rwlock_v1_t) + (PSI_rwlock_key key, void *identity); + +/** + Rwlock instrumentation destruction API. + @param rwlock the rwlock to destroy +*/ +typedef void (*destroy_rwlock_v1_t)(struct PSI_rwlock *rwlock); + +/** + Cond instrumentation initialisation API. + @param key the registered key + @param identity the address of the rwlock itself + @return an instrumented cond +*/ +typedef struct PSI_cond* (*init_cond_v1_t) + (PSI_cond_key key, void *identity); + +/** + Cond instrumentation destruction API. + @param cond the rcond to destroy +*/ +typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond); + +/** + Socket instrumentation initialisation API. + @param key the registered mutex key + @param socket descriptor + @param addr the socket ip address + @param addr_len length of socket ip address + @return an instrumented socket +*/ +typedef struct PSI_socket* (*init_socket_v1_t) + (PSI_socket_key key, const my_socket *fd, + const struct sockaddr *addr, socklen_t addr_len); + +/** + socket instrumentation destruction API. + @param socket the socket to destroy +*/ +typedef void (*destroy_socket_v1_t)(struct PSI_socket *socket); + +/** + Acquire a table share instrumentation. + @param temporary True for temporary tables + @param share The SQL layer table share + @return a table share instrumentation, or NULL +*/ +typedef struct PSI_table_share* (*get_table_share_v1_t) + (my_bool temporary, struct TABLE_SHARE *share); + +/** + Release a table share. + @param info the table share to release +*/ +typedef void (*release_table_share_v1_t)(struct PSI_table_share *share); + +/** + Drop a table share. + @param temporary True for temporary tables + @param schema_name the table schema name + @param schema_name_length the table schema name length + @param table_name the table name + @param table_name_length the table name length +*/ +typedef void (*drop_table_share_v1_t) + (my_bool temporary, const char *schema_name, int schema_name_length, + const char *table_name, int table_name_length); + +/** + Open an instrumentation table handle. + @param share the table to open + @param identity table handle identity + @return a table handle, or NULL +*/ +typedef struct PSI_table* (*open_table_v1_t) + (struct PSI_table_share *share, const void *identity); + +/** + Unbind a table handle from the current thread. + This operation happens when an opened table is added to the open table cache. + @param table the table to unbind +*/ +typedef void (*unbind_table_v1_t) + (struct PSI_table *table); + +/** + Rebind a table handle to the current thread. + This operation happens when a table from the open table cache + is reused for a thread. + @param table the table to unbind +*/ +typedef PSI_table* (*rebind_table_v1_t) + (PSI_table_share *share, const void *identity, PSI_table *table); + +/** + Close an instrumentation table handle. + Note that the table handle is invalid after this call. + @param table the table handle to close +*/ +typedef void (*close_table_v1_t)(struct TABLE_SHARE *server_share, + struct PSI_table *table); + +/** + Create a file instrumentation for a created file. + This method does not create the file itself, but is used to notify the + instrumentation interface that a file was just created. + @param key the file instrumentation key for this file + @param name the file name + @param file the file handle +*/ +typedef void (*create_file_v1_t)(PSI_file_key key, const char *name, + File file); + +/** + Spawn a thread. + This method creates a new thread, with instrumentation. + @param key the instrumentation key for this thread + @param thread the resulting thread + @param attr the thread attributes + @param start_routine the thread start routine + @param arg the thread start routine argument +*/ +typedef int (*spawn_thread_v1_t)(PSI_thread_key key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); + +/** + Create instrumentation for a thread. + @param key the registered key + @param identity an address typical of the thread + @return an instrumented thread +*/ +typedef struct PSI_thread* (*new_thread_v1_t) + (PSI_thread_key key, const void *identity, ulonglong thread_id); + +/** + Assign a THD to an instrumented thread. + @param thread the instrumented thread + @param THD the sql layer THD to assign +*/ +typedef void (*set_thread_THD_v1_t)(struct PSI_thread *thread, + THD *thd); + +/** + Assign an id to an instrumented thread. + @param thread the instrumented thread + @param id the id to assign +*/ +typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread, + ulonglong id); + +/** + Assign the current operating system thread id to an instrumented thread. + The operating system task id is obtained from @c gettid() + @param thread the instrumented thread +*/ +typedef void (*set_thread_os_id_v1_t)(struct PSI_thread *thread); + +/** + Get the instrumentation for the running thread. + For this function to return a result, + the thread instrumentation must have been attached to the + running thread using @c set_thread() + @return the instrumentation for the running thread +*/ +typedef struct PSI_thread* (*get_thread_v1_t)(void); + +/** + Assign a user name to the instrumented thread. + @param user the user name + @param user_len the user name length +*/ +typedef void (*set_thread_user_v1_t)(const char *user, int user_len); + +/** + Assign a user name and host name to the instrumented thread. + @param user the user name + @param user_len the user name length + @param host the host name + @param host_len the host name length +*/ +typedef void (*set_thread_account_v1_t)(const char *user, int user_len, + const char *host, int host_len); + +/** + Assign a current database to the instrumented thread. + @param db the database name + @param db_len the database name length +*/ +typedef void (*set_thread_db_v1_t)(const char* db, int db_len); + +/** + Assign a current command to the instrumented thread. + @param command the current command +*/ +typedef void (*set_thread_command_v1_t)(int command); + +/** + Assign a connection type to the instrumented thread. + @param conn_type the connection type +*/ +typedef void (*set_connection_type_v1_t)(opaque_vio_type conn_type); + + +/** + Assign a start time to the instrumented thread. + @param start_time the thread start time +*/ +typedef void (*set_thread_start_time_v1_t)(time_t start_time); + +/** + Assign a state to the instrumented thread. + @param state the thread state +*/ +typedef void (*set_thread_state_v1_t)(const char* state); + +/** + Assign a process info to the instrumented thread. + @param info the process into string + @param info_len the process into string length +*/ +typedef void (*set_thread_info_v1_t)(const char* info, uint info_len); + +/** + Attach a thread instrumentation to the running thread. + In case of thread pools, this method should be called when + a worker thread picks a work item and runs it. + Also, this method should be called if the instrumented code does not + keep the pointer returned by @c new_thread() and relies on @c get_thread() + instead. + @param thread the thread instrumentation +*/ +typedef void (*set_thread_v1_t)(struct PSI_thread *thread); + +/** + Assign the remote (peer) port to the instrumented thread. + + @param thread pointer to the thread instrumentation + @param port the remote port +*/ +typedef void (*set_thread_peer_port_v1_t)(PSI_thread *thread, + unsigned int port); + +/** Delete the current thread instrumentation. */ +typedef void (*delete_current_thread_v1_t)(void); + +/** Delete a thread instrumentation. */ +typedef void (*delete_thread_v1_t)(struct PSI_thread *thread); + +/** + Get a file instrumentation locker, for opening or creating a file. + @param state data storage for the locker + @param key the file instrumentation key + @param op the operation to perform + @param name the file name + @param identity a pointer representative of this file. + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_name_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + PSI_file_key key, enum PSI_file_operation op, const char *name, + const void *identity); + +/** + Get a file stream instrumentation locker. + @param state data storage for the locker + @param file the file stream to access + @param op the operation to perform + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_stream_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + struct PSI_file *file, enum PSI_file_operation op); + +/** + Get a file instrumentation locker. + @param state data storage for the locker + @param file the file descriptor to access + @param op the operation to perform + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_descriptor_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + File file, enum PSI_file_operation op); + +/** + Record a mutex instrumentation unlock event. + @param mutex the mutex instrumentation +*/ +typedef void (*unlock_mutex_v1_t) + (struct PSI_mutex *mutex); + +/** + Record a rwlock instrumentation unlock event. + @param rwlock the rwlock instrumentation +*/ +typedef void (*unlock_rwlock_v1_t) + (struct PSI_rwlock *rwlock); + +/** + Record a condition instrumentation signal event. + @param cond the cond instrumentation +*/ +typedef void (*signal_cond_v1_t) + (struct PSI_cond *cond); + +/** + Record a condition instrumentation broadcast event. + @param cond the cond instrumentation +*/ +typedef void (*broadcast_cond_v1_t) + (struct PSI_cond *cond); + +/** + Record an idle instrumentation wait start event. + @param state data storage for the locker + @param file the source file name + @param line the source line number + @return an idle locker, or NULL +*/ +typedef struct PSI_idle_locker* (*start_idle_wait_v1_t) + (struct PSI_idle_locker_state_v1 *state, const char *src_file, uint src_line); + +/** + Record an idle instrumentation wait end event. + @param locker a thread locker for the running thread +*/ +typedef void (*end_idle_wait_v1_t) + (struct PSI_idle_locker *locker); + +/** + Record a mutex instrumentation wait start event. + @param state data storage for the locker + @param mutex the instrumented mutex to lock + @param op the operation to perform + @param file the source file name + @param line the source line number + @return a mutex locker, or NULL +*/ +typedef struct PSI_mutex_locker* (*start_mutex_wait_v1_t) + (struct PSI_mutex_locker_state_v1 *state, + struct PSI_mutex *mutex, + enum PSI_mutex_operation op, + const char *src_file, uint src_line); + +/** + Record a mutex instrumentation wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_mutex_wait_v1_t) + (struct PSI_mutex_locker *locker, int rc); + +/** + Record a rwlock instrumentation read wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for lock, 0 for trylock +*/ +typedef struct PSI_rwlock_locker* (*start_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker_state_v1 *state, + struct PSI_rwlock *rwlock, + enum PSI_rwlock_operation op, + const char *src_file, uint src_line); + +/** + Record a rwlock instrumentation read wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); + +/** + Record a rwlock instrumentation write wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for lock, 0 for trylock +*/ +typedef struct PSI_rwlock_locker* (*start_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker_state_v1 *state, + struct PSI_rwlock *rwlock, + enum PSI_rwlock_operation op, + const char *src_file, uint src_line); + +/** + Record a rwlock instrumentation write wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); + +/** + Record a condition instrumentation wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for wait, 0 for timedwait +*/ +typedef struct PSI_cond_locker* (*start_cond_wait_v1_t) + (struct PSI_cond_locker_state_v1 *state, + struct PSI_cond *cond, + struct PSI_mutex *mutex, + enum PSI_cond_operation op, + const char *src_file, uint src_line); + +/** + Record a condition instrumentation wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_cond_wait_v1_t) + (struct PSI_cond_locker *locker, int rc); + +/** + Record a table instrumentation io wait start event. + @param locker a table locker for the running thread + @param file the source file name + @param line the source line number +*/ +typedef struct PSI_table_locker* (*start_table_io_wait_v1_t) + (struct PSI_table_locker_state *state, + struct PSI_table *table, + enum PSI_table_io_operation op, + uint index, + const char *src_file, uint src_line); + +/** + Record a table instrumentation io wait end event. + @param locker a table locker for the running thread + @param numrows the number of rows involved in io +*/ +typedef void (*end_table_io_wait_v1_t) + (struct PSI_table_locker *locker, + ulonglong numrows); + +/** + Record a table instrumentation lock wait start event. + @param locker a table locker for the running thread + @param file the source file name + @param line the source line number +*/ +typedef struct PSI_table_locker* (*start_table_lock_wait_v1_t) + (struct PSI_table_locker_state *state, + struct PSI_table *table, + enum PSI_table_lock_operation op, + ulong flags, + const char *src_file, uint src_line); + +/** + Record a table instrumentation lock wait end event. + @param locker a table locker for the running thread +*/ +typedef void (*end_table_lock_wait_v1_t)(struct PSI_table_locker *locker); + +typedef void (*unlock_table_v1_t)(struct PSI_table *table); + +/** + Start a file instrumentation open operation. + @param locker the file locker + @param op the operation to perform + @param src_file the source file name + @param src_line the source line number +*/ +typedef void (*start_file_open_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); + +/** + End a file instrumentation open operation, for file streams. + @param locker the file locker. + @param result the opened file (NULL indicates failure, non NULL success). + @return an instrumented file handle +*/ +typedef struct PSI_file* (*end_file_open_wait_v1_t) + (struct PSI_file_locker *locker, void *result); + +/** + End a file instrumentation open operation, for non stream files. + @param locker the file locker. + @param file the file number assigned by open() or create() for this file. +*/ +typedef void (*end_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file); + +/** + End a file instrumentation open operation, for non stream temporary files. + @param locker the file locker. + @param file the file number assigned by open() or create() for this file. + @param filename the file name generated during temporary file creation. +*/ +typedef void (*end_temp_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file, const char *filename); + +/** + Record a file instrumentation start event. + @param locker a file locker for the running thread + @param op file operation to be performed + @param count the number of bytes requested, or 0 if not applicable + @param src_file the source file name + @param src_line the source line number +*/ +typedef void (*start_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count, + const char *src_file, uint src_line); + +/** + Record a file instrumentation end event. + Note that for file close operations, the instrumented file handle + associated with the file (which was provided to obtain a locker) + is invalid after this call. + @param locker a file locker for the running thread + @param count the number of bytes actually used in the operation, + or 0 if not applicable, or -1 if the operation failed + @sa get_thread_file_name_locker + @sa get_thread_file_stream_locker + @sa get_thread_file_descriptor_locker +*/ +typedef void (*end_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count); + +/** + Start a file instrumentation close operation. + @param locker the file locker + @param op the operation to perform + @param src_file the source file name + @param src_line the source line number +*/ +typedef void (*start_file_close_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); + +/** + End a file instrumentation close operation. + @param locker the file locker. + @param rc the close operation return code (0 for success). + @return an instrumented file handle +*/ +typedef void (*end_file_close_wait_v1_t) + (struct PSI_file_locker *locker, int rc); + +/** + Rename a file instrumentation close operation. + @param locker the file locker. + @param old_name name of the file to be renamed. + @param new_name name of the file after rename. + @param rc the rename operation return code (0 for success). +*/ +typedef void (*end_file_rename_wait_v1_t) + (struct PSI_file_locker *locker, const char *old_name, + const char *new_name, int rc); + +/** + Start a new stage, and implicitly end the previous stage. + @param key the key of the new stage + @param src_file the source file name + @param src_line the source line number + @return the new stage progress +*/ +typedef PSI_stage_progress* (*start_stage_v1_t) + (PSI_stage_key key, const char *src_file, int src_line); + +typedef PSI_stage_progress* (*get_current_stage_progress_v1_t)(void); + +/** End the current stage. */ +typedef void (*end_stage_v1_t) (void); + +/** + Get a statement instrumentation locker. + @param state data storage for the locker + @param key the statement instrumentation key + @param charset client character set + @return a statement locker, or NULL +*/ +typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t) + (struct PSI_statement_locker_state_v1 *state, + PSI_statement_key key, const void *charset, PSI_sp_share *sp_share); + +/** + Refine a statement locker to a more specific key. + Note that only events declared mutable can be refined. + @param the statement locker for the current event + @param key the new key for the event + @sa PSI_FLAG_MUTABLE +*/ +typedef struct PSI_statement_locker* (*refine_statement_v1_t) + (struct PSI_statement_locker *locker, + PSI_statement_key key); + +/** + Start a new statement event. + @param locker the statement locker for this event + @param db the active database name for this statement + @param db_length the active database name length for this statement + @param src_file source file name + @param src_line source line number +*/ +typedef void (*start_statement_v1_t) + (struct PSI_statement_locker *locker, + const char *db, uint db_length, + const char *src_file, uint src_line); + +/** + Set the statement text for a statement event. + @param locker the current statement locker + @param text the statement text + @param text_len the statement text length +*/ +typedef void (*set_statement_text_v1_t) + (struct PSI_statement_locker *locker, + const char *text, uint text_len); + +/** + Set a statement event lock time. + @param locker the statement locker + @param lock_time the locked time, in microseconds +*/ +typedef void (*set_statement_lock_time_t) + (struct PSI_statement_locker *locker, ulonglong lock_time); + +/** + Set a statement event rows sent metric. + @param locker the statement locker + @param count the number of rows sent +*/ +typedef void (*set_statement_rows_sent_t) + (struct PSI_statement_locker *locker, ulonglong count); + +/** + Set a statement event rows examined metric. + @param locker the statement locker + @param count the number of rows examined +*/ +typedef void (*set_statement_rows_examined_t) + (struct PSI_statement_locker *locker, ulonglong count); + +/** + Increment a statement event "created tmp disk tables" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_created_tmp_disk_tables_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "created tmp tables" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_created_tmp_tables_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select full join" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_full_join_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select full range join" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_full_range_join_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select range join" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_range_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select range check" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_range_check_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "select scan" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_select_scan_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "sort merge passes" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_sort_merge_passes_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "sort range" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_sort_range_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "sort rows" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_sort_rows_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Increment a statement event "sort scan" metric. + @param locker the statement locker + @param count the metric increment value +*/ +typedef void (*inc_statement_sort_scan_t) + (struct PSI_statement_locker *locker, ulong count); + +/** + Set a statement event "no index used" metric. + @param locker the statement locker + @param count the metric value +*/ +typedef void (*set_statement_no_index_used_t) + (struct PSI_statement_locker *locker); + +/** + Set a statement event "no good index used" metric. + @param locker the statement locker + @param count the metric value +*/ +typedef void (*set_statement_no_good_index_used_t) + (struct PSI_statement_locker *locker); + +/** + End a statement event. + @param locker the statement locker + @param stmt_da the statement diagnostics area. + @sa Diagnostics_area +*/ +typedef void (*end_statement_v1_t) + (struct PSI_statement_locker *locker, void *stmt_da); + +/** + Get a transaction instrumentation locker. + @param state data storage for the locker + @param xid the xid for this transaction + @param trxid the InnoDB transaction id + @param iso_level isolation level for this transaction + @param read_only true if transaction access mode is read-only + @param autocommit true if transaction is autocommit + @return a transaction locker, or NULL +*/ +typedef struct PSI_transaction_locker* (*get_thread_transaction_locker_v1_t) + (struct PSI_transaction_locker_state_v1 *state, const void *xid, + ulonglong trxid, int isolation_level, my_bool read_only, + my_bool autocommit); + +/** + Start a new transaction event. + @param locker the transaction locker for this event + @param src_file source file name + @param src_line source line number +*/ +typedef void (*start_transaction_v1_t) + (struct PSI_transaction_locker *locker, + const char *src_file, uint src_line); + +/** + Set the transaction xid. + @param locker the transaction locker for this event + @param xid the id of the XA transaction + #param xa_state is the state of the XA transaction +*/ +typedef void (*set_transaction_xid_v1_t) + (struct PSI_transaction_locker *locker, + const void *xid, int xa_state); + +/** + Set the state of the XA transaction. + @param locker the transaction locker for this event + @param xa_state the new state of the xa transaction +*/ +typedef void (*set_transaction_xa_state_v1_t) + (struct PSI_transaction_locker *locker, + int xa_state); + +/** + Set the transaction gtid. + @param locker the transaction locker for this event + @param sid the source id for the transaction, mapped from sidno + @param gtid_spec the gtid specifier for the transaction +*/ +typedef void (*set_transaction_gtid_v1_t) + (struct PSI_transaction_locker *locker, + const void *sid, const void *gtid_spec); + +/** + Set the transaction trx_id. + @param locker the transaction locker for this event + @param trxid the storage engine transaction ID +*/ +typedef void (*set_transaction_trxid_v1_t) + (struct PSI_transaction_locker *locker, + const ulonglong *trxid); + +/** + Increment a transaction event savepoint count. + @param locker the transaction locker + @param count the increment value +*/ +typedef void (*inc_transaction_savepoints_v1_t) + (struct PSI_transaction_locker *locker, ulong count); + +/** + Increment a transaction event rollback to savepoint count. + @param locker the transaction locker + @param count the increment value +*/ +typedef void (*inc_transaction_rollback_to_savepoint_v1_t) + (struct PSI_transaction_locker *locker, ulong count); + +/** + Increment a transaction event release savepoint count. + @param locker the transaction locker + @param count the increment value +*/ +typedef void (*inc_transaction_release_savepoint_v1_t) + (struct PSI_transaction_locker *locker, ulong count); + +/** + Commit or rollback the transaction. + @param locker the transaction locker for this event + @param commit true if transaction was committed, false if rolled back +*/ +typedef void (*end_transaction_v1_t) + (struct PSI_transaction_locker *locker, + my_bool commit); + +/** + Record a socket instrumentation start event. + @param locker a socket locker for the running thread + @param op socket operation to be performed + @param count the number of bytes requested, or 0 if not applicable + @param src_file the source file name + @param src_line the source line number +*/ +typedef struct PSI_socket_locker* (*start_socket_wait_v1_t) + (struct PSI_socket_locker_state_v1 *state, + struct PSI_socket *socket, + enum PSI_socket_operation op, + size_t count, + const char *src_file, uint src_line); + +/** + Record a socket instrumentation end event. + Note that for socket close operations, the instrumented socket handle + associated with the socket (which was provided to obtain a locker) + is invalid after this call. + @param locker a socket locker for the running thread + @param count the number of bytes actually used in the operation, + or 0 if not applicable, or -1 if the operation failed + @sa get_thread_socket_locker +*/ +typedef void (*end_socket_wait_v1_t) + (struct PSI_socket_locker *locker, size_t count); + +/** + Set the socket state for an instrumented socket. + @param socket the instrumented socket + @param state socket state + */ +typedef void (*set_socket_state_v1_t)(struct PSI_socket *socket, + enum PSI_socket_state state); + +/** + Set the socket info for an instrumented socket. + @param socket the instrumented socket + @param fd the socket descriptor + @param addr the socket ip address + @param addr_len length of socket ip address + @param thread_id associated thread id +*/ +typedef void (*set_socket_info_v1_t)(struct PSI_socket *socket, + const my_socket *fd, + const struct sockaddr *addr, + socklen_t addr_len); + +/** + Bind a socket to the thread that owns it. + @param socket instrumented socket +*/ +typedef void (*set_socket_thread_owner_v1_t)(struct PSI_socket *socket); + +/** + Get a prepare statement. + @param locker a statement locker for the running thread. +*/ +typedef PSI_prepared_stmt* (*create_prepared_stmt_v1_t) + (void *identity, uint stmt_id, PSI_statement_locker *locker, + const char *stmt_name, size_t stmt_name_length); + +/** + destroy a prepare statement. + @param prepared_stmt prepared statement. +*/ +typedef void (*destroy_prepared_stmt_v1_t) + (PSI_prepared_stmt *prepared_stmt); + +/** + repreare a prepare statement. + @param prepared_stmt prepared statement. +*/ +typedef void (*reprepare_prepared_stmt_v1_t) + (PSI_prepared_stmt *prepared_stmt); + +/** + Record a prepare statement instrumentation execute event. + @param locker a statement locker for the running thread. + @param prepared_stmt prepared statement. +*/ +typedef void (*execute_prepared_stmt_v1_t) + (PSI_statement_locker *locker, PSI_prepared_stmt* prepared_stmt); + +/** + Set the statement text for a prepared statement event. + @param prepared_stmt prepared statement. + @param text the prepared statement text + @param text_len the prepared statement text length +*/ +typedef void (*set_prepared_stmt_text_v1_t)(PSI_prepared_stmt *prepared_stmt, + const char *text, + uint text_len); +/** + Get a digest locker for the current statement. + @param locker a statement locker for the running thread +*/ +typedef struct PSI_digest_locker * (*digest_start_v1_t) + (struct PSI_statement_locker *locker); + +/** + Add a token to the current digest instrumentation. + @param locker a digest locker for the current statement + @param token the lexical token to add + @param yylval the lexical token attributes +*/ +typedef void (*digest_end_v1_t) + (struct PSI_digest_locker *locker, const struct sql_digest_storage *digest); + +typedef PSI_sp_locker* (*start_sp_v1_t) + (struct PSI_sp_locker_state_v1 *state, struct PSI_sp_share* sp_share); + +typedef void (*end_sp_v1_t) + (struct PSI_sp_locker *locker); + +typedef void (*drop_sp_v1_t) + (uint object_type, + const char *schema_name, uint schema_name_length, + const char *object_name, uint object_name_length); + +/** + Acquire a sp share instrumentation. + @param type of stored program + @param schema name of stored program + @param name of stored program + @return a stored program share instrumentation, or NULL +*/ +typedef struct PSI_sp_share* (*get_sp_share_v1_t) + (uint object_type, + const char *schema_name, uint schema_name_length, + const char *object_name, uint object_name_length); + +/** + Release a stored program share. + @param info the stored program share to release +*/ +typedef void (*release_sp_share_v1_t)(struct PSI_sp_share *share); + +typedef PSI_metadata_lock* (*create_metadata_lock_v1_t) + (void *identity, + const MDL_key *key, + opaque_mdl_type mdl_type, + opaque_mdl_duration mdl_duration, + opaque_mdl_status mdl_status, + const char *src_file, + uint src_line); + +typedef void (*set_metadata_lock_status_v1_t)(PSI_metadata_lock *lock, + opaque_mdl_status mdl_status); + +typedef void (*destroy_metadata_lock_v1_t)(PSI_metadata_lock *lock); + +typedef struct PSI_metadata_locker* (*start_metadata_wait_v1_t) + (struct PSI_metadata_locker_state_v1 *state, + struct PSI_metadata_lock *mdl, + const char *src_file, uint src_line); + +typedef void (*end_metadata_wait_v1_t) + (struct PSI_metadata_locker *locker, int rc); + +/** + Stores an array of connection attributes + @param buffer char array of length encoded connection attributes + in network format + @param length length of the data in buffer + @param from_cs charset in which @c buffer is encoded + @return state + @retval non_0 attributes truncated + @retval 0 stored the attribute +*/ +typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length, + const void *from_cs); + +/** + Performance Schema Interface, version 1. + @since PSI_VERSION_1 +*/ +struct PSI_v1 +{ + /** @sa register_mutex_v1_t. */ + register_mutex_v1_t register_mutex; + /** @sa register_rwlock_v1_t. */ + register_rwlock_v1_t register_rwlock; + /** @sa register_cond_v1_t. */ + register_cond_v1_t register_cond; + /** @sa register_thread_v1_t. */ + register_thread_v1_t register_thread; + /** @sa register_file_v1_t. */ + register_file_v1_t register_file; + /** @sa register_stage_v1_t. */ + register_stage_v1_t register_stage; + /** @sa register_statement_v1_t. */ + register_statement_v1_t register_statement; + /** @sa register_socket_v1_t. */ + register_socket_v1_t register_socket; + /** @sa init_mutex_v1_t. */ + init_mutex_v1_t init_mutex; + /** @sa destroy_mutex_v1_t. */ + destroy_mutex_v1_t destroy_mutex; + /** @sa init_rwlock_v1_t. */ + init_rwlock_v1_t init_rwlock; + /** @sa destroy_rwlock_v1_t. */ + destroy_rwlock_v1_t destroy_rwlock; + /** @sa init_cond_v1_t. */ + init_cond_v1_t init_cond; + /** @sa destroy_cond_v1_t. */ + destroy_cond_v1_t destroy_cond; + /** @sa init_socket_v1_t. */ + init_socket_v1_t init_socket; + /** @sa destroy_socket_v1_t. */ + destroy_socket_v1_t destroy_socket; + + /** @sa get_table_share_v1_t. */ + get_table_share_v1_t get_table_share; + /** @sa release_table_share_v1_t. */ + release_table_share_v1_t release_table_share; + /** @sa drop_table_share_v1_t. */ + drop_table_share_v1_t drop_table_share; + /** @sa open_table_v1_t. */ + open_table_v1_t open_table; + /** @sa unbind_table_v1_t. */ + unbind_table_v1_t unbind_table; + /** @sa rebind_table_v1_t. */ + rebind_table_v1_t rebind_table; + /** @sa close_table_v1_t. */ + close_table_v1_t close_table; + /** @sa create_file_v1_t. */ + create_file_v1_t create_file; + /** @sa spawn_thread_v1_t. */ + spawn_thread_v1_t spawn_thread; + /** @sa new_thread_v1_t. */ + new_thread_v1_t new_thread; + /** @sa set_thread_id_v1_t. */ + set_thread_id_v1_t set_thread_id; + /** @sa set_thread_THD_v1_t. */ + set_thread_THD_v1_t set_thread_THD; + /** @sa set_thread_os_id_v1_t. */ + set_thread_os_id_v1_t set_thread_os_id; + /** @sa get_thread_v1_t. */ + get_thread_v1_t get_thread; + /** @sa set_thread_user_v1_t. */ + set_thread_user_v1_t set_thread_user; + /** @sa set_thread_account_v1_t. */ + set_thread_account_v1_t set_thread_account; + /** @sa set_thread_db_v1_t. */ + set_thread_db_v1_t set_thread_db; + /** @sa set_thread_command_v1_t. */ + set_thread_command_v1_t set_thread_command; + /** @sa set_connection_type_v1_t. */ + set_connection_type_v1_t set_connection_type; + /** @sa set_thread_start_time_v1_t. */ + set_thread_start_time_v1_t set_thread_start_time; + /** @sa set_thread_state_v1_t. */ + set_thread_state_v1_t set_thread_state; + /** @sa set_thread_info_v1_t. */ + set_thread_info_v1_t set_thread_info; + /** @sa set_thread_v1_t. */ + set_thread_v1_t set_thread; + /** @sa delete_current_thread_v1_t. */ + delete_current_thread_v1_t delete_current_thread; + /** @sa delete_thread_v1_t. */ + delete_thread_v1_t delete_thread; + /** @sa get_thread_file_name_locker_v1_t. */ + get_thread_file_name_locker_v1_t get_thread_file_name_locker; + /** @sa get_thread_file_stream_locker_v1_t. */ + get_thread_file_stream_locker_v1_t get_thread_file_stream_locker; + /** @sa get_thread_file_descriptor_locker_v1_t. */ + get_thread_file_descriptor_locker_v1_t get_thread_file_descriptor_locker; + /** @sa unlock_mutex_v1_t. */ + unlock_mutex_v1_t unlock_mutex; + /** @sa unlock_rwlock_v1_t. */ + unlock_rwlock_v1_t unlock_rwlock; + /** @sa signal_cond_v1_t. */ + signal_cond_v1_t signal_cond; + /** @sa broadcast_cond_v1_t. */ + broadcast_cond_v1_t broadcast_cond; + /** @sa start_idle_wait_v1_t. */ + start_idle_wait_v1_t start_idle_wait; + /** @sa end_idle_wait_v1_t. */ + end_idle_wait_v1_t end_idle_wait; + /** @sa start_mutex_wait_v1_t. */ + start_mutex_wait_v1_t start_mutex_wait; + /** @sa end_mutex_wait_v1_t. */ + end_mutex_wait_v1_t end_mutex_wait; + /** @sa start_rwlock_rdwait_v1_t. */ + start_rwlock_rdwait_v1_t start_rwlock_rdwait; + /** @sa end_rwlock_rdwait_v1_t. */ + end_rwlock_rdwait_v1_t end_rwlock_rdwait; + /** @sa start_rwlock_wrwait_v1_t. */ + start_rwlock_wrwait_v1_t start_rwlock_wrwait; + /** @sa end_rwlock_wrwait_v1_t. */ + end_rwlock_wrwait_v1_t end_rwlock_wrwait; + /** @sa start_cond_wait_v1_t. */ + start_cond_wait_v1_t start_cond_wait; + /** @sa end_cond_wait_v1_t. */ + end_cond_wait_v1_t end_cond_wait; + /** @sa start_table_io_wait_v1_t. */ + start_table_io_wait_v1_t start_table_io_wait; + /** @sa end_table_io_wait_v1_t. */ + end_table_io_wait_v1_t end_table_io_wait; + /** @sa start_table_lock_wait_v1_t. */ + start_table_lock_wait_v1_t start_table_lock_wait; + /** @sa end_table_lock_wait_v1_t. */ + end_table_lock_wait_v1_t end_table_lock_wait; + /** @sa start_file_open_wait_v1_t. */ + start_file_open_wait_v1_t start_file_open_wait; + /** @sa end_file_open_wait_v1_t. */ + end_file_open_wait_v1_t end_file_open_wait; + /** @sa end_file_open_wait_and_bind_to_descriptor_v1_t. */ + end_file_open_wait_and_bind_to_descriptor_v1_t + end_file_open_wait_and_bind_to_descriptor; + /** @sa end_temp_file_open_wait_and_bind_to_descriptor_v1_t. */ + end_temp_file_open_wait_and_bind_to_descriptor_v1_t + end_temp_file_open_wait_and_bind_to_descriptor; + /** @sa start_file_wait_v1_t. */ + start_file_wait_v1_t start_file_wait; + /** @sa end_file_wait_v1_t. */ + end_file_wait_v1_t end_file_wait; + /** @sa start_file_close_wait_v1_t. */ + start_file_close_wait_v1_t start_file_close_wait; + /** @sa end_file_close_wait_v1_t. */ + end_file_close_wait_v1_t end_file_close_wait; + /** @sa rename_file_close_wait_v1_t. */ + end_file_rename_wait_v1_t end_file_rename_wait; + /** @sa start_stage_v1_t. */ + start_stage_v1_t start_stage; + /** @sa get_current_stage_progress_v1_t. */ + get_current_stage_progress_v1_t get_current_stage_progress; + /** @sa end_stage_v1_t. */ + end_stage_v1_t end_stage; + /** @sa get_thread_statement_locker_v1_t. */ + get_thread_statement_locker_v1_t get_thread_statement_locker; + /** @sa refine_statement_v1_t. */ + refine_statement_v1_t refine_statement; + /** @sa start_statement_v1_t. */ + start_statement_v1_t start_statement; + /** @sa set_statement_text_v1_t. */ + set_statement_text_v1_t set_statement_text; + /** @sa set_statement_lock_time_t. */ + set_statement_lock_time_t set_statement_lock_time; + /** @sa set_statement_rows_sent_t. */ + set_statement_rows_sent_t set_statement_rows_sent; + /** @sa set_statement_rows_examined_t. */ + set_statement_rows_examined_t set_statement_rows_examined; + /** @sa inc_statement_created_tmp_disk_tables. */ + inc_statement_created_tmp_disk_tables_t inc_statement_created_tmp_disk_tables; + /** @sa inc_statement_created_tmp_tables. */ + inc_statement_created_tmp_tables_t inc_statement_created_tmp_tables; + /** @sa inc_statement_select_full_join. */ + inc_statement_select_full_join_t inc_statement_select_full_join; + /** @sa inc_statement_select_full_range_join. */ + inc_statement_select_full_range_join_t inc_statement_select_full_range_join; + /** @sa inc_statement_select_range. */ + inc_statement_select_range_t inc_statement_select_range; + /** @sa inc_statement_select_range_check. */ + inc_statement_select_range_check_t inc_statement_select_range_check; + /** @sa inc_statement_select_scan. */ + inc_statement_select_scan_t inc_statement_select_scan; + /** @sa inc_statement_sort_merge_passes. */ + inc_statement_sort_merge_passes_t inc_statement_sort_merge_passes; + /** @sa inc_statement_sort_range. */ + inc_statement_sort_range_t inc_statement_sort_range; + /** @sa inc_statement_sort_rows. */ + inc_statement_sort_rows_t inc_statement_sort_rows; + /** @sa inc_statement_sort_scan. */ + inc_statement_sort_scan_t inc_statement_sort_scan; + /** @sa set_statement_no_index_used. */ + set_statement_no_index_used_t set_statement_no_index_used; + /** @sa set_statement_no_good_index_used. */ + set_statement_no_good_index_used_t set_statement_no_good_index_used; + /** @sa end_statement_v1_t. */ + end_statement_v1_t end_statement; + /** @sa get_thread_transaction_locker_v1_t. */ + get_thread_transaction_locker_v1_t get_thread_transaction_locker; + /** @sa start_transaction_v1_t. */ + start_transaction_v1_t start_transaction; + /** @sa set_transaction_xid_v1_t. */ + set_transaction_xid_v1_t set_transaction_xid; + /** @sa set_transaction_xa_state_v1_t. */ + set_transaction_xa_state_v1_t set_transaction_xa_state; + /** @sa set_transaction_gtid_v1_t. */ + set_transaction_gtid_v1_t set_transaction_gtid; + /** @sa set_transaction_trxid_v1_t. */ + set_transaction_trxid_v1_t set_transaction_trxid; + /** @sa inc_transaction_savepoints_v1_t. */ + inc_transaction_savepoints_v1_t inc_transaction_savepoints; + /** @sa inc_transaction_rollback_to_savepoint_v1_t. */ + inc_transaction_rollback_to_savepoint_v1_t inc_transaction_rollback_to_savepoint; + /** @sa inc_transaction_release_savepoint_v1_t. */ + inc_transaction_release_savepoint_v1_t inc_transaction_release_savepoint; + /** @sa end_transaction_v1_t. */ + end_transaction_v1_t end_transaction; + /** @sa start_socket_wait_v1_t. */ + start_socket_wait_v1_t start_socket_wait; + /** @sa end_socket_wait_v1_t. */ + end_socket_wait_v1_t end_socket_wait; + /** @sa set_socket_state_v1_t. */ + set_socket_state_v1_t set_socket_state; + /** @sa set_socket_info_v1_t. */ + set_socket_info_v1_t set_socket_info; + /** @sa set_socket_thread_owner_v1_t. */ + set_socket_thread_owner_v1_t set_socket_thread_owner; + /** @sa create_prepared_stmt_v1_t. */ + create_prepared_stmt_v1_t create_prepared_stmt; + /** @sa destroy_prepared_stmt_v1_t. */ + destroy_prepared_stmt_v1_t destroy_prepared_stmt; + /** @sa reprepare_prepared_stmt_v1_t. */ + reprepare_prepared_stmt_v1_t reprepare_prepared_stmt; + /** @sa execute_prepared_stmt_v1_t. */ + execute_prepared_stmt_v1_t execute_prepared_stmt; + /** @sa set_prepared_stmt_text_v1_t. */ + set_prepared_stmt_text_v1_t set_prepared_stmt_text; + /** @sa digest_start_v1_t. */ + digest_start_v1_t digest_start; + /** @sa digest_end_v1_t. */ + digest_end_v1_t digest_end; + /** @sa set_thread_connect_attrs_v1_t. */ + set_thread_connect_attrs_v1_t set_thread_connect_attrs; + /** @sa start_sp_v1_t. */ + start_sp_v1_t start_sp; + /** @sa start_sp_v1_t. */ + end_sp_v1_t end_sp; + /** @sa drop_sp_v1_t. */ + drop_sp_v1_t drop_sp; + /** @sa get_sp_share_v1_t. */ + get_sp_share_v1_t get_sp_share; + /** @sa release_sp_share_v1_t. */ + release_sp_share_v1_t release_sp_share; + /** @sa register_memory_v1_t. */ + register_memory_v1_t register_memory; + /** @sa memory_alloc_v1_t. */ + memory_alloc_v1_t memory_alloc; + /** @sa memory_realloc_v1_t. */ + memory_realloc_v1_t memory_realloc; + /** @sa memory_claim_v1_t. */ + memory_claim_v1_t memory_claim; + /** @sa memory_free_v1_t. */ + memory_free_v1_t memory_free; + + unlock_table_v1_t unlock_table; + + create_metadata_lock_v1_t create_metadata_lock; + set_metadata_lock_status_v1_t set_metadata_lock_status; + destroy_metadata_lock_v1_t destroy_metadata_lock; + + start_metadata_wait_v1_t start_metadata_wait; + end_metadata_wait_v1_t end_metadata_wait; + + set_thread_peer_port_v1_t set_thread_peer_port; +}; + +/** @} (end of group Group_PSI_v1) */ + +#endif /* HAVE_PSI_1 */ + +#ifdef USE_PSI_2 +#define HAVE_PSI_2 +#endif + +#ifdef HAVE_PSI_2 + +/** + @defgroup Group_PSI_v2 Application Binary Interface, version 2 + @ingroup Instrumentation_interface + @{ +*/ + +/** + Performance Schema Interface, version 2. + This is a placeholder, this interface is not defined yet. + @since PSI_VERSION_2 +*/ +struct PSI_v2 +{ + /** Placeholder */ + int placeholder; + /* ... extended interface ... */ +}; + +/** Placeholder */ +struct PSI_mutex_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_rwlock_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_cond_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_thread_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_file_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_stage_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_statement_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_transaction_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_idle_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_mutex_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_rwlock_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_cond_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_file_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_statement_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_transaction_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_socket_locker_state_v2 +{ + /** Placeholder */ + int placeholder; +}; + +struct PSI_metadata_locker_state_v2 +{ + int placeholder; +}; + +/** @} (end of group Group_PSI_v2) */ + +#endif /* HAVE_PSI_2 */ + +/** + @typedef PSI + The instrumentation interface for the current version. + @sa PSI_CURRENT_VERSION +*/ + +/** + @typedef PSI_mutex_info + The mutex information structure for the current version. +*/ + +/** + @typedef PSI_rwlock_info + The rwlock information structure for the current version. +*/ + +/** + @typedef PSI_cond_info + The cond information structure for the current version. +*/ + +/** + @typedef PSI_thread_info + The thread information structure for the current version. +*/ + +/** + @typedef PSI_file_info + The file information structure for the current version. +*/ + +/* Export the required version */ +#ifdef USE_PSI_1 +typedef struct PSI_v1 PSI; +typedef struct PSI_mutex_info_v1 PSI_mutex_info; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info; +typedef struct PSI_cond_info_v1 PSI_cond_info; +typedef struct PSI_thread_info_v1 PSI_thread_info; +typedef struct PSI_file_info_v1 PSI_file_info; +typedef struct PSI_stage_info_v1 PSI_stage_info; +typedef struct PSI_statement_info_v1 PSI_statement_info; +typedef struct PSI_transaction_info_v1 PSI_transaction_info; +typedef struct PSI_socket_info_v1 PSI_socket_info; +typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state; +typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state; +typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state; +typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state; +typedef struct PSI_file_locker_state_v1 PSI_file_locker_state; +typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state; +typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state; +typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state; +typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state; +typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state; +#endif + +#ifdef USE_PSI_2 +typedef struct PSI_v2 PSI; +typedef struct PSI_mutex_info_v2 PSI_mutex_info; +typedef struct PSI_rwlock_info_v2 PSI_rwlock_info; +typedef struct PSI_cond_info_v2 PSI_cond_info; +typedef struct PSI_thread_info_v2 PSI_thread_info; +typedef struct PSI_file_info_v2 PSI_file_info; +typedef struct PSI_stage_info_v2 PSI_stage_info; +typedef struct PSI_statement_info_v2 PSI_statement_info; +typedef struct PSI_transaction_info_v2 PSI_transaction_info; +typedef struct PSI_socket_info_v2 PSI_socket_info; +typedef struct PSI_idle_locker_state_v2 PSI_idle_locker_state; +typedef struct PSI_mutex_locker_state_v2 PSI_mutex_locker_state; +typedef struct PSI_rwlock_locker_state_v2 PSI_rwlock_locker_state; +typedef struct PSI_cond_locker_state_v2 PSI_cond_locker_state; +typedef struct PSI_file_locker_state_v2 PSI_file_locker_state; +typedef struct PSI_statement_locker_state_v2 PSI_statement_locker_state; +typedef struct PSI_transaction_locker_state_v2 PSI_transaction_locker_state; +typedef struct PSI_socket_locker_state_v2 PSI_socket_locker_state; +typedef struct PSI_sp_locker_state_v2 PSI_sp_locker_state; +typedef struct PSI_metadata_locker_state_v2 PSI_metadata_locker_state; +#endif + +#ifndef HAVE_PSI_INTERFACE + +/** + Dummy structure, used to declare PSI_server when no instrumentation + is available. + The content does not matter, since PSI_server will be NULL. +*/ +struct PSI_none +{ + int opaque; +}; +typedef struct PSI_none PSI; + +/** + Stage instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented stage. +*/ +struct PSI_stage_info_none +{ + /** Unused stage key. */ + unsigned int m_key; + /** The name of the stage instrument. */ + const char *m_name; + /** Unused stage flags. */ + int m_flags; +}; + +/** + The stage instrumentation has to co exist with the legacy + THD::set_proc_info instrumentation. + To avoid duplication of the instrumentation in the server, + the common PSI_stage_info structure is used, + so we export it here, even when not building + with HAVE_PSI_INTERFACE. +*/ +typedef struct PSI_stage_info_none PSI_stage_info; +typedef struct PSI_stage_info_none PSI_statement_info; +typedef struct PSI_stage_info_none PSI_sp_locker_state; +typedef struct PSI_stage_info_none PSI_metadata_locker_state; +typedef struct PSI_stage_info_none PSI_metadata_locker; + +#endif /* HAVE_PSI_INTERFACE */ + +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; + +/* + Allow to override PSI_XXX_CALL at compile time + with more efficient implementations, if available. + If nothing better is available, + make a dynamic call using the PSI_server function pointer. +*/ + +#define PSI_DYNAMIC_CALL(M) PSI_server->M + +/** @} */ + +C_MODE_END +#endif /* MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H */ + diff --git a/include/mysql/psi/psi_abi_v0.h b/include/mysql/psi/psi_abi_v0.h new file mode 100644 index 00000000..c75a51f7 --- /dev/null +++ b/include/mysql/psi/psi_abi_v0.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2011, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file mysql/psi/psi_abi_v0.h + ABI check for mysql/psi/psi.h, when compiling without instrumentation. + This file is only used to automate detection of changes between versions. + Do not include this file, include mysql/psi/psi.h instead. +*/ +#define MY_GLOBAL_INCLUDED +#include "mysql/psi/psi.h" + diff --git a/include/mysql/psi/psi_abi_v0.h.pp b/include/mysql/psi/psi_abi_v0.h.pp new file mode 100644 index 00000000..47dc72b7 --- /dev/null +++ b/include/mysql/psi/psi_abi_v0.h.pp @@ -0,0 +1,100 @@ +#include "mysql/psi/psi.h" +#include "psi_base.h" +#include "psi_memory.h" +#include "psi_base.h" +struct PSI_thread; +typedef unsigned int PSI_memory_key; +C_MODE_START +struct MDL_key; +typedef struct MDL_key MDL_key; +typedef int opaque_mdl_type; +typedef int opaque_mdl_duration; +typedef int opaque_mdl_status; +typedef int opaque_vio_type; +struct TABLE_SHARE; +struct sql_digest_storage; + struct opaque_THD + { + int dummy; + }; + typedef struct opaque_THD THD; +struct PSI_mutex; +typedef struct PSI_mutex PSI_mutex; +struct PSI_rwlock; +typedef struct PSI_rwlock PSI_rwlock; +struct PSI_cond; +typedef struct PSI_cond PSI_cond; +struct PSI_table_share; +typedef struct PSI_table_share PSI_table_share; +struct PSI_table; +typedef struct PSI_table PSI_table; +struct PSI_thread; +typedef struct PSI_thread PSI_thread; +struct PSI_file; +typedef struct PSI_file PSI_file; +struct PSI_socket; +typedef struct PSI_socket PSI_socket; +struct PSI_prepared_stmt; +typedef struct PSI_prepared_stmt PSI_prepared_stmt; +struct PSI_table_locker; +typedef struct PSI_table_locker PSI_table_locker; +struct PSI_statement_locker; +typedef struct PSI_statement_locker PSI_statement_locker; +struct PSI_transaction_locker; +typedef struct PSI_transaction_locker PSI_transaction_locker; +struct PSI_idle_locker; +typedef struct PSI_idle_locker PSI_idle_locker; +struct PSI_digest_locker; +typedef struct PSI_digest_locker PSI_digest_locker; +struct PSI_sp_share; +typedef struct PSI_sp_share PSI_sp_share; +struct PSI_sp_locker; +typedef struct PSI_sp_locker PSI_sp_locker; +struct PSI_metadata_lock; +typedef struct PSI_metadata_lock PSI_metadata_lock; +struct PSI_stage_progress +{ + ulonglong m_work_completed; + ulonglong m_work_estimated; +}; +typedef struct PSI_stage_progress PSI_stage_progress; +enum PSI_table_io_operation +{ + PSI_TABLE_FETCH_ROW= 0, + PSI_TABLE_WRITE_ROW= 1, + PSI_TABLE_UPDATE_ROW= 2, + PSI_TABLE_DELETE_ROW= 3 +}; +typedef enum PSI_table_io_operation PSI_table_io_operation; +struct PSI_table_locker_state +{ + uint m_flags; + enum PSI_table_io_operation m_io_operation; + struct PSI_table *m_table; + struct PSI_table_share *m_table_share; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; + uint m_index; +}; +typedef struct PSI_table_locker_state PSI_table_locker_state; +struct PSI_bootstrap +{ + void* (*get_interface)(int version); +}; +typedef struct PSI_bootstrap PSI_bootstrap; +struct PSI_none +{ + int opaque; +}; +typedef struct PSI_none PSI; +struct PSI_stage_info_none +{ + unsigned int m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_stage_info_none PSI_stage_info; +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; +C_MODE_END diff --git a/include/mysql/psi/psi_abi_v1.h b/include/mysql/psi/psi_abi_v1.h new file mode 100644 index 00000000..e195ea5b --- /dev/null +++ b/include/mysql/psi/psi_abi_v1.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file mysql/psi/psi_abi_v1.h + ABI check for mysql/psi/psi.h, when using PSI_VERSION_1. + This file is only used to automate detection of changes between versions. + Do not include this file, include mysql/psi/psi.h instead. +*/ +#define USE_PSI_1 +#define HAVE_PSI_INTERFACE +#define MY_GLOBAL_INCLUDED +#include "mysql/psi/psi.h" + diff --git a/include/mysql/psi/psi_abi_v1.h.pp b/include/mysql/psi/psi_abi_v1.h.pp new file mode 100644 index 00000000..ca0d0206 --- /dev/null +++ b/include/mysql/psi/psi_abi_v1.h.pp @@ -0,0 +1,857 @@ +extern "C" { +typedef unsigned int PSI_memory_key; +} +extern "C" { +struct PSI_thread; +struct PSI_memory_info_v1 +{ + PSI_memory_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_memory_info_v1 PSI_memory_info_v1; +typedef void (*register_memory_v1_t) + (const char *category, struct PSI_memory_info_v1 *info, int count); +typedef PSI_memory_key (*memory_alloc_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread ** owner); +typedef PSI_memory_key (*memory_realloc_v1_t) + (PSI_memory_key key, size_t old_size, size_t new_size, struct PSI_thread ** owner); +typedef PSI_memory_key (*memory_claim_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread ** owner); +typedef void (*memory_free_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread * owner); +typedef struct PSI_memory_info_v1 PSI_memory_info; +} +C_MODE_START +struct MDL_key; +typedef struct MDL_key MDL_key; +typedef int opaque_mdl_type; +typedef int opaque_mdl_duration; +typedef int opaque_mdl_status; +typedef int opaque_vio_type; +struct TABLE_SHARE; +struct sql_digest_storage; + class THD; +struct PSI_mutex; +typedef struct PSI_mutex PSI_mutex; +struct PSI_rwlock; +typedef struct PSI_rwlock PSI_rwlock; +struct PSI_cond; +typedef struct PSI_cond PSI_cond; +struct PSI_table_share; +typedef struct PSI_table_share PSI_table_share; +struct PSI_table; +typedef struct PSI_table PSI_table; +struct PSI_thread; +typedef struct PSI_thread PSI_thread; +struct PSI_file; +typedef struct PSI_file PSI_file; +struct PSI_socket; +typedef struct PSI_socket PSI_socket; +struct PSI_prepared_stmt; +typedef struct PSI_prepared_stmt PSI_prepared_stmt; +struct PSI_table_locker; +typedef struct PSI_table_locker PSI_table_locker; +struct PSI_statement_locker; +typedef struct PSI_statement_locker PSI_statement_locker; +struct PSI_transaction_locker; +typedef struct PSI_transaction_locker PSI_transaction_locker; +struct PSI_idle_locker; +typedef struct PSI_idle_locker PSI_idle_locker; +struct PSI_digest_locker; +typedef struct PSI_digest_locker PSI_digest_locker; +struct PSI_sp_share; +typedef struct PSI_sp_share PSI_sp_share; +struct PSI_sp_locker; +typedef struct PSI_sp_locker PSI_sp_locker; +struct PSI_metadata_lock; +typedef struct PSI_metadata_lock PSI_metadata_lock; +struct PSI_stage_progress +{ + ulonglong m_work_completed; + ulonglong m_work_estimated; +}; +typedef struct PSI_stage_progress PSI_stage_progress; +enum PSI_table_io_operation +{ + PSI_TABLE_FETCH_ROW= 0, + PSI_TABLE_WRITE_ROW= 1, + PSI_TABLE_UPDATE_ROW= 2, + PSI_TABLE_DELETE_ROW= 3 +}; +typedef enum PSI_table_io_operation PSI_table_io_operation; +struct PSI_table_locker_state +{ + uint m_flags; + enum PSI_table_io_operation m_io_operation; + struct PSI_table *m_table; + struct PSI_table_share *m_table_share; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; + uint m_index; +}; +typedef struct PSI_table_locker_state PSI_table_locker_state; +struct PSI_bootstrap +{ + void* (*get_interface)(int version); +}; +typedef struct PSI_bootstrap PSI_bootstrap; +struct PSI_mutex_locker; +typedef struct PSI_mutex_locker PSI_mutex_locker; +struct PSI_rwlock_locker; +typedef struct PSI_rwlock_locker PSI_rwlock_locker; +struct PSI_cond_locker; +typedef struct PSI_cond_locker PSI_cond_locker; +struct PSI_file_locker; +typedef struct PSI_file_locker PSI_file_locker; +struct PSI_socket_locker; +typedef struct PSI_socket_locker PSI_socket_locker; +struct PSI_metadata_locker; +typedef struct PSI_metadata_locker PSI_metadata_locker; +enum PSI_mutex_operation +{ + PSI_MUTEX_LOCK= 0, + PSI_MUTEX_TRYLOCK= 1 +}; +typedef enum PSI_mutex_operation PSI_mutex_operation; +enum PSI_rwlock_operation +{ + PSI_RWLOCK_READLOCK= 0, + PSI_RWLOCK_WRITELOCK= 1, + PSI_RWLOCK_TRYREADLOCK= 2, + PSI_RWLOCK_TRYWRITELOCK= 3, + PSI_RWLOCK_SHAREDLOCK= 4, + PSI_RWLOCK_SHAREDEXCLUSIVELOCK= 5, + PSI_RWLOCK_EXCLUSIVELOCK= 6, + PSI_RWLOCK_TRYSHAREDLOCK= 7, + PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK= 8, + PSI_RWLOCK_TRYEXCLUSIVELOCK= 9 +}; +typedef enum PSI_rwlock_operation PSI_rwlock_operation; +enum PSI_cond_operation +{ + PSI_COND_WAIT= 0, + PSI_COND_TIMEDWAIT= 1 +}; +typedef enum PSI_cond_operation PSI_cond_operation; +enum PSI_file_operation +{ + PSI_FILE_CREATE= 0, + PSI_FILE_CREATE_TMP= 1, + PSI_FILE_OPEN= 2, + PSI_FILE_STREAM_OPEN= 3, + PSI_FILE_CLOSE= 4, + PSI_FILE_STREAM_CLOSE= 5, + PSI_FILE_READ= 6, + PSI_FILE_WRITE= 7, + PSI_FILE_SEEK= 8, + PSI_FILE_TELL= 9, + PSI_FILE_FLUSH= 10, + PSI_FILE_STAT= 11, + PSI_FILE_FSTAT= 12, + PSI_FILE_CHSIZE= 13, + PSI_FILE_DELETE= 14, + PSI_FILE_RENAME= 15, + PSI_FILE_SYNC= 16 +}; +typedef enum PSI_file_operation PSI_file_operation; +enum PSI_table_lock_operation +{ + PSI_TABLE_LOCK= 0, + PSI_TABLE_EXTERNAL_LOCK= 1 +}; +typedef enum PSI_table_lock_operation PSI_table_lock_operation; +enum PSI_socket_state +{ + PSI_SOCKET_STATE_IDLE= 1, + PSI_SOCKET_STATE_ACTIVE= 2 +}; +typedef enum PSI_socket_state PSI_socket_state; +enum PSI_socket_operation +{ + PSI_SOCKET_CREATE= 0, + PSI_SOCKET_CONNECT= 1, + PSI_SOCKET_BIND= 2, + PSI_SOCKET_CLOSE= 3, + PSI_SOCKET_SEND= 4, + PSI_SOCKET_RECV= 5, + PSI_SOCKET_SENDTO= 6, + PSI_SOCKET_RECVFROM= 7, + PSI_SOCKET_SENDMSG= 8, + PSI_SOCKET_RECVMSG= 9, + PSI_SOCKET_SEEK= 10, + PSI_SOCKET_OPT= 11, + PSI_SOCKET_STAT= 12, + PSI_SOCKET_SHUTDOWN= 13, + PSI_SOCKET_SELECT= 14 +}; +typedef enum PSI_socket_operation PSI_socket_operation; +typedef unsigned int PSI_mutex_key; +typedef unsigned int PSI_rwlock_key; +typedef unsigned int PSI_cond_key; +typedef unsigned int PSI_thread_key; +typedef unsigned int PSI_file_key; +typedef unsigned int PSI_stage_key; +typedef unsigned int PSI_statement_key; +typedef unsigned int PSI_socket_key; +struct PSI_mutex_info_v1 +{ + PSI_mutex_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_mutex_info_v1 PSI_mutex_info_v1; +struct PSI_rwlock_info_v1 +{ + PSI_rwlock_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info_v1; +struct PSI_cond_info_v1 +{ + PSI_cond_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_cond_info_v1 PSI_cond_info_v1; +struct PSI_thread_info_v1 +{ + PSI_thread_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_thread_info_v1 PSI_thread_info_v1; +struct PSI_file_info_v1 +{ + PSI_file_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_file_info_v1 PSI_file_info_v1; +struct PSI_stage_info_v1 +{ + PSI_stage_key m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_stage_info_v1 PSI_stage_info_v1; +struct PSI_statement_info_v1 +{ + PSI_statement_key m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_statement_info_v1 PSI_statement_info_v1; +struct PSI_socket_info_v1 +{ + PSI_socket_key *m_key; + const char *m_name; + int m_flags; +}; +typedef struct PSI_socket_info_v1 PSI_socket_info_v1; +struct PSI_idle_locker_state_v1 +{ + uint m_flags; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state_v1; +struct PSI_mutex_locker_state_v1 +{ + uint m_flags; + enum PSI_mutex_operation m_operation; + struct PSI_mutex *m_mutex; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state_v1; +struct PSI_rwlock_locker_state_v1 +{ + uint m_flags; + enum PSI_rwlock_operation m_operation; + struct PSI_rwlock *m_rwlock; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state_v1; +struct PSI_cond_locker_state_v1 +{ + uint m_flags; + enum PSI_cond_operation m_operation; + struct PSI_cond *m_cond; + struct PSI_mutex *m_mutex; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state_v1; +struct PSI_file_locker_state_v1 +{ + uint m_flags; + enum PSI_file_operation m_operation; + struct PSI_file *m_file; + const char *m_name; + void *m_class; + struct PSI_thread *m_thread; + size_t m_number_of_bytes; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_file_locker_state_v1 PSI_file_locker_state_v1; +struct PSI_metadata_locker_state_v1 +{ + uint m_flags; + struct PSI_metadata_lock *m_metadata_lock; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; +}; +typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state_v1; +struct PSI_statement_locker_state_v1 +{ + my_bool m_discarded; + my_bool m_in_prepare; + uchar m_no_index_used; + uchar m_no_good_index_used; + uint m_flags; + void *m_class; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_statement; + ulonglong m_lock_time; + ulonglong m_rows_sent; + ulonglong m_rows_examined; + ulong m_created_tmp_disk_tables; + ulong m_created_tmp_tables; + ulong m_select_full_join; + ulong m_select_full_range_join; + ulong m_select_range; + ulong m_select_range_check; + ulong m_select_scan; + ulong m_sort_merge_passes; + ulong m_sort_range; + ulong m_sort_rows; + ulong m_sort_scan; + const struct sql_digest_storage *m_digest; + char m_schema_name[(64 * 3)]; + uint m_schema_name_length; + uint m_cs_number; + PSI_sp_share *m_parent_sp_share; + PSI_prepared_stmt *m_parent_prepared_stmt; +}; +typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state_v1; +struct PSI_transaction_locker_state_v1 +{ + uint m_flags; + void *m_class; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_transaction; + my_bool m_read_only; + my_bool m_autocommit; + ulong m_statement_count; + ulong m_savepoint_count; + ulong m_rollback_to_savepoint_count; + ulong m_release_savepoint_count; +}; +typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state_v1; +struct PSI_socket_locker_state_v1 +{ + uint m_flags; + struct PSI_socket *m_socket; + struct PSI_thread *m_thread; + size_t m_number_of_bytes; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + enum PSI_socket_operation m_operation; + const char* m_src_file; + int m_src_line; + void *m_wait; +}; +typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state_v1; +struct PSI_sp_locker_state_v1 +{ + uint m_flags; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + PSI_sp_share* m_sp_share; +}; +typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state_v1; +typedef void (*register_mutex_v1_t) + (const char *category, struct PSI_mutex_info_v1 *info, int count); +typedef void (*register_rwlock_v1_t) + (const char *category, struct PSI_rwlock_info_v1 *info, int count); +typedef void (*register_cond_v1_t) + (const char *category, struct PSI_cond_info_v1 *info, int count); +typedef void (*register_thread_v1_t) + (const char *category, struct PSI_thread_info_v1 *info, int count); +typedef void (*register_file_v1_t) + (const char *category, struct PSI_file_info_v1 *info, int count); +typedef void (*register_stage_v1_t) + (const char *category, struct PSI_stage_info_v1 **info, int count); +typedef void (*register_statement_v1_t) + (const char *category, struct PSI_statement_info_v1 *info, int count); +typedef void (*register_socket_v1_t) + (const char *category, struct PSI_socket_info_v1 *info, int count); +typedef struct PSI_mutex* (*init_mutex_v1_t) + (PSI_mutex_key key, void *identity); +typedef void (*destroy_mutex_v1_t)(struct PSI_mutex *mutex); +typedef struct PSI_rwlock* (*init_rwlock_v1_t) + (PSI_rwlock_key key, void *identity); +typedef void (*destroy_rwlock_v1_t)(struct PSI_rwlock *rwlock); +typedef struct PSI_cond* (*init_cond_v1_t) + (PSI_cond_key key, void *identity); +typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond); +typedef struct PSI_socket* (*init_socket_v1_t) + (PSI_socket_key key, const my_socket *fd, + const struct sockaddr *addr, socklen_t addr_len); +typedef void (*destroy_socket_v1_t)(struct PSI_socket *socket); +typedef struct PSI_table_share* (*get_table_share_v1_t) + (my_bool temporary, struct TABLE_SHARE *share); +typedef void (*release_table_share_v1_t)(struct PSI_table_share *share); +typedef void (*drop_table_share_v1_t) + (my_bool temporary, const char *schema_name, int schema_name_length, + const char *table_name, int table_name_length); +typedef struct PSI_table* (*open_table_v1_t) + (struct PSI_table_share *share, const void *identity); +typedef void (*unbind_table_v1_t) + (struct PSI_table *table); +typedef PSI_table* (*rebind_table_v1_t) + (PSI_table_share *share, const void *identity, PSI_table *table); +typedef void (*close_table_v1_t)(struct TABLE_SHARE *server_share, + struct PSI_table *table); +typedef void (*create_file_v1_t)(PSI_file_key key, const char *name, + File file); +typedef int (*spawn_thread_v1_t)(PSI_thread_key key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); +typedef struct PSI_thread* (*new_thread_v1_t) + (PSI_thread_key key, const void *identity, ulonglong thread_id); +typedef void (*set_thread_THD_v1_t)(struct PSI_thread *thread, + THD *thd); +typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread, + ulonglong id); +typedef void (*set_thread_os_id_v1_t)(struct PSI_thread *thread); +typedef struct PSI_thread* (*get_thread_v1_t)(void); +typedef void (*set_thread_user_v1_t)(const char *user, int user_len); +typedef void (*set_thread_account_v1_t)(const char *user, int user_len, + const char *host, int host_len); +typedef void (*set_thread_db_v1_t)(const char* db, int db_len); +typedef void (*set_thread_command_v1_t)(int command); +typedef void (*set_connection_type_v1_t)(opaque_vio_type conn_type); +typedef void (*set_thread_start_time_v1_t)(time_t start_time); +typedef void (*set_thread_state_v1_t)(const char* state); +typedef void (*set_thread_info_v1_t)(const char* info, uint info_len); +typedef void (*set_thread_v1_t)(struct PSI_thread *thread); +typedef void (*set_thread_peer_port_v1_t)(PSI_thread *thread, + unsigned int port); +typedef void (*delete_current_thread_v1_t)(void); +typedef void (*delete_thread_v1_t)(struct PSI_thread *thread); +typedef struct PSI_file_locker* (*get_thread_file_name_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + PSI_file_key key, enum PSI_file_operation op, const char *name, + const void *identity); +typedef struct PSI_file_locker* (*get_thread_file_stream_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + struct PSI_file *file, enum PSI_file_operation op); +typedef struct PSI_file_locker* (*get_thread_file_descriptor_locker_v1_t) + (struct PSI_file_locker_state_v1 *state, + File file, enum PSI_file_operation op); +typedef void (*unlock_mutex_v1_t) + (struct PSI_mutex *mutex); +typedef void (*unlock_rwlock_v1_t) + (struct PSI_rwlock *rwlock); +typedef void (*signal_cond_v1_t) + (struct PSI_cond *cond); +typedef void (*broadcast_cond_v1_t) + (struct PSI_cond *cond); +typedef struct PSI_idle_locker* (*start_idle_wait_v1_t) + (struct PSI_idle_locker_state_v1 *state, const char *src_file, uint src_line); +typedef void (*end_idle_wait_v1_t) + (struct PSI_idle_locker *locker); +typedef struct PSI_mutex_locker* (*start_mutex_wait_v1_t) + (struct PSI_mutex_locker_state_v1 *state, + struct PSI_mutex *mutex, + enum PSI_mutex_operation op, + const char *src_file, uint src_line); +typedef void (*end_mutex_wait_v1_t) + (struct PSI_mutex_locker *locker, int rc); +typedef struct PSI_rwlock_locker* (*start_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker_state_v1 *state, + struct PSI_rwlock *rwlock, + enum PSI_rwlock_operation op, + const char *src_file, uint src_line); +typedef void (*end_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); +typedef struct PSI_rwlock_locker* (*start_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker_state_v1 *state, + struct PSI_rwlock *rwlock, + enum PSI_rwlock_operation op, + const char *src_file, uint src_line); +typedef void (*end_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); +typedef struct PSI_cond_locker* (*start_cond_wait_v1_t) + (struct PSI_cond_locker_state_v1 *state, + struct PSI_cond *cond, + struct PSI_mutex *mutex, + enum PSI_cond_operation op, + const char *src_file, uint src_line); +typedef void (*end_cond_wait_v1_t) + (struct PSI_cond_locker *locker, int rc); +typedef struct PSI_table_locker* (*start_table_io_wait_v1_t) + (struct PSI_table_locker_state *state, + struct PSI_table *table, + enum PSI_table_io_operation op, + uint index, + const char *src_file, uint src_line); +typedef void (*end_table_io_wait_v1_t) + (struct PSI_table_locker *locker, + ulonglong numrows); +typedef struct PSI_table_locker* (*start_table_lock_wait_v1_t) + (struct PSI_table_locker_state *state, + struct PSI_table *table, + enum PSI_table_lock_operation op, + ulong flags, + const char *src_file, uint src_line); +typedef void (*end_table_lock_wait_v1_t)(struct PSI_table_locker *locker); +typedef void (*unlock_table_v1_t)(struct PSI_table *table); +typedef void (*start_file_open_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); +typedef struct PSI_file* (*end_file_open_wait_v1_t) + (struct PSI_file_locker *locker, void *result); +typedef void (*end_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file); +typedef void (*end_temp_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file, const char *filename); +typedef void (*start_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count, + const char *src_file, uint src_line); +typedef void (*end_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count); +typedef void (*start_file_close_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); +typedef void (*end_file_close_wait_v1_t) + (struct PSI_file_locker *locker, int rc); +typedef void (*end_file_rename_wait_v1_t) + (struct PSI_file_locker *locker, const char *old_name, + const char *new_name, int rc); +typedef PSI_stage_progress* (*start_stage_v1_t) + (PSI_stage_key key, const char *src_file, int src_line); +typedef PSI_stage_progress* (*get_current_stage_progress_v1_t)(void); +typedef void (*end_stage_v1_t) (void); +typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t) + (struct PSI_statement_locker_state_v1 *state, + PSI_statement_key key, const void *charset, PSI_sp_share *sp_share); +typedef struct PSI_statement_locker* (*refine_statement_v1_t) + (struct PSI_statement_locker *locker, + PSI_statement_key key); +typedef void (*start_statement_v1_t) + (struct PSI_statement_locker *locker, + const char *db, uint db_length, + const char *src_file, uint src_line); +typedef void (*set_statement_text_v1_t) + (struct PSI_statement_locker *locker, + const char *text, uint text_len); +typedef void (*set_statement_lock_time_t) + (struct PSI_statement_locker *locker, ulonglong lock_time); +typedef void (*set_statement_rows_sent_t) + (struct PSI_statement_locker *locker, ulonglong count); +typedef void (*set_statement_rows_examined_t) + (struct PSI_statement_locker *locker, ulonglong count); +typedef void (*inc_statement_created_tmp_disk_tables_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_created_tmp_tables_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_full_join_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_full_range_join_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_range_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_range_check_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_select_scan_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_sort_merge_passes_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_sort_range_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_sort_rows_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*inc_statement_sort_scan_t) + (struct PSI_statement_locker *locker, ulong count); +typedef void (*set_statement_no_index_used_t) + (struct PSI_statement_locker *locker); +typedef void (*set_statement_no_good_index_used_t) + (struct PSI_statement_locker *locker); +typedef void (*end_statement_v1_t) + (struct PSI_statement_locker *locker, void *stmt_da); +typedef struct PSI_transaction_locker* (*get_thread_transaction_locker_v1_t) + (struct PSI_transaction_locker_state_v1 *state, const void *xid, + ulonglong trxid, int isolation_level, my_bool read_only, + my_bool autocommit); +typedef void (*start_transaction_v1_t) + (struct PSI_transaction_locker *locker, + const char *src_file, uint src_line); +typedef void (*set_transaction_xid_v1_t) + (struct PSI_transaction_locker *locker, + const void *xid, int xa_state); +typedef void (*set_transaction_xa_state_v1_t) + (struct PSI_transaction_locker *locker, + int xa_state); +typedef void (*set_transaction_gtid_v1_t) + (struct PSI_transaction_locker *locker, + const void *sid, const void *gtid_spec); +typedef void (*set_transaction_trxid_v1_t) + (struct PSI_transaction_locker *locker, + const ulonglong *trxid); +typedef void (*inc_transaction_savepoints_v1_t) + (struct PSI_transaction_locker *locker, ulong count); +typedef void (*inc_transaction_rollback_to_savepoint_v1_t) + (struct PSI_transaction_locker *locker, ulong count); +typedef void (*inc_transaction_release_savepoint_v1_t) + (struct PSI_transaction_locker *locker, ulong count); +typedef void (*end_transaction_v1_t) + (struct PSI_transaction_locker *locker, + my_bool commit); +typedef struct PSI_socket_locker* (*start_socket_wait_v1_t) + (struct PSI_socket_locker_state_v1 *state, + struct PSI_socket *socket, + enum PSI_socket_operation op, + size_t count, + const char *src_file, uint src_line); +typedef void (*end_socket_wait_v1_t) + (struct PSI_socket_locker *locker, size_t count); +typedef void (*set_socket_state_v1_t)(struct PSI_socket *socket, + enum PSI_socket_state state); +typedef void (*set_socket_info_v1_t)(struct PSI_socket *socket, + const my_socket *fd, + const struct sockaddr *addr, + socklen_t addr_len); +typedef void (*set_socket_thread_owner_v1_t)(struct PSI_socket *socket); +typedef PSI_prepared_stmt* (*create_prepared_stmt_v1_t) + (void *identity, uint stmt_id, PSI_statement_locker *locker, + const char *stmt_name, size_t stmt_name_length); +typedef void (*destroy_prepared_stmt_v1_t) + (PSI_prepared_stmt *prepared_stmt); +typedef void (*reprepare_prepared_stmt_v1_t) + (PSI_prepared_stmt *prepared_stmt); +typedef void (*execute_prepared_stmt_v1_t) + (PSI_statement_locker *locker, PSI_prepared_stmt* prepared_stmt); +typedef void (*set_prepared_stmt_text_v1_t)(PSI_prepared_stmt *prepared_stmt, + const char *text, + uint text_len); +typedef struct PSI_digest_locker * (*digest_start_v1_t) + (struct PSI_statement_locker *locker); +typedef void (*digest_end_v1_t) + (struct PSI_digest_locker *locker, const struct sql_digest_storage *digest); +typedef PSI_sp_locker* (*start_sp_v1_t) + (struct PSI_sp_locker_state_v1 *state, struct PSI_sp_share* sp_share); +typedef void (*end_sp_v1_t) + (struct PSI_sp_locker *locker); +typedef void (*drop_sp_v1_t) + (uint object_type, + const char *schema_name, uint schema_name_length, + const char *object_name, uint object_name_length); +typedef struct PSI_sp_share* (*get_sp_share_v1_t) + (uint object_type, + const char *schema_name, uint schema_name_length, + const char *object_name, uint object_name_length); +typedef void (*release_sp_share_v1_t)(struct PSI_sp_share *share); +typedef PSI_metadata_lock* (*create_metadata_lock_v1_t) + (void *identity, + const MDL_key *key, + opaque_mdl_type mdl_type, + opaque_mdl_duration mdl_duration, + opaque_mdl_status mdl_status, + const char *src_file, + uint src_line); +typedef void (*set_metadata_lock_status_v1_t)(PSI_metadata_lock *lock, + opaque_mdl_status mdl_status); +typedef void (*destroy_metadata_lock_v1_t)(PSI_metadata_lock *lock); +typedef struct PSI_metadata_locker* (*start_metadata_wait_v1_t) + (struct PSI_metadata_locker_state_v1 *state, + struct PSI_metadata_lock *mdl, + const char *src_file, uint src_line); +typedef void (*end_metadata_wait_v1_t) + (struct PSI_metadata_locker *locker, int rc); +typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length, + const void *from_cs); +struct PSI_v1 +{ + register_mutex_v1_t register_mutex; + register_rwlock_v1_t register_rwlock; + register_cond_v1_t register_cond; + register_thread_v1_t register_thread; + register_file_v1_t register_file; + register_stage_v1_t register_stage; + register_statement_v1_t register_statement; + register_socket_v1_t register_socket; + init_mutex_v1_t init_mutex; + destroy_mutex_v1_t destroy_mutex; + init_rwlock_v1_t init_rwlock; + destroy_rwlock_v1_t destroy_rwlock; + init_cond_v1_t init_cond; + destroy_cond_v1_t destroy_cond; + init_socket_v1_t init_socket; + destroy_socket_v1_t destroy_socket; + get_table_share_v1_t get_table_share; + release_table_share_v1_t release_table_share; + drop_table_share_v1_t drop_table_share; + open_table_v1_t open_table; + unbind_table_v1_t unbind_table; + rebind_table_v1_t rebind_table; + close_table_v1_t close_table; + create_file_v1_t create_file; + spawn_thread_v1_t spawn_thread; + new_thread_v1_t new_thread; + set_thread_id_v1_t set_thread_id; + set_thread_THD_v1_t set_thread_THD; + set_thread_os_id_v1_t set_thread_os_id; + get_thread_v1_t get_thread; + set_thread_user_v1_t set_thread_user; + set_thread_account_v1_t set_thread_account; + set_thread_db_v1_t set_thread_db; + set_thread_command_v1_t set_thread_command; + set_connection_type_v1_t set_connection_type; + set_thread_start_time_v1_t set_thread_start_time; + set_thread_state_v1_t set_thread_state; + set_thread_info_v1_t set_thread_info; + set_thread_v1_t set_thread; + delete_current_thread_v1_t delete_current_thread; + delete_thread_v1_t delete_thread; + get_thread_file_name_locker_v1_t get_thread_file_name_locker; + get_thread_file_stream_locker_v1_t get_thread_file_stream_locker; + get_thread_file_descriptor_locker_v1_t get_thread_file_descriptor_locker; + unlock_mutex_v1_t unlock_mutex; + unlock_rwlock_v1_t unlock_rwlock; + signal_cond_v1_t signal_cond; + broadcast_cond_v1_t broadcast_cond; + start_idle_wait_v1_t start_idle_wait; + end_idle_wait_v1_t end_idle_wait; + start_mutex_wait_v1_t start_mutex_wait; + end_mutex_wait_v1_t end_mutex_wait; + start_rwlock_rdwait_v1_t start_rwlock_rdwait; + end_rwlock_rdwait_v1_t end_rwlock_rdwait; + start_rwlock_wrwait_v1_t start_rwlock_wrwait; + end_rwlock_wrwait_v1_t end_rwlock_wrwait; + start_cond_wait_v1_t start_cond_wait; + end_cond_wait_v1_t end_cond_wait; + start_table_io_wait_v1_t start_table_io_wait; + end_table_io_wait_v1_t end_table_io_wait; + start_table_lock_wait_v1_t start_table_lock_wait; + end_table_lock_wait_v1_t end_table_lock_wait; + start_file_open_wait_v1_t start_file_open_wait; + end_file_open_wait_v1_t end_file_open_wait; + end_file_open_wait_and_bind_to_descriptor_v1_t + end_file_open_wait_and_bind_to_descriptor; + end_temp_file_open_wait_and_bind_to_descriptor_v1_t + end_temp_file_open_wait_and_bind_to_descriptor; + start_file_wait_v1_t start_file_wait; + end_file_wait_v1_t end_file_wait; + start_file_close_wait_v1_t start_file_close_wait; + end_file_close_wait_v1_t end_file_close_wait; + end_file_rename_wait_v1_t end_file_rename_wait; + start_stage_v1_t start_stage; + get_current_stage_progress_v1_t get_current_stage_progress; + end_stage_v1_t end_stage; + get_thread_statement_locker_v1_t get_thread_statement_locker; + refine_statement_v1_t refine_statement; + start_statement_v1_t start_statement; + set_statement_text_v1_t set_statement_text; + set_statement_lock_time_t set_statement_lock_time; + set_statement_rows_sent_t set_statement_rows_sent; + set_statement_rows_examined_t set_statement_rows_examined; + inc_statement_created_tmp_disk_tables_t inc_statement_created_tmp_disk_tables; + inc_statement_created_tmp_tables_t inc_statement_created_tmp_tables; + inc_statement_select_full_join_t inc_statement_select_full_join; + inc_statement_select_full_range_join_t inc_statement_select_full_range_join; + inc_statement_select_range_t inc_statement_select_range; + inc_statement_select_range_check_t inc_statement_select_range_check; + inc_statement_select_scan_t inc_statement_select_scan; + inc_statement_sort_merge_passes_t inc_statement_sort_merge_passes; + inc_statement_sort_range_t inc_statement_sort_range; + inc_statement_sort_rows_t inc_statement_sort_rows; + inc_statement_sort_scan_t inc_statement_sort_scan; + set_statement_no_index_used_t set_statement_no_index_used; + set_statement_no_good_index_used_t set_statement_no_good_index_used; + end_statement_v1_t end_statement; + get_thread_transaction_locker_v1_t get_thread_transaction_locker; + start_transaction_v1_t start_transaction; + set_transaction_xid_v1_t set_transaction_xid; + set_transaction_xa_state_v1_t set_transaction_xa_state; + set_transaction_gtid_v1_t set_transaction_gtid; + set_transaction_trxid_v1_t set_transaction_trxid; + inc_transaction_savepoints_v1_t inc_transaction_savepoints; + inc_transaction_rollback_to_savepoint_v1_t inc_transaction_rollback_to_savepoint; + inc_transaction_release_savepoint_v1_t inc_transaction_release_savepoint; + end_transaction_v1_t end_transaction; + start_socket_wait_v1_t start_socket_wait; + end_socket_wait_v1_t end_socket_wait; + set_socket_state_v1_t set_socket_state; + set_socket_info_v1_t set_socket_info; + set_socket_thread_owner_v1_t set_socket_thread_owner; + create_prepared_stmt_v1_t create_prepared_stmt; + destroy_prepared_stmt_v1_t destroy_prepared_stmt; + reprepare_prepared_stmt_v1_t reprepare_prepared_stmt; + execute_prepared_stmt_v1_t execute_prepared_stmt; + set_prepared_stmt_text_v1_t set_prepared_stmt_text; + digest_start_v1_t digest_start; + digest_end_v1_t digest_end; + set_thread_connect_attrs_v1_t set_thread_connect_attrs; + start_sp_v1_t start_sp; + end_sp_v1_t end_sp; + drop_sp_v1_t drop_sp; + get_sp_share_v1_t get_sp_share; + release_sp_share_v1_t release_sp_share; + register_memory_v1_t register_memory; + memory_alloc_v1_t memory_alloc; + memory_realloc_v1_t memory_realloc; + memory_claim_v1_t memory_claim; + memory_free_v1_t memory_free; + unlock_table_v1_t unlock_table; + create_metadata_lock_v1_t create_metadata_lock; + set_metadata_lock_status_v1_t set_metadata_lock_status; + destroy_metadata_lock_v1_t destroy_metadata_lock; + start_metadata_wait_v1_t start_metadata_wait; + end_metadata_wait_v1_t end_metadata_wait; + set_thread_peer_port_v1_t set_thread_peer_port; +}; +typedef struct PSI_v1 PSI; +typedef struct PSI_mutex_info_v1 PSI_mutex_info; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info; +typedef struct PSI_cond_info_v1 PSI_cond_info; +typedef struct PSI_thread_info_v1 PSI_thread_info; +typedef struct PSI_file_info_v1 PSI_file_info; +typedef struct PSI_stage_info_v1 PSI_stage_info; +typedef struct PSI_statement_info_v1 PSI_statement_info; +typedef struct PSI_transaction_info_v1 PSI_transaction_info; +typedef struct PSI_socket_info_v1 PSI_socket_info; +typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state; +typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state; +typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state; +typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state; +typedef struct PSI_file_locker_state_v1 PSI_file_locker_state; +typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state; +typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state; +typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state; +typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state; +typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state; +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; +C_MODE_END diff --git a/include/mysql/psi/psi_abi_v2.h b/include/mysql/psi/psi_abi_v2.h new file mode 100644 index 00000000..fdbd36f2 --- /dev/null +++ b/include/mysql/psi/psi_abi_v2.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file mysql/psi/psi_abi_v1.h + ABI check for mysql/psi/psi.h, when using PSI_VERSION_2. + This file is only used to automate detection of changes between versions. + Do not include this file, include mysql/psi/psi.h instead. +*/ +#define USE_PSI_2 +#define HAVE_PSI_INTERFACE +#define MY_GLOBAL_INCLUDED +#include "mysql/psi/psi.h" + diff --git a/include/mysql/psi/psi_abi_v2.h.pp b/include/mysql/psi/psi_abi_v2.h.pp new file mode 100644 index 00000000..91889548 --- /dev/null +++ b/include/mysql/psi/psi_abi_v2.h.pp @@ -0,0 +1,279 @@ +extern "C" { +typedef unsigned int PSI_memory_key; +} +extern "C" { +struct PSI_thread; +struct PSI_memory_info_v2 +{ + int placeholder; +}; +typedef struct PSI_memory_info_v2 PSI_memory_info; +} +C_MODE_START +struct MDL_key; +typedef struct MDL_key MDL_key; +typedef int opaque_mdl_type; +typedef int opaque_mdl_duration; +typedef int opaque_mdl_status; +typedef int opaque_vio_type; +struct TABLE_SHARE; +struct sql_digest_storage; + class THD; +struct PSI_mutex; +typedef struct PSI_mutex PSI_mutex; +struct PSI_rwlock; +typedef struct PSI_rwlock PSI_rwlock; +struct PSI_cond; +typedef struct PSI_cond PSI_cond; +struct PSI_table_share; +typedef struct PSI_table_share PSI_table_share; +struct PSI_table; +typedef struct PSI_table PSI_table; +struct PSI_thread; +typedef struct PSI_thread PSI_thread; +struct PSI_file; +typedef struct PSI_file PSI_file; +struct PSI_socket; +typedef struct PSI_socket PSI_socket; +struct PSI_prepared_stmt; +typedef struct PSI_prepared_stmt PSI_prepared_stmt; +struct PSI_table_locker; +typedef struct PSI_table_locker PSI_table_locker; +struct PSI_statement_locker; +typedef struct PSI_statement_locker PSI_statement_locker; +struct PSI_transaction_locker; +typedef struct PSI_transaction_locker PSI_transaction_locker; +struct PSI_idle_locker; +typedef struct PSI_idle_locker PSI_idle_locker; +struct PSI_digest_locker; +typedef struct PSI_digest_locker PSI_digest_locker; +struct PSI_sp_share; +typedef struct PSI_sp_share PSI_sp_share; +struct PSI_sp_locker; +typedef struct PSI_sp_locker PSI_sp_locker; +struct PSI_metadata_lock; +typedef struct PSI_metadata_lock PSI_metadata_lock; +struct PSI_stage_progress +{ + ulonglong m_work_completed; + ulonglong m_work_estimated; +}; +typedef struct PSI_stage_progress PSI_stage_progress; +enum PSI_table_io_operation +{ + PSI_TABLE_FETCH_ROW= 0, + PSI_TABLE_WRITE_ROW= 1, + PSI_TABLE_UPDATE_ROW= 2, + PSI_TABLE_DELETE_ROW= 3 +}; +typedef enum PSI_table_io_operation PSI_table_io_operation; +struct PSI_table_locker_state +{ + uint m_flags; + enum PSI_table_io_operation m_io_operation; + struct PSI_table *m_table; + struct PSI_table_share *m_table_share; + struct PSI_thread *m_thread; + ulonglong m_timer_start; + ulonglong (*m_timer)(void); + void *m_wait; + uint m_index; +}; +typedef struct PSI_table_locker_state PSI_table_locker_state; +struct PSI_bootstrap +{ + void* (*get_interface)(int version); +}; +typedef struct PSI_bootstrap PSI_bootstrap; +struct PSI_mutex_locker; +typedef struct PSI_mutex_locker PSI_mutex_locker; +struct PSI_rwlock_locker; +typedef struct PSI_rwlock_locker PSI_rwlock_locker; +struct PSI_cond_locker; +typedef struct PSI_cond_locker PSI_cond_locker; +struct PSI_file_locker; +typedef struct PSI_file_locker PSI_file_locker; +struct PSI_socket_locker; +typedef struct PSI_socket_locker PSI_socket_locker; +struct PSI_metadata_locker; +typedef struct PSI_metadata_locker PSI_metadata_locker; +enum PSI_mutex_operation +{ + PSI_MUTEX_LOCK= 0, + PSI_MUTEX_TRYLOCK= 1 +}; +typedef enum PSI_mutex_operation PSI_mutex_operation; +enum PSI_rwlock_operation +{ + PSI_RWLOCK_READLOCK= 0, + PSI_RWLOCK_WRITELOCK= 1, + PSI_RWLOCK_TRYREADLOCK= 2, + PSI_RWLOCK_TRYWRITELOCK= 3, + PSI_RWLOCK_SHAREDLOCK= 4, + PSI_RWLOCK_SHAREDEXCLUSIVELOCK= 5, + PSI_RWLOCK_EXCLUSIVELOCK= 6, + PSI_RWLOCK_TRYSHAREDLOCK= 7, + PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK= 8, + PSI_RWLOCK_TRYEXCLUSIVELOCK= 9 +}; +typedef enum PSI_rwlock_operation PSI_rwlock_operation; +enum PSI_cond_operation +{ + PSI_COND_WAIT= 0, + PSI_COND_TIMEDWAIT= 1 +}; +typedef enum PSI_cond_operation PSI_cond_operation; +enum PSI_file_operation +{ + PSI_FILE_CREATE= 0, + PSI_FILE_CREATE_TMP= 1, + PSI_FILE_OPEN= 2, + PSI_FILE_STREAM_OPEN= 3, + PSI_FILE_CLOSE= 4, + PSI_FILE_STREAM_CLOSE= 5, + PSI_FILE_READ= 6, + PSI_FILE_WRITE= 7, + PSI_FILE_SEEK= 8, + PSI_FILE_TELL= 9, + PSI_FILE_FLUSH= 10, + PSI_FILE_STAT= 11, + PSI_FILE_FSTAT= 12, + PSI_FILE_CHSIZE= 13, + PSI_FILE_DELETE= 14, + PSI_FILE_RENAME= 15, + PSI_FILE_SYNC= 16 +}; +typedef enum PSI_file_operation PSI_file_operation; +enum PSI_table_lock_operation +{ + PSI_TABLE_LOCK= 0, + PSI_TABLE_EXTERNAL_LOCK= 1 +}; +typedef enum PSI_table_lock_operation PSI_table_lock_operation; +enum PSI_socket_state +{ + PSI_SOCKET_STATE_IDLE= 1, + PSI_SOCKET_STATE_ACTIVE= 2 +}; +typedef enum PSI_socket_state PSI_socket_state; +enum PSI_socket_operation +{ + PSI_SOCKET_CREATE= 0, + PSI_SOCKET_CONNECT= 1, + PSI_SOCKET_BIND= 2, + PSI_SOCKET_CLOSE= 3, + PSI_SOCKET_SEND= 4, + PSI_SOCKET_RECV= 5, + PSI_SOCKET_SENDTO= 6, + PSI_SOCKET_RECVFROM= 7, + PSI_SOCKET_SENDMSG= 8, + PSI_SOCKET_RECVMSG= 9, + PSI_SOCKET_SEEK= 10, + PSI_SOCKET_OPT= 11, + PSI_SOCKET_STAT= 12, + PSI_SOCKET_SHUTDOWN= 13, + PSI_SOCKET_SELECT= 14 +}; +typedef enum PSI_socket_operation PSI_socket_operation; +typedef unsigned int PSI_mutex_key; +typedef unsigned int PSI_rwlock_key; +typedef unsigned int PSI_cond_key; +typedef unsigned int PSI_thread_key; +typedef unsigned int PSI_file_key; +typedef unsigned int PSI_stage_key; +typedef unsigned int PSI_statement_key; +typedef unsigned int PSI_socket_key; +struct PSI_v2 +{ + int placeholder; +}; +struct PSI_mutex_info_v2 +{ + int placeholder; +}; +struct PSI_rwlock_info_v2 +{ + int placeholder; +}; +struct PSI_cond_info_v2 +{ + int placeholder; +}; +struct PSI_thread_info_v2 +{ + int placeholder; +}; +struct PSI_file_info_v2 +{ + int placeholder; +}; +struct PSI_stage_info_v2 +{ + int placeholder; +}; +struct PSI_statement_info_v2 +{ + int placeholder; +}; +struct PSI_transaction_info_v2 +{ + int placeholder; +}; +struct PSI_idle_locker_state_v2 +{ + int placeholder; +}; +struct PSI_mutex_locker_state_v2 +{ + int placeholder; +}; +struct PSI_rwlock_locker_state_v2 +{ + int placeholder; +}; +struct PSI_cond_locker_state_v2 +{ + int placeholder; +}; +struct PSI_file_locker_state_v2 +{ + int placeholder; +}; +struct PSI_statement_locker_state_v2 +{ + int placeholder; +}; +struct PSI_transaction_locker_state_v2 +{ + int placeholder; +}; +struct PSI_socket_locker_state_v2 +{ + int placeholder; +}; +struct PSI_metadata_locker_state_v2 +{ + int placeholder; +}; +typedef struct PSI_v2 PSI; +typedef struct PSI_mutex_info_v2 PSI_mutex_info; +typedef struct PSI_rwlock_info_v2 PSI_rwlock_info; +typedef struct PSI_cond_info_v2 PSI_cond_info; +typedef struct PSI_thread_info_v2 PSI_thread_info; +typedef struct PSI_file_info_v2 PSI_file_info; +typedef struct PSI_stage_info_v2 PSI_stage_info; +typedef struct PSI_statement_info_v2 PSI_statement_info; +typedef struct PSI_transaction_info_v2 PSI_transaction_info; +typedef struct PSI_socket_info_v2 PSI_socket_info; +typedef struct PSI_idle_locker_state_v2 PSI_idle_locker_state; +typedef struct PSI_mutex_locker_state_v2 PSI_mutex_locker_state; +typedef struct PSI_rwlock_locker_state_v2 PSI_rwlock_locker_state; +typedef struct PSI_cond_locker_state_v2 PSI_cond_locker_state; +typedef struct PSI_file_locker_state_v2 PSI_file_locker_state; +typedef struct PSI_statement_locker_state_v2 PSI_statement_locker_state; +typedef struct PSI_transaction_locker_state_v2 PSI_transaction_locker_state; +typedef struct PSI_socket_locker_state_v2 PSI_socket_locker_state; +typedef struct PSI_sp_locker_state_v2 PSI_sp_locker_state; +typedef struct PSI_metadata_locker_state_v2 PSI_metadata_locker_state; +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; +C_MODE_END diff --git a/include/mysql/psi/psi_base.h b/include/mysql/psi/psi_base.h new file mode 100644 index 00000000..6cf53195 --- /dev/null +++ b/include/mysql/psi/psi_base.h @@ -0,0 +1,185 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_PSI_BASE_H +#define MYSQL_PSI_BASE_H + +#ifdef EMBEDDED_LIBRARY +#define DISABLE_ALL_PSI +#endif /* EMBEDDED_LIBRARY */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @file mysql/psi/psi_base.h + Performance schema instrumentation interface. + + @defgroup Instrumentation_interface Instrumentation Interface + @ingroup Performance_schema + @{ +*/ + +#define PSI_INSTRUMENT_ME 0 +#define PSI_INSTRUMENT_MEM ((PSI_memory_key)0) + +#define PSI_NOT_INSTRUMENTED 0 + +/** + Global flag. + This flag indicate that an instrumentation point is a global variable, + or a singleton. +*/ +#define PSI_FLAG_GLOBAL (1 << 0) + +/** + Mutable flag. + This flag indicate that an instrumentation point is a general placeholder, + that can mutate into a more specific instrumentation point. +*/ +#define PSI_FLAG_MUTABLE (1 << 1) + +#define PSI_FLAG_THREAD (1 << 2) + +/** + Stage progress flag. + This flag apply to the stage instruments only. + It indicates the instrumentation provides progress data. +*/ +#define PSI_FLAG_STAGE_PROGRESS (1 << 3) + +/** + Shared Exclusive flag. + Indicates that rwlock support the shared exclusive state. +*/ +#define PSI_RWLOCK_FLAG_SX (1 << 4) + +/** + Transferable flag. + This flag indicate that an instrumented object can + be created by a thread and destroyed by another thread. +*/ +#define PSI_FLAG_TRANSFER (1 << 5) + +/** + Volatility flag. + This flag indicate that an instrumented object + has a volatility (life cycle) comparable + to the volatility of a session. +*/ +#define PSI_FLAG_VOLATILITY_SESSION (1 << 6) + +/** + System thread flag. + Indicates that the instrumented object exists on a system thread. +*/ +#define PSI_FLAG_THREAD_SYSTEM (1 << 9) + +#ifdef HAVE_PSI_INTERFACE + +/** + @def PSI_VERSION_1 + Performance Schema Interface number for version 1. + This version is supported. +*/ +#define PSI_VERSION_1 1 + +/** + @def PSI_VERSION_2 + Performance Schema Interface number for version 2. + This version is not implemented, it's a placeholder. +*/ +#define PSI_VERSION_2 2 + +/** + @def PSI_CURRENT_VERSION + Performance Schema Interface number for the most recent version. + The most current version is @c PSI_VERSION_1 +*/ +#define PSI_CURRENT_VERSION 1 + +/** + @def USE_PSI_1 + Define USE_PSI_1 to use the interface version 1. +*/ + +/** + @def USE_PSI_2 + Define USE_PSI_2 to use the interface version 2. +*/ + +/** + @def HAVE_PSI_1 + Define HAVE_PSI_1 if the interface version 1 needs to be compiled in. +*/ + +/** + @def HAVE_PSI_2 + Define HAVE_PSI_2 if the interface version 2 needs to be compiled in. +*/ + +#ifndef USE_PSI_2 +#ifndef USE_PSI_1 +#define USE_PSI_1 +#endif +#endif + +#ifdef USE_PSI_1 +#define HAVE_PSI_1 +#endif + +#ifdef USE_PSI_2 +#define HAVE_PSI_2 +#endif + +/* + Allow to override PSI_XXX_CALL at compile time + with more efficient implementations, if available. + If nothing better is available, + make a dynamic call using the PSI_server function pointer. +*/ + +#define PSI_DYNAMIC_CALL(M) PSI_server->M + +#endif /* HAVE_PSI_INTERFACE */ + +/** @} */ + +/** + Instrumented memory key. + To instrument memory, a memory key must be obtained using @c register_memory. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_memory_key; + +#ifdef __cplusplus +} +#endif + +#endif /* MYSQL_PSI_BASE_H */ + diff --git a/include/mysql/psi/psi_memory.h b/include/mysql/psi/psi_memory.h new file mode 100644 index 00000000..f06ec525 --- /dev/null +++ b/include/mysql/psi/psi_memory.h @@ -0,0 +1,164 @@ +/* Copyright (c) 2013, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. + + 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, version 2.0, 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, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_PSI_MEMORY_H +#define MYSQL_PSI_MEMORY_H + +#include "psi_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @file mysql/psi/psi_memory.h + Performance schema instrumentation interface. + + @defgroup Instrumentation_interface Instrumentation Interface + @ingroup Performance_schema + @{ +*/ + +#ifdef HAVE_PSI_INTERFACE +#ifndef DISABLE_ALL_PSI +#ifndef DISABLE_PSI_MEMORY +#define HAVE_PSI_MEMORY_INTERFACE +#endif /* DISABLE_PSI_MEMORY */ +#endif /* DISABLE_ALL_PSI */ +#endif /* HAVE_PSI_INTERFACE */ + +struct PSI_thread; + +#ifdef HAVE_PSI_1 + +/** + @defgroup Group_PSI_v1 Application Binary Interface, version 1 + @ingroup Instrumentation_interface + @{ +*/ + +/** + Memory instrument information. + @since PSI_VERSION_1 + This structure is used to register instrumented memory. +*/ +struct PSI_memory_info_v1 +{ + /** Pointer to the key assigned to the registered memory. */ + PSI_memory_key *m_key; + /** The name of the memory instrument to register. */ + const char *m_name; + /** + The flags of the socket instrument to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; +typedef struct PSI_memory_info_v1 PSI_memory_info_v1; + +/** + Memory registration API. + @param category a category name (typically a plugin name) + @param info an array of memory info to register + @param count the size of the info array +*/ +typedef void (*register_memory_v1_t) + (const char *category, struct PSI_memory_info_v1 *info, int count); + +/** + Instrument memory allocation. + @param key the memory instrument key + @param size the size of memory allocated + @param[out] owner the memory owner + @return the effective memory instrument key +*/ +typedef PSI_memory_key (*memory_alloc_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread ** owner); + +/** + Instrument memory re allocation. + @param key the memory instrument key + @param old_size the size of memory previously allocated + @param new_size the size of memory re allocated + @param[in, out] owner the memory owner + @return the effective memory instrument key +*/ +typedef PSI_memory_key (*memory_realloc_v1_t) + (PSI_memory_key key, size_t old_size, size_t new_size, struct PSI_thread ** owner); + +/** + Instrument memory claim. + @param key the memory instrument key + @param size the size of memory allocated + @param[in, out] owner the memory owner + @return the effective memory instrument key +*/ +typedef PSI_memory_key (*memory_claim_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread ** owner); + +/** + Instrument memory free. + @param key the memory instrument key + @param size the size of memory allocated + @param owner the memory owner +*/ +typedef void (*memory_free_v1_t) + (PSI_memory_key key, size_t size, struct PSI_thread * owner); + +/** @} (end of group Group_PSI_v1) */ + +#ifdef _AIX +PSI_memory_key key_memory_log_event; +#endif + +#endif /* HAVE_PSI_1 */ + +#ifdef HAVE_PSI_2 +struct PSI_memory_info_v2 +{ + int placeholder; +}; + +#endif /* HAVE_PSI_2 */ + +#ifdef USE_PSI_1 +typedef struct PSI_memory_info_v1 PSI_memory_info; +#endif + +#ifdef USE_PSI_2 +typedef struct PSI_memory_info_v2 PSI_memory_info; +#endif + +/** @} (end of group Instrumentation_interface) */ + +#ifdef __cplusplus +} +#endif + + +#endif /* MYSQL_PSI_MEMORY_H */ + diff --git a/include/mysql/service_base64.h b/include/mysql/service_base64.h new file mode 100644 index 00000000..fa54b492 --- /dev/null +++ b/include/mysql/service_base64.h @@ -0,0 +1,82 @@ +#ifndef MYSQL_SERVICE_BASE64_INCLUDED +/* Copyright (c) 2017, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my base64 service + + Functions for base64 en- and decoding +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +/* Allow multiple chunks 'AAA= AA== AA==', binlog uses this */ +#define MY_BASE64_DECODE_ALLOW_MULTIPLE_CHUNKS 1 + +extern struct base64_service_st { + int (*base64_needed_encoded_length_ptr)(int length_of_data); + int (*base64_encode_max_arg_length_ptr)(void); + int (*base64_needed_decoded_length_ptr)(int length_of_encoded_data); + int (*base64_decode_max_arg_length_ptr)(); + int (*base64_encode_ptr)(const void *src, size_t src_len, char *dst); + int (*base64_decode_ptr)(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); +} *base64_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_base64_needed_encoded_length(A) base64_service->base64_needed_encoded_length_ptr(A) +#define my_base64_encode_max_arg_length() base64_service->base64_encode_max_arg_length_ptr() +#define my_base64_needed_decoded_length(A) base64_service->base64_needed_decoded_length_ptr(A) +#define my_base64_decode_max_arg_length() base64_service->base64_decode_max_arg_length_ptr() +#define my_base64_encode(A,B,C) base64_service->base64_encode_ptr(A,B,C) +#define my_base64_decode(A,B,C,D,E) base64_service->base64_decode_ptr(A,B,C,D,E) + +#else + +/* Calculate how much memory needed for dst of my_base64_encode() */ +int my_base64_needed_encoded_length(int length_of_data); + +/* Maximum length my_base64_encode_needed_length() can accept with no overflow. */ +int my_base64_encode_max_arg_length(void); + +/* Calculate how much memory needed for dst of my_base64_decode() */ +int my_base64_needed_decoded_length(int length_of_encoded_data); + +/* Maximum length my_base64_decode_needed_length() can accept with no overflow. */ +int my_base64_decode_max_arg_length(); + +/* Encode data as a my_base64 string */ +int my_base64_encode(const void *src, size_t src_len, char *dst); + +/* Decode a my_base64 string into data */ +int my_base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr, int flags); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_BASE64_INCLUDED +#endif diff --git a/include/mysql/service_debug_sync.h b/include/mysql/service_debug_sync.h new file mode 100644 index 00000000..0bd49a13 --- /dev/null +++ b/include/mysql/service_debug_sync.h @@ -0,0 +1,361 @@ +#ifndef MYSQL_SERVICE_DEBUG_SYNC_INCLUDED +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, Monty Program Ab + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + == Debug Sync Facility == + + The Debug Sync Facility allows placement of synchronization points in + the server code by using the DEBUG_SYNC macro: + + open_tables(...) + + DEBUG_SYNC(thd, "after_open_tables"); + + lock_tables(...) + + When activated, a sync point can + + - Emit a signal and/or + - Wait for a signal + + Nomenclature: + + - signal: A value of a global variable that persists + until overwritten by a new signal. The global + variable can also be seen as a "signal post" + or "flag mast". Then the signal is what is + attached to the "signal post" or "flag mast". + + - emit a signal: Assign the value (the signal) to the global + variable ("set a flag") and broadcast a + global condition to wake those waiting for + a signal. + + - wait for a signal: Loop over waiting for the global condition until + the global value matches the wait-for signal. + + By default, all sync points are inactive. They do nothing (except to + burn a couple of CPU cycles for checking if they are active). + + A sync point becomes active when an action is requested for it. + To do so, put a line like this in the test case file: + + SET DEBUG_SYNC= 'after_open_tables SIGNAL opened WAIT_FOR flushed'; + + This activates the sync point 'after_open_tables'. It requests it to + emit the signal 'opened' and wait for another thread to emit the signal + 'flushed' when the thread's execution runs through the sync point. + + For every sync point there can be one action per thread only. Every + thread can request multiple actions, but only one per sync point. In + other words, a thread can activate multiple sync points. + + Here is an example how to activate and use the sync points: + + --connection conn1 + SET DEBUG_SYNC= 'after_open_tables SIGNAL opened WAIT_FOR flushed'; + send INSERT INTO t1 VALUES(1); + --connection conn2 + SET DEBUG_SYNC= 'now WAIT_FOR opened'; + SET DEBUG_SYNC= 'after_abort_locks SIGNAL flushed'; + FLUSH TABLE t1; + + When conn1 runs through the INSERT statement, it hits the sync point + 'after_open_tables'. It notices that it is active and executes its + action. It emits the signal 'opened' and waits for another thread to + emit the signal 'flushed'. + + conn2 waits immediately at the special sync point 'now' for another + thread to emit the 'opened' signal. + + A signal remains in effect until it is overwritten. If conn1 signals + 'opened' before conn2 reaches 'now', conn2 will still find the 'opened' + signal. It does not wait in this case. + + When conn2 reaches 'after_abort_locks', it signals 'flushed', which lets + conn1 awake. + + Normally the activation of a sync point is cleared when it has been + executed. Sometimes it is necessary to keep the sync point active for + another execution. You can add an execute count to the action: + + SET DEBUG_SYNC= 'name SIGNAL sig EXECUTE 3'; + + This sets the signal point's activation counter to 3. Each execution + decrements the counter. After the third execution the sync point + becomes inactive. + + One of the primary goals of this facility is to eliminate sleeps from + the test suite. In most cases it should be possible to rewrite test + cases so that they do not need to sleep. (But this facility cannot + synchronize multiple processes.) However, to support test development, + and as a last resort, sync point waiting times out. There is a default + timeout, but it can be overridden: + + SET DEBUG_SYNC= 'name WAIT_FOR sig TIMEOUT 10 EXECUTE 2'; + + TIMEOUT 0 is special: If the signal is not present, the wait times out + immediately. + + When a wait timed out (even on TIMEOUT 0), a warning is generated so + that it shows up in the test result. + + You can throw an error message and kill the query when a synchronization + point is hit a certain number of times: + + SET DEBUG_SYNC= 'name HIT_LIMIT 3'; + + Or combine it with signal and/or wait: + + SET DEBUG_SYNC= 'name SIGNAL sig EXECUTE 2 HIT_LIMIT 3'; + + Here the first two hits emit the signal, the third hit returns the error + message and kills the query. + + For cases where you are not sure that an action is taken and thus + cleared in any case, you can force to clear (deactivate) a sync point: + + SET DEBUG_SYNC= 'name CLEAR'; + + If you want to clear all actions and clear the global signal, use: + + SET DEBUG_SYNC= 'RESET'; + + This is the only way to reset the global signal to an empty string. + + For testing of the facility itself you can execute a sync point just + as if it had been hit: + + SET DEBUG_SYNC= 'name TEST'; + + + === Formal Syntax === + + The string to "assign" to the DEBUG_SYNC variable can contain: + + {RESET | + <sync point name> TEST | + <sync point name> CLEAR | + <sync point name> {{SIGNAL <signal name> | + WAIT_FOR <signal name> [TIMEOUT <seconds>]} + [EXECUTE <count>] &| HIT_LIMIT <count>} + + Here '&|' means 'and/or'. This means that one of the sections + separated by '&|' must be present or both of them. + + + === Activation/Deactivation === + + The facility is an optional part of the MySQL server. + It is enabled in a debug server by default. + + ./configure --enable-debug-sync + + The Debug Sync Facility, when compiled in, is disabled by default. It + can be enabled by a mysqld command line option: + + --debug-sync-timeout[=default_wait_timeout_value_in_seconds] + + 'default_wait_timeout_value_in_seconds' is the default timeout for the + WAIT_FOR action. If set to zero, the facility stays disabled. + + The facility is enabled by default in the test suite, but can be + disabled with: + + mysql-test-run.pl ... --debug-sync-timeout=0 ... + + Likewise the default wait timeout can be set: + + mysql-test-run.pl ... --debug-sync-timeout=10 ... + + The command line option influences the readable value of the system + variable 'debug_sync'. + + * If the facility is not compiled in, the system variable does not exist. + + * If --debug-sync-timeout=0 the value of the variable reads as "OFF". + + * Otherwise the value reads as "ON - current signal: " followed by the + current signal string, which can be empty. + + The readable variable value is the same, regardless if read as global + or session value. + + Setting the 'debug-sync' system variable requires 'SUPER' privilege. + You can never read back the string that you assigned to the variable, + unless you assign the value that the variable does already have. But + that would give a parse error. A syntactically correct string is + parsed into a debug sync action and stored apart from the variable value. + + + === Implementation === + + Pseudo code for a sync point: + + #define DEBUG_SYNC(thd, sync_point_name) + if (unlikely(opt_debug_sync_timeout)) + debug_sync(thd, STRING_WITH_LEN(sync_point_name)) + + The sync point performs a binary search in a sorted array of actions + for this thread. + + The SET DEBUG_SYNC statement adds a requested action to the array or + overwrites an existing action for the same sync point. When it adds a + new action, the array is sorted again. + + + === A typical synchronization pattern === + + There are quite a few places in MySQL, where we use a synchronization + pattern like this: + + mysql_mutex_lock(&mutex); + thd->enter_cond(&condition_variable, &mutex, new_message); + #if defined(ENABLE_DEBUG_SYNC) + if (!thd->killed && !end_of_wait_condition) + DEBUG_SYNC(thd, "sync_point_name"); + #endif + while (!thd->killed && !end_of_wait_condition) + mysql_cond_wait(&condition_variable, &mutex); + thd->exit_cond(old_message); + + Here some explanations: + + thd->enter_cond() is used to register the condition variable and the + mutex in thd->mysys_var. This is done to allow the thread to be + interrupted (killed) from its sleep. Another thread can find the + condition variable to signal and mutex to use for synchronization in + this thread's THD::mysys_var. + + thd->enter_cond() requires the mutex to be acquired in advance. + + thd->exit_cond() unregisters the condition variable and mutex and + releases the mutex. + + If you want to have a Debug Sync point with the wait, please place it + behind enter_cond(). Only then you can safely decide, if the wait will + be taken. Also you will have THD::proc_info correct when the sync + point emits a signal. DEBUG_SYNC sets its own proc_info, but restores + the previous one before releasing its internal mutex. As soon as + another thread sees the signal, it does also see the proc_info from + before entering the sync point. In this case it will be "new_message", + which is associated with the wait that is to be synchronized. + + In the example above, the wait condition is repeated before the sync + point. This is done to skip the sync point, if no wait takes place. + The sync point is before the loop (not inside the loop) to have it hit + once only. It is possible that the condition variable is signaled + multiple times without the wait condition to be true. + + A bit off-topic: At some places, the loop is taken around the whole + synchronization pattern: + + while (!thd->killed && !end_of_wait_condition) + { + mysql_mutex_lock(&mutex); + thd->enter_cond(&condition_variable, &mutex, new_message); + if (!thd->killed [&& !end_of_wait_condition]) + { + [DEBUG_SYNC(thd, "sync_point_name");] + mysql_cond_wait(&condition_variable, &mutex); + } + thd->exit_cond(old_message); + } + + Note that it is important to repeat the test for thd->killed after + enter_cond(). Otherwise the killing thread may kill this thread after + it tested thd->killed in the loop condition and before it registered + the condition variable and mutex in enter_cond(). In this case, the + killing thread does not know that this thread is going to wait on a + condition variable. It would just set THD::killed. But if we would not + test it again, we would go asleep though we are killed. If the killing + thread would kill us when we are after the second test, but still + before sleeping, we hold the mutex, which is registered in mysys_var. + The killing thread would try to acquire the mutex before signaling + the condition variable. Since the mutex is only released implicitly in + mysql_cond_wait(), the signaling happens at the right place. We + have a safe synchronization. + + === Co-work with the DBUG facility === + + When running the MySQL test suite with the --debug-dbug command line + option, the Debug Sync Facility writes trace messages to the DBUG + trace. The following shell commands proved very useful in extracting + relevant information: + + egrep 'query:|debug_sync_exec:' mysql-test/var/log/mysqld.1.trace + + It shows all executed SQL statements and all actions executed by + synchronization points. + + Sometimes it is also useful to see, which synchronization points have + been run through (hit) with or without executing actions. Then add + "|debug_sync_point:" to the egrep pattern. + + === Further reading === + + For a discussion of other methods to synchronize threads see + http://forge.mysql.com/wiki/MySQL_Internals_Test_Synchronization + + For complete syntax tests, functional tests, and examples see the test + case debug_sync.test. + + See also http://forge.mysql.com/worklog/task.php?id=4259 +*/ + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef MYSQL_DYNAMIC_PLUGIN +extern void (*debug_sync_service)(MYSQL_THD, const char *, size_t); +#else +#define debug_sync_service debug_sync_C_callback_ptr +extern void (*debug_sync_C_callback_ptr)(MYSQL_THD, const char *, size_t); +#endif + +#ifdef ENABLED_DEBUG_SYNC +#define DEBUG_SYNC(thd, name) \ + do { \ + if (debug_sync_service) \ + debug_sync_service(thd, STRING_WITH_LEN(name)); \ + } while(0) + +#define DEBUG_SYNC_C_IF_THD(thd, name) \ + do { \ + if (debug_sync_service && thd) \ + debug_sync_service((MYSQL_THD) thd, STRING_WITH_LEN(name)); \ + } while(0) +#else +#define DEBUG_SYNC(thd,name) do { } while(0) +#define DEBUG_SYNC_C_IF_THD(thd, _sync_point_name_) do { } while(0) +#endif /* defined(ENABLED_DEBUG_SYNC) */ + +/* compatibility macro */ +#define DEBUG_SYNC_C(name) DEBUG_SYNC(NULL, name) + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_DEBUG_SYNC_INCLUDED +#endif diff --git a/include/mysql/service_encryption.h b/include/mysql/service_encryption.h new file mode 100644 index 00000000..49639407 --- /dev/null +++ b/include/mysql/service_encryption.h @@ -0,0 +1,127 @@ +#ifndef MYSQL_SERVICE_ENCRYPTION_INCLUDED +/* Copyright (c) 2015, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + encryption service + + Functions to support data encryption and encryption key management. + They are normally implemented in an encryption plugin, so this service + connects encryption *consumers* (e.g. storage engines) to the encryption + *provider* (encryption plugin). +*/ + +#ifndef MYSQL_ABI_CHECK +#include <my_alloca.h> +#ifdef _WIN32 +#ifndef __cplusplus +#define inline __inline +#endif +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* returned from encryption_key_get_latest_version() */ +#define ENCRYPTION_KEY_VERSION_INVALID (~(unsigned int)0) +#define ENCRYPTION_KEY_NOT_ENCRYPTED (0) + +#define ENCRYPTION_KEY_SYSTEM_DATA 1 +#define ENCRYPTION_KEY_TEMPORARY_DATA 2 + +/* returned from encryption_key_get() */ +#define ENCRYPTION_KEY_BUFFER_TOO_SMALL (100) + +#define ENCRYPTION_FLAG_DECRYPT 0 +#define ENCRYPTION_FLAG_ENCRYPT 1 +#define ENCRYPTION_FLAG_NOPAD 2 + +struct encryption_service_st { + unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id); + unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version, + unsigned char* buffer, unsigned int* length); + unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version); + int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, + unsigned int key_version); + int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen); + int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen); + unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version); +}; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +extern struct encryption_service_st *encryption_service; + +#define encryption_key_get_latest_version(KI) encryption_service->encryption_key_get_latest_version_func(KI) +#define encryption_key_get(KI,KV,K,S) encryption_service->encryption_key_get_func((KI),(KV),(K),(S)) +#define encryption_ctx_size(KI,KV) encryption_service->encryption_ctx_size_func((KI),(KV)) +#define encryption_ctx_init(CTX,K,KL,IV,IVL,F,KI,KV) encryption_service->encryption_ctx_init_func((CTX),(K),(KL),(IV),(IVL),(F),(KI),(KV)) +#define encryption_ctx_update(CTX,S,SL,D,DL) encryption_service->encryption_ctx_update_func((CTX),(S),(SL),(D),(DL)) +#define encryption_ctx_finish(CTX,D,DL) encryption_service->encryption_ctx_finish_func((CTX),(D),(DL)) +#define encryption_encrypted_length(SL,KI,KV) encryption_service->encryption_encrypted_length_func((SL),(KI),(KV)) +#else + +extern struct encryption_service_st encryption_handler; + +#define encryption_key_get_latest_version(KI) encryption_handler.encryption_key_get_latest_version_func(KI) +#define encryption_key_get(KI,KV,K,S) encryption_handler.encryption_key_get_func((KI),(KV),(K),(S)) +#define encryption_ctx_size(KI,KV) encryption_handler.encryption_ctx_size_func((KI),(KV)) +#define encryption_ctx_init(CTX,K,KL,IV,IVL,F,KI,KV) encryption_handler.encryption_ctx_init_func((CTX),(K),(KL),(IV),(IVL),(F),(KI),(KV)) +#define encryption_ctx_update(CTX,S,SL,D,DL) encryption_handler.encryption_ctx_update_func((CTX),(S),(SL),(D),(DL)) +#define encryption_ctx_finish(CTX,D,DL) encryption_handler.encryption_ctx_finish_func((CTX),(D),(DL)) +#define encryption_encrypted_length(SL,KI,KV) encryption_handler.encryption_encrypted_length_func((SL),(KI),(KV)) +#endif + +static inline unsigned int encryption_key_id_exists(unsigned int id) +{ + return encryption_key_get_latest_version(id) != ENCRYPTION_KEY_VERSION_INVALID; +} + +static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version) +{ + unsigned int unused; + return encryption_key_get(id, version, NULL, &unused) != ENCRYPTION_KEY_VERSION_INVALID; +} + +static inline int encryption_crypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen, + int flags, unsigned int key_id, unsigned int key_version) +{ + void *ctx= alloca(encryption_ctx_size(key_id, key_version)); + int res1, res2; + unsigned int d1, d2; + if ((res1= encryption_ctx_init(ctx, key, klen, iv, ivlen, flags, key_id, key_version))) + return res1; + res1= encryption_ctx_update(ctx, src, slen, dst, &d1); + res2= encryption_ctx_finish(ctx, dst + d1, &d2); + *dlen= d1 + d2; + return res1 ? res1 : res2; +} + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_ENCRYPTION_INCLUDED +#endif + diff --git a/include/mysql/service_encryption_scheme.h b/include/mysql/service_encryption_scheme.h new file mode 100644 index 00000000..bcd4d646 --- /dev/null +++ b/include/mysql/service_encryption_scheme.h @@ -0,0 +1,133 @@ +#ifndef MYSQL_SERVICE_ENCRYPTION_SCHEME_INCLUDED +/* Copyright (c) 2015, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + encryption scheme service + + A higher-level access to encryption service. + + This is a helper service that storage engines use to encrypt tables on disk. + It requests keys from the plugin, generates temporary or local keys + from the global (as returned by the plugin) keys, etc. + + To use the service: + + * st_encryption_scheme object is created per space. A "space" can be + a table space in XtraDB/InnoDB, a file in Aria, etc. The whole + space is encrypted with the one key id. + + * The service does not take the key and the IV as parameters for + encryption or decryption. Instead it takes two 32-bit integers and + one 64-bit integer (and requests the key from an encryption + plugin, if needed). + + * The service requests the global key from the encryption plugin + automatically as needed. Three last keys are cached in the + st_encryption_scheme. Number of key requests (number of cache + misses) are counted in st_encryption_scheme::keyserver_requests + + * If an st_encryption_scheme can be used concurrently by different + threads, it needs to be able to lock itself when accessing the key + cache. Set the st_encryption_scheme::locker appropriately. If + non-zero, it will be invoked by encrypt/decrypt functions to lock + and unlock the scheme when needed. + + * Implementation details (in particular, key derivation) are defined + by the scheme type. Currently only schema type 1 is supported. + + In the schema type 1, every "space" (table space in XtraDB/InnoDB, + file in Aria) is encrypted with a different space-local key: + + * Every space has a 16-byte unique identifier (typically it's + generated randomly and stored in the space). The caller should + put it into st_encryption_scheme::iv. + + * Space-local key is generated by encrypting this identifier with + the global encryption key (of the given id and version) using AES_ECB. + + * Encryption/decryption parameters for a page are typically the + 4-byte space id, 4-byte page position (offset, page number, etc), + and the 8-byte LSN. This guarantees that they'll be different for + any two pages (of the same or different tablespaces) and also that + they'll change for the same page when it's modified. They don't need + to be secret (they create the IV, not the encryption key). +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ENCRYPTION_SCHEME_KEY_INVALID -1 +#define ENCRYPTION_SCHEME_BLOCK_LENGTH 16 + +struct st_encryption_scheme_key { + unsigned int version; + unsigned char key[ENCRYPTION_SCHEME_BLOCK_LENGTH]; +}; + +struct st_encryption_scheme { + unsigned char iv[ENCRYPTION_SCHEME_BLOCK_LENGTH]; + struct st_encryption_scheme_key key[3]; + unsigned int keyserver_requests; + unsigned int key_id; + unsigned int type; + + void (*locker)(struct st_encryption_scheme *self, int release); +}; + +extern struct encryption_scheme_service_st { + int (*encryption_scheme_encrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + int (*encryption_scheme_decrypt_func) + (const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +} *encryption_scheme_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define encryption_scheme_encrypt(S,SL,D,DL,SCH,KV,I32,J32,I64) encryption_scheme_service->encryption_scheme_encrypt_func(S,SL,D,DL,SCH,KV,I32,J32,I64) +#define encryption_scheme_decrypt(S,SL,D,DL,SCH,KV,I32,J32,I64) encryption_scheme_service->encryption_scheme_decrypt_func(S,SL,D,DL,SCH,KV,I32,J32,I64) + +#else + +int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); +int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, + unsigned char* dst, unsigned int* dlen, + struct st_encryption_scheme *scheme, + unsigned int key_version, unsigned int i32_1, + unsigned int i32_2, unsigned long long i64); + +#endif + + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_ENCRYPTION_SCHEME_INCLUDED +#endif diff --git a/include/mysql/service_json.h b/include/mysql/service_json.h new file mode 100644 index 00000000..cb748c0c --- /dev/null +++ b/include/mysql/service_json.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2018 MariaDB Corporation + + 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, Fifth Floor, Boston, MA 02111-1301 USA */ + +#ifndef MYSQL_SERVICE_JSON +#define MYSQL_SERVICE_JSON + +/** + @file + json service + + Exports JSON parsing methods for plugins to use. + + Functions of the service: + json_type - returns the type of the JSON argument, + and the parsed value if it's scalar (not object or array) + + json_get_array_item - expects JSON array as an argument, + and returns the type of the element at index `n_item`. + Returns JSV_NOTHING type if the array is shorter + than n_item and the actual length of the array in value_len. + If successful, then `value` up till `value[value_len]` contains the array + element at the desired index (n_item). + + json_get_object_key - expects JSON object as an argument, + searches for a key in the object, return it's type and stores its value in `value`. + JSV_NOTHING if no such key found, the number of keys + in v_len. + + json_get_object_nkey - expects JSON object as an argument. + finds n_key's key in the object, returns it's name, type and value. + JSV_NOTHING if object has less keys than n_key. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; + +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **value, int *value_len); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define json_type json_service->json_type +#define json_get_array_item json_service->json_get_array_item +#define json_get_object_key json_service->json_get_object_key +#define json_get_object_nkey json_service->json_get_object_nkey +#define json_escape_string json_service->json_escape_string +#define json_unescape_json json_service->json_unescape_json + +#else + +enum json_types json_type(const char *js, const char *js_end, + const char **value, int *value_len); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **value, int *value_len); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **value, int *value_len); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **value, int *value_len); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); + +#endif /*MYSQL_DYNAMIC_PLUGIN*/ + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_JSON */ + + diff --git a/include/mysql/service_kill_statement.h b/include/mysql/service_kill_statement.h new file mode 100644 index 00000000..9f3415a7 --- /dev/null +++ b/include/mysql/service_kill_statement.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2013, 2018, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_SERVICE_KILL_STATEMENT_INCLUDED +#define MYSQL_SERVICE_KILL_STATEMENT_INCLUDED + +/** + @file + This service provides functions that allow plugins to support + the KILL statement. + + In MySQL support for the KILL statement is cooperative. The KILL + statement only sets a "killed" flag. This function returns the value + of that flag. A thread should check it often, especially inside + time-consuming loops, and gracefully abort the operation if it is + non-zero. + + thd_killed(thd) + @return 0 - no KILL statement was issued, continue normally + @return 1 - there was a KILL statement, abort the execution. + + thd_kill_level(thd) + @return thd_kill_levels_enum values +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +enum thd_kill_levels { + THD_IS_NOT_KILLED=0, + THD_ABORT_SOFTLY=50, /**< abort when possible, don't leave tables corrupted */ + THD_ABORT_ASAP=100, /**< abort asap */ +}; + +extern struct kill_statement_service_st { + enum thd_kill_levels (*thd_kill_level_func)(const MYSQL_THD); +} *thd_kill_statement_service; + +/* backward compatibility helper */ +#define thd_killed(THD) (thd_kill_level(THD) == THD_ABORT_ASAP) + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_kill_level(THD) \ + thd_kill_statement_service->thd_kill_level_func(THD) + +#else + +enum thd_kill_levels thd_kill_level(const MYSQL_THD); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/service_logger.h b/include/mysql/service_logger.h new file mode 100644 index 00000000..5979901b --- /dev/null +++ b/include/mysql/service_logger.h @@ -0,0 +1,105 @@ +/* Copyright (C) 2012 Monty Program Ab + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_SERVICE_LOGGER_INCLUDED +#define MYSQL_SERVICE_LOGGER_INCLUDED + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#endif + +/** + @file + logger service + + Log file with rotation implementation. + + This service implements logging with possible rotation + of the log files. Interface intentionally tries to be similar to FILE* + related functions. + + So that one can open the log with logger_open(), specifying + the limit on the logfile size and the rotations number. + + Then it's possible to write messages to the log with + logger_printf or logger_vprintf functions. + + As the size of the logfile grows over the specified limit, + it is renamed to 'logfile.1'. The former 'logfile.1' becomes + 'logfile.2', etc. The file 'logfile.rotations' is removed. + That's how the rotation works. + + The rotation can be forced with the logger_rotate() call. + + Finally the log should be closed with logger_close(). + +@notes: + Implementation checks the size of the log file before it starts new + printf into it. So the size of the file gets over the limit when it rotates. + + The access is secured with the mutex, so the log is threadsafe. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct logger_handle_st LOGGER_HANDLE; + +extern struct logger_service_st { + void (*logger_init_mutexes)(); + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define logger_init_mutexes logger_service->logger_init_mutexes +#define logger_open(path, size_limit, rotations) \ + (logger_service->open(path, size_limit, rotations)) +#define logger_close(log) (logger_service->close(log)) +#define logger_rotate(log) (logger_service->rotate(log)) +#define logger_vprintf(log, fmt, argptr) (logger_service->\ + vprintf(log, fmt, argptr)) +#define logger_printf (*logger_service->printf) +#define logger_write(log, buffer, size) \ + (logger_service->write(log, buffer, size)) +#else + + void logger_init_mutexes(); + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); + int logger_rotate(LOGGER_HANDLE *log); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_LOGGER_INCLUDED*/ + diff --git a/include/mysql/service_md5.h b/include/mysql/service_md5.h new file mode 100644 index 00000000..336cf70f --- /dev/null +++ b/include/mysql/service_md5.h @@ -0,0 +1,69 @@ +#ifndef MYSQL_SERVICE_MD5_INCLUDED +/* Copyright (c) 2014, Monty Program Ab + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my md5 service + + Functions to calculate MD5 hash from a memory buffer +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#define MY_MD5_HASH_SIZE 16 /* Hash size in bytes */ + +extern struct my_md5_service_st { + void (*my_md5_type)(unsigned char*, const char*, size_t); + void (*my_md5_multi_type)(unsigned char*, ...); + size_t (*my_md5_context_size_type)(); + void (*my_md5_init_type)(void *); + void (*my_md5_input_type)(void *, const unsigned char *, size_t); + void (*my_md5_result_type)(void *, unsigned char *); +} *my_md5_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_md5(A,B,C) my_md5_service->my_md5_type(A,B,C) +#define my_md5_multi my_md5_service->my_md5_multi_type +#define my_md5_context_size() my_md5_service->my_md5_context_size_type() +#define my_md5_init(A) my_md5_service->my_md5_init_type(A) +#define my_md5_input(A,B,C) my_md5_service->my_md5_input_type(A,B,C) +#define my_md5_result(A,B) my_md5_service->my_md5_result_type(A,B) + +#else + +void my_md5(unsigned char*, const char*, size_t); +void my_md5_multi(unsigned char*, ...); +size_t my_md5_context_size(); +void my_md5_init(void *context); +void my_md5_input(void *context, const unsigned char *buf, size_t len); +void my_md5_result(void *context, unsigned char *digest); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_MD5_INCLUDED +#endif + diff --git a/include/mysql/service_my_crypt.h b/include/mysql/service_my_crypt.h new file mode 100644 index 00000000..1a4ebcfd --- /dev/null +++ b/include/mysql/service_my_crypt.h @@ -0,0 +1,120 @@ +#ifndef MYSQL_SERVICE_MY_CRYPT_INCLUDED +#define MYSQL_SERVICE_MY_CRYPT_INCLUDED + +/* + Copyright (c) 2014 Google Inc. + Copyright (c) 2014, 2015 MariaDB Corporation + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my crypt service + + AES encryption functions, and a function to generate random bytes. + + Include my_config.h before this file to use CTR and GCM modes + (they only work if server was compiled with openssl). +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* return values from my_aes_encrypt/my_aes_decrypt functions */ +#define MY_AES_OK 0 +#define MY_AES_BAD_DATA -100 +#define MY_AES_OPENSSL_ERROR -101 +#define MY_AES_BAD_KEYSIZE -102 + +/* The block size for all supported algorithms */ +#define MY_AES_BLOCK_SIZE 16 + +/* The max key length of all supported algorithms */ +#define MY_AES_MAX_KEY_LENGTH 32 + +#define MY_AES_CTX_SIZE 1040 + +enum my_aes_mode { + MY_AES_ECB, MY_AES_CBC +#ifdef HAVE_EncryptAes128Ctr + , MY_AES_CTR +#endif +#ifdef HAVE_EncryptAes128Gcm + , MY_AES_GCM +#endif +}; + +extern struct my_crypt_service_st { + int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); + int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen); + int (*my_aes_crypt)(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); + unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); + int (*my_random_bytes)(unsigned char* buf, int num); +} *my_crypt_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_aes_crypt_init(A,B,C,D,E,F,G) \ + my_crypt_service->my_aes_crypt_init(A,B,C,D,E,F,G) + +#define my_aes_crypt_update(A,B,C,D,E) \ + my_crypt_service->my_aes_crypt_update(A,B,C,D,E) + +#define my_aes_crypt_finish(A,B,C) \ + my_crypt_service->my_aes_crypt_finish(A,B,C) + +#define my_aes_crypt(A,B,C,D,E,F,G,H,I,J) \ + my_crypt_service->my_aes_crypt(A,B,C,D,E,F,G,H,I,J) + +#define my_aes_get_size(A,B)\ + my_crypt_service->my_aes_get_size(A,B) + +#define my_aes_ctx_size(A)\ + my_crypt_service->my_aes_ctx_size(A) + +#define my_random_bytes(A,B)\ + my_crypt_service->my_random_bytes(A,B) + +#else + +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen); +int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int *dlen); +int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen); +int my_aes_crypt(enum my_aes_mode mode, int flags, + const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, + const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); + +int my_random_bytes(unsigned char* buf, int num); +unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length); +unsigned int my_aes_ctx_size(enum my_aes_mode mode); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* MYSQL_SERVICE_MY_CRYPT_INCLUDED */ diff --git a/include/mysql/service_my_print_error.h b/include/mysql/service_my_print_error.h new file mode 100644 index 00000000..74ba6a2a --- /dev/null +++ b/include/mysql/service_my_print_error.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2016, MariaDB + +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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_SERVICE_MY_PRINT_ERROR_INCLUDED +#define MYSQL_SERVICE_MY_PRINT_ERROR_INCLUDED + +/** + @file include/mysql/service_my_print_error.h + + This service provides functions for plugins to report + errors to client (without client, the errors are written to the error log). + +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#include <stdlib.h> +#endif + +#define ME_ERROR_LOG 64 /* Write the message to the error log */ +#define ME_ERROR_LOG_ONLY 128 /* Write the error message to error log only */ +#define ME_NOTE 1024 /* Not an error, just a note */ +#define ME_WARNING 2048 /* Not an error, just a warning */ +#define ME_FATAL 4096 /* Fatal statement error */ + +extern struct my_print_error_service_st { + void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); + void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...); + void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap); +} *my_print_error_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_error my_print_error_service->my_error_func +#define my_printf_error my_print_error_service->my_printf_error_func +#define my_printv_error(A,B,C,D) my_print_error_service->my_printv_error_func(A,B,C,D) + +#else +extern void my_error(unsigned int nr, unsigned long MyFlags, ...); +extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...); +extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap); +#endif /* MYSQL_DYNAMIC_PLUGIN */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/service_my_snprintf.h b/include/mysql/service_my_snprintf.h new file mode 100644 index 00000000..fcc832fc --- /dev/null +++ b/include/mysql/service_my_snprintf.h @@ -0,0 +1,110 @@ +#ifndef MYSQL_SERVICE_MY_SNPRINTF_INCLUDED +/* Copyright (c) 2009, 2012, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my_snprintf service + + Portable and limited vsnprintf() implementation. + + This is a portable, limited vsnprintf() implementation, with some + extra features. "Portable" means that it'll produce identical result + on all platforms (for example, on Windows and Linux system printf %e + formats the exponent differently, on different systems %p either + prints leading 0x or not, %s may accept null pointer or crash on + it). "Limited" means that it does not support all the C89 features. + But it supports few extensions, not in any standard. + + my_vsnprintf(to, n, fmt, ap) + + @param[out] to A buffer to store the result in + @param[in] n Store up to n-1 characters, followed by an end 0 + @param[in] fmt printf-like format string + @param[in] ap Arguments + + @return a number of bytes written to a buffer *excluding* terminating '\0' + + @post + The syntax of a format string is generally the same: + % <flag> <width> <precision> <length modifier> <format> + where everything but the format is optional. + + Three one-character flags are recognized: + '0' has the standard zero-padding semantics; + '-' is parsed, but silently ignored; + '`' (backtick) is only supported for strings (%s) and means that the + string will be quoted according to MySQL identifier quoting rules. + + Both <width> and <precision> can be specified as numbers or '*'. + If an asterisk is used, an argument of type int is consumed. + + <length modifier> can be 'l', 'll', or 'z'. + + Supported formats are 's' (null pointer is accepted, printed as + "(null)"), 'b' (extension, see below), 'c', 'd', 'i', 'u', 'x', 'o', + 'X', 'p' (works as 0x%x), 'f', 'g', 'M' (extension, see below), + 'T' (extension, see below). + + Standard syntax for positional arguments $n is supported. + + Extensions: + + Flag '`' (backtick): see above. + + Format 'b': binary buffer, prints exactly <precision> bytes from the + argument, without stopping at '\0'. + + Format 'M': takes one integer, prints this integer, space, double quote + error message, double quote. In other words + printf("%M", n) === printf("%d \"%s\"", n, strerror(n)) + + Format 'T': takes string and print it like s but if the strints should be + truncated puts "..." at the end. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdarg.h> +#include <stdlib.h> +#endif + +extern struct my_snprintf_service_st { + size_t (*my_snprintf_type)(char*, size_t, const char*, ...); + size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); +} *my_snprintf_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_vsnprintf my_snprintf_service->my_vsnprintf_type +#define my_snprintf my_snprintf_service->my_snprintf_type + +#else + +size_t my_snprintf(char* to, size_t n, const char* fmt, ...); +size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_MY_SNPRINTF_INCLUDED +#endif + diff --git a/include/mysql/service_progress_report.h b/include/mysql/service_progress_report.h new file mode 100644 index 00000000..11fc24dc --- /dev/null +++ b/include/mysql/service_progress_report.h @@ -0,0 +1,82 @@ +#ifndef MYSQL_SERVICE_PROGRESS_REPORT_INCLUDED +/* Copyright (C) 2011 Monty Program Ab + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service allows plugins to report progress of long running operations + to the server. The progress report is visible in SHOW PROCESSLIST, + INFORMATION_SCHEMA.PROCESSLIST, and is sent to the client + if requested. + + The functions are documented at + https://mariadb.com/kb/en/progress-reporting/#how-to-add-support-for-progress-reporting-to-a-storage-engine +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define thd_proc_info(thd, msg) set_thd_proc_info(thd, msg, \ + __func__, __FILE__, __LINE__) + +extern struct progress_report_service_st { + void (*thd_progress_init_func)(MYSQL_THD thd, unsigned int max_stage); + void (*thd_progress_report_func)(MYSQL_THD thd, + unsigned long long progress, + unsigned long long max_progress); + void (*thd_progress_next_stage_func)(MYSQL_THD thd); + void (*thd_progress_end_func)(MYSQL_THD thd); + const char *(*set_thd_proc_info_func)(MYSQL_THD, const char *info, + const char *func, + const char *file, + unsigned int line); +} *progress_report_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_progress_init(thd,max_stage) (progress_report_service->thd_progress_init_func((thd),(max_stage))) +#define thd_progress_report(thd, progress, max_progress) (progress_report_service->thd_progress_report_func((thd), (progress), (max_progress))) +#define thd_progress_next_stage(thd) (progress_report_service->thd_progress_next_stage_func(thd)) +#define thd_progress_end(thd) (progress_report_service->thd_progress_end_func(thd)) +#define set_thd_proc_info(thd,info,func,file,line) (progress_report_service->set_thd_proc_info_func((thd),(info),(func),(file),(line))) + +#else + +/** + Report progress for long running operations + + @param thd User thread connection handle + @param progress Where we are now + @param max_progress Progress will continue up to this +*/ +void thd_progress_init(MYSQL_THD thd, unsigned int max_stage); +void thd_progress_report(MYSQL_THD thd, + unsigned long long progress, + unsigned long long max_progress); +void thd_progress_next_stage(MYSQL_THD thd); +void thd_progress_end(MYSQL_THD thd); +const char *set_thd_proc_info(MYSQL_THD, const char * info, const char *func, + const char *file, unsigned int line); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_PROGRESS_REPORT_INCLUDED +#endif + diff --git a/include/mysql/service_sha1.h b/include/mysql/service_sha1.h new file mode 100644 index 00000000..d864e23f --- /dev/null +++ b/include/mysql/service_sha1.h @@ -0,0 +1,69 @@ +#ifndef MYSQL_SERVICE_SHA1_INCLUDED +/* Copyright (c) 2013, 2014, Monty Program Ab + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my sha1 service + + Functions to calculate SHA1 hash from a memory buffer +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#define MY_SHA1_HASH_SIZE 20 /* Hash size in bytes */ + +extern struct my_sha1_service_st { + void (*my_sha1_type)(unsigned char*, const char*, size_t); + void (*my_sha1_multi_type)(unsigned char*, ...); + size_t (*my_sha1_context_size_type)(); + void (*my_sha1_init_type)(void *); + void (*my_sha1_input_type)(void *, const unsigned char *, size_t); + void (*my_sha1_result_type)(void *, unsigned char *); +} *my_sha1_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_sha1(A,B,C) my_sha1_service->my_sha1_type(A,B,C) +#define my_sha1_multi my_sha1_service->my_sha1_multi_type +#define my_sha1_context_size() my_sha1_service->my_sha1_context_size_type() +#define my_sha1_init(A) my_sha1_service->my_sha1_init_type(A) +#define my_sha1_input(A,B,C) my_sha1_service->my_sha1_input_type(A,B,C) +#define my_sha1_result(A,B) my_sha1_service->my_sha1_result_type(A,B) + +#else + +void my_sha1(unsigned char*, const char*, size_t); +void my_sha1_multi(unsigned char*, ...); +size_t my_sha1_context_size(); +void my_sha1_init(void *context); +void my_sha1_input(void *context, const unsigned char *buf, size_t len); +void my_sha1_result(void *context, unsigned char *digest); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_SHA1_INCLUDED +#endif + diff --git a/include/mysql/service_sha2.h b/include/mysql/service_sha2.h new file mode 100644 index 00000000..00834a9b --- /dev/null +++ b/include/mysql/service_sha2.h @@ -0,0 +1,130 @@ +#ifndef MYSQL_SERVICE_SHA2_INCLUDED +/* Copyright (c) 2017, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + my sha2 service + + Functions to calculate SHA2 hash from a memory buffer +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +extern struct my_sha2_service_st { + void (*my_sha224_type)(unsigned char*, const char*, size_t); + void (*my_sha224_multi_type)(unsigned char*, ...); + size_t (*my_sha224_context_size_type)(); + void (*my_sha224_init_type)(void *); + void (*my_sha224_input_type)(void *, const unsigned char *, size_t); + void (*my_sha224_result_type)(void *, unsigned char *); + + void (*my_sha256_type)(unsigned char*, const char*, size_t); + void (*my_sha256_multi_type)(unsigned char*, ...); + size_t (*my_sha256_context_size_type)(); + void (*my_sha256_init_type)(void *); + void (*my_sha256_input_type)(void *, const unsigned char *, size_t); + void (*my_sha256_result_type)(void *, unsigned char *); + + void (*my_sha384_type)(unsigned char*, const char*, size_t); + void (*my_sha384_multi_type)(unsigned char*, ...); + size_t (*my_sha384_context_size_type)(); + void (*my_sha384_init_type)(void *); + void (*my_sha384_input_type)(void *, const unsigned char *, size_t); + void (*my_sha384_result_type)(void *, unsigned char *); + + void (*my_sha512_type)(unsigned char*, const char*, size_t); + void (*my_sha512_multi_type)(unsigned char*, ...); + size_t (*my_sha512_context_size_type)(); + void (*my_sha512_init_type)(void *); + void (*my_sha512_input_type)(void *, const unsigned char *, size_t); + void (*my_sha512_result_type)(void *, unsigned char *); +} *my_sha2_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_sha224(A,B,C) my_sha2_service->my_sha224_type(A,B,C) +#define my_sha224_multi my_sha2_service->my_sha224_multi_type +#define my_sha224_context_size() my_sha2_service->my_sha224_context_size_type() +#define my_sha224_init(A) my_sha2_service->my_sha224_init_type(A) +#define my_sha224_input(A,B,C) my_sha2_service->my_sha224_input_type(A,B,C) +#define my_sha224_result(A,B) my_sha2_service->my_sha224_result_type(A,B) + +#define my_sha256(A,B,C) my_sha2_service->my_sha256_type(A,B,C) +#define my_sha256_multi my_sha2_service->my_sha256_multi_type +#define my_sha256_context_size() my_sha2_service->my_sha256_context_size_type() +#define my_sha256_init(A) my_sha2_service->my_sha256_init_type(A) +#define my_sha256_input(A,B,C) my_sha2_service->my_sha256_input_type(A,B,C) +#define my_sha256_result(A,B) my_sha2_service->my_sha256_result_type(A,B) + +#define my_sha384(A,B,C) my_sha2_service->my_sha384_type(A,B,C) +#define my_sha384_multi my_sha2_service->my_sha384_multi_type +#define my_sha384_context_size() my_sha2_service->my_sha384_context_size_type() +#define my_sha384_init(A) my_sha2_service->my_sha384_init_type(A) +#define my_sha384_input(A,B,C) my_sha2_service->my_sha384_input_type(A,B,C) +#define my_sha384_result(A,B) my_sha2_service->my_sha384_result_type(A,B) + +#define my_sha512(A,B,C) my_sha2_service->my_sha512_type(A,B,C) +#define my_sha512_multi my_sha2_service->my_sha512_multi_type +#define my_sha512_context_size() my_sha2_service->my_sha512_context_size_type() +#define my_sha512_init(A) my_sha2_service->my_sha512_init_type(A) +#define my_sha512_input(A,B,C) my_sha2_service->my_sha512_input_type(A,B,C) +#define my_sha512_result(A,B) my_sha2_service->my_sha512_result_type(A,B) + +#else + +void my_sha224(unsigned char*, const char*, size_t); +void my_sha224_multi(unsigned char*, ...); +size_t my_sha224_context_size(); +void my_sha224_init(void *context); +void my_sha224_input(void *context, const unsigned char *buf, size_t len); +void my_sha224_result(void *context, unsigned char *digest); + +void my_sha256(unsigned char*, const char*, size_t); +void my_sha256_multi(unsigned char*, ...); +size_t my_sha256_context_size(); +void my_sha256_init(void *context); +void my_sha256_input(void *context, const unsigned char *buf, size_t len); +void my_sha256_result(void *context, unsigned char *digest); + +void my_sha384(unsigned char*, const char*, size_t); +void my_sha384_multi(unsigned char*, ...); +size_t my_sha384_context_size(); +void my_sha384_init(void *context); +void my_sha384_input(void *context, const unsigned char *buf, size_t len); +void my_sha384_result(void *context, unsigned char *digest); + +void my_sha512(unsigned char*, const char*, size_t); +void my_sha512_multi(unsigned char*, ...); +size_t my_sha512_context_size(); +void my_sha512_init(void *context); +void my_sha512_input(void *context, const unsigned char *buf, size_t len); +void my_sha512_result(void *context, unsigned char *digest); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_SHA2_INCLUDED +#endif + diff --git a/include/mysql/service_sql.h b/include/mysql/service_sql.h new file mode 100644 index 00000000..2fee56ca --- /dev/null +++ b/include/mysql/service_sql.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2021 MariaDB Corporation + + 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, Fifth Floor, Boston, MA 02111-1301 USA */ + +#ifndef MYSQL_SERVICE_SQL +#define MYSQL_SERVICE_SQL + +#ifndef MYSQL_ABI_CHECK +#include <mysql.h> +#endif + +/** + @file + SQL service + + Interface for plugins to execute SQL queries on the local server. + + Functions of the service are the 'server-limited' client library: + mysql_init + mysql_real_connect_local + mysql_real_connect + mysql_errno + mysql_error + mysql_real_query + mysql_affected_rows + mysql_num_rows + mysql_store_result + mysql_free_result + mysql_fetch_row + mysql_close +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); +} *sql_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define mysql_init(M) sql_service->mysql_init_func(M) +#define mysql_real_connect_local(M) sql_service->mysql_real_connect_local_func(M) +#define mysql_real_connect(M,H,U,PW,D,P,S,F) sql_service->mysql_real_connect_func(M,H,U,PW,D,P,S,F) +#define mysql_errno(M) sql_service->mysql_errno_func(M) +#define mysql_error(M) sql_service->mysql_error_func(M) +#define mysql_real_query sql_service->mysql_real_query_func +#define mysql_affected_rows(M) sql_service->mysql_affected_rows_func(M) +#define mysql_num_rows(R) sql_service->mysql_num_rows_func(R) +#define mysql_store_result(M) sql_service->mysql_store_result_func(M) +#define mysql_free_result(R) sql_service->mysql_free_result_func(R) +#define mysql_fetch_row(R) sql_service->mysql_fetch_row_func(R) +#define mysql_close(M) sql_service->mysql_close_func(M) +#define mysql_options(M,O,V) sql_service->mysql_options_func(M,O,V) +#define mysql_fetch_lengths(R) sql_service->mysql_fetch_lengths_func(R) +#define mysql_set_character_set(M,C) sql_service->mysql_set_character_set_func(M,C) +#define mysql_num_fields(R) sql_service->mysql_num_fields_func(R) +#define mysql_select_db(M,D) sql_service->mysql_select_db_func(M,D) + +#else + +/* + Establishes the connection to the 'local' server that started the plugin. + Like the mysql_real_connect() does for the remote server. + The established connection has no user/host associated to it, + neither it has the current db, so the queries should have + database/table name specified. +*/ +MYSQL *mysql_real_connect_local(MYSQL *mysql); + +/* The rest of the function declarations must be taken from the mysql.h */ + +#endif /*MYSQL_DYNAMIC_PLUGIN*/ + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_SQL */ + + diff --git a/include/mysql/service_thd_alloc.h b/include/mysql/service_thd_alloc.h new file mode 100644 index 00000000..0be4687b --- /dev/null +++ b/include/mysql/service_thd_alloc.h @@ -0,0 +1,139 @@ +#ifndef MYSQL_SERVICE_THD_ALLOC_INCLUDED +/* Copyright (c) 2009, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides functions to allocate memory in a connection local + memory pool. The memory allocated there will be automatically freed at the + end of the statement, don't use it for allocations that should live longer + than that. For short living allocations this is more efficient than + using my_malloc and friends, and automatic "garbage collection" allows not + to think about memory leaks. + + The pool is best for small to medium objects, don't use it for large + allocations - they are better served with my_malloc. +*/ + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct st_mysql_lex_string +{ + char *str; + size_t length; +}; +typedef struct st_mysql_lex_string MYSQL_LEX_STRING; + +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING; + +extern struct thd_alloc_service_st { + void *(*thd_alloc_func)(MYSQL_THD, size_t); + void *(*thd_calloc_func)(MYSQL_THD, size_t); + char *(*thd_strdup_func)(MYSQL_THD, const char *); + char *(*thd_strmake_func)(MYSQL_THD, const char *, size_t); + void *(*thd_memdup_func)(MYSQL_THD, const void*, size_t); + MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(MYSQL_THD, + MYSQL_CONST_LEX_STRING *, + const char *, size_t, int); +} *thd_alloc_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_alloc(thd,size) (thd_alloc_service->thd_alloc_func((thd), (size))) + +#define thd_calloc(thd,size) (thd_alloc_service->thd_calloc_func((thd), (size))) + +#define thd_strdup(thd,str) (thd_alloc_service->thd_strdup_func((thd), (str))) + +#define thd_strmake(thd,str,size) \ + (thd_alloc_service->thd_strmake_func((thd), (str), (size))) + +#define thd_memdup(thd,str,size) \ + (thd_alloc_service->thd_memdup_func((thd), (str), (size))) + +#define thd_make_lex_string(thd, lex_str, str, size, allocate_lex_string) \ + (thd_alloc_service->thd_make_lex_string_func((thd), (lex_str), (str), \ + (size), (allocate_lex_string))) + +#else + +/** + Allocate memory in the connection's local memory pool + + @details + When properly used in place of @c my_malloc(), this can significantly + improve concurrency. Don't use this or related functions to allocate + large chunks of memory. Use for temporary storage only. The memory + will be freed automatically at the end of the statement; no explicit + code is required to prevent memory leaks. + + @see alloc_root() +*/ +void *thd_alloc(MYSQL_THD thd, size_t size); +/** + @see thd_alloc() +*/ +void *thd_calloc(MYSQL_THD thd, size_t size); +/** + @see thd_alloc() +*/ +char *thd_strdup(MYSQL_THD thd, const char *str); +/** + @see thd_alloc() +*/ +char *thd_strmake(MYSQL_THD thd, const char *str, size_t size); +/** + @see thd_alloc() +*/ +void *thd_memdup(MYSQL_THD thd, const void* str, size_t size); + +/** + Create a LEX_STRING in this connection's local memory pool + + @param thd user thread connection handle + @param lex_str pointer to LEX_STRING object to be initialized + @param str initializer to be copied into lex_str + @param size length of str, in bytes + @param allocate_lex_string flag: if TRUE, allocate new LEX_STRING object, + instead of using lex_str value + @return NULL on failure, or pointer to the LEX_STRING object + + @see thd_alloc() +*/ +MYSQL_CONST_LEX_STRING +*thd_make_lex_string(MYSQL_THD thd, MYSQL_CONST_LEX_STRING *lex_str, + const char *str, size_t size, + int allocate_lex_string); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_ALLOC_INCLUDED +#endif + diff --git a/include/mysql/service_thd_autoinc.h b/include/mysql/service_thd_autoinc.h new file mode 100644 index 00000000..28bd2bb1 --- /dev/null +++ b/include/mysql/service_thd_autoinc.h @@ -0,0 +1,53 @@ +#ifndef MYSQL_SERVICE_THD_AUTOINC_INCLUDED +/* Copyright (C) 2013 MariaDB Foundation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides access to the auto_increment related system variables: + + @@auto_increment_offset + @@auto_increment_increment +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct thd_autoinc_service_st { + void (*thd_get_autoinc_func)(const MYSQL_THD thd, + unsigned long* off, unsigned long* inc); +} *thd_autoinc_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +#define thd_get_autoinc(thd, off, inc) \ + (thd_autoinc_service->thd_get_autoinc_func((thd), (off), (inc))) +#else +/** + Return autoincrement system variables + @param IN thd user thread connection handle + @param OUT off the value of @@SESSION.auto_increment_offset + @param OUT inc the value of @@SESSION.auto_increment_increment +*/ +void thd_get_autoinc(const MYSQL_THD thd, + unsigned long* off, unsigned long* inc); +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_AUTOINC_INCLUDED +#endif diff --git a/include/mysql/service_thd_error_context.h b/include/mysql/service_thd_error_context.h new file mode 100644 index 00000000..0b9082dd --- /dev/null +++ b/include/mysql/service_thd_error_context.h @@ -0,0 +1,93 @@ +#ifndef MYSQL_SERVICE_THD_STMT_DA_INCLUDED +/* Copyright (C) 2013 MariaDB Foundation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides access to the statement diagnostics area: + - error message + - error number + - row for warning (e.g. for multi-row INSERT statements) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct thd_error_context_service_st { + const char *(*thd_get_error_message_func)(const MYSQL_THD thd); + unsigned int (*thd_get_error_number_func)(const MYSQL_THD thd); + unsigned long (*thd_get_error_row_func)(const MYSQL_THD thd); + void (*thd_inc_error_row_func)(MYSQL_THD thd); + char *(*thd_get_error_context_description_func)(MYSQL_THD thd, + char *buffer, + unsigned int length, + unsigned int max_query_length); +} *thd_error_context_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +#define thd_get_error_message(thd) \ + (thd_error_context_service->thd_get_error_message_func((thd))) +#define thd_get_error_number(thd) \ + (thd_error_context_service->thd_get_error_number_func((thd))) +#define thd_get_error_row(thd) \ + (thd_error_context_service->thd_get_error_row_func((thd))) +#define thd_inc_error_row(thd) \ + (thd_error_context_service->thd_inc_error_row_func((thd))) +#define thd_get_error_context_description(thd, buffer, length, max_query_len) \ + (thd_error_context_service->thd_get_error_context_description_func((thd), \ + (buffer), \ + (length), \ + (max_query_len))) +#else +/** + Return error message + @param thd user thread connection handle + @return error text +*/ +const char *thd_get_error_message(const MYSQL_THD thd); +/** + Return error number + @param thd user thread connection handle + @return error number +*/ +unsigned int thd_get_error_number(const MYSQL_THD thd); +/** + Return the current row number (i.e. in a multiple INSERT statement) + @param thd user thread connection handle + @return row number +*/ +unsigned long thd_get_error_row(const MYSQL_THD thd); +/** + Increment the current row number + @param thd user thread connection handle +*/ +void thd_inc_error_row(MYSQL_THD thd); +/** + Return a text description of a thread, its security context (user,host) + and the current query. +*/ +char *thd_get_error_context_description(MYSQL_THD thd, + char *buffer, unsigned int length, + unsigned int max_query_length); +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_STMT_DA_INCLUDED +#endif diff --git a/include/mysql/service_thd_mdl.h b/include/mysql/service_thd_mdl.h new file mode 100644 index 00000000..19b04769 --- /dev/null +++ b/include/mysql/service_thd_mdl.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2019, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#pragma once + +/** + @file include/mysql/service_thd_mdl.h + This service provides functions for plugins and storage engines to access + metadata locks. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct thd_mdl_service_st { + void *(*thd_mdl_context)(MYSQL_THD); +} *thd_mdl_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +# define thd_mdl_context(_THD) thd_mdl_service->thd_mdl_context(_THD) +#else +/** + MDL_context accessor + @param thd the current session + @return pointer to thd->mdl_context +*/ +void *thd_mdl_context(MYSQL_THD thd); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/include/mysql/service_thd_rnd.h b/include/mysql/service_thd_rnd.h new file mode 100644 index 00000000..8761077e --- /dev/null +++ b/include/mysql/service_thd_rnd.h @@ -0,0 +1,62 @@ +#ifndef MYSQL_SERVICE_THD_RND_INCLUDED +/* Copyright (C) 2017 MariaDB Corporation + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides access to the thd-local random number generator. + + It's preferable over the global one, because concurrent threads + can generate random numbers without fighting each other over the access + to the shared rnd state. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +extern struct thd_rnd_service_st { + double (*thd_rnd_ptr)(MYSQL_THD thd); + void (*thd_c_r_p_ptr)(MYSQL_THD thd, char *to, size_t length); +} *thd_rnd_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +#define thd_rnd(A) thd_rnd_service->thd_rnd_ptr(A) +#define thd_create_random_password(A,B,C) thd_rnd_service->thd_c_r_p_ptr(A,B,C) +#else + +double thd_rnd(MYSQL_THD thd); + +/** + Generate string of printable random characters of requested length. + + @param to[out] Buffer for generation; must be at least length+1 bytes + long; result string is always null-terminated + @param length[in] How many random characters to put in buffer +*/ +void thd_create_random_password(MYSQL_THD thd, char *to, size_t length); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_RND_INCLUDED +#endif diff --git a/include/mysql/service_thd_specifics.h b/include/mysql/service_thd_specifics.h new file mode 100644 index 00000000..a4078bd5 --- /dev/null +++ b/include/mysql/service_thd_specifics.h @@ -0,0 +1,110 @@ +#ifndef MYSQL_SERVICE_THD_SPECIFICS_INCLUDED +/* Copyright (c) 2009, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + THD specific for plugin(s) + + This API provides pthread_getspecific like functionality to plugin authors. + This is a functional alternative to the declarative MYSQL_THDVAR + + A plugin should at init call thd_key_create that create a key that + will have storage in each THD. The key should be used by all threads + and can be used concurrently from all threads. + + A plugin should at deinit call thd_key_delete. + + Alternatively, a plugin can use thd_key_create_from_var(K,V) to create + a key that corresponds to a named MYSQL_THDVAR variable. + + This API is also safe when using pool-of-threads in which case + pthread_getspecific is not, because the actual OS thread may change. + + @note + + Normally one should prefer MYSQL_THDVAR declarative API. + + The benefits are: + + - It supports typed variables (int, char*, enum, etc), not only void*. + - The memory allocated for MYSQL_THDVAR is free'd automatically + (if PLUGIN_VAR_MEMALLOC is specified). + - Continuous loading and unloading of the same plugin does not allocate + memory for same variables over and over again. + + An example of using MYSQL_THDVAR for a thd local storage: + + MYSQL_THDVAR_STR(my_tls, + PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT, + "thd local storage example", 0, 0, 0); +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int MYSQL_THD_KEY_T; + +extern struct thd_specifics_service_st { + int (*thd_key_create_func)(MYSQL_THD_KEY_T *key); + void (*thd_key_delete_func)(MYSQL_THD_KEY_T *key); + void *(*thd_getspecific_func)(MYSQL_THD thd, MYSQL_THD_KEY_T key); + int (*thd_setspecific_func)(MYSQL_THD thd, MYSQL_THD_KEY_T key, void *value); +} *thd_specifics_service; + +#define thd_key_create_from_var(K, V) do { *(K)= MYSQL_SYSVAR_NAME(V).offset; } while(0) + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_key_create(K) (thd_specifics_service->thd_key_create_func(K)) +#define thd_key_delete(K) (thd_specifics_service->thd_key_delete_func(K)) +#define thd_getspecific(T, K) (thd_specifics_service->thd_getspecific_func(T, K)) +#define thd_setspecific(T, K, V) (thd_specifics_service->thd_setspecific_func(T, K, V)) + +#else + +/** + * create THD specific storage + * @return 0 on success + * else errno is returned + */ +int thd_key_create(MYSQL_THD_KEY_T *key); + +/** + * delete THD specific storage + */ +void thd_key_delete(MYSQL_THD_KEY_T *key); + +/** + * get/set thd specific storage + * - first time this is called from a thread it will return 0 + * - this call is thread-safe in that different threads may call this + * simultaneously if operating on different THDs. + * - this call acquires no mutexes and is implemented as an array lookup + */ +void* thd_getspecific(MYSQL_THD thd, MYSQL_THD_KEY_T key); +int thd_setspecific(MYSQL_THD thd, MYSQL_THD_KEY_T key, void *value); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_SPECIFICS_INCLUDED +#endif + diff --git a/include/mysql/service_thd_timezone.h b/include/mysql/service_thd_timezone.h new file mode 100644 index 00000000..66713774 --- /dev/null +++ b/include/mysql/service_thd_timezone.h @@ -0,0 +1,73 @@ +#ifndef MYSQL_SERVICE_THD_TIMEZONE_INCLUDED +/* Copyright (C) 2013 MariaDB Foundation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + This service provides functions to convert between my_time_t and + MYSQL_TIME taking into account the current value of the time_zone + session variable. + + The values of the my_time_t type are in Unix timestamp format, + i.e. the number of seconds since "1970-01-01 00:00:00 UTC". + + The values of the MYSQL_TIME type are in the current time zone, + according to thd->variables.time_zone. + + If the MYSQL_THD parameter is NULL, then global_system_variables.time_zone + is used for conversion. +*/ + +#ifndef MYSQL_ABI_CHECK +/* + This service currently does not depend on any system headers. + If it needs system headers in the future, make sure to put + them inside this ifndef. +*/ +#endif + +#include "mysql_time.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(MYSQL_THD thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_TIME_to_gmt_sec(thd, ltime, errcode) \ + (thd_timezone_service->thd_TIME_to_gmt_sec((thd), (ltime), (errcode))) + +#define thd_gmt_sec_to_TIME(thd, ltime, t) \ + (thd_timezone_service->thd_gmt_sec_to_TIME((thd), (ltime), (t))) + +#else + +my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime, unsigned int *errcode); +void thd_gmt_sec_to_TIME(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_TIMEZONE_INCLUDED +#endif diff --git a/include/mysql/service_thd_wait.h b/include/mysql/service_thd_wait.h new file mode 100644 index 00000000..c20878fd --- /dev/null +++ b/include/mysql/service_thd_wait.h @@ -0,0 +1,104 @@ +/* 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef MYSQL_SERVICE_THD_WAIT_INCLUDED +#define MYSQL_SERVICE_THD_WAIT_INCLUDED + +/** + @file include/mysql/service_thd_wait.h + This service provides functions for plugins and storage engines to report + when they are going to sleep/stall. + + SYNOPSIS + thd_wait_begin() - call just before a wait begins + thd Thread object + Use NULL if the thd is NOT known. + wait_type Type of wait + 1 -- short wait (e.g. for mutex) + 2 -- medium wait (e.g. for disk io) + 3 -- large wait (e.g. for locked row/table) + NOTES + This is used by the threadpool to have better knowledge of which + threads that currently are actively running on CPUs. When a thread + reports that it's going to sleep/stall, the threadpool scheduler is + free to start another thread in the pool most likely. The expected wait + time is simply an indication of how long the wait is expected to + become, the real wait time could be very different. + + thd_wait_end() called immediately after the wait is complete + + thd_wait_end() MUST be called if thd_wait_begin() was called. + + Using thd_wait_...() service is optional but recommended. Using it will + improve performance as the thread pool will be more active at managing the + thread workload. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + One should only report wait events that could potentially block for a + long time. A mutex wait is too short of an event to report. The reason + is that an event which is reported leads to a new thread starts + executing a query and this has a negative impact of usage of CPU caches + and thus the expected gain of starting a new thread must be higher than + the expected cost of lost performance due to starting a new thread. + + Good examples of events that should be reported are waiting for row locks + that could easily be for many milliseconds or even seconds and the same + holds true for global read locks, table locks and other meta data locks. + Another event of interest is going to sleep for an extended time. +*/ +typedef enum _thd_wait_type_e { + THD_WAIT_SLEEP= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_NET= 11, + THD_WAIT_LAST= 12 +} thd_wait_type; + +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(MYSQL_THD, int); + void (*thd_wait_end_func)(MYSQL_THD); +} *thd_wait_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_wait_begin(_THD, _WAIT_TYPE) \ + thd_wait_service->thd_wait_begin_func(_THD, _WAIT_TYPE) +#define thd_wait_end(_THD) thd_wait_service->thd_wait_end_func(_THD) + +#else + +void thd_wait_begin(MYSQL_THD thd, int wait_type); +void thd_wait_end(MYSQL_THD thd); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h new file mode 100644 index 00000000..8add7093 --- /dev/null +++ b/include/mysql/service_wsrep.h @@ -0,0 +1,257 @@ +#ifndef MYSQL_SERVICE_WSREP_INCLUDED +#define MYSQL_SERVICE_WSREP_INCLUDED + +enum Wsrep_service_key_type +{ + WSREP_SERVICE_KEY_SHARED, + WSREP_SERVICE_KEY_REFERENCE, + WSREP_SERVICE_KEY_UPDATE, + WSREP_SERVICE_KEY_EXCLUSIVE +}; + +#if (defined (MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED)) || (!defined(MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_STATIC_INCLUDED)) + +#else + +/* Copyright (c) 2015, 2020, MariaDB Corporation Ab + 2018 Codership Oy <info@codership.com> + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + wsrep service + + Interface to WSREP functionality in the server. + For engines that want to support galera. +*/ +#include <my_pthread.h> +#ifdef __cplusplus +#endif + +struct xid_t; +struct wsrep_ws_handle; +struct wsrep_buf; + +/* Must match to definition in sql/mysqld.h */ +typedef int64 query_id_t; + + +extern struct wsrep_service_st { + my_bool (*get_wsrep_recovery_func)(); + bool (*wsrep_consistency_check_func)(MYSQL_THD thd); + int (*wsrep_is_wsrep_xid_func)(const void *xid); + long long (*wsrep_xid_seqno_func)(const struct xid_t *xid); + const unsigned char* (*wsrep_xid_uuid_func)(const struct xid_t *xid); + my_bool (*wsrep_on_func)(const MYSQL_THD thd); + bool (*wsrep_prepare_key_for_innodb_func)(MYSQL_THD thd, const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*); + void (*wsrep_thd_LOCK_func)(const MYSQL_THD thd); + int (*wsrep_thd_TRYLOCK_func)(const MYSQL_THD thd); + void (*wsrep_thd_UNLOCK_func)(const MYSQL_THD thd); + const char * (*wsrep_thd_query_func)(const MYSQL_THD thd); + int (*wsrep_thd_retry_counter_func)(const MYSQL_THD thd); + bool (*wsrep_thd_ignore_table_func)(MYSQL_THD thd); + long long (*wsrep_thd_trx_seqno_func)(const MYSQL_THD thd); + my_bool (*wsrep_thd_is_aborting_func)(const MYSQL_THD thd); + void (*wsrep_set_data_home_dir_func)(const char *data_dir); + my_bool (*wsrep_thd_is_BF_func)(const MYSQL_THD thd, my_bool sync); + my_bool (*wsrep_thd_is_local_func)(const MYSQL_THD thd); + void (*wsrep_thd_self_abort_func)(MYSQL_THD thd); + int (*wsrep_thd_append_key_func)(MYSQL_THD thd, const struct wsrep_key* key, + int n_keys, enum Wsrep_service_key_type); + int (*wsrep_thd_append_table_key_func)(MYSQL_THD thd, const char* db, + const char* table, enum Wsrep_service_key_type); + my_bool (*wsrep_thd_is_local_transaction)(const MYSQL_THD thd); + const char* (*wsrep_thd_client_state_str_func)(const MYSQL_THD thd); + const char* (*wsrep_thd_client_mode_str_func)(const MYSQL_THD thd); + const char* (*wsrep_thd_transaction_state_str_func)(const MYSQL_THD thd); + query_id_t (*wsrep_thd_transaction_id_func)(const MYSQL_THD thd); + my_bool (*wsrep_thd_bf_abort_func)(MYSQL_THD bf_thd, + MYSQL_THD victim_thd, + my_bool signal); + my_bool (*wsrep_thd_order_before_func)(const MYSQL_THD left, const MYSQL_THD right); + void (*wsrep_handle_SR_rollback_func)(MYSQL_THD BF_thd, MYSQL_THD victim_thd); + my_bool (*wsrep_thd_skip_locking_func)(const MYSQL_THD thd); + const char* (*wsrep_get_sr_table_name_func)(); + my_bool (*wsrep_get_debug_func)(); + void (*wsrep_commit_ordered_func)(MYSQL_THD thd); + my_bool (*wsrep_thd_is_applying_func)(const MYSQL_THD thd); + ulong (*wsrep_OSU_method_get_func)(const MYSQL_THD thd); + my_bool (*wsrep_thd_has_ignored_error_func)(const MYSQL_THD thd); + void (*wsrep_thd_set_ignored_error_func)(MYSQL_THD thd, my_bool val); + void (*wsrep_report_bf_lock_wait_func)(const MYSQL_THD thd, + unsigned long long trx_id); + void (*wsrep_thd_kill_LOCK_func)(const MYSQL_THD thd); + void (*wsrep_thd_kill_UNLOCK_func)(const MYSQL_THD thd); + void (*wsrep_thd_set_wsrep_PA_unsafe_func)(MYSQL_THD thd); +} *wsrep_service; + +#define MYSQL_SERVICE_WSREP_INCLUDED +#endif + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED +#define get_wsrep_recovery() wsrep_service->get_wsrep_recovery_func() +#define wsrep_consistency_check(T) wsrep_service->wsrep_consistency_check_func(T) +#define wsrep_is_wsrep_xid(X) wsrep_service->wsrep_is_wsrep_xid_func(X) +#define wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X) +#define wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X) +#define wsrep_on(thd) (thd) && WSREP_ON && wsrep_service->wsrep_on_func(thd) +#define wsrep_prepare_key_for_innodb(A,B,C,D,E,F,G) wsrep_service->wsrep_prepare_key_for_innodb_func(A,B,C,D,E,F,G) +#define wsrep_thd_LOCK(T) wsrep_service->wsrep_thd_LOCK_func(T) +#define wsrep_thd_TRYLOCK(T) wsrep_service->wsrep_thd_TRYLOCK_func(T) +#define wsrep_thd_UNLOCK(T) wsrep_service->wsrep_thd_UNLOCK_func(T) +#define wsrep_thd_kill_LOCK(T) wsrep_service->wsrep_thd_kill_LOCK_func(T) +#define wsrep_thd_kill_UNLOCK(T) wsrep_service->wsrep_thd_kill_UNLOCK_func(T) +#define wsrep_thd_query(T) wsrep_service->wsrep_thd_query_func(T) +#define wsrep_thd_retry_counter(T) wsrep_service->wsrep_thd_retry_counter_func(T) +#define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T) +#define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T) +#define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A) +#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S) +#define wsrep_thd_is_aborting(T) wsrep_service->wsrep_thd_is_aborting_func(T) +#define wsrep_thd_is_local(T) wsrep_service->wsrep_thd_is_local_func(T) +#define wsrep_thd_self_abort(T) wsrep_service->wsrep_thd_self_abort_func(T) +#define wsrep_thd_append_key(T,W,N,K) wsrep_service->wsrep_thd_append_key_func(T,W,N,K) +#define wsrep_thd_append_table_key(T,D,B,K) wsrep_service->wsrep_thd_append_table_key_func(T,D,B,K) +#define wsrep_thd_is_local_transaction(T) wsrep_service->wsrep_thd_is_local_transaction_func(T) +#define wsrep_thd_client_state_str(T) wsrep_service->wsrep_thd_client_state_str_func(T) +#define wsrep_thd_client_mode_str(T) wsrep_service->wsrep_thd_client_mode_str_func(T) +#define wsrep_thd_transaction_state_str(T) wsrep_service->wsrep_thd_transaction_state_str_func(T) +#define wsrep_thd_transaction_id(T) wsrep_service->wsrep_thd_transaction_id_func(T) +#define wsrep_thd_bf_abort(T,T2,S) wsrep_service->wsrep_thd_bf_abort_func(T,T2,S) +#define wsrep_thd_order_before(L,R) wsrep_service->wsrep_thd_order_before_func(L,R) +#define wsrep_handle_SR_rollback(B,V) wsrep_service->wsrep_handle_SR_rollback_func(B,V) +#define wsrep_thd_skip_locking(T) wsrep_service->wsrep_thd_skip_locking_func(T) +#define wsrep_get_sr_table_name() wsrep_service->wsrep_get_sr_table_name_func() +#define wsrep_get_debug() wsrep_service->wsrep_get_debug_func() +#define wsrep_commit_ordered(T) wsrep_service->wsrep_commit_ordered_func(T) +#define wsrep_thd_is_applying(T) wsrep_service->wsrep_thd_is_applying_func(T) +#define wsrep_OSU_method_get(T) wsrep_service->wsrep_OSU_method_get_func(T) +#define wsrep_thd_has_ignored_error(T) wsrep_service->wsrep_thd_has_ignored_error_func(T) +#define wsrep_thd_set_ignored_error(T,V) wsrep_service->wsrep_thd_set_ignored_error_func(T,V) +#define wsrep_report_bf_lock_wait(T,I) wsrep_service->wsrep_report_bf_lock_wait(T,I) +#define wsrep_thd_set_PA_unsafe(T) wsrep_service->wsrep_thd_set_PA_unsafe_func(T) +#else + +#define MYSQL_SERVICE_WSREP_STATIC_INCLUDED +extern ulong wsrep_debug; +extern my_bool wsrep_log_conflicts; +extern my_bool wsrep_certify_nonPK; +extern my_bool wsrep_load_data_splitting; +extern my_bool wsrep_drupal_282555_workaround; +extern my_bool wsrep_recovery; +extern long wsrep_protocol_version; + +extern "C" bool wsrep_consistency_check(MYSQL_THD thd); +bool wsrep_prepare_key_for_innodb(MYSQL_THD thd, const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len); +extern "C" const char *wsrep_thd_query(const MYSQL_THD thd); +extern "C" int wsrep_is_wsrep_xid(const void* xid); +extern "C" long long wsrep_xid_seqno(const struct xid_t* xid); +const unsigned char* wsrep_xid_uuid(const struct xid_t* xid); +extern "C" long long wsrep_thd_trx_seqno(const MYSQL_THD thd); +my_bool get_wsrep_recovery(); +bool wsrep_thd_ignore_table(MYSQL_THD thd); +void wsrep_set_data_home_dir(const char *data_dir); + +/* from mysql wsrep-lib */ +#include "my_global.h" +#include "my_pthread.h" + +/* Return true if wsrep is enabled for a thd. This means that + wsrep is enabled globally and the thd has wsrep on */ +extern "C" my_bool wsrep_on(const MYSQL_THD thd); +/* Lock thd wsrep lock */ +extern "C" void wsrep_thd_LOCK(const MYSQL_THD thd); +/* Try thd wsrep lock. Return non-zero if lock could not be taken. */ +extern "C" int wsrep_thd_TRYLOCK(const MYSQL_THD thd); +/* Unlock thd wsrep lock */ +extern "C" void wsrep_thd_UNLOCK(const MYSQL_THD thd); + +extern "C" void wsrep_thd_kill_LOCK(const MYSQL_THD thd); +extern "C" void wsrep_thd_kill_UNLOCK(const MYSQL_THD thd); + +/* Return thd client state string */ +extern "C" const char* wsrep_thd_client_state_str(const MYSQL_THD thd); +/* Return thd client mode string */ +extern "C" const char* wsrep_thd_client_mode_str(const MYSQL_THD thd); +/* Return thd transaction state string */ +extern "C" const char* wsrep_thd_transaction_state_str(const MYSQL_THD thd); + +/* Return current transaction id */ +extern "C" query_id_t wsrep_thd_transaction_id(const MYSQL_THD thd); +/* Mark thd own transaction as aborted */ +extern "C" void wsrep_thd_self_abort(MYSQL_THD thd); +/* Return true if thd is in replicating mode */ +extern "C" my_bool wsrep_thd_is_local(const MYSQL_THD thd); +/* Return true if thd is in high priority mode */ +/* todo: rename to is_high_priority() */ +extern "C" my_bool wsrep_thd_is_applying(const MYSQL_THD thd); +/* Return true if thd is in TOI mode */ +extern "C" my_bool wsrep_thd_is_toi(const MYSQL_THD thd); +/* Return true if thd is in replicating TOI mode */ +extern "C" my_bool wsrep_thd_is_local_toi(const MYSQL_THD thd); +/* Return true if thd is in RSU mode */ +extern "C" my_bool wsrep_thd_is_in_rsu(const MYSQL_THD thd); +/* Return true if thd is in BF mode, either high_priority or TOI */ +extern "C" my_bool wsrep_thd_is_BF(const MYSQL_THD thd, my_bool sync); +/* Return true if thd is streaming */ +extern "C" my_bool wsrep_thd_is_SR(const MYSQL_THD thd); +extern "C" void wsrep_handle_SR_rollback(MYSQL_THD BF_thd, MYSQL_THD victim_thd); +/* Return thd retry counter */ +extern "C" int wsrep_thd_retry_counter(const MYSQL_THD thd); +/* BF abort victim_thd */ +extern "C" my_bool wsrep_thd_bf_abort(MYSQL_THD bf_thd, + MYSQL_THD victim_thd, + my_bool signal); +/* Return true if left thd is ordered before right thd */ +extern "C" my_bool wsrep_thd_order_before(const MYSQL_THD left, const MYSQL_THD right); +/* Return true if thd should skip locking. This means that the thd + is operating on shared resource inside commit order critical section. */ +extern "C" my_bool wsrep_thd_skip_locking(const MYSQL_THD thd); +/* Return true if thd is aborting */ +extern "C" my_bool wsrep_thd_is_aborting(const MYSQL_THD thd); + +struct wsrep_key; +struct wsrep_key_array; +extern "C" int wsrep_thd_append_key(MYSQL_THD thd, + const struct wsrep_key* key, + int n_keys, + enum Wsrep_service_key_type); + +extern "C" int wsrep_thd_append_table_key(MYSQL_THD thd, + const char* db, + const char* table, + enum Wsrep_service_key_type); + +extern "C" my_bool wsrep_thd_is_local_transaction(const MYSQL_THD thd); + +extern const char* wsrep_sr_table_name_full; + +extern "C" const char* wsrep_get_sr_table_name(); + +extern "C" my_bool wsrep_get_debug(); + +extern "C" void wsrep_commit_ordered(MYSQL_THD thd); +extern "C" my_bool wsrep_thd_is_applying(const MYSQL_THD thd); +extern "C" ulong wsrep_OSU_method_get(const MYSQL_THD thd); +extern "C" my_bool wsrep_thd_has_ignored_error(const MYSQL_THD thd); +extern "C" void wsrep_thd_set_ignored_error(MYSQL_THD thd, my_bool val); +extern "C" void wsrep_report_bf_lock_wait(const THD *thd, + unsigned long long trx_id); +/* declare parallel applying unsafety for the THD */ +extern "C" void wsrep_thd_set_PA_unsafe(MYSQL_THD thd); +#endif +#endif /* MYSQL_SERVICE_WSREP_INCLUDED */ diff --git a/include/mysql/services.h b/include/mysql/services.h new file mode 100644 index 00000000..94f7bb3b --- /dev/null +++ b/include/mysql/services.h @@ -0,0 +1,52 @@ +#ifndef MYSQL_SERVICES_INCLUDED +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, 2017, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <mysql/service_base64.h> +#include <mysql/service_debug_sync.h> +#include <mysql/service_encryption.h> +#include <mysql/service_encryption_scheme.h> +#include <mysql/service_kill_statement.h> +#include <mysql/service_logger.h> +#include <mysql/service_md5.h> +#include <mysql/service_my_crypt.h> +#include <mysql/service_my_print_error.h> +#include <mysql/service_my_snprintf.h> +#include <mysql/service_progress_report.h> +#include <mysql/service_sha1.h> +#include <mysql/service_sha2.h> +#include <mysql/service_thd_alloc.h> +#include <mysql/service_thd_autoinc.h> +#include <mysql/service_thd_error_context.h> +#include <mysql/service_thd_rnd.h> +#include <mysql/service_thd_specifics.h> +#include <mysql/service_thd_timezone.h> +#include <mysql/service_thd_wait.h> +#include <mysql/service_json.h> +/*#include <mysql/service_wsrep.h>*/ +#include <mysql/service_sql.h> + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICES_INCLUDED +#endif + diff --git a/include/mysql_com.h b/include/mysql_com.h new file mode 100644 index 00000000..1bc2fcc7 --- /dev/null +++ b/include/mysql_com.h @@ -0,0 +1,773 @@ +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2010, 2017, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* +** Common definition between mysql server & client +*/ + +#ifndef _mysql_com_h +#define _mysql_com_h + +#include "my_decimal_limits.h" + +#define HOSTNAME_LENGTH 255 +#define HOSTNAME_LENGTH_STR STRINGIFY_ARG(HOSTNAME_LENGTH) +#define SYSTEM_CHARSET_MBMAXLEN 3 +#define NAME_CHAR_LEN 64 /* Field/table name length */ +#define USERNAME_CHAR_LENGTH 128 +#define USERNAME_CHAR_LENGTH_STR STRINGIFY_ARG(USERNAME_CHAR_LENGTH) + +#define NAME_LEN (NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN) +#define USERNAME_LENGTH (USERNAME_CHAR_LENGTH*SYSTEM_CHARSET_MBMAXLEN) +#define DEFINER_CHAR_LENGTH (USERNAME_CHAR_LENGTH + HOSTNAME_LENGTH + 1) +#define DEFINER_LENGTH (USERNAME_LENGTH + HOSTNAME_LENGTH + 1) + +#define MYSQL_AUTODETECT_CHARSET_NAME "auto" + +#define MYSQL50_TABLE_NAME_PREFIX "#mysql50#" +#define MYSQL50_TABLE_NAME_PREFIX_LENGTH (sizeof(MYSQL50_TABLE_NAME_PREFIX)-1) +#define SAFE_NAME_LEN (NAME_LEN + MYSQL50_TABLE_NAME_PREFIX_LENGTH) + +/* + MDEV-4088 + + MySQL (and MariaDB 5.x before the fix) was using the first character of the + server version string (as sent in the first handshake protocol packet) to + decide on the replication event formats. And for 10.x the first character + is "1", which the slave thought comes from some ancient 1.x version + (ignoring the fact that the first ever MySQL version was 3.x). + + To support replication to these old clients, we fake the version in the + first handshake protocol packet to start from "5.5.5-" (for example, + it might be "5.5.5-10.0.1-MariaDB-debug-log". + + On the client side we remove this fake version prefix to restore the + correct server version. The version "5.5.5" did not support + pluggable authentication, so any version starting from "5.5.5-" and + claiming to support pluggable auth, must be using this fake prefix. +*/ +/* this version must be the one that *does not* support pluggable auth */ +#define RPL_VERSION_HACK "5.5.5-" + +#define SERVER_VERSION_LENGTH 60 +#define SQLSTATE_LENGTH 5 +#define LIST_PROCESS_HOST_LEN 64 + +/* + Maximum length of comments +*/ +#define TABLE_COMMENT_INLINE_MAXLEN 180 /* pre 5.5: 60 characters */ +#define TABLE_COMMENT_MAXLEN 2048 +#define COLUMN_COMMENT_MAXLEN 1024 +#define INDEX_COMMENT_MAXLEN 1024 +#define TABLE_PARTITION_COMMENT_MAXLEN 1024 +#define DATABASE_COMMENT_MAXLEN 1024 + +/* + Maximum length of protocol packet. + OK packet length limit also restricted to this value as any length greater + than this value will have first byte of OK packet to be 254 thus does not + provide a means to identify if this is OK or EOF packet. +*/ +#define MAX_PACKET_LENGTH (256L*256L*256L-1) + +/* + USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain + username and hostname parts of the user identifier with trailing zero in + MySQL standard format: + user_name_part@host_name_part\0 +*/ +#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_LENGTH + 2 + +#define LOCAL_HOST "localhost" +#define LOCAL_HOST_NAMEDPIPE "." + + +#if defined(_WIN32) && !defined( _CUSTOMCONFIG_) +#define MYSQL_NAMEDPIPE "MySQL" +#define MYSQL_SERVICENAME "MySQL" +#endif + +/* + You should add new commands to the end of this list, otherwise old + servers won't be able to handle them as 'unsupported'. +*/ + +enum enum_server_command +{ + COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST, + COM_CREATE_DB, COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS, + COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING, + COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP, + COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE, + COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE, + COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON, + COM_UNIMPLEMENTED, /* COM_BINLOG_DUMP_GTID in MySQL */ + COM_RESET_CONNECTION, + /* don't forget to update const char *command_name[] in sql_parse.cc */ + COM_MDB_GAP_BEG, + COM_MDB_GAP_END=249, + COM_STMT_BULK_EXECUTE=250, + COM_SLAVE_WORKER=251, + COM_SLAVE_IO=252, + COM_SLAVE_SQL=253, + COM_RESERVED_1=254, /* Old COM_MULTI, now removed */ + /* Must be last */ + COM_END=255 +}; + + +/* + Bulk PS protocol indicator value: +*/ +enum enum_indicator_type +{ + STMT_INDICATOR_NONE= 0, + STMT_INDICATOR_NULL, + STMT_INDICATOR_DEFAULT, + STMT_INDICATOR_IGNORE +}; + +/* + bulk PS flags +*/ +#define STMT_BULK_FLAG_CLIENT_SEND_TYPES 128 +#define STMT_BULK_FLAG_INSERT_ID_REQUEST 64 + + +/* sql type stored in .frm files for virtual fields */ +#define MYSQL_TYPE_VIRTUAL 245 +/* + Length of random string sent by server on handshake; this is also length of + obfuscated password, received from client +*/ +#define SCRAMBLE_LENGTH 20 +#define SCRAMBLE_LENGTH_323 8 +/* length of password stored in the db: new passwords are preceded with '*' */ +#define SCRAMBLED_PASSWORD_CHAR_LENGTH (SCRAMBLE_LENGTH*2+1) +#define SCRAMBLED_PASSWORD_CHAR_LENGTH_323 (SCRAMBLE_LENGTH_323*2) + + +#define NOT_NULL_FLAG 1U /* Field can't be NULL */ +#define PRI_KEY_FLAG 2U /* Field is part of a primary key */ +#define UNIQUE_KEY_FLAG 4U /* Field is part of a unique key */ +#define MULTIPLE_KEY_FLAG 8U /* Field is part of a key */ +#define BLOB_FLAG 16U /* Field is a blob */ +#define UNSIGNED_FLAG 32U /* Field is unsigned */ +#define ZEROFILL_FLAG 64U /* Field is zerofill */ +#define BINARY_FLAG 128U /* Field is binary */ + +/* The following are only sent to new clients */ +#define ENUM_FLAG 256U /* field is an enum */ +#define AUTO_INCREMENT_FLAG 512U /* field is a autoincrement field */ +#define TIMESTAMP_FLAG 1024U /* Field is a timestamp */ +#define SET_FLAG 2048U /* field is a set */ +#define NO_DEFAULT_VALUE_FLAG 4096U /* Field doesn't have default value */ +#define ON_UPDATE_NOW_FLAG 8192U /* Field is set to NOW on UPDATE */ +#define NUM_FLAG 32768U /* Field is num (for clients) */ +#define PART_KEY_FLAG 16384U /* Intern; Part of some key */ +#define GROUP_FLAG 32768U /* Intern: Group field */ +#define CONTEXT_COLLATION_FLAG 131072U /* Intern: Used by sql_yacc */ +#define GET_FIXED_FIELDS_FLAG (1U << 18) /* Used to get fields in item tree */ +#define FIELD_IN_PART_FUNC_FLAG (1U << 19)/* Field part of partition func */ +#define PART_INDIRECT_KEY_FLAG (1U << 20) + +/** + Intern: Field in TABLE object for new version of altered table, + which participates in a newly added index. +*/ +#define FIELD_IN_ADD_INDEX (1U << 20) +#define FIELD_IS_RENAMED (1U << 21) /* Intern: Field is being renamed */ +#define FIELD_FLAGS_STORAGE_MEDIA 22 /* Field storage media, bit 22-23 */ +#define FIELD_FLAGS_STORAGE_MEDIA_MASK (3U << FIELD_FLAGS_STORAGE_MEDIA) +#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25 */ +#define FIELD_FLAGS_COLUMN_FORMAT_MASK (3U << FIELD_FLAGS_COLUMN_FORMAT) +#define FIELD_IS_DROPPED (1U << 26) /* Intern: Field is being dropped */ + +#define VERS_ROW_START (1 << 27) /* autogenerated column declared with + `generated always as row start` + (see II.a SQL Standard) */ +#define VERS_ROW_END (1 << 28) /* autogenerated column declared with + `generated always as row end` + (see II.a SQL Standard).*/ +#define VERS_SYSTEM_FIELD (VERS_ROW_START | VERS_ROW_END) +#define VERS_UPDATE_UNVERSIONED_FLAG (1 << 29) /* column that doesn't support + system versioning when table + itself supports it*/ +#define LONG_UNIQUE_HASH_FIELD (1<< 30) /* This field will store hash for unique + column */ +#define FIELD_PART_OF_TMP_UNIQUE (1<< 31) /* part of an unique constrain + for a tmporary table*/ + +#define REFRESH_GRANT (1ULL << 0) /* Refresh grant tables */ +#define REFRESH_LOG (1ULL << 1) /* Start on new log file */ +#define REFRESH_TABLES (1ULL << 2) /* close all tables */ +#define REFRESH_HOSTS (1ULL << 3) /* Flush host cache */ +#define REFRESH_STATUS (1ULL << 4) /* Flush status variables */ +#define REFRESH_THREADS (1ULL << 5) /* Flush thread cache */ +#define REFRESH_SLAVE (1ULL << 6) /* Reset master info and restart slave + thread */ +#define REFRESH_MASTER (1ULL << 7) /* Remove all bin logs in the index + and truncate the index */ + +/* The following can't be set with mysql_refresh() */ +#define REFRESH_ERROR_LOG (1ULL << 8) /* Rotate only the error log */ +#define REFRESH_ENGINE_LOG (1ULL << 9) /* Flush all storage engine logs */ +#define REFRESH_BINARY_LOG (1ULL << 10) /* Flush the binary log */ +#define REFRESH_RELAY_LOG (1ULL << 11) /* Flush the relay log */ +#define REFRESH_GENERAL_LOG (1ULL << 12) /* Flush the general log */ +#define REFRESH_SLOW_LOG (1ULL << 13) /* Flush the slow query log */ + +#define REFRESH_READ_LOCK (1ULL << 14) /* Lock tables for read */ +#define REFRESH_CHECKPOINT (1ULL << 15) /* With REFRESH_READ_LOCK: block checkpoints too */ + +#define REFRESH_QUERY_CACHE (1ULL << 16) /* clear the query cache */ +#define REFRESH_QUERY_CACHE_FREE (1ULL << 17) /* pack query cache */ +#define REFRESH_DES_KEY_FILE (1ULL << 18) +#define REFRESH_USER_RESOURCES (1ULL << 19) +#define REFRESH_FOR_EXPORT (1ULL << 20) /* FLUSH TABLES ... FOR EXPORT */ +#define REFRESH_SSL (1ULL << 21) + +#define REFRESH_GENERIC (1ULL << 30) +#define REFRESH_FAST (1ULL << 31) /* Intern flag */ + +#define CLIENT_LONG_PASSWORD 0 /* obsolete flag */ +#define CLIENT_MYSQL 1ULL /* mysql/old mariadb server/client */ +#define CLIENT_FOUND_ROWS 2ULL /* Found instead of affected rows */ +#define CLIENT_LONG_FLAG 4ULL /* Get all column flags */ +#define CLIENT_CONNECT_WITH_DB 8ULL /* One can specify db on connect */ +#define CLIENT_NO_SCHEMA 16ULL /* Don't allow database.table.column */ +#define CLIENT_COMPRESS 32ULL /* Can use compression protocol */ +#define CLIENT_ODBC 64ULL /* Odbc client */ +#define CLIENT_LOCAL_FILES 128ULL /* Can use LOAD DATA LOCAL */ +#define CLIENT_IGNORE_SPACE 256ULL /* Ignore spaces before '(' */ +#define CLIENT_PROTOCOL_41 512ULL /* New 4.1 protocol */ +#define CLIENT_INTERACTIVE 1024ULL /* This is an interactive client */ +#define CLIENT_SSL 2048ULL /* Switch to SSL after handshake */ +#define CLIENT_IGNORE_SIGPIPE 4096ULL /* IGNORE sigpipes */ +#define CLIENT_TRANSACTIONS 8192ULL /* Client knows about transactions */ +#define CLIENT_RESERVED 16384ULL /* Old flag for 4.1 protocol */ +#define CLIENT_SECURE_CONNECTION 32768ULL /* New 4.1 authentication */ +#define CLIENT_MULTI_STATEMENTS (1ULL << 16) /* Enable/disable multi-stmt support */ +#define CLIENT_MULTI_RESULTS (1ULL << 17) /* Enable/disable multi-results */ +#define CLIENT_PS_MULTI_RESULTS (1ULL << 18) /* Multi-results in PS-protocol */ + +#define CLIENT_PLUGIN_AUTH (1ULL << 19) /* Client supports plugin authentication */ +#define CLIENT_CONNECT_ATTRS (1ULL << 20) /* Client supports connection attributes */ +/* Enable authentication response packet to be larger than 255 bytes. */ +#define CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA (1ULL << 21) +/* Don't close the connection for a connection with expired password. */ +#define CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS (1ULL << 22) + +/** + Capable of handling server state change information. Its a hint to the + server to include the state change information in Ok packet. +*/ +#define CLIENT_SESSION_TRACK (1ULL << 23) +/* Client no longer needs EOF packet */ +#define CLIENT_DEPRECATE_EOF (1ULL << 24) + +#define CLIENT_PROGRESS_OBSOLETE (1ULL << 29) +#define CLIENT_SSL_VERIFY_SERVER_CERT_OBSOLETE (1ULL << 30) +/* + It used to be that if mysql_real_connect() failed, it would delete any + options set by the client, unless the CLIENT_REMEMBER_OPTIONS flag was + given. + That behaviour does not appear very useful, and it seems unlikely that + any applications would actually depend on this. So from MariaDB 5.5 we + always preserve any options set in case of failed connect, and this + option is effectively always set. +*/ +#define CLIENT_REMEMBER_OPTIONS (1ULL << 31) + +/* MariaDB extended capability flags */ +#define MARIADB_CLIENT_FLAGS_MASK 0xffffffff00000000ULL +/* Client support progress indicator */ +#define MARIADB_CLIENT_PROGRESS (1ULL << 32) + +/* Old COM_MULTI experiment (functionality removed).*/ +#define MARIADB_CLIENT_RESERVED_1 (1ULL << 33) + +/* support of array binding */ +#define MARIADB_CLIENT_STMT_BULK_OPERATIONS (1ULL << 34) +/* support of extended metadata (e.g. type/format information) */ +#define MARIADB_CLIENT_EXTENDED_METADATA (1ULL << 35) + +/* Do not resend metadata for prepared statements, since 10.6*/ +#define MARIADB_CLIENT_CACHE_METADATA (1ULL << 36) + +#ifdef HAVE_COMPRESS +#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS +#else +#define CAN_CLIENT_COMPRESS 0 +#endif + +/* + Gather all possible capabilities (flags) supported by the server + + MARIADB_* flags supported only by MariaDB connector(s). +*/ +#define CLIENT_ALL_FLAGS (\ + CLIENT_FOUND_ROWS | \ + CLIENT_LONG_FLAG | \ + CLIENT_CONNECT_WITH_DB | \ + CLIENT_NO_SCHEMA | \ + CLIENT_COMPRESS | \ + CLIENT_ODBC | \ + CLIENT_LOCAL_FILES | \ + CLIENT_IGNORE_SPACE | \ + CLIENT_PROTOCOL_41 | \ + CLIENT_INTERACTIVE | \ + CLIENT_SSL | \ + CLIENT_IGNORE_SIGPIPE | \ + CLIENT_TRANSACTIONS | \ + CLIENT_RESERVED | \ + CLIENT_SECURE_CONNECTION | \ + CLIENT_MULTI_STATEMENTS | \ + CLIENT_MULTI_RESULTS | \ + CLIENT_PS_MULTI_RESULTS | \ + CLIENT_REMEMBER_OPTIONS | \ + MARIADB_CLIENT_PROGRESS | \ + CLIENT_PLUGIN_AUTH | \ + CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \ + CLIENT_SESSION_TRACK |\ + CLIENT_DEPRECATE_EOF |\ + CLIENT_CONNECT_ATTRS |\ + MARIADB_CLIENT_STMT_BULK_OPERATIONS |\ + MARIADB_CLIENT_EXTENDED_METADATA|\ + MARIADB_CLIENT_CACHE_METADATA |\ + CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS) +/* + Switch off the flags that are optional and depending on build flags + If any of the optional flags is supported by the build it will be switched + on before sending to the client during the connection handshake. +*/ +#define CLIENT_BASIC_FLAGS ((CLIENT_ALL_FLAGS & ~CLIENT_SSL) \ + & ~CLIENT_COMPRESS) + +enum mariadb_field_attr_t +{ + MARIADB_FIELD_ATTR_DATA_TYPE_NAME= 0, + MARIADB_FIELD_ATTR_FORMAT_NAME= 1 +}; + +#define MARIADB_FIELD_ATTR_LAST MARIADB_FIELD_ATTR_FORMAT_NAME + + +/** + Is raised when a multi-statement transaction + has been started, either explicitly, by means + of BEGIN or COMMIT AND CHAIN, or + implicitly, by the first transactional + statement, when autocommit=off. +*/ +#define SERVER_STATUS_IN_TRANS 1U +#define SERVER_STATUS_AUTOCOMMIT 2U /* Server in auto_commit mode */ +#define SERVER_MORE_RESULTS_EXISTS 8U /* Multi query - next query exists */ +#define SERVER_QUERY_NO_GOOD_INDEX_USED 16U +#define SERVER_QUERY_NO_INDEX_USED 32U +/** + The server was able to fulfill the clients request and opened a + read-only non-scrollable cursor for a query. This flag comes + in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands. +*/ +#define SERVER_STATUS_CURSOR_EXISTS 64U +/** + This flag is sent when a read-only cursor is exhausted, in reply to + COM_STMT_FETCH command. +*/ +#define SERVER_STATUS_LAST_ROW_SENT 128U +#define SERVER_STATUS_DB_DROPPED 256U /* A database was dropped */ +#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512U +/** + Sent to the client if after a prepared statement reprepare + we discovered that the new statement returns a different + number of result set columns. +*/ +#define SERVER_STATUS_METADATA_CHANGED 1024U +#define SERVER_QUERY_WAS_SLOW 2048U + +/** + To mark ResultSet containing output parameter values. +*/ +#define SERVER_PS_OUT_PARAMS 4096U + +/** + Set at the same time as SERVER_STATUS_IN_TRANS if the started + multi-statement transaction is a read-only transaction. Cleared + when the transaction commits or aborts. Since this flag is sent + to clients in OK and EOF packets, the flag indicates the + transaction status at the end of command execution. +*/ +#define SERVER_STATUS_IN_TRANS_READONLY 8192U + +/** + This status flag, when on, implies that one of the state information has + changed on the server because of the execution of the last statement. +*/ +#define SERVER_SESSION_STATE_CHANGED 16384U + +#define SERVER_STATUS_ANSI_QUOTES 32768U + +/** + Server status flags that must be cleared when starting + execution of a new SQL statement. + Flags from this set are only added to the + current server status by the execution engine, but + never removed -- the execution engine expects them + to disappear automagically by the next command. +*/ +#define SERVER_STATUS_CLEAR_SET (SERVER_QUERY_NO_GOOD_INDEX_USED| \ + SERVER_QUERY_NO_INDEX_USED|\ + SERVER_MORE_RESULTS_EXISTS|\ + SERVER_STATUS_METADATA_CHANGED |\ + SERVER_QUERY_WAS_SLOW |\ + SERVER_STATUS_DB_DROPPED |\ + SERVER_STATUS_CURSOR_EXISTS|\ + SERVER_STATUS_LAST_ROW_SENT|\ + SERVER_SESSION_STATE_CHANGED) + +#define MYSQL_ERRMSG_SIZE 512 +#define NET_READ_TIMEOUT 30 /* Timeout on read */ +#define NET_WRITE_TIMEOUT 60 /* Timeout on write */ +#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */ + +struct st_vio; /* Only C */ +typedef struct st_vio Vio; + +#define MAX_TINYINT_WIDTH 3 /* Max width for a TINY w.o. sign */ +#define MAX_SMALLINT_WIDTH 5 /* Max width for a SHORT w.o. sign */ +#define MAX_MEDIUMINT_WIDTH 8 /* Max width for a INT24 w.o. sign */ +#define MAX_INT_WIDTH 10 /* Max width for a LONG w.o. sign */ +#define MAX_BIGINT_WIDTH 20 /* Max width for a LONGLONG */ +#define MAX_CHAR_WIDTH 255 /* Max length for a CHAR column */ +#define MAX_BLOB_WIDTH 16777216 /* Default width for blob */ + +typedef struct st_net { +#if !defined(CHECK_EMBEDDED_DIFFERENCES) || !defined(EMBEDDED_LIBRARY) + Vio *vio; + unsigned char *buff,*buff_end,*write_pos,*read_pos; + my_socket fd; /* For Perl DBI/dbd */ + /* + The following variable is set if we are doing several queries in one + command ( as in LOAD TABLE ... FROM MASTER ), + and do not want to confuse the client with OK at the wrong time + */ + unsigned long remain_in_buf,length, buf_length, where_b; + unsigned long max_packet,max_packet_size; + unsigned int pkt_nr,compress_pkt_nr; + unsigned int write_timeout, read_timeout, retry_count; + int fcntl; + unsigned int *return_status; + unsigned char reading_or_writing; + char save_char; + char net_skip_rest_factor; + my_bool thread_specific_malloc; + unsigned char compress; + my_bool unused3; /* Please remove with the next incompatible ABI change. */ + /* + Pointer to query object in query cache, do not equal NULL (0) for + queries in cache that have not stored its results yet + */ +#endif + void *thd; /* Used by MariaDB server to avoid calling current_thd */ + unsigned int last_errno; + unsigned char error; + my_bool unused4; /* Please remove with the next incompatible ABI change. */ + my_bool unused5; /* Please remove with the next incompatible ABI change. */ + /** Client library error message buffer. Actually belongs to struct MYSQL. */ + char last_error[MYSQL_ERRMSG_SIZE]; + /** Client library sqlstate buffer. Set along with the error message. */ + char sqlstate[SQLSTATE_LENGTH+1]; + void *extension; +} NET; + + +#define packet_error ~0UL + +enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, + MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP, + MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24, + MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, + MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR, + MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, + MYSQL_TYPE_BIT, + /* + mysql-5.6 compatibility temporal types. + They're only used internally for reading RBR + mysql-5.6 binary log events and mysql-5.6 frm files. + They're never sent to the client. + */ + MYSQL_TYPE_TIMESTAMP2, + MYSQL_TYPE_DATETIME2, + MYSQL_TYPE_TIME2, + /* Compressed types are only used internally for RBR. */ + MYSQL_TYPE_BLOB_COMPRESSED= 140, + MYSQL_TYPE_VARCHAR_COMPRESSED= 141, + + MYSQL_TYPE_NEWDECIMAL=246, + MYSQL_TYPE_ENUM=247, + MYSQL_TYPE_SET=248, + MYSQL_TYPE_TINY_BLOB=249, + MYSQL_TYPE_MEDIUM_BLOB=250, + MYSQL_TYPE_LONG_BLOB=251, + MYSQL_TYPE_BLOB=252, + MYSQL_TYPE_VAR_STRING=253, + MYSQL_TYPE_STRING=254, + MYSQL_TYPE_GEOMETRY=255 + +}; + +/* For backward compatibility */ +#define CLIENT_MULTI_QUERIES CLIENT_MULTI_STATEMENTS +#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL +#define FIELD_TYPE_NEWDECIMAL MYSQL_TYPE_NEWDECIMAL +#define FIELD_TYPE_TINY MYSQL_TYPE_TINY +#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT +#define FIELD_TYPE_LONG MYSQL_TYPE_LONG +#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT +#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE +#define FIELD_TYPE_NULL MYSQL_TYPE_NULL +#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP +#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG +#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24 +#define FIELD_TYPE_DATE MYSQL_TYPE_DATE +#define FIELD_TYPE_TIME MYSQL_TYPE_TIME +#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME +#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR +#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE +#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM +#define FIELD_TYPE_SET MYSQL_TYPE_SET +#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB +#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB +#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB +#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB +#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING +#define FIELD_TYPE_STRING MYSQL_TYPE_STRING +#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY +#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM +#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY +#define FIELD_TYPE_BIT MYSQL_TYPE_BIT + + +/* Shutdown/kill enums and constants */ + +/* Bits for THD::killable. */ +#define MYSQL_SHUTDOWN_KILLABLE_CONNECT (unsigned char)(1 << 0) +#define MYSQL_SHUTDOWN_KILLABLE_TRANS (unsigned char)(1 << 1) +#define MYSQL_SHUTDOWN_KILLABLE_LOCK_TABLE (unsigned char)(1 << 2) +#define MYSQL_SHUTDOWN_KILLABLE_UPDATE (unsigned char)(1 << 3) + +enum mysql_enum_shutdown_level { + /* + We want levels to be in growing order of hardness (because we use number + comparisons). Note that DEFAULT does not respect the growing property, but + it's ok. + */ + SHUTDOWN_DEFAULT = 0, + /* wait for existing connections to finish */ + SHUTDOWN_WAIT_CONNECTIONS= MYSQL_SHUTDOWN_KILLABLE_CONNECT, + /* wait for existing trans to finish */ + SHUTDOWN_WAIT_TRANSACTIONS= MYSQL_SHUTDOWN_KILLABLE_TRANS, + /* wait for existing updates to finish (=> no partial MyISAM update) */ + SHUTDOWN_WAIT_UPDATES= MYSQL_SHUTDOWN_KILLABLE_UPDATE, + /* flush InnoDB buffers and other storage engines' buffers*/ + SHUTDOWN_WAIT_ALL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1), + /* don't flush InnoDB buffers, flush other storage engines' buffers*/ + SHUTDOWN_WAIT_CRITICAL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1) + 1 +}; + +enum enum_cursor_type +{ + CURSOR_TYPE_NO_CURSOR= 0, + CURSOR_TYPE_READ_ONLY= 1, + CURSOR_TYPE_FOR_UPDATE= 2, + CURSOR_TYPE_SCROLLABLE= 4 +}; + + +/* options for mysql_set_option */ +enum enum_mysql_set_option +{ + MYSQL_OPTION_MULTI_STATEMENTS_ON, + MYSQL_OPTION_MULTI_STATEMENTS_OFF +}; + +/* + Type of state change information that the server can include in the Ok + packet. +*/ +enum enum_session_state_type +{ + SESSION_TRACK_SYSTEM_VARIABLES, /* Session system variables */ + SESSION_TRACK_SCHEMA, /* Current schema */ + SESSION_TRACK_STATE_CHANGE, /* track session state changes */ + SESSION_TRACK_GTIDS, + SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */ + SESSION_TRACK_TRANSACTION_STATE, /* Transaction state */ +#ifdef USER_VAR_TRACKING + SESSION_TRACK_MYSQL_RESERVED1, + SESSION_TRACK_MYSQL_RESERVED2, + SESSION_TRACK_MYSQL_RESERVED3, + SESSION_TRACK_MYSQL_RESERVED4, + SESSION_TRACK_MYSQL_RESERVED5, + SESSION_TRACK_MYSQL_RESERVED6, + SESSION_TRACK_USER_VARIABLES, +#endif // USER_VAR_TRACKING + SESSION_TRACK_always_at_the_end /* must be last */ +}; + +#define SESSION_TRACK_BEGIN SESSION_TRACK_SYSTEM_VARIABLES + +#define IS_SESSION_STATE_TYPE(T) \ + (((int)(T) >= SESSION_TRACK_BEGIN) && ((T) < SESSION_TRACK_always_at_the_end)) + +#define net_new_transaction(net) ((net)->pkt_nr=0) + +#ifdef __cplusplus +extern "C" { +#endif + +my_bool my_net_init(NET *net, Vio* vio, void *thd, unsigned int my_flags); +void my_net_local_init(NET *net); +void net_end(NET *net); +void net_clear(NET *net, my_bool clear_buffer); +my_bool net_realloc(NET *net, size_t length); +my_bool net_flush(NET *net); +my_bool my_net_write(NET *net,const unsigned char *packet, size_t len); +my_bool net_write_command(NET *net,unsigned char command, + const unsigned char *header, size_t head_len, + const unsigned char *packet, size_t len); +int net_real_write(NET *net,const unsigned char *packet, size_t len); +unsigned long my_net_read_packet(NET *net, my_bool read_from_server); +unsigned long my_net_read_packet_reallen(NET *net, my_bool read_from_server, + unsigned long* reallen); +#define my_net_read(A) my_net_read_packet((A), 0) + +#ifdef MY_GLOBAL_INCLUDED +void my_net_set_write_timeout(NET *net, uint timeout); +void my_net_set_read_timeout(NET *net, uint timeout); +#endif + +struct sockaddr; +int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen, + unsigned int timeout); +struct my_rnd_struct; + +#ifdef __cplusplus +} +#endif + + /* The following is for user defined functions */ + +enum Item_result +{ + STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT, + TIME_RESULT +}; + +typedef struct st_udf_args +{ + unsigned int arg_count; /* Number of arguments */ + enum Item_result *arg_type; /* Pointer to item_results */ + char **args; /* Pointer to argument */ + unsigned long *lengths; /* Length of string arguments */ + char *maybe_null; /* Set to 1 for all maybe_null args */ + const char **attributes; /* Pointer to attribute name */ + unsigned long *attribute_lengths; /* Length of attribute arguments */ + void *extension; +} UDF_ARGS; + + /* This holds information about the result */ + +typedef struct st_udf_init +{ + my_bool maybe_null; /* 1 if function can return NULL */ + unsigned int decimals; /* for real functions */ + unsigned long max_length; /* For string functions */ + char *ptr; /* free pointer for function data */ + my_bool const_item; /* 1 if function always returns the same value */ + void *extension; +} UDF_INIT; +/* + TODO: add a notion for determinism of the UDF. + See Item_udf_func::update_used_tables () +*/ + + /* Constants when using compression */ +#define NET_HEADER_SIZE 4 /* standard header size */ +#define COMP_HEADER_SIZE 3 /* compression header extra size */ + + /* Prototypes to password functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + These functions are used for authentication by client and server and + implemented in sql/password.c +*/ + +void create_random_string(char *to, unsigned int length, + struct my_rnd_struct *rand_st); + +void hash_password(unsigned long *to, const char *password, unsigned int password_len); +void make_scrambled_password_323(char *to, const char *password); +void scramble_323(char *to, const char *message, const char *password); +my_bool check_scramble_323(const unsigned char *reply, const char *message, + unsigned long *salt); +void get_salt_from_password_323(unsigned long *res, const char *password); +void make_scrambled_password(char *to, const char *password); +void scramble(char *to, const char *message, const char *password); +my_bool check_scramble(const unsigned char *reply, const char *message, + const unsigned char *hash_stage2); +void get_salt_from_password(unsigned char *res, const char *password); +char *octet2hex(char *to, const char *str, size_t len); + +/* end of password.c */ + +char *get_tty_password(const char *opt_message); +void get_tty_password_buff(const char *opt_message, char *to, size_t length); +const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); + +/* Some other useful functions */ + +my_bool my_thread_init(void); +void my_thread_end(void); + +#ifdef MY_GLOBAL_INCLUDED +#include "pack.h" +#endif + +#ifdef __cplusplus +} +#endif + +#define NULL_LENGTH ~0UL /* For net_store_length */ +#define MYSQL_STMT_HEADER 4U +#define MYSQL_LONG_DATA_HEADER 6U + +/* + If a float or double field have more than this number of decimals, + it's regarded as floating point field without any specific number of + decimals +*/ + + +#endif diff --git a/include/mysql_com_server.h b/include/mysql_com_server.h new file mode 100644 index 00000000..d8bf531c --- /dev/null +++ b/include/mysql_com_server.h @@ -0,0 +1,41 @@ +/* Copyright (c) 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Definitions private to the server, + used in the networking layer to notify specific events. +*/ + +#ifndef _mysql_com_server_h +#define _mysql_com_server_h + +struct st_net_server; + +typedef void (*before_header_callback_fn) + (struct st_net *net, void *user_data, size_t count); + +typedef void (*after_header_callback_fn) + (struct st_net *net, void *user_data, size_t count, my_bool rc); + +struct st_net_server +{ + before_header_callback_fn m_before_header; + after_header_callback_fn m_after_header; + void *m_user_data; +}; + +typedef struct st_net_server NET_SERVER; + +#endif diff --git a/include/mysql_embed.h b/include/mysql_embed.h new file mode 100644 index 00000000..775040ac --- /dev/null +++ b/include/mysql_embed.h @@ -0,0 +1,30 @@ +#ifndef MYSQL_EMBED_INCLUDED +#define MYSQL_EMBED_INCLUDED + +/* + Copyright (c) 2000, 2011, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Defines that are unique to the embedded version of MySQL */ + +#ifdef EMBEDDED_LIBRARY + +/* Things we don't need in the embedded version of MySQL */ +/* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */ + +#undef HAVE_DLOPEN /* No udf functions */ + +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_EMBED_INCLUDED */ diff --git a/include/mysql_time.h b/include/mysql_time.h new file mode 100644 index 00000000..ef78441b --- /dev/null +++ b/include/mysql_time.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2004, 2006 MySQL AB + Use is subject to license terms + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _mysql_time_h_ +#define _mysql_time_h_ + +/* + Portable time_t replacement. + Should be signed and hold seconds for 1902 -- 2038-01-19 range + i.e at least a 32bit variable + + Using the system built in time_t is not an option as + we rely on the above requirements in the time functions +*/ +typedef long my_time_t; + + +/* + Time declarations shared between the server and client API: + you should not add anything to this header unless it's used + (and hence should be visible) in mysql.h. + If you're looking for a place to add new time-related declaration, + it's most likely my_time.h. See also "C API Handling of Date + and Time Values" chapter in documentation. +*/ + +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; + + +/* + Structure which is used to represent datetime values inside MySQL. + + We assume that values in this structure are normalized, i.e. year <= 9999, + month <= 12, day <= 31, hour <= 23, hour <= 59, hour <= 59. Many functions + in server such as my_system_gmt_sec() or make_time() family of functions + rely on this (actually now usage of make_*() family relies on a bit weaker + restriction). Also functions that produce MYSQL_TIME as result ensure this. + There is one exception to this rule though if this structure holds time + value (time_type == MYSQL_TIMESTAMP_TIME) days and hour member can hold + bigger values. +*/ +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; + +#endif /* _mysql_time_h_ */ diff --git a/include/mysql_version.h.in b/include/mysql_version.h.in new file mode 100644 index 00000000..82a13283 --- /dev/null +++ b/include/mysql_version.h.in @@ -0,0 +1,42 @@ +/* Copyright Abandoned 1996,1999 TCX DataKonsult AB & Monty Program KB + & Detron HB, 1996, 1999-2004, 2007 MySQL AB. + This file is public domain and comes with NO WARRANTY of any kind +*/ + +/* Version numbers for protocol & mysqld */ + +#ifndef _mysql_version_h +#define _mysql_version_h +#ifdef _CUSTOMCONFIG_ +#include <custom_conf.h> +#else +#define PROTOCOL_VERSION @PROTOCOL_VERSION@ +#define MYSQL_SERVER_VERSION "@VERSION@-MariaDB" +#define MYSQL_BASE_VERSION "mysqld-@MYSQL_BASE_VERSION@" +#define MARIADB_BASE_VERSION "mariadb-@MYSQL_BASE_VERSION@" +#define MARIADBD_BASE_VERSION "mariadbd-@MYSQL_BASE_VERSION@" +#define MYSQL_SERVER_SUFFIX_DEF "@MYSQL_SERVER_SUFFIX@" +#define FRM_VER @DOT_FRM_VERSION@ +#define MYSQL_VERSION_ID @MYSQL_VERSION_ID@ +#define MARIADB_PORT @MYSQL_TCP_PORT@ +#define MYSQL_PORT_DEFAULT @MYSQL_TCP_PORT_DEFAULT@ +#define MARIADB_UNIX_ADDR "@MYSQL_UNIX_ADDR@" +#define MYSQL_CONFIG_NAME "my" +#define MYSQL_COMPILATION_COMMENT "@COMPILATION_COMMENT@" +#define SERVER_MATURITY_LEVEL @SERVER_MATURITY_LEVEL@ + +#define MYSQL_PORT MARIADB_PORT +#define MYSQL_UNIX_ADDR MARIADB_UNIX_ADDR + +#ifdef WITH_WSREP +#define WSREP_PATCH_VERSION "@WSREP_PATCH_VERSION@" +#endif + +/* mysqld compile time options */ +#endif /* _CUSTOMCONFIG_ */ + +#ifndef LICENSE +#define LICENSE GPL +#endif /* LICENSE */ + +#endif /* _mysql_version_h */ diff --git a/include/mysqld_default_groups.h b/include/mysqld_default_groups.h new file mode 100644 index 00000000..cf6e92e3 --- /dev/null +++ b/include/mysqld_default_groups.h @@ -0,0 +1,9 @@ +const char *load_default_groups[]= { +"mysqld", "server", MYSQL_BASE_VERSION, +"mariadb", MARIADB_BASE_VERSION, +"mariadbd", MARIADBD_BASE_VERSION, +"client-server", +#ifdef WITH_WSREP +"galera", +#endif +0, 0}; diff --git a/include/mysys_err.h b/include/mysys_err.h new file mode 100644 index 00000000..e0e97d02 --- /dev/null +++ b/include/mysys_err.h @@ -0,0 +1,99 @@ +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _mysys_err_h +#define _mysys_err_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define GLOBERRS (EE_ERROR_LAST - EE_ERROR_FIRST + 1) /* Nr of global errors */ +#define EE(X) (globerrs[(X) - EE_ERROR_FIRST]) + +extern const char *globerrs[]; /* my_error_messages is here */ + +/* Error message numbers in global map */ +/* + Do not add error numbers before EE_ERROR_FIRST. + If necessary to add lower numbers, change EE_ERROR_FIRST accordingly. + + We start with error 1 to not confuse peoples with 'error 0' +*/ + +#define EE_ERROR_FIRST 1 /*Copy first error nr.*/ +#define EE_CANTCREATEFILE 1 +#define EE_READ 2 +#define EE_WRITE 3 +#define EE_BADCLOSE 4 +#define EE_OUTOFMEMORY 5 +#define EE_DELETE 6 +#define EE_LINK 7 +#define EE_EOFERR 9 +#define EE_CANTLOCK 10 +#define EE_CANTUNLOCK 11 +#define EE_DIR 12 +#define EE_STAT 13 +#define EE_CANT_CHSIZE 14 +#define EE_CANT_OPEN_STREAM 15 +#define EE_GETWD 16 +#define EE_SETWD 17 +#define EE_LINK_WARNING 18 +#define EE_OPEN_WARNING 19 +#define EE_DISK_FULL 20 +#define EE_CANT_MKDIR 21 +#define EE_UNKNOWN_CHARSET 22 +#define EE_OUT_OF_FILERESOURCES 23 +#define EE_CANT_READLINK 24 +#define EE_CANT_SYMLINK 25 +#define EE_REALPATH 26 +#define EE_SYNC 27 +#define EE_UNKNOWN_COLLATION 28 +#define EE_FILENOTFOUND 29 +#define EE_FILE_NOT_CLOSED 30 +#define EE_CHANGE_OWNERSHIP 31 +#define EE_CHANGE_PERMISSIONS 32 +#define EE_CANT_SEEK 33 +#define EE_CANT_CHMOD 34 +#define EE_CANT_COPY_OWNERSHIP 35 +#define EE_BADMEMORYRELEASE 36 +#define EE_PERM_LOCK_MEMORY 37 +#define EE_MEMCNTL 38 +#define EE_DUPLICATE_CHARSET 39 +#define EE_ERROR_LAST 39 /* Copy last error nr */ + +/* Add error numbers before EE_ERROR_LAST and change it accordingly. */ + + /* exit codes for all MySQL programs */ + +#define EXIT_UNSPECIFIED_ERROR 1 +#define EXIT_UNKNOWN_OPTION 2 +#define EXIT_AMBIGUOUS_OPTION 3 +#define EXIT_NO_ARGUMENT_ALLOWED 4 +#define EXIT_ARGUMENT_REQUIRED 5 +#define EXIT_VAR_PREFIX_NOT_UNIQUE 6 +#define EXIT_UNKNOWN_VARIABLE 7 +#define EXIT_OUT_OF_MEMORY 8 +#define EXIT_UNKNOWN_SUFFIX 9 +#define EXIT_NO_PTR_TO_VARIABLE 10 +#define EXIT_CANNOT_CONNECT_TO_SERVICE 11 +#define EXIT_OPTION_DISABLED 12 +#define EXIT_ARGUMENT_INVALID 13 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/no_valgrind_without_big.inc b/include/no_valgrind_without_big.inc new file mode 100644 index 00000000..ea1f2ac9 --- /dev/null +++ b/include/no_valgrind_without_big.inc @@ -0,0 +1,13 @@ +# include/no_valgrind_without_big.inc +# +# If we are running with Valgrind ($VALGRIND_TEST <> 0) than the resource +# consumption (storage space needed, runtime ...) will be extreme. +# Therefore we require that the option "--big-test" is also set. +# + +if ($VALGRIND_TEST) { + if (!$BIG_TEST) + { + --skip Need "--big-test" when running with Valgrind + } +} diff --git a/include/pack.h b/include/pack.h new file mode 100644 index 00000000..f991e723 --- /dev/null +++ b/include/pack.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2016, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifdef __cplusplus +extern "C" { +#endif + +ulong net_field_length(uchar **packet); +my_ulonglong net_field_length_ll(uchar **packet); +my_ulonglong safe_net_field_length_ll(uchar **packet, size_t packet_len); +uchar *net_store_length(uchar *pkg, ulonglong length); +uchar *safe_net_store_length(uchar *pkg, size_t pkg_len, ulonglong length); +unsigned int net_length_size(ulonglong num); + +#ifdef __cplusplus +} +#endif diff --git a/include/password.h b/include/password.h new file mode 100644 index 00000000..a076a6a3 --- /dev/null +++ b/include/password.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2006, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef PASSWORD_INCLUDED +#define PASSWORD_INCLUDED + +C_MODE_START + +void my_make_scrambled_password_323(char *to, const char *password, + size_t pass_len); +void my_make_scrambled_password(char *to, const char *password, + size_t pass_len); + +void hash_password(ulong *result, const char *password, uint password_len); + +C_MODE_END + +#endif /* PASSWORD_INCLUDED */ diff --git a/include/pfs_file_provider.h b/include/pfs_file_provider.h new file mode 100644 index 00000000..3df99989 --- /dev/null +++ b/include/pfs_file_provider.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_FILE_PROVIDER_H +#define PFS_FILE_PROVIDER_H + +/** + @file include/pfs_file_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_FILE_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_FILE_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +void pfs_register_file_v1(const char *category, + PSI_file_info_v1 *info, + int count); + +void pfs_create_file_v1(PSI_file_key key, const char *name, File file); + +PSI_file_locker* +pfs_get_thread_file_name_locker_v1(PSI_file_locker_state *state, + PSI_file_key key, + PSI_file_operation op, + const char *name, const void *identity); + +PSI_file_locker* +pfs_get_thread_file_stream_locker_v1(PSI_file_locker_state *state, + PSI_file *file, PSI_file_operation op); + +PSI_file_locker* +pfs_get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state, + File file, PSI_file_operation op); + +void pfs_start_file_open_wait_v1(PSI_file_locker *locker, + const char *src_file, + uint src_line); + +PSI_file* pfs_end_file_open_wait_v1(PSI_file_locker *locker, void *result); + +void pfs_end_file_open_wait_and_bind_to_descriptor_v1 + (PSI_file_locker *locker, File file); + +void pfs_end_temp_file_open_wait_and_bind_to_descriptor_v1 + (PSI_file_locker *locker, File file, const char *filename); + +void pfs_start_file_wait_v1(PSI_file_locker *locker, + size_t count, + const char *src_file, + uint src_line); + +void pfs_end_file_wait_v1(PSI_file_locker *locker, + size_t byte_count); + +void pfs_start_file_close_wait_v1(PSI_file_locker *locker, + const char *src_file, + uint src_line); + +void pfs_end_file_close_wait_v1(PSI_file_locker *locker, int rc); + +void pfs_end_file_rename_wait_v1(PSI_file_locker *locker, const char *old_name, + const char *new_name, int rc); + +C_MODE_END + +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_FILE_INTERFACE */ + +#endif + diff --git a/include/pfs_idle_provider.h b/include/pfs_idle_provider.h new file mode 100644 index 00000000..71d116f7 --- /dev/null +++ b/include/pfs_idle_provider.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_IDLE_PROVIDER_H +#define PFS_IDLE_PROVIDER_H + +/** + @file include/pfs_idle_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_IDLE_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_IDLE_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +PSI_idle_locker* +pfs_start_idle_wait_v1(PSI_idle_locker_state* state, const char *src_file, uint src_line); + +void pfs_end_idle_wait_v1(PSI_idle_locker* locker); + +C_MODE_END + +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_IDLE_INTERFACE */ + +#endif + diff --git a/include/pfs_memory_provider.h b/include/pfs_memory_provider.h new file mode 100644 index 00000000..ea60f9de --- /dev/null +++ b/include/pfs_memory_provider.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_MEMORY_PROVIDER_H +#define PFS_MEMORY_PROVIDER_H + +/** + @file include/pfs_memory_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_MEMORY_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_MEMORY_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +void pfs_register_memory_v1 + (const char *category, struct PSI_memory_info_v1 *info, int count); + +PSI_memory_key +pfs_memory_alloc_v1 + (PSI_memory_key key, size_t size, PSI_thread **owner); + +PSI_memory_key +pfs_memory_realloc_v1 + (PSI_memory_key key, size_t old_size, size_t new_size, PSI_thread **owner); + +void pfs_memory_free_v1 + (PSI_memory_key key, size_t size, PSI_thread *owner); + +C_MODE_END + +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_MEMORY_INTERFACE */ + +#endif + diff --git a/include/pfs_metadata_provider.h b/include/pfs_metadata_provider.h new file mode 100644 index 00000000..cf3dd0d0 --- /dev/null +++ b/include/pfs_metadata_provider.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_METADATA_PROVIDER_H +#define PFS_METADATA_PROVIDER_H + +/** + @file include/pfs_metadata_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_METADATA_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_METADATA_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +PSI_metadata_lock* pfs_create_metadata_lock_v1 + (void *identity, + const MDL_key *key, + opaque_mdl_type mdl_type, + opaque_mdl_duration mdl_duration, + opaque_mdl_status mdl_status, + const char *src_file, + uint src_line); + +void pfs_set_metadata_lock_status_v1 + (PSI_metadata_lock *lock, + opaque_mdl_status mdl_status); + +void pfs_destroy_metadata_lock_v1(PSI_metadata_lock *lock); + +struct PSI_metadata_locker* +pfs_start_metadata_wait_v1 + (struct PSI_metadata_locker_state_v1 *state, + struct PSI_metadata_lock *mdl, + const char *src_file, uint src_line); + +void pfs_end_metadata_wait_v1 + (struct PSI_metadata_locker *locker, int rc); + +C_MODE_END + +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_METADATA_INTERFACE */ + +#endif + diff --git a/include/pfs_socket_provider.h b/include/pfs_socket_provider.h new file mode 100644 index 00000000..bfafdaaf --- /dev/null +++ b/include/pfs_socket_provider.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_SOCKET_PROVIDER_H +#define PFS_SOCKET_PROVIDER_H + +/** + @file include/pfs_socket_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_SOCKET_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_SOCKET_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +void pfs_register_socket_v1(const char *category, + PSI_socket_info_v1 *info, + int count); + +PSI_socket* +pfs_init_socket_v1(PSI_socket_key key, const my_socket *fd, + const struct sockaddr *addr, socklen_t addr_len); + +void pfs_destroy_socket_v1(PSI_socket *socket); + +PSI_socket_locker* +pfs_start_socket_wait_v1(PSI_socket_locker_state *state, + PSI_socket *socket, + PSI_socket_operation op, + size_t count, + const char *src_file, uint src_line); + +void pfs_end_socket_wait_v1(PSI_socket_locker *locker, size_t byte_count); + +void pfs_set_socket_state_v1(PSI_socket *socket, PSI_socket_state state); + +void pfs_set_socket_info_v1(PSI_socket *socket, + const my_socket *fd, + const struct sockaddr *addr, + socklen_t addr_len); + +void pfs_set_socket_thread_owner_v1(PSI_socket *socket); + +C_MODE_END + +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_SOCKET_INTERFACE */ + +#endif + diff --git a/include/pfs_stage_provider.h b/include/pfs_stage_provider.h new file mode 100644 index 00000000..2ad2faab --- /dev/null +++ b/include/pfs_stage_provider.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_STAGE_PROVIDER_H +#define PFS_STAGE_PROVIDER_H + +/** + @file include/pfs_stage_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_STAGE_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_STAGE_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +void pfs_register_stage_v1(const char *category, + PSI_stage_info_v1 **info_array, + int count); + +PSI_stage_progress* pfs_start_stage_v1(PSI_stage_key key, const char *src_file, int src_line); +PSI_stage_progress* pfs_get_current_stage_progress_v1(); + +void pfs_end_stage_v1(); + +C_MODE_END + +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_STAGE_INTERFACE */ + +#endif + diff --git a/include/pfs_statement_provider.h b/include/pfs_statement_provider.h new file mode 100644 index 00000000..96870d84 --- /dev/null +++ b/include/pfs_statement_provider.h @@ -0,0 +1,118 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_STATEMENT_PROVIDER_H +#define PFS_STATEMENT_PROVIDER_H + +/** + @file include/pfs_statement_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_STATEMENT_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_STATEMENT_CALL(M) pfs_ ## M ## _v1 +#define PSI_DIGEST_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +void pfs_register_statement_v1(const char *category, + PSI_statement_info_v1 *info, + int count); + +PSI_statement_locker* +pfs_get_thread_statement_locker_v1(PSI_statement_locker_state *state, + PSI_statement_key key, + const void *charset, + PSI_sp_share *sp_share); + +PSI_statement_locker* +pfs_refine_statement_v1(PSI_statement_locker *locker, + PSI_statement_key key); + +void pfs_start_statement_v1(PSI_statement_locker *locker, + const char *db, uint db_len, + const char *src_file, uint src_line); + +void pfs_set_statement_text_v1(PSI_statement_locker *locker, + const char *text, uint text_len); + +void pfs_set_statement_lock_time_v1(PSI_statement_locker *locker, + ulonglong count); + +void pfs_set_statement_rows_sent_v1(PSI_statement_locker *locker, + ulonglong count); + +void pfs_set_statement_rows_examined_v1(PSI_statement_locker *locker, + ulonglong count); + +void pfs_inc_statement_created_tmp_disk_tables_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_created_tmp_tables_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_select_full_join_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_select_full_range_join_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_select_range_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_select_range_check_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_select_scan_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_sort_merge_passes_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_sort_range_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_sort_rows_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_inc_statement_sort_scan_v1(PSI_statement_locker *locker, + ulong count); + +void pfs_set_statement_no_index_used_v1(PSI_statement_locker *locker); + +void pfs_set_statement_no_good_index_used_v1(PSI_statement_locker *locker); + +void pfs_end_statement_v1(PSI_statement_locker *locker, void *stmt_da); + +PSI_digest_locker *pfs_digest_start_v1(PSI_statement_locker *locker); + +void pfs_digest_end_v1(PSI_digest_locker *locker, + const sql_digest_storage *digest); + +C_MODE_END + +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_STATEMENT_INTERFACE */ + +#endif + diff --git a/include/pfs_table_provider.h b/include/pfs_table_provider.h new file mode 100644 index 00000000..0d7ee762 --- /dev/null +++ b/include/pfs_table_provider.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_TABLE_PROVIDER_H +#define PFS_TABLE_PROVIDER_H + +/** + @file include/pfs_table_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_TABLE_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_TABLE_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +PSI_table_share* +pfs_get_table_share_v1(my_bool temporary, struct TABLE_SHARE *share); + +void pfs_release_table_share_v1(PSI_table_share* share); + +void +pfs_drop_table_share_v1(my_bool temporary, + const char *schema_name, int schema_name_length, + const char *table_name, int table_name_length); + +PSI_table* +pfs_open_table_v1(PSI_table_share *share, const void *identity); + +void pfs_unbind_table_v1(PSI_table *table); + +PSI_table * +pfs_rebind_table_v1(PSI_table_share *share, const void *identity, PSI_table *table); + +void pfs_close_table_v1(struct TABLE_SHARE *server_share, PSI_table *table); + +PSI_table_locker* +pfs_start_table_io_wait_v1(PSI_table_locker_state *state, + PSI_table *table, + PSI_table_io_operation op, + uint index, + const char *src_file, uint src_line); + +PSI_table_locker* +pfs_start_table_lock_wait_v1(PSI_table_locker_state *state, + PSI_table *table, + PSI_table_lock_operation op, + ulong op_flags, + const char *src_file, uint src_line); + +void pfs_end_table_io_wait_v1(PSI_table_locker* locker, ulonglong numrows); + +void pfs_end_table_lock_wait_v1(PSI_table_locker* locker); + +void pfs_unlock_table_v1(PSI_table *table); + +C_MODE_END + +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_TABLE_INTERFACE */ + +#endif + diff --git a/include/pfs_thread_provider.h b/include/pfs_thread_provider.h new file mode 100644 index 00000000..6b563372 --- /dev/null +++ b/include/pfs_thread_provider.h @@ -0,0 +1,172 @@ +/* Copyright (c) 2012, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_THREAD_PROVIDER_H +#define PFS_THREAD_PROVIDER_H + +/** + @file include/pfs_thread_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_THREAD_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_MUTEX_CALL(M) pfs_ ## M ## _v1 +#define PSI_RWLOCK_CALL(M) pfs_ ## M ## _v1 +#define PSI_COND_CALL(M) pfs_ ## M ## _v1 +#define PSI_THREAD_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +void pfs_register_mutex_v1(const char *category, + PSI_mutex_info_v1 *info, + int count); + +void pfs_register_rwlock_v1(const char *category, + PSI_rwlock_info_v1 *info, + int count); + +void pfs_register_cond_v1(const char *category, + PSI_cond_info_v1 *info, + int count); + +void pfs_register_thread_v1(const char *category, + PSI_thread_info_v1 *info, + int count); + +PSI_mutex* +pfs_init_mutex_v1(PSI_mutex_key key, void *identity); + +void pfs_destroy_mutex_v1(PSI_mutex* mutex); + +PSI_rwlock* +pfs_init_rwlock_v1(PSI_rwlock_key key, void *identity); + +void pfs_destroy_rwlock_v1(PSI_rwlock* rwlock); + +PSI_cond* +pfs_init_cond_v1(PSI_cond_key key, void *identity); + +void pfs_destroy_cond_v1(PSI_cond* cond); + +int pfs_spawn_thread_v1(PSI_thread_key key, + pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); + +PSI_thread* +pfs_new_thread_v1(PSI_thread_key key, const void *identity, ulonglong processlist_id); + +void pfs_set_thread_id_v1(PSI_thread *thread, ulonglong processlist_id); +void pfs_set_thread_THD_v1(PSI_thread *thread, THD *thd); +void pfs_set_thread_os_id_v1(PSI_thread *thread); + +PSI_thread* +pfs_get_thread_v1(void); + +void pfs_set_thread_user_v1(const char *user, int user_len); + +void pfs_set_thread_account_v1(const char *user, int user_len, + const char *host, int host_len); + +void pfs_set_thread_db_v1(const char* db, int db_len); + +void pfs_set_thread_command_v1(int command); + +void pfs_set_thread_start_time_v1(time_t start_time); + +void pfs_set_thread_state_v1(const char* state); + +void pfs_set_connection_type_v1(opaque_vio_type conn_type); + +void pfs_set_thread_info_v1(const char* info, uint info_len); + +void pfs_set_thread_v1(PSI_thread* thread); + +void pfs_set_thread_peer_port_v1(PSI_thread *thread, uint port); + +void pfs_delete_current_thread_v1(void); + +void pfs_delete_thread_v1(PSI_thread *thread); + +PSI_mutex_locker* +pfs_start_mutex_wait_v1(PSI_mutex_locker_state *state, + PSI_mutex *mutex, PSI_mutex_operation op, + const char *src_file, uint src_line); + +PSI_rwlock_locker* +pfs_start_rwlock_rdwait_v1(PSI_rwlock_locker_state *state, + PSI_rwlock *rwlock, + PSI_rwlock_operation op, + const char *src_file, uint src_line); + +PSI_rwlock_locker* +pfs_start_rwlock_wrwait_v1(PSI_rwlock_locker_state *state, + PSI_rwlock *rwlock, + PSI_rwlock_operation op, + const char *src_file, uint src_line); + +PSI_cond_locker* +pfs_start_cond_wait_v1(PSI_cond_locker_state *state, + PSI_cond *cond, PSI_mutex *mutex, + PSI_cond_operation op, + const char *src_file, uint src_line); + +PSI_table_locker* +pfs_start_table_io_wait_v1(PSI_table_locker_state *state, + PSI_table *table, + PSI_table_io_operation op, + uint index, + const char *src_file, uint src_line); + +PSI_table_locker* +pfs_start_table_lock_wait_v1(PSI_table_locker_state *state, + PSI_table *table, + PSI_table_lock_operation op, + ulong op_flags, + const char *src_file, uint src_line); + +void pfs_unlock_mutex_v1(PSI_mutex *mutex); + +void pfs_unlock_rwlock_v1(PSI_rwlock *rwlock); + +void pfs_signal_cond_v1(PSI_cond* cond); + +void pfs_broadcast_cond_v1(PSI_cond* cond); + +void pfs_end_mutex_wait_v1(PSI_mutex_locker* locker, int rc); + +void pfs_end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc); + +void pfs_end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc); + +void pfs_end_cond_wait_v1(PSI_cond_locker* locker, int rc); + +int pfs_set_thread_connect_attrs_v1(const char *buffer, uint length, + const void *from_cs); + +C_MODE_END + +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_THREAD_INTERFACE */ + +#endif + diff --git a/include/pfs_transaction_provider.h b/include/pfs_transaction_provider.h new file mode 100644 index 00000000..fdaad8ae --- /dev/null +++ b/include/pfs_transaction_provider.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2013, 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, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef PFS_TRANSACTION_PROVIDER_H +#define PFS_TRANSACTION_PROVIDER_H + +/** + @file include/pfs_transaction_provider.h + Performance schema instrumentation (declarations). +*/ + +#ifdef HAVE_PSI_TRANSACTION_INTERFACE +#ifdef MYSQL_SERVER +#ifndef EMBEDDED_LIBRARY +#ifndef MYSQL_DYNAMIC_PLUGIN + +#include "mysql/psi/psi.h" + +#define PSI_TRANSACTION_CALL(M) pfs_ ## M ## _v1 + +C_MODE_START + +PSI_transaction_locker* +pfs_get_thread_transaction_locker_v1(PSI_transaction_locker_state *state, + const void *xid, + ulonglong trxid, + int isolation_level, + my_bool read_only, + my_bool autocommit); + +void pfs_start_transaction_v1(PSI_transaction_locker *locker, + const char *src_file, uint src_line); + +void pfs_set_transaction_xid_v1(PSI_transaction_locker *locker, + const void *xid, + int xa_state); + +void pfs_set_transaction_xa_state_v1(PSI_transaction_locker *locker, + int xa_state); + +void pfs_set_transaction_gtid_v1(PSI_transaction_locker *locker, + const void *sid, + const void *gtid_spec); + +void pfs_set_transaction_trxid_v1(PSI_transaction_locker *locker, + const ulonglong *trxid); + +void pfs_inc_transaction_savepoints_v1(PSI_transaction_locker *locker, + ulong count); + +void pfs_inc_transaction_rollback_to_savepoint_v1(PSI_transaction_locker *locker, + ulong count); + +void pfs_inc_transaction_release_savepoint_v1(PSI_transaction_locker *locker, + ulong count); + +void pfs_end_transaction_v1(PSI_transaction_locker *locker, my_bool commit); + +C_MODE_END + +#endif /* MYSQL_DYNAMIC_PLUGIN */ +#endif /* EMBEDDED_LIBRARY */ +#endif /* MYSQL_SERVER */ +#endif /* HAVE_PSI_TRANSACTION_INTERFACE */ + +#endif + diff --git a/include/probes_mysql.d.base b/include/probes_mysql.d.base new file mode 100644 index 00000000..68daa5d7 --- /dev/null +++ b/include/probes_mysql.d.base @@ -0,0 +1,177 @@ +/* Copyright (c) 2008, 2009 Sun Microsystems, Inc. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + The actual probe names in DTrace scripts will replace '__' by '-'. Thus + insert__row__start will be insert-row-start. + + Recommendations for adding new probes: + + - each probe should have the minimal set of arguments required to + unambiguously identify the context in which the probe fires. Redundant + arguments (i.e. the ones that can be obtained in user scripts from previous + probes' arguments or otherwise) may be added for convenience. + + - try to avoid computationally expensive probe arguments. If impossible, + use *_ENABLED() macros to check if the probe is activated before + performing expensive calculations for a probe argument. + + - all *-done probes should have a status argument wherever applicable to make + it possible for user scripts to figure out whether the completed operation + was successful or not. + + - for all status arguments, a non-zero value should be returned on error or + failure, 0 should be returned on success. +*/ + +provider mysql { + + /* The following ones fire when creating or closing a client connection */ + probe connection__start(unsigned long conn_id, char *user, char *host); + probe connection__done(int status, unsigned long conn_id); + + /* + Fire at the start/end of any client command processing (including SQL + queries). + */ + probe command__start(unsigned long conn_id, int command, + char *user, char *host); + probe command__done(int status); + + /* + The following probes fire at the start/end of any SQL query processing, + respectively. + + query_start() has a lot of parameters that can be used to pick up + parameters for a lot of other probes here. For simplicity reasons we also + add the query string to most other DTrace probes as well. Hostname is + either the hostname or the IP address of the MySQL Client. + */ + probe query__start(char *query, + unsigned long conn_id, + char *db_name, + char *user, + char *host); + probe query__done(int status); + + /* Fire at the start/end of SQL query parsing */ + probe query__parse__start(char *query); + probe query__parse__done(int status); + + /* Track whether the query hits the query cache or not */ + probe query__cache__hit(char *query, unsigned long rows); + probe query__cache__miss(char *query); + + /* + This probe fires when the actual query execution starts, i.e. after + parsing and checking the query cache, but before privilege checks, + optimizing, etc. + + Query means also all independent queries of a stored procedure and prepared + statements. Also the stored procedure itself is a query. + + exec_type is: + 0: Executed query from sql_parse, top-level query (sql_parse.cc) + 1: Executed prepared statement (sql_prepare.cc) + 2: Executed cursor statement (sql_cursor.cc) + 3: Executed query in stored procedure (sp_head.cc) + */ + probe query__exec__start(char *query, + unsigned long connid, + char *db_name, + char *user, + char *host, + int exec_type); + probe query__exec__done(int status); + + /* These probes fire when performing row operations towards any handler */ + probe insert__row__start(char *db, char *table); + probe insert__row__done(int status); + probe update__row__start(char *db, char *table); + probe update__row__done(int status); + probe delete__row__start(char *db, char *table); + probe delete__row__done(int status); + probe read__row__start(char *db, char *table, int scan_flag); + probe read__row__done(int status); + probe index__read__row__start(char *db, char *table); + probe index__read__row__done(int status); + + /* + These probes fire when calling external_lock for any handler + depending on the lock type being acquired or released. + */ + probe handler__rdlock__start(char *db, char *table); + probe handler__wrlock__start(char *db, char *table); + probe handler__unlock__start(char *db, char *table); + probe handler__rdlock__done(int status); + probe handler__wrlock__done(int status); + probe handler__unlock__done(int status); + + /* + These probes fire when a filesort activity happens in a query. + */ + probe filesort__start(char *db, char *table); + probe filesort__done(int status, unsigned long rows); + /* + The query types SELECT, INSERT, INSERT AS SELECT, UPDATE, UPDATE with + multiple tables, DELETE, DELETE with multiple tables are all probed. + The start probe always contains the query text. + */ + probe select__start(char *query); + probe select__done(int status, unsigned long rows); + probe insert__start(char *query); + probe insert__done(int status, unsigned long rows); + probe insert__select__start(char *query); + probe insert__select__done(int status, unsigned long rows); + probe update__start(char *query); + probe update__done(int status, + unsigned long rowsmatches, unsigned long rowschanged); + probe multi__update__start(char *query); + probe multi__update__done(int status, + unsigned long rowsmatches, + unsigned long rowschanged); + probe delete__start(char *query); + probe delete__done(int status, unsigned long rows); + probe multi__delete__start(char *query); + probe multi__delete__done(int status, unsigned long rows); + + /* + These probes can be used to measure the time waiting for network traffic + or identify network-related problems. + */ + probe net__read__start(); + probe net__read__done(int status, unsigned long bytes); + probe net__write__start(unsigned long bytes); + probe net__write__done(int status); + + /* MyISAM Key cache probes */ + probe keycache__read__start(char *filepath, unsigned long bytes, + unsigned long mem_used, unsigned long mem_free); + probe keycache__read__block(unsigned long bytes); + probe keycache__read__hit(); + probe keycache__read__miss(); + probe keycache__read__done(unsigned long mem_used, unsigned long mem_free); + probe keycache__write__start(char *filepath, unsigned long bytes, + unsigned long mem_used, unsigned long mem_free); + probe keycache__write__block(unsigned long bytes); + probe keycache__write__done(unsigned long mem_used, unsigned long mem_free); +}; + +#pragma D attributes Evolving/Evolving/Common provider mysql provider +#pragma D attributes Evolving/Evolving/Common provider mysql module +#pragma D attributes Evolving/Evolving/Common provider mysql function +#pragma D attributes Evolving/Evolving/Common provider mysql name +#pragma D attributes Evolving/Evolving/Common provider mysql args diff --git a/include/probes_mysql.h b/include/probes_mysql.h new file mode 100644 index 00000000..ce5be041 --- /dev/null +++ b/include/probes_mysql.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2008 Sun Microsystems, Inc. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef PROBES_MYSQL_H + +#define PROBES_MYSQL_H + +#if defined(HAVE_DTRACE) && !defined(DISABLE_DTRACE) +#include "probes_mysql_dtrace.h" +#else /* no dtrace */ +#include "probes_mysql_nodtrace.h" +#endif +#endif /* PROBES_MYSQL_H */ diff --git a/include/probes_mysql_nodtrace.h.in b/include/probes_mysql_nodtrace.h.in new file mode 100644 index 00000000..2155e848 --- /dev/null +++ b/include/probes_mysql_nodtrace.h.in @@ -0,0 +1,132 @@ +/* + * Generated by dheadgen(1). + */ + +#ifndef _PROBES_MYSQL_D +#define _PROBES_MYSQL_D + +#ifdef __cplusplus +extern "C" { +#define MYSQL_DTRACE_DISABLED false +#else +#define MYSQL_DTRACE_DISABLED 0 +#endif + +#define MYSQL_CONNECTION_START(arg0, arg1, arg2) +#define MYSQL_CONNECTION_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_CONNECTION_DONE(arg0, arg1) +#define MYSQL_CONNECTION_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_COMMAND_START(arg0, arg1, arg2, arg3) +#define MYSQL_COMMAND_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_COMMAND_DONE(arg0) +#define MYSQL_COMMAND_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_QUERY_START(arg0, arg1, arg2, arg3, arg4) +#define MYSQL_QUERY_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_QUERY_DONE(arg0) +#define MYSQL_QUERY_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_QUERY_PARSE_START(arg0) +#define MYSQL_QUERY_PARSE_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_QUERY_PARSE_DONE(arg0) +#define MYSQL_QUERY_PARSE_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_QUERY_CACHE_HIT(arg0, arg1) +#define MYSQL_QUERY_CACHE_HIT_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_QUERY_CACHE_MISS(arg0) +#define MYSQL_QUERY_CACHE_MISS_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_QUERY_EXEC_START(arg0, arg1, arg2, arg3, arg4, arg5) +#define MYSQL_QUERY_EXEC_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_QUERY_EXEC_DONE(arg0) +#define MYSQL_QUERY_EXEC_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_INSERT_ROW_START(arg0, arg1) +#define MYSQL_INSERT_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_INSERT_ROW_DONE(arg0) +#define MYSQL_INSERT_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_UPDATE_ROW_START(arg0, arg1) +#define MYSQL_UPDATE_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_UPDATE_ROW_DONE(arg0) +#define MYSQL_UPDATE_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_DELETE_ROW_START(arg0, arg1) +#define MYSQL_DELETE_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_DELETE_ROW_DONE(arg0) +#define MYSQL_DELETE_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_READ_ROW_START(arg0, arg1, arg2) +#define MYSQL_READ_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_READ_ROW_DONE(arg0) +#define MYSQL_READ_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_INDEX_READ_ROW_START(arg0, arg1) +#define MYSQL_INDEX_READ_ROW_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_INDEX_READ_ROW_DONE(arg0) +#define MYSQL_INDEX_READ_ROW_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_HANDLER_RDLOCK_START(arg0, arg1) +#define MYSQL_HANDLER_RDLOCK_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_HANDLER_WRLOCK_START(arg0, arg1) +#define MYSQL_HANDLER_WRLOCK_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_HANDLER_UNLOCK_START(arg0, arg1) +#define MYSQL_HANDLER_UNLOCK_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_HANDLER_RDLOCK_DONE(arg0) +#define MYSQL_HANDLER_RDLOCK_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_HANDLER_WRLOCK_DONE(arg0) +#define MYSQL_HANDLER_WRLOCK_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_HANDLER_UNLOCK_DONE(arg0) +#define MYSQL_HANDLER_UNLOCK_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_FILESORT_START(arg0, arg1) +#define MYSQL_FILESORT_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_FILESORT_DONE(arg0, arg1) +#define MYSQL_FILESORT_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_SELECT_START(arg0) +#define MYSQL_SELECT_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_SELECT_DONE(arg0, arg1) +#define MYSQL_SELECT_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_INSERT_START(arg0) +#define MYSQL_INSERT_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_INSERT_DONE(arg0, arg1) +#define MYSQL_INSERT_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_INSERT_SELECT_START(arg0) +#define MYSQL_INSERT_SELECT_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_INSERT_SELECT_DONE(arg0, arg1) +#define MYSQL_INSERT_SELECT_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_UPDATE_START(arg0) +#define MYSQL_UPDATE_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_UPDATE_DONE(arg0, arg1, arg2) +#define MYSQL_UPDATE_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_MULTI_UPDATE_START(arg0) +#define MYSQL_MULTI_UPDATE_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_MULTI_UPDATE_DONE(arg0, arg1, arg2) +#define MYSQL_MULTI_UPDATE_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_DELETE_START(arg0) +#define MYSQL_DELETE_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_DELETE_DONE(arg0, arg1) +#define MYSQL_DELETE_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_MULTI_DELETE_START(arg0) +#define MYSQL_MULTI_DELETE_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_MULTI_DELETE_DONE(arg0, arg1) +#define MYSQL_MULTI_DELETE_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_NET_READ_START() +#define MYSQL_NET_READ_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_NET_READ_DONE(arg0, arg1) +#define MYSQL_NET_READ_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_NET_WRITE_START(arg0) +#define MYSQL_NET_WRITE_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_NET_WRITE_DONE(arg0) +#define MYSQL_NET_WRITE_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_KEYCACHE_READ_START(arg0, arg1, arg2, arg3) +#define MYSQL_KEYCACHE_READ_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_KEYCACHE_READ_BLOCK(arg0) +#define MYSQL_KEYCACHE_READ_BLOCK_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_KEYCACHE_READ_HIT() +#define MYSQL_KEYCACHE_READ_HIT_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_KEYCACHE_READ_MISS() +#define MYSQL_KEYCACHE_READ_MISS_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_KEYCACHE_READ_DONE(arg0, arg1) +#define MYSQL_KEYCACHE_READ_DONE_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_KEYCACHE_WRITE_START(arg0, arg1, arg2, arg3) +#define MYSQL_KEYCACHE_WRITE_START_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_KEYCACHE_WRITE_BLOCK(arg0) +#define MYSQL_KEYCACHE_WRITE_BLOCK_ENABLED() MYSQL_DTRACE_DISABLED +#define MYSQL_KEYCACHE_WRITE_DONE(arg0, arg1) +#define MYSQL_KEYCACHE_WRITE_DONE_ENABLED() MYSQL_DTRACE_DISABLED + +#ifdef __cplusplus +} +#endif + +#endif /* _PROBES_MYSQL_D */ diff --git a/include/providers/bzlib.h b/include/providers/bzlib.h new file mode 100644 index 00000000..b48c940b --- /dev/null +++ b/include/providers/bzlib.h @@ -0,0 +1,126 @@ +/** + @file bzlib.h + This service provides dynamic access to BZip2. +*/ + +#ifndef BZIP2_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdbool.h> +#endif + +#ifndef MYSQL_DYNAMIC_PLUGIN +#define provider_service_bzip2 provider_service_bzip2_static +#endif + +#ifndef BZ_RUN +#define BZ_RUN 0 +#define BZ_FINISH 2 + +#define BZ_OK 0 +#define BZ_RUN_OK 1 +#define BZ_FINISH_OK 3 +#define BZ_STREAM_END 4 + +typedef struct +{ + char *next_in; + unsigned int avail_in; + unsigned int total_in_lo32; + unsigned int total_in_hi32; + + char *next_out; + unsigned int avail_out; + unsigned int total_out_lo32; + unsigned int total_out_hi32; + + void *state; + + void *(*bzalloc)(void *, int, int); + void (*bzfree)(void *, void *); + void *opaque; +} bz_stream; + +#define BZ2_bzBuffToBuffCompress(...) provider_service_bzip2->BZ2_bzBuffToBuffCompress_ptr (__VA_ARGS__) +#define BZ2_bzBuffToBuffDecompress(...) provider_service_bzip2->BZ2_bzBuffToBuffDecompress_ptr (__VA_ARGS__) +#define BZ2_bzCompress(...) provider_service_bzip2->BZ2_bzCompress_ptr (__VA_ARGS__) +#define BZ2_bzCompressEnd(...) provider_service_bzip2->BZ2_bzCompressEnd_ptr (__VA_ARGS__) +#define BZ2_bzCompressInit(...) provider_service_bzip2->BZ2_bzCompressInit_ptr (__VA_ARGS__) +#define BZ2_bzDecompress(...) provider_service_bzip2->BZ2_bzDecompress_ptr (__VA_ARGS__) +#define BZ2_bzDecompressEnd(...) provider_service_bzip2->BZ2_bzDecompressEnd_ptr (__VA_ARGS__) +#define BZ2_bzDecompressInit(...) provider_service_bzip2->BZ2_bzDecompressInit_ptr (__VA_ARGS__) +#endif + +#define DEFINE_BZ2_bzBuffToBuffCompress(NAME) NAME( \ + char *dest, \ + unsigned int *destLen, \ + char *source, \ + unsigned int sourceLen, \ + int blockSize100k, \ + int verbosity, \ + int workFactor \ +) + +#define DEFINE_BZ2_bzBuffToBuffDecompress(NAME) NAME( \ + char *dest, \ + unsigned int *destLen, \ + char *source, \ + unsigned int sourceLen, \ + int small, \ + int verbosity \ +) + +#define DEFINE_BZ2_bzCompress(NAME) NAME( \ + bz_stream *strm, \ + int action \ +) + +#define DEFINE_BZ2_bzCompressEnd(NAME) NAME( \ + bz_stream *strm \ +) + +#define DEFINE_BZ2_bzCompressInit(NAME) NAME( \ + bz_stream *strm, \ + int blockSize100k, \ + int verbosity, \ + int workFactor \ +) + +#define DEFINE_BZ2_bzDecompress(NAME) NAME( \ + bz_stream *strm \ +) + +#define DEFINE_BZ2_bzDecompressEnd(NAME) NAME( \ + bz_stream *strm \ +) + +#define DEFINE_BZ2_bzDecompressInit(NAME) NAME( \ + bz_stream *strm, \ + int verbosity, \ + int small \ +) + +struct provider_service_bzip2_st{ + int DEFINE_BZ2_bzBuffToBuffCompress((*BZ2_bzBuffToBuffCompress_ptr)); + int DEFINE_BZ2_bzBuffToBuffDecompress((*BZ2_bzBuffToBuffDecompress_ptr)); + int DEFINE_BZ2_bzCompress((*BZ2_bzCompress_ptr)); + int DEFINE_BZ2_bzCompressEnd((*BZ2_bzCompressEnd_ptr)); + int DEFINE_BZ2_bzCompressInit((*BZ2_bzCompressInit_ptr)); + int DEFINE_BZ2_bzDecompress((*BZ2_bzDecompress_ptr)); + int DEFINE_BZ2_bzDecompressEnd((*BZ2_bzDecompressEnd_ptr)); + int DEFINE_BZ2_bzDecompressInit((*BZ2_bzDecompressInit_ptr)); + + bool is_loaded; +}; + +extern struct provider_service_bzip2_st *provider_service_bzip2; + +#ifdef __cplusplus +} +#endif + +#define BZIP2_INCLUDED +#endif diff --git a/include/providers/lz4.h b/include/providers/lz4.h new file mode 100644 index 00000000..4ac6b2c8 --- /dev/null +++ b/include/providers/lz4.h @@ -0,0 +1,63 @@ +/** + @file lz4.h + This service provides dynamic access to LZ4. +*/ + +#ifndef LZ4_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#endif + +#ifndef MYSQL_DYNAMIC_PLUGIN +#define provider_service_lz4 provider_service_lz4_static +#endif + +#ifndef LZ4_VERSION_NUMBER +#define LZ4_MAX_INPUT_SIZE 0x7E000000 + +#define LZ4_compressBound(...) provider_service_lz4->LZ4_compressBound_ptr (__VA_ARGS__) +#define LZ4_compress_default(...) provider_service_lz4->LZ4_compress_default_ptr (__VA_ARGS__) +#define LZ4_decompress_safe(...) provider_service_lz4->LZ4_decompress_safe_ptr (__VA_ARGS__) +#endif + +#define DEFINE_LZ4_compressBound(NAME) NAME( \ + int inputSize \ +) + +#define DEFINE_LZ4_compress_default(NAME) NAME( \ + const char *src, \ + char *dst, \ + int srcSize, \ + int dstCapacity \ +) + +#define DEFINE_LZ4_decompress_safe(NAME) NAME( \ + const char *src, \ + char *dst, \ + int compressedSize, \ + int dstCapacity \ +) + +struct provider_service_lz4_st +{ + int DEFINE_LZ4_compressBound((*LZ4_compressBound_ptr)); + int DEFINE_LZ4_compress_default((*LZ4_compress_default_ptr)); + int DEFINE_LZ4_decompress_safe((*LZ4_decompress_safe_ptr)); + + bool is_loaded; +}; + +extern struct provider_service_lz4_st *provider_service_lz4; + +#ifdef __cplusplus +} +#endif + +#define LZ4_INCLUDED +#endif diff --git a/include/providers/lzma.h b/include/providers/lzma.h new file mode 100644 index 00000000..8125bb8c --- /dev/null +++ b/include/providers/lzma.h @@ -0,0 +1,102 @@ +/** + @file lzma.h + This service provides dynamic access to LZMA. +*/ + +#ifndef LZMA_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdbool.h> +#include <stdint.h> +#include <stddef.h> +#endif + +#ifndef MYSQL_DYNAMIC_PLUGIN +#define provider_service_lzma provider_service_lzma_static +#endif + +#ifndef LZMA_VERSION +typedef enum +{ + LZMA_OK = 0, + LZMA_STREAM_END = 1, + LZMA_NO_CHECK = 2, + LZMA_UNSUPPORTED_CHECK = 3, + LZMA_GET_CHECK = 4, + LZMA_MEM_ERROR = 5, + LZMA_MEMLIMIT_ERROR = 6, + LZMA_FORMAT_ERROR = 7, + LZMA_OPTIONS_ERROR = 8, + LZMA_DATA_ERROR = 9, + LZMA_BUF_ERROR = 10, + LZMA_PROG_ERROR = 11, +} lzma_ret; + +typedef struct +{ + void *(*alloc)(void *opaque, size_t nmemb, size_t size); + void (*free)(void *opaque, void *ptr); + void *opaque; +} lzma_allocator; + +typedef enum +{ + LZMA_CHECK_NONE = 0, + LZMA_CHECK_CRC32 = 1, + LZMA_CHECK_CRC64 = 4, + LZMA_CHECK_SHA256 = 10 +} lzma_check; + +#define lzma_stream_buffer_decode(...) provider_service_lzma->lzma_stream_buffer_decode_ptr (__VA_ARGS__) +#define lzma_easy_buffer_encode(...) provider_service_lzma->lzma_easy_buffer_encode_ptr (__VA_ARGS__) +#elif LZMA_VERSION < 50010030 +#define lzma_maybe_const +#endif + +#ifndef lzma_maybe_const +#define lzma_maybe_const const +#endif + +#define DEFINE_lzma_stream_buffer_decode(NAME) NAME( \ + uint64_t *memlimit, \ + uint32_t flags, \ + lzma_maybe_const lzma_allocator *allocator, \ + const uint8_t *in, \ + size_t *in_pos, \ + size_t in_size, \ + uint8_t *out, \ + size_t *out_pos, \ + size_t out_size \ +) + +#define DEFINE_lzma_easy_buffer_encode(NAME) NAME( \ + uint32_t preset, \ + lzma_check check, \ + lzma_maybe_const lzma_allocator *allocator, \ + const uint8_t *in, \ + size_t in_size, \ + uint8_t *out, \ + size_t *out_pos, \ + size_t out_size \ +) + +struct provider_service_lzma_st +{ + lzma_ret DEFINE_lzma_stream_buffer_decode((*lzma_stream_buffer_decode_ptr)); + lzma_ret DEFINE_lzma_easy_buffer_encode((*lzma_easy_buffer_encode_ptr)); + + bool is_loaded; +}; + +extern struct provider_service_lzma_st *provider_service_lzma; + + +#ifdef __cplusplus +} +#endif + +#define LZMA_INCLUDED +#endif diff --git a/include/providers/lzo/lzo1x.h b/include/providers/lzo/lzo1x.h new file mode 100644 index 00000000..93d1461f --- /dev/null +++ b/include/providers/lzo/lzo1x.h @@ -0,0 +1,62 @@ +/** + @file lzo/lzo1x.h + This service provides dynamic access to LZO. +*/ + +#ifndef LZO_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stdbool.h> +#endif + +#ifndef MYSQL_DYNAMIC_PLUGIN +#define provider_service_lzo provider_service_lzo_static +#endif + +#ifndef LZO_E_OK +#define LZO_E_OK 0 +#define LZO_E_INTERNAL_ERROR (-99) + +#define LZO1X_1_15_MEM_COMPRESS ((unsigned int) (32768L * ((unsigned) sizeof(unsigned char *)))) + +typedef size_t lzo_uint; + +#define lzo1x_1_15_compress(...) provider_service_lzo->lzo1x_1_15_compress_ptr (__VA_ARGS__) +#define lzo1x_decompress_safe(...) provider_service_lzo->lzo1x_decompress_safe_ptr (__VA_ARGS__) +#endif + +#define DEFINE_lzo1x_1_15_compress(NAME) NAME( \ + const unsigned char *src, \ + lzo_uint src_len, \ + unsigned char *dst, \ + lzo_uint *dst_len, \ + void *wrkmem \ +) + +#define DEFINE_lzo1x_decompress_safe(NAME) NAME( \ + const unsigned char *src, \ + lzo_uint src_len, \ + unsigned char *dst, \ + lzo_uint *dst_len, \ + void *wrkmem \ +) + +struct provider_service_lzo_st +{ + int DEFINE_lzo1x_1_15_compress((*lzo1x_1_15_compress_ptr)); + int DEFINE_lzo1x_decompress_safe((*lzo1x_decompress_safe_ptr)); + + bool is_loaded; +}; + +extern struct provider_service_lzo_st *provider_service_lzo; + +#ifdef __cplusplus +} +#endif + +#define LZO_INCLUDED +#endif diff --git a/include/providers/snappy-c.h b/include/providers/snappy-c.h new file mode 100644 index 00000000..afc6aef2 --- /dev/null +++ b/include/providers/snappy-c.h @@ -0,0 +1,75 @@ +/** + @file snappy-c.h + This service provides dynamic access to Snappy as a C header. +*/ + +#ifndef SNAPPY_C_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MYSQL_ABI_CHECK +#include <stddef.h> +#include <stdbool.h> +#endif + +#ifndef MYSQL_DYNAMIC_PLUGIN +#define provider_service_snappy provider_service_snappy_static +#endif + +#ifndef SNAPPY_C +typedef enum +{ + SNAPPY_OK = 0, + SNAPPY_INVALID_INPUT = 1, + SNAPPY_BUFFER_TOO_SMALL = 2 +} snappy_status; + +#define snappy_max_compressed_length(...) provider_service_snappy->snappy_max_compressed_length_ptr (__VA_ARGS__) +#define snappy_compress(...) provider_service_snappy->snappy_compress_ptr (__VA_ARGS__) +#define snappy_uncompressed_length(...) provider_service_snappy->snappy_uncompressed_length_ptr (__VA_ARGS__) +#define snappy_uncompress(...) provider_service_snappy->snappy_uncompress_ptr (__VA_ARGS__) +#endif + +#define DEFINE_snappy_max_compressed_length(NAME) NAME( \ + size_t source_length \ +) + +#define DEFINE_snappy_compress(NAME) NAME( \ + const char *input, \ + size_t input_length, \ + char *compressed, \ + size_t *compressed_length \ +) + +#define DEFINE_snappy_uncompressed_length(NAME) NAME( \ + const char *compressed, \ + size_t compressed_length, \ + size_t *result \ +) + +#define DEFINE_snappy_uncompress(NAME) NAME( \ + const char *compressed, \ + size_t compressed_length, \ + char *uncompressed, \ + size_t *uncompressed_length \ +) + +struct provider_service_snappy_st +{ + size_t DEFINE_snappy_max_compressed_length((*snappy_max_compressed_length_ptr)); + snappy_status DEFINE_snappy_compress((*snappy_compress_ptr)); + snappy_status DEFINE_snappy_uncompressed_length((*snappy_uncompressed_length_ptr)); + snappy_status DEFINE_snappy_uncompress((*snappy_uncompress_ptr)); + + bool is_loaded; +}; + +extern struct provider_service_snappy_st *provider_service_snappy; + +#ifdef __cplusplus +} +#endif + +#define SNAPPY_C_INCLUDED +#endif diff --git a/include/queues.h b/include/queues.h new file mode 100644 index 00000000..9cc7c15a --- /dev/null +++ b/include/queues.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2010 Monty Program Ab + All Rights reserved + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + Code for general handling of priority Queues. + Implementation of queues from "Algorithms in C" by Robert Sedgewick. +*/ + +#ifndef _queues_h +#define _queues_h + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_queue { + uchar **root; + void *first_cmp_arg; + uint elements; + uint max_elements; + uint offset_to_key; /* compare is done on element+offset */ + uint offset_to_queue_pos; /* If we want to store position in element */ + uint auto_extent; + int max_at_top; /* Normally 1, set to -1 if queue_top gives max */ + int (*compare)(void *, uchar *,uchar *); +} QUEUE; + +#define queue_first_element(queue) 1 +#define queue_last_element(queue) (queue)->elements +#define queue_empty(queue) ((queue)->elements == 0) +#define queue_top(queue) ((queue)->root[1]) +#define queue_element(queue,index) ((queue)->root[index]) +#define queue_end(queue) ((queue)->root[(queue)->elements]) +#define queue_replace_top(queue) _downheap(queue, 1) +#define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg +#define queue_set_max_at_top(queue, set_arg) \ + (queue)->max_at_top= set_arg ? -1 : 1 +#define queue_remove_top(queue_arg) queue_remove((queue_arg), queue_first_element(queue_arg)) +typedef int (*queue_compare)(void *,uchar *, uchar *); + +int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key, + my_bool max_at_top, queue_compare compare, + void *first_cmp_arg, uint offset_to_queue_pos, + uint auto_extent); +int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key, + my_bool max_at_top, queue_compare compare, + void *first_cmp_arg, uint offset_to_queue_pos, + uint auto_extent); +int resize_queue(QUEUE *queue, uint max_elements); +void delete_queue(QUEUE *queue); +void queue_insert(QUEUE *queue, uchar *element); +int queue_insert_safe(QUEUE *queue, uchar *element); +uchar *queue_remove(QUEUE *queue,uint idx); +void queue_replace(QUEUE *queue,uint idx); + +#define queue_remove_all(queue) { (queue)->elements= 0; } +#define queue_is_full(queue) (queue->elements == queue->max_elements) +void _downheap(QUEUE *queue, uint idx); +void queue_fix(QUEUE *queue); +#define is_queue_inited(queue) ((queue)->root != 0) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/rijndael.h b/include/rijndael.h new file mode 100644 index 00000000..552430ae --- /dev/null +++ b/include/rijndael.h @@ -0,0 +1,47 @@ +#ifndef RIJNDAEL_INCLUDED +#define RIJNDAEL_INCLUDED + +/* Copyright (c) 2002, 2006 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + + +/* + rijndael-alg-fst.h + + @version 3.0 (December 2000) + Optimised ANSI C code for the Rijndael cipher (now AES) + @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> + @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> + @author Paulo Barreto <paulo.barreto@terra.com.br> + + This code is hereby placed in the public domain. + Modified by Peter Zaitsev to fit MySQL coding style. + */ + +#define AES_MAXKC (256/32) +#define AES_MAXKB (256/8) +#define AES_MAXNR 14 + +int rijndaelKeySetupEnc(uint32 rk[/*4*(Nr + 1)*/], const uint8 cipherKey[], + int keyBits); +int rijndaelKeySetupDec(uint32 rk[/*4*(Nr + 1)*/], const uint8 cipherKey[], + int keyBits); +void rijndaelEncrypt(const uint32 rk[/*4*(Nr + 1)*/], int Nr, + const uint8 pt[16], uint8 ct[16]); +void rijndaelDecrypt(const uint32 rk[/*4*(Nr + 1)*/], int Nr, + const uint8 ct[16], uint8 pt[16]); + +#endif /* RIJNDAEL_INCLUDED */ diff --git a/include/scope.h b/include/scope.h new file mode 100644 index 00000000..e0e9fc62 --- /dev/null +++ b/include/scope.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2020, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include <type_traits> +#include <utility> + +namespace detail +{ + +template <typename Callable> class scope_exit +{ +public: + template <typename F> + explicit scope_exit(F &&f) : function_(std::forward<F>(f)) + { + } + + scope_exit(scope_exit &&rhs) + : function_(std::move(rhs.function_)), engaged_(rhs.engaged_) + { + rhs.release(); + } + + scope_exit(const scope_exit &)= delete; + scope_exit &operator=(scope_exit &&)= delete; + scope_exit &operator=(const scope_exit &)= delete; + + void release() { engaged_= false; } + + ~scope_exit() + { + if (engaged_) + function_(); + } + +private: + Callable function_; + bool engaged_= true; +}; + +} // end namespace detail + +template <typename Callable> +detail::scope_exit<typename std::decay<Callable>::type> +make_scope_exit(Callable &&f) +{ + return detail::scope_exit<typename std::decay<Callable>::type>( + std::forward<Callable>(f)); +} + +#define CONCAT_IMPL(x, y) x##y + +#define CONCAT(x, y) CONCAT_IMPL(x, y) + +#define ANONYMOUS_VARIABLE CONCAT(_anonymous_variable, __LINE__) + +#define SCOPE_EXIT auto ANONYMOUS_VARIABLE= make_scope_exit diff --git a/include/service_versions.h b/include/service_versions.h new file mode 100644 index 00000000..9abae740 --- /dev/null +++ b/include/service_versions.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, 2021, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef _WIN32 +#define SERVICE_VERSION __declspec(dllexport) void * +#else +#define SERVICE_VERSION void * +#endif + +#define VERSION_debug_sync 0x1000 +#define VERSION_kill_statement 0x1000 + +#define VERSION_base64 0x0100 +#define VERSION_encryption 0x0300 +#define VERSION_encryption_scheme 0x0100 +#define VERSION_logger 0x0100 +#define VERSION_my_crypt 0x0100 +#define VERSION_my_md5 0x0100 +#define VERSION_my_print_error 0x0100 +#define VERSION_my_sha1 0x0101 +#define VERSION_my_sha2 0x0100 +#define VERSION_my_snprintf 0x0100 +#define VERSION_progress_report 0x0100 +#define VERSION_thd_alloc 0x0200 +#define VERSION_thd_autoinc 0x0100 +#define VERSION_thd_error_context 0x0200 +#define VERSION_thd_rnd 0x0100 +#define VERSION_thd_specifics 0x0100 +#define VERSION_thd_timezone 0x0100 +#define VERSION_thd_wait 0x0100 +#define VERSION_wsrep 0x0500 +#define VERSION_json 0x0100 +#define VERSION_thd_mdl 0x0100 +#define VERSION_sql_service 0x0101 + +#define VERSION_provider_bzip2 0x0100 +#define VERSION_provider_lz4 0x0100 +#define VERSION_provider_lzma 0x0100 +#define VERSION_provider_lzo 0x0100 +#define VERSION_provider_snappy 0x0100 diff --git a/include/source_revision.h.in b/include/source_revision.h.in new file mode 100644 index 00000000..991df992 --- /dev/null +++ b/include/source_revision.h.in @@ -0,0 +1 @@ +#define SOURCE_REVISION "@SOURCE_REVISION@" diff --git a/include/span.h b/include/span.h new file mode 100644 index 00000000..4ea200f5 --- /dev/null +++ b/include/span.h @@ -0,0 +1,161 @@ +/***************************************************************************** + +Copyright (c) 2019, 2020 MariaDB Corporation. + +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, Fifth Floor, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +#pragma once + +#include <cstddef> +#include <iterator> + +namespace st_ +{ + +namespace detail +{ + +template <class T> struct remove_cv +{ + typedef T type; +}; +template <class T> struct remove_cv<const T> +{ + typedef T type; +}; +template <class T> struct remove_cv<volatile T> +{ + typedef T type; +}; +template <class T> struct remove_cv<const volatile T> +{ + typedef T type; +}; + +} // namespace detail + +template <class ElementType> class span +{ +public: + typedef ElementType element_type; + typedef typename detail::remove_cv<ElementType>::type value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef element_type *pointer; + typedef const element_type *const_pointer; + typedef element_type &reference; + typedef const element_type &const_reference; + typedef pointer iterator; + typedef const_pointer const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + span() : data_(NULL), size_(0) {} + + span(pointer ptr, size_type count) : data_(ptr), size_(count) {} + + span(pointer first, pointer last) : data_(first), size_(last - first) {} + + template <size_t N> span(element_type (&arr)[N]) : data_(arr), size_(N) {} + + template <class Container> + span(Container &cont) : data_(cont.data()), size_(cont.size()) + { + } + + template <class Container> + span(const Container &cont) : data_(cont.data()), size_(cont.size()) + { + } + + span(const span &other) : data_(other.data_), size_(other.size_) {} + + ~span() = default; + + span &operator=(const span &other) + { + data_= other.data(); + size_= other.size(); + return *this; + } + + template <size_t Count> span<element_type> first() const + { + assert(!empty()); + return span(data(), 1); + } + template <size_t Count> span<element_type> last() const + { + assert(!empty()); + return span(data() + size() - 1, 1); + } + + span<element_type> first(size_type count) const + { + assert(!empty()); + return span(data(), 1); + } + span<element_type> last(size_type count) const + { + assert(!empty()); + return span(data() + size() - 1, 1); + } + span<element_type> subspan(size_type offset, size_type count) const + { + assert(!empty()); + assert(size() >= offset + count); + return span(data() + offset, count); + } + + size_type size() const { return size_; } + size_type size_bytes() const { return size() * sizeof(ElementType); } + bool empty() const __attribute__((warn_unused_result)) + { + return size() == 0; + } + + reference operator[](size_type idx) const + { + assert(size() > idx); + return data()[idx]; + } + reference front() const + { + assert(!empty()); + return data()[0]; + } + reference back() const + { + assert(!empty()); + return data()[size() - 1]; + } + pointer data() const { return data_; } + + iterator begin() const { return data_; } + iterator end() const { return data_ + size_; } + reverse_iterator rbegin() const + { + return std::reverse_iterator<iterator>(end()); + } + reverse_iterator rend() const + { + return std::reverse_iterator<iterator>(begin()); + } + +private: + pointer data_; + size_type size_; +}; + +} // namespace st_ diff --git a/include/sql_common.h b/include/sql_common.h new file mode 100644 index 00000000..2a79261c --- /dev/null +++ b/include/sql_common.h @@ -0,0 +1,132 @@ +#ifndef SQL_COMMON_INCLUDED +#define SQL_COMMON_INCLUDED +/* Copyright (c) 2003, 2018, Oracle and/or its affiliates. + Copyright (c) 2010, 2018, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <mysql.h> +#include <hash.h> + +extern const char *unknown_sqlstate; +extern const char *cant_connect_sqlstate; +extern const char *not_error_sqlstate; + + +struct st_mysql_options_extention { + char *plugin_dir; + char *default_auth; + char *ssl_crl; /* PEM CRL file */ + char *ssl_crlpath; /* PEM directory of CRL-s? */ + void (*report_progress)(const MYSQL *mysql, + unsigned int stage, + unsigned int max_stage, + double progress, + const char *proc_info, + uint proc_info_length); + HASH connection_attributes; + size_t connection_attributes_length; + my_bool tls_verify_server_cert; +}; + +typedef struct st_mysql_methods +{ + my_bool (*read_query_result)(MYSQL *mysql); + my_bool (*advanced_command)(MYSQL *mysql, + enum enum_server_command command, + const unsigned char *header, + unsigned long header_length, + const unsigned char *arg, + unsigned long arg_length, + my_bool skip_check, + MYSQL_STMT *stmt); + MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + unsigned int fields); + MYSQL_RES * (*use_result)(MYSQL *mysql); + void (*fetch_lengths)(unsigned long *to, + MYSQL_ROW column, unsigned int field_count); + void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results); + int (*read_change_user_result)(MYSQL *mysql); + void (*on_close_free)(MYSQL *mysql); +#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) + MYSQL_FIELD * (*list_fields)(MYSQL *mysql); + my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); + int (*stmt_execute)(MYSQL_STMT *stmt); + int (*read_binary_rows)(MYSQL_STMT *stmt); + int (*unbuffered_fetch)(MYSQL *mysql, char **row); + const char *(*read_statistics)(MYSQL *mysql); + my_bool (*next_result)(MYSQL *mysql); + int (*read_rows_from_cursor)(MYSQL_STMT *stmt); +#endif +} MYSQL_METHODS; + +#ifdef LIBMARIADB +#define simple_command(mysql, command, arg, length, skip_check) ma_simple_command(mysql, command, (char *)arg, length, skip_check, NULL) +#else +#define simple_command(mysql, command, arg, length, skip_check) \ + (*(mysql)->methods->advanced_command)(mysql, command, 0, \ + 0, arg, length, skip_check, NULL) +#endif +#define stmt_command(mysql, command, arg, length, stmt) \ + (*(mysql)->methods->advanced_command)(mysql, command, 0, \ + 0, arg, length, 1, stmt) + +extern CHARSET_INFO *default_client_charset_info; +MYSQL_FIELD *unpack_fields(MYSQL *mysql, MYSQL_DATA *data,MEM_ROOT *alloc, + uint fields, my_bool default_value, + uint server_capabilities); +void free_rows(MYSQL_DATA *cur); +void free_old_query(MYSQL *mysql); +void end_server(MYSQL *mysql); +my_bool mysql_reconnect(MYSQL *mysql); +void mysql_read_default_options(struct st_mysql_options *options, + const char *filename,const char *group); +my_bool +cli_advanced_command(MYSQL *mysql, enum enum_server_command command, + const unsigned char *header, ulong header_length, + const unsigned char *arg, ulong arg_length, + my_bool skip_check, MYSQL_STMT *stmt); +unsigned long cli_safe_read(MYSQL *mysql); +unsigned long cli_safe_read_reallen(MYSQL *mysql, ulong* reallen); +void net_clear_error(NET *net); +void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net); +void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate, + const char *err); +void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate); +void set_mysql_extended_error(MYSQL *mysql, int errcode, const char *sqlstate, + const char *format, ...); + +/* client side of the pluggable authentication */ +struct st_vio; +struct st_plugin_vio_info; +void mpvio_info(struct st_vio *vio, struct st_plugin_vio_info *info); +int run_plugin_auth(MYSQL *mysql, char *data, uint data_len, + const char *data_plugin, const char *db); +int mysql_client_plugin_init(); +void mysql_client_plugin_deinit(); +struct st_mysql_client_plugin; +extern struct st_mysql_client_plugin *mysql_client_builtins[]; +uchar * send_client_connect_attrs(MYSQL *mysql, uchar *buf); + +#ifdef __cplusplus +} +#endif + +#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41) + +#endif /* SQL_COMMON_INCLUDED */ diff --git a/include/ssl_compat.h b/include/ssl_compat.h new file mode 100644 index 00000000..3327eee0 --- /dev/null +++ b/include/ssl_compat.h @@ -0,0 +1,105 @@ +/* + Copyright (c) 2016, 2022, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include <openssl/opensslv.h> + +/* OpenSSL version specific definitions */ +#if defined(OPENSSL_VERSION_NUMBER) + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x30500000L) +#define HAVE_OPENSSL11 1 +#define SSL_LIBRARY OpenSSL_version(OPENSSL_VERSION) +#define ERR_remove_state(X) ERR_clear_error() +#define EVP_CIPHER_CTX_SIZE 200 +#define EVP_MD_CTX_SIZE 80 +#undef EVP_MD_CTX_init +#define EVP_MD_CTX_init(X) do { memset((X), 0, EVP_MD_CTX_SIZE); EVP_MD_CTX_reset(X); } while(0) +#undef EVP_CIPHER_CTX_init +#define EVP_CIPHER_CTX_init(X) do { memset((X), 0, EVP_CIPHER_CTX_SIZE); EVP_CIPHER_CTX_reset(X); } while(0) + +/* + Macros below are deprecated. OpenSSL 1.1 may define them or not, + depending on how it was built. +*/ +#undef ERR_free_strings +#define ERR_free_strings() +#undef EVP_cleanup +#define EVP_cleanup() +#undef CRYPTO_cleanup_all_ex_data +#define CRYPTO_cleanup_all_ex_data() +#undef SSL_load_error_strings +#define SSL_load_error_strings() + +#else +#define HAVE_OPENSSL10 1 +#ifdef HAVE_WOLFSSL +#define SSL_LIBRARY "WolfSSL " WOLFSSL_VERSION +#else +#define SSL_LIBRARY SSLeay_version(SSLEAY_VERSION) +#endif + +#ifdef HAVE_WOLFSSL +#undef ERR_remove_state +#define ERR_remove_state(x) do {} while(0) +#elif defined (HAVE_ERR_remove_thread_state) +#define ERR_remove_state(X) ERR_remove_thread_state(NULL) +#endif /* HAVE_ERR_remove_thread_state */ + +#endif /* HAVE_OPENSSL11 */ +#endif + +#ifdef HAVE_WOLFSSL +#define EVP_MD_CTX_SIZE sizeof(wc_Md5) +#endif + +#ifndef HAVE_OPENSSL11 +#ifndef ASN1_STRING_get0_data +#define ASN1_STRING_get0_data(X) ASN1_STRING_data(X) +#endif +#ifndef EVP_MD_CTX_SIZE +#define EVP_MD_CTX_SIZE sizeof(EVP_MD_CTX) +#endif + +#ifndef DH_set0_pqg +#define DH_set0_pqg(D,P,Q,G) ((D)->p= (P), (D)->g= (G)) +#endif + +#define EVP_CIPHER_CTX_encrypting(ctx) ((ctx)->encrypt) +#define EVP_CIPHER_CTX_SIZE sizeof(EVP_CIPHER_CTX) + +#ifndef HAVE_WOLFSSL +#define OPENSSL_init_ssl(X,Y) SSL_library_init() +#define EVP_MD_CTX_reset(X) EVP_MD_CTX_cleanup(X) +#define EVP_CIPHER_CTX_reset(X) EVP_CIPHER_CTX_cleanup(X) +#define X509_get0_notBefore(X) X509_get_notBefore(X) +#define X509_get0_notAfter(X) X509_get_notAfter(X) +#endif +#endif + +#ifndef TLS1_3_VERSION +#define SSL_CTX_set_ciphersuites(X,Y) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int check_openssl_compatibility(); + +#ifdef __cplusplus +} +#endif diff --git a/include/sslopt-case.h b/include/sslopt-case.h new file mode 100644 index 00000000..11351247 --- /dev/null +++ b/include/sslopt-case.h @@ -0,0 +1,44 @@ +#ifndef SSLOPT_CASE_INCLUDED +#define SSLOPT_CASE_INCLUDED + +/* Copyright (c) 2000, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + case OPT_SSL_KEY: + case OPT_SSL_CERT: + case OPT_SSL_CA: + case OPT_SSL_CAPATH: + case OPT_SSL_CIPHER: + case OPT_SSL_CRL: + case OPT_SSL_CRLPATH: + /* + Enable use of SSL if we are using any ssl option + One can disable SSL later by using --skip-ssl or --ssl=0 + */ + opt_use_ssl= 1; +#if defined (HAVE_WOLFSSL) +#if defined(MYSQL_SERVER) + /* CRL does not work with WolfSSL (server) */ + opt_ssl_crl= NULL; +#endif +#if !defined(_WIN32) || !defined(LIBMARIADB) + /* CRL_PATH does not work with WolfSSL (server) and GnuTLS (client) */ + opt_ssl_crlpath= NULL; +#endif +#endif + break; +#endif +#endif /* SSLOPT_CASE_INCLUDED */ diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h new file mode 100644 index 00000000..63d1a42c --- /dev/null +++ b/include/sslopt-longopts.h @@ -0,0 +1,62 @@ +#ifndef SSLOPT_LONGOPTS_INCLUDED +#define SSLOPT_LONGOPTS_INCLUDED + +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + + {"ssl", OPT_SSL_SSL, + "Enable SSL for connection (automatically enabled with other flags).", + &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, + {"ssl-ca", OPT_SSL_CA, + "CA file in PEM format (check OpenSSL docs, implies --ssl).", + &opt_ssl_ca, &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-capath", OPT_SSL_CAPATH, + "CA directory (check OpenSSL docs, implies --ssl).", + &opt_ssl_capath, &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl).", + &opt_ssl_cert, &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).", + &opt_ssl_cipher, &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).", + &opt_ssl_key, &opt_ssl_key, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-crl", OPT_SSL_CRL, "Certificate revocation list (implies --ssl).", + &opt_ssl_crl, &opt_ssl_crl, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"ssl-crlpath", OPT_SSL_CRLPATH, + "Certificate revocation list path (implies --ssl).", + &opt_ssl_crlpath, &opt_ssl_crlpath, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + {"tls-version", OPT_TLS_VERSION, + "TLS protocol version for secure connection.", + &opt_tls_version, &opt_tls_version, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, + +#ifdef MYSQL_CLIENT + {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT, + "Verify server's \"Common Name\" in its cert against hostname used " + "when connecting. This option is disabled by default.", + &opt_ssl_verify_server_cert, &opt_ssl_verify_server_cert, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#endif +#endif /* HAVE_OPENSSL */ +#endif /* SSLOPT_LONGOPTS_INCLUDED */ diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h new file mode 100644 index 00000000..d263e5db --- /dev/null +++ b/include/sslopt-vars.h @@ -0,0 +1,38 @@ +#ifndef SSLOPT_VARS_INCLUDED +#define SSLOPT_VARS_INCLUDED + +/* Copyright (c) 2000, 2010, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) +#ifdef SSL_VARS_NOT_STATIC +#define SSL_STATIC +#else +#define SSL_STATIC static +#endif +SSL_STATIC my_bool opt_use_ssl = 1; +SSL_STATIC char *opt_ssl_ca = 0; +SSL_STATIC char *opt_ssl_capath = 0; +SSL_STATIC char *opt_ssl_cert = 0; +SSL_STATIC char *opt_ssl_cipher = 0; +SSL_STATIC char *opt_ssl_key = 0; +SSL_STATIC char *opt_ssl_crl = 0; +SSL_STATIC char *opt_ssl_crlpath = 0; +SSL_STATIC char *opt_tls_version = 0; +#ifdef MYSQL_CLIENT +SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; +#endif +#endif +#endif /* SSLOPT_VARS_INCLUDED */ diff --git a/include/t_ctype.h b/include/t_ctype.h new file mode 100644 index 00000000..9164c622 --- /dev/null +++ b/include/t_ctype.h @@ -0,0 +1,255 @@ +/* Copyright (C) 2000 MySQL AB + Use is subject to license terms + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + Copyright (C) 1998, 1999 by Pruet Boonma, all rights reserved. + Copyright (C) 1998 by Theppitak Karoonboonyanan, all rights reserved. + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies. + Smaphan Raruenrom and Pruet Boonma makes no representations about + the suitability of this software for any purpose. It is provided + "as is" without express or implied warranty. +*/ + +/* LC_COLLATE category + Level information */ + +#ifndef _t_ctype_h +#define _t_ctype_h + +#define TOT_LEVELS 5 +#define LAST_LEVEL 4 /* TOT_LEVELS - 1 */ + +#define IGNORE 0 + + +/* level 1 symbols & order */ +enum l1_symbols { + L1_08 = TOT_LEVELS, + L1_18, + L1_28, + L1_38, + L1_48, + L1_58, + L1_68, + L1_78, + L1_88, + L1_98, + L1_A8, + L1_B8, + L1_C8, + L1_D8, + L1_E8, + L1_F8, + L1_G8, + L1_H8, + L1_I8, + L1_J8, + L1_K8, + L1_L8, + L1_M8, + L1_N8, + L1_O8, + L1_P8, + L1_Q8, + L1_R8, + L1_S8, + L1_T8, + L1_U8, + L1_V8, + L1_W8, + L1_X8, + L1_Y8, + L1_Z8, + L1_KO_KAI, + L1_KHO_KHAI, + L1_KHO_KHUAT, + L1_KHO_KHWAI, + L1_KHO_KHON, + L1_KHO_RAKHANG, + L1_NGO_NGU, + L1_CHO_CHAN, + L1_CHO_CHING, + L1_CHO_CHANG, + L1_SO_SO, + L1_CHO_CHOE, + L1_YO_YING, + L1_DO_CHADA, + L1_TO_PATAK, + L1_THO_THAN, + L1_THO_NANGMONTHO, + L1_THO_PHUTHAO, + L1_NO_NEN, + L1_DO_DEK, + L1_TO_TAO, + L1_THO_THUNG, + L1_THO_THAHAN, + L1_THO_THONG, + L1_NO_NU, + L1_BO_BAIMAI, + L1_PO_PLA, + L1_PHO_PHUNG, + L1_FO_FA, + L1_PHO_PHAN, + L1_FO_FAN, + L1_PHO_SAMPHAO, + L1_MO_MA, + L1_YO_YAK, + L1_RO_RUA, + L1_RU, + L1_LO_LING, + L1_LU, + L1_WO_WAEN, + L1_SO_SALA, + L1_SO_RUSI, + L1_SO_SUA, + L1_HO_HIP, + L1_LO_CHULA, + L1_O_ANG, + L1_HO_NOKHUK, + L1_NKHIT, + L1_SARA_A, + L1_MAI_HAN_AKAT, + L1_SARA_AA, + L1_SARA_AM, + L1_SARA_I, + L1_SARA_II, + L1_SARA_UE, + L1_SARA_UEE, + L1_SARA_U, + L1_SARA_UU, + L1_SARA_E, + L1_SARA_AE, + L1_SARA_O, + L1_SARA_AI_MAIMUAN, + L1_SARA_AI_MAIMALAI +}; + +/* level 2 symbols & order */ +enum l2_symbols { + L2_BLANK = TOT_LEVELS, + L2_THAII, + L2_YAMAK, + L2_PINTHU, + L2_GARAN, + L2_TYKHU, + L2_TONE1, + L2_TONE2, + L2_TONE3, + L2_TONE4 +}; + +/* level 3 symbols & order */ +enum l3_symbols { + L3_BLANK = TOT_LEVELS, + L3_SPACE, + L3_NB_SACE, + L3_LOW_LINE, + L3_HYPHEN, + L3_COMMA, + L3_SEMICOLON, + L3_COLON, + L3_EXCLAMATION, + L3_QUESTION, + L3_SOLIDUS, + L3_FULL_STOP, + L3_PAIYAN_NOI, + L3_MAI_YAMOK, + L3_GRAVE, + L3_CIRCUMFLEX, + L3_TILDE, + L3_APOSTROPHE, + L3_QUOTATION, + L3_L_PARANTHESIS, + L3_L_BRACKET, + L3_L_BRACE, + L3_R_BRACE, + L3_R_BRACKET, + L3_R_PARENTHESIS, + L3_AT, + L3_BAHT, + L3_DOLLAR, + L3_FONGMAN, + L3_ANGKHANKHU, + L3_KHOMUT, + L3_ASTERISK, + L3_BK_SOLIDUS, + L3_AMPERSAND, + L3_NUMBER, + L3_PERCENT, + L3_PLUS, + L3_LESS_THAN, + L3_EQUAL, + L3_GREATER_THAN, + L3_V_LINE +}; + +/* level 4 symbols & order */ +enum l4_symbols { + L4_BLANK = TOT_LEVELS, + L4_MIN, + L4_CAP, + L4_EXT +}; + +enum level_symbols { + L_UPRUPR = TOT_LEVELS, + L_UPPER, + L_MIDDLE, + L_LOWER +}; + +#define _is(c) (t_ctype[(c)][LAST_LEVEL]) +#define _level 8 +#define _consnt 16 +#define _ldvowel 32 +#define _fllwvowel 64 +#define _uprvowel 128 +#define _lwrvowel 256 +#define _tone 512 +#define _diacrt1 1024 +#define _diacrt2 2048 +#define _combine 4096 +#define _stone 8192 +#define _tdig 16384 +#define _rearvowel (_fllwvowel | _uprvowel | _lwrvowel) +#define _diacrt (_diacrt1 | _diacrt2) +#define levelof(c) ( _is(c) & _level ) +#define isthai(c) ( (c) >= 128 ) +#define istalpha(c) ( _is(c) & (_consnt|_ldvowel|_rearvowel|\ + _tone|_diacrt1|_diacrt2) ) +#define isconsnt(c) ( _is(c) & _consnt ) +#define isldvowel(c) ( _is(c) & _ldvowel ) +#define isfllwvowel(c) ( _is(c) & _fllwvowel ) +#define ismidvowel(c) ( _is(c) & (_ldvowel|_fllwvowel) ) +#define isuprvowel(c) ( _is(c) & _uprvowel ) +#define islwrvowel(c) ( _is(c) & _lwrvowel ) +#define isuprlwrvowel(c) ( _is(c) & (_lwrvowel | _uprvowel)) +#define isrearvowel(c) ( _is(c) & _rearvowel ) +#define isvowel(c) ( _is(c) & (_ldvowel|_rearvowel) ) +#define istone(c) ( _is(c) & _tone ) +#define isunldable(c) ( _is(c) & (_rearvowel|_tone|_diacrt1|_diacrt2) ) +#define iscombinable(c) ( _is(c) & _combine ) +#define istdigit(c) ( _is(c) & _tdig ) +#define isstone(c) ( _is(c) & _stone ) +#define isdiacrt1(c) ( _is(c) & _diacrt1) +#define isdiacrt2(c) ( _is(c) & _diacrt2) +#define isdiacrt(c) ( _is(c) & _diacrt) + +/* Function prototype called by sql/field.cc */ +void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length); + +#endif diff --git a/include/thr_alarm.h b/include/thr_alarm.h new file mode 100644 index 00000000..e0f3fdd1 --- /dev/null +++ b/include/thr_alarm.h @@ -0,0 +1,115 @@ +/* Copyright (c) 2000, 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Prototypes when using thr_alarm library functions */ + +#ifndef _thr_alarm_h +#define _thr_alarm_h +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef USE_ALARM_THREAD +#define USE_ONE_SIGNAL_HAND /* One must call process_alarm */ +#endif +#ifdef HAVE_rts_threads +#undef USE_ONE_SIGNAL_HAND +#define USE_ALARM_THREAD +#define THR_SERVER_ALARM SIGUSR1 +#else +#define THR_SERVER_ALARM SIGALRM +#endif + +typedef struct st_alarm_info +{ + time_t next_alarm_time; + uint active_alarms; + uint max_used_alarms; +} ALARM_INFO; + +void thr_alarm_info(ALARM_INFO *info); +extern my_bool my_disable_thr_alarm; + +#ifdef _WIN32 +#define DONT_USE_THR_ALARM +#endif +#if defined(DONT_USE_THR_ALARM) + +#define USE_ALARM_THREAD +#undef USE_ONE_SIGNAL_HAND + +typedef my_bool thr_alarm_t; +typedef my_bool ALARM; + +#define thr_alarm_init(A) (*(A))=0 +#define thr_alarm_in_use(A) (*(A) != 0) +#define thr_end_alarm(A) +#define thr_alarm(A,B,C) ((*(A)=1)-1) +/* The following should maybe be (*(A)) */ +#define thr_got_alarm(A) 0 +#define init_thr_alarm(A) +#define thr_alarm_kill(A) +#define resize_thr_alarm(N) +#define end_thr_alarm(A) + +#else +#if defined(_WIN32) +typedef struct st_thr_alarm_entry +{ + UINT_PTR crono; +} thr_alarm_entry; + +#else /* System with posix threads */ + +typedef int thr_alarm_entry; + +#define thr_got_alarm(thr_alarm) (**(thr_alarm)) + +#endif /* _WIN32 */ + +typedef thr_alarm_entry* thr_alarm_t; + +typedef struct st_alarm { + time_t expire_time; + thr_alarm_entry alarmed; /* set when alarm is due */ + pthread_t thread; + my_thread_id thread_id; + uint index_in_queue; + my_bool malloced; +} ALARM; + +extern uint thr_client_alarm; +extern pthread_t alarm_thread; + +#define thr_alarm_init(A) (*(A))=0 +#define thr_alarm_in_use(A) (*(A)!= 0) +void init_thr_alarm(uint max_alarm); +void resize_thr_alarm(uint max_alarms); +my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); +void thr_alarm_kill(my_thread_id thread_id); +void thr_end_alarm(thr_alarm_t *alarmed); +void end_thr_alarm(my_bool free_structures); +sig_handler process_alarm(int); +#ifndef thr_got_alarm +my_bool thr_got_alarm(thr_alarm_t *alrm); +#endif + + +#endif /* DONT_USE_THR_ALARM */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _thr_alarm_h */ diff --git a/include/thr_lock.h b/include/thr_lock.h new file mode 100644 index 00000000..d918d6d7 --- /dev/null +++ b/include/thr_lock.h @@ -0,0 +1,195 @@ +/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, MariaDB Corporation. + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* For use with thr_lock:s */ + +#ifndef _thr_lock_h +#define _thr_lock_h +#ifdef __cplusplus +extern "C" { +#endif +#include <my_pthread.h> +#include <my_list.h> + +struct st_thr_lock; +extern ulong locks_immediate,locks_waited ; + +/* + Important: if a new lock type is added, a matching lock description + must be added to sql_test.cc's lock_descriptions array. +*/ +enum thr_lock_type { TL_IGNORE=-1, + TL_UNLOCK, /* UNLOCK ANY LOCK */ + /* + Parser only! At open_tables() becomes TL_READ or + TL_READ_NO_INSERT depending on the binary log format + (SBR/RBR) and on the table category (log table). + Used for tables that are read by statements which + modify tables. + */ + TL_READ_DEFAULT, + TL_READ, /* Read lock */ + TL_READ_WITH_SHARED_LOCKS, + /* High prior. than TL_WRITE. Allow concurrent insert */ + TL_READ_HIGH_PRIORITY, + /* READ, Don't allow concurrent insert */ + TL_READ_NO_INSERT, + /* READ, but skip locks if found */ + TL_READ_SKIP_LOCKED, + /* + Write lock, but allow other threads to read / write. + Used by BDB tables in MySQL to mark that someone is + reading/writing to the table. + */ + TL_WRITE_ALLOW_WRITE, + /* + WRITE lock used by concurrent insert. Will allow + READ, if one could use concurrent insert on table. + */ + TL_WRITE_CONCURRENT_INSERT, + /* Write used by INSERT DELAYED. Allows READ locks */ + TL_WRITE_DELAYED, + /* + parser only! Late bound low_priority flag. + At open_tables() becomes thd->update_lock_default. + */ + TL_WRITE_DEFAULT, + /* WRITE lock that has lower priority than TL_READ */ + TL_WRITE_LOW_PRIORITY, + /* WRITE, but skip locks if found */ + TL_WRITE_SKIP_LOCKED, + /* Normal WRITE lock */ + TL_WRITE, + /* Abort new lock request with an error */ + TL_WRITE_ONLY}; + +/* + TL_FIRST_WRITE is here to impose some consistency in the sql + layer on determining read/write transactions and to + provide some API compatibility if additional transactions + are added. Above or equal to TL_FIRST_WRITE is a write transaction + while < TL_FIRST_WRITE is a read transaction. +*/ +#define TL_FIRST_WRITE TL_WRITE_ALLOW_WRITE + +enum enum_thr_lock_result { THR_LOCK_SUCCESS= 0, THR_LOCK_ABORTED= 1, + THR_LOCK_WAIT_TIMEOUT= 2, THR_LOCK_DEADLOCK= 3 }; + + +/* Priority for locks */ +#define THR_LOCK_LATE_PRIV 1U /* For locks to be merged with org lock */ +#define THR_LOCK_MERGE_PRIV 2U /* For merge tables */ + +#define THR_UNLOCK_UPDATE_STATUS 1U + +extern ulong max_write_lock_count; +extern my_bool thr_lock_inited; +extern enum thr_lock_type thr_upgraded_concurrent_insert_lock; + +/* + A description of the thread which owns the lock. The address + of an instance of this structure is used to uniquely identify the thread. +*/ + +typedef struct st_thr_lock_info +{ + pthread_t thread; + my_thread_id thread_id; + void *mysql_thd; // THD pointer +} THR_LOCK_INFO; + + +typedef struct st_thr_lock_data { + THR_LOCK_INFO *owner; + struct st_thr_lock_data *next,**prev; + struct st_thr_lock *lock; + mysql_cond_t *cond; + void *status_param; /* Param to status functions */ + void *debug_print_param; /* For error messages */ + struct PSI_table *m_psi; + enum thr_lock_type type; + enum thr_lock_type org_type; /* Cache for MariaDB */ + uint priority; +} THR_LOCK_DATA; + +struct st_lock_list { + THR_LOCK_DATA *data,**last; +}; + +typedef struct st_thr_lock { + LIST list; + mysql_mutex_t mutex; + struct st_lock_list read_wait; + struct st_lock_list read; + struct st_lock_list write_wait; + struct st_lock_list write; + /* write_lock_count is incremented for write locks and reset on read locks */ + ulong write_lock_count; + uint read_no_write_count; + my_bool (*get_status)(void*, my_bool);/* Called when one gets a lock */ + void (*copy_status)(void*,void*); + void (*update_status)(void*); /* Before release of write */ + void (*restore_status)(void*); /* Before release of read */ + my_bool (*start_trans)(void*); /* When all locks are taken */ + my_bool (*check_status)(void *); + void (*fix_status)(void *, void *);/* For thr_merge_locks() */ + const char *name; /* Used for error reporting */ + my_bool allow_multiple_concurrent_insert; +} THR_LOCK; + + +extern LIST *thr_lock_thread_list; +extern mysql_mutex_t THR_LOCK_lock; +struct st_my_thread_var; + +my_bool init_thr_lock(void); /* Must be called once/thread */ +void thr_lock_info_init(THR_LOCK_INFO *info, struct st_my_thread_var *tmp); +void thr_lock_init(THR_LOCK *lock); +void thr_lock_delete(THR_LOCK *lock); +void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, + void *status_param); +void thr_unlock(THR_LOCK_DATA *data, uint unlock_flags); +enum enum_thr_lock_result thr_multi_lock(THR_LOCK_DATA **data, + uint count, THR_LOCK_INFO *owner, + ulong lock_wait_timeout); +void thr_multi_unlock(THR_LOCK_DATA **data,uint count, uint unlock_flags); +void thr_merge_locks(THR_LOCK_DATA **data, uint org_count, uint new_count); +void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock); +my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread); +void thr_print_locks(void); /* For debugging */ +my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type, + ulong lock_wait_timeout); +void thr_downgrade_write_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type); +my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data, + ulong lock_wait_timeout); +void thr_set_lock_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)); + +#ifdef WITH_WSREP + typedef my_bool (* wsrep_thd_is_brute_force_fun)(const MYSQL_THD, my_bool); + typedef my_bool(* wsrep_abort_thd_fun)(MYSQL_THD, MYSQL_THD, my_bool); + typedef my_bool (* wsrep_on_fun)(const MYSQL_THD); + void wsrep_thr_lock_init( + wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun, + my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _thr_lock_h */ diff --git a/include/thr_timer.h b/include/thr_timer.h new file mode 100644 index 00000000..6bca8154 --- /dev/null +++ b/include/thr_timer.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2014 Monty Program Ab + + 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 or later 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* Prototypes when using thr_timer functions */ + +#ifndef THR_TIMER_INCLUDED +#define THR_TIMER_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_timer { + struct timespec expire_time; + ulonglong period; + my_bool expired; + uint index_in_queue; + void (*func)(void*); + void *func_arg; +} thr_timer_t; + +/* Main functions for library */ +my_bool init_thr_timer(uint init_size_for_timer_queue); +void end_thr_timer(); + +/* Functions for handling one timer */ +void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*), + void *arg); +void thr_timer_set_period(thr_timer_t* timer_data, ulonglong microseconds); +my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong microseconds); +void thr_timer_end(thr_timer_t *timer_data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* THR_TIMER_INCLUDED */ diff --git a/include/typelib.h b/include/typelib.h new file mode 100644 index 00000000..dc315dd3 --- /dev/null +++ b/include/typelib.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + + +#ifndef _typelib_h +#define _typelib_h + +#include "my_alloc.h" + +typedef struct st_typelib { /* Different types saved here */ + unsigned int count; /* How many types */ + const char *name; /* Name of typelib */ + const char **type_names; + unsigned int *type_lengths; +} TYPELIB; + +extern my_ulonglong find_typeset(const char *x, TYPELIB *typelib, + int *error_position); +extern int find_type_with_warning(const char *x, TYPELIB *typelib, + const char *option); +#define FIND_TYPE_BASIC 0 +/** makes @c find_type() require the whole name, no prefix */ +#define FIND_TYPE_NO_PREFIX (1U << 0) +/** always implicitly on, so unused, but old code may pass it */ +#define FIND_TYPE_NO_OVERWRITE 0 +/** makes @c find_type() accept a number. Not used either */ +#define FIND_TYPE_ALLOW_NUMBER 0 +/** makes @c find_type() treat ',' and '=' as terminators */ +#define FIND_TYPE_COMMA_TERM (1U << 3) + +extern int find_type(const char *x, const TYPELIB *typelib, unsigned int flags); +extern void make_type(char *to,unsigned int nr,TYPELIB *typelib); +extern const char *get_type(TYPELIB *typelib,unsigned int nr); +extern TYPELIB *copy_typelib(MEM_ROOT *root, const TYPELIB *from); + +extern TYPELIB sql_protocol_typelib; + +my_ulonglong find_set_from_flags(const TYPELIB *lib, unsigned int default_name, + my_ulonglong cur_set, my_ulonglong default_set, + const char *str, unsigned int length, + char **err_pos, unsigned int *err_len); + +#endif /* _typelib_h */ diff --git a/include/violite.h b/include/violite.h new file mode 100644 index 00000000..b823e62b --- /dev/null +++ b/include/violite.h @@ -0,0 +1,284 @@ +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2012, 2020, MariaDB Corporation. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* + * Vio Lite. + * Purpose: include file for Vio that will work with C and C++ + */ + +#ifndef vio_violite_h_ +#define vio_violite_h_ + +#include "my_net.h" /* needed because of struct in_addr */ +#include <mysql/psi/mysql_socket.h> + +/* Simple vio interface in C; The functions are implemented in violite.c */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef __cplusplus +typedef struct st_vio Vio; +#endif /* __cplusplus */ + +enum enum_vio_type +{ + VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE, + VIO_TYPE_SSL + /* see also vio_type_names[] */ +}; +#define FIRST_VIO_TYPE VIO_CLOSED +#define LAST_VIO_TYPE VIO_TYPE_SSL + +/** + VIO I/O events. +*/ +enum enum_vio_io_event +{ + VIO_IO_EVENT_READ, + VIO_IO_EVENT_WRITE, + VIO_IO_EVENT_CONNECT +}; + +struct vio_keepalive_opts +{ + int interval; + int idle; + int probes; +}; + + +#define VIO_TLSv1_0 1 +#define VIO_TLSv1_1 2 +#define VIO_TLSv1_2 4 +#define VIO_TLSv1_3 8 + +#define VIO_LOCALHOST 1U /* a localhost connection */ +#define VIO_BUFFERED_READ 2U /* use buffered read */ +#define VIO_READ_BUFFER_SIZE 16384U /* size of read buffer */ +#define VIO_DESCRIPTION_SIZE 30 /* size of description */ + +Vio* vio_new(my_socket sd, enum enum_vio_type type, uint flags); +Vio* mysql_socket_vio_new(MYSQL_SOCKET mysql_socket, enum enum_vio_type type, uint flags); +#ifdef _WIN32 +Vio* vio_new_win32pipe(HANDLE hPipe); +#else +#define HANDLE void * +#endif /* _WIN32 */ + +void vio_delete(Vio* vio); +int vio_close(Vio* vio); +my_bool vio_reset(Vio* vio, enum enum_vio_type type, + my_socket sd, void *ssl, uint flags); +size_t vio_read(Vio *vio, uchar * buf, size_t size); +size_t vio_read_buff(Vio *vio, uchar * buf, size_t size); +size_t vio_write(Vio *vio, const uchar * buf, size_t size); +int vio_blocking(Vio *vio, my_bool onoff, my_bool *old_mode); +my_bool vio_is_blocking(Vio *vio); +/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible */ +int vio_nodelay(Vio *vio, my_bool on); +int vio_fastsend(Vio *vio); +/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible */ +int vio_keepalive(Vio *vio, my_bool onoff); +int vio_set_keepalive_options(Vio * vio, const struct vio_keepalive_opts *opts); +/* Whenever we should retry the last read/write operation. */ +my_bool vio_should_retry(Vio *vio); +/* Check that operation was timed out */ +my_bool vio_was_timeout(Vio *vio); +/* Short text description of the socket for those, who are curious.. */ +const char* vio_description(Vio *vio); +/* Return the type of the connection */ +enum enum_vio_type vio_type(Vio* vio); +/* Return last error number */ +int vio_errno(Vio*vio); +/* Get socket number */ +my_socket vio_fd(Vio*vio); +/* Remote peer's address and name in text form */ +my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen); +/* Wait for an I/O event notification. */ +int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout); +my_bool vio_is_connected(Vio *vio); +ssize_t vio_pending(Vio *vio); +/* Set timeout for a network operation. */ +extern int vio_timeout(Vio *vio, uint which, int timeout_sec); +extern void vio_set_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)); +/* Connect to a peer. */ +my_bool vio_socket_connect(Vio *vio, struct sockaddr *addr, socklen_t len, + int timeout); + +void vio_get_normalized_ip(const struct sockaddr *src, size_t src_length, struct sockaddr *dst); + +my_bool vio_get_normalized_ip_string(const struct sockaddr *addr, size_t addr_length, + char *ip_string, size_t ip_string_size); + +my_bool vio_is_no_name_error(int err_code); + +int vio_getnameinfo(const struct sockaddr *sa, + char *hostname, size_t hostname_size, + char *port, size_t port_size, + int flags); + +#ifdef HAVE_OPENSSL +/* apple deprecated openssl in MacOSX Lion */ +#ifdef __APPLE__ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +#define HEADER_DES_LOCL_H dummy_something +#define YASSL_MYSQL_COMPATIBLE +#ifndef YASSL_PREFIX +#define YASSL_PREFIX +#endif +/* Set yaSSL to use same type as MySQL do for socket handles */ +typedef my_socket YASSL_SOCKET_T; +#define YASSL_SOCKET_T_DEFINED +#define template _template /* bug in WolfSSL 4.4.0, see also my_crypt.cc */ +#include <openssl/ssl.h> +#undef template +#include <openssl/err.h> +#ifdef DEPRECATED +#undef DEPRECATED +#endif + +enum enum_ssl_init_error +{ + SSL_INITERR_NOERROR= 0, SSL_INITERR_CERT, SSL_INITERR_KEY, + SSL_INITERR_NOMATCH, SSL_INITERR_BAD_PATHS, SSL_INITERR_CIPHERS, + SSL_INITERR_MEMFAIL, SSL_INITERR_DH, SSL_INITERR_PROTOCOL, + SSL_INITERR_LASTERR +}; +const char* sslGetErrString(enum enum_ssl_init_error err); + +struct st_VioSSLFd +{ + SSL_CTX *ssl_context; +}; + +int sslaccept(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); +int sslconnect(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); + +void vio_check_ssl_init(); + +struct st_VioSSLFd +*new_VioSSLConnectorFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher, enum enum_ssl_init_error *error, + const char *crl_file, const char *crl_path); +struct st_VioSSLFd +*new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, + const char *ca_file,const char *ca_path, + const char *cipher, enum enum_ssl_init_error *error, + const char *crl_file, const char *crl_path, + ulonglong tls_version); +void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd); +#endif /* HAVE_OPENSSL */ + +void vio_end(void); + +const char *vio_type_name(enum enum_vio_type vio_type, size_t *len); + +#ifdef __cplusplus +} +#endif + +#if !defined(DONT_MAP_VIO) +#define vio_delete(vio) (vio)->viodelete(vio) +#define vio_errno(vio) (vio)->vioerrno(vio) +#define vio_read(vio, buf, size) ((vio)->read)(vio,buf,size) +#define vio_write(vio, buf, size) ((vio)->write)(vio, buf, size) +#define vio_blocking(vio, set_blocking_mode, old_mode)\ + (vio)->vioblocking(vio, set_blocking_mode, old_mode) +#define vio_is_blocking(vio) (vio)->is_blocking(vio) +#define vio_fastsend(vio) (vio)->fastsend(vio) +#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive) +#define vio_should_retry(vio) (vio)->should_retry(vio) +#define vio_was_timeout(vio) (vio)->was_timeout(vio) +#define vio_close(vio) ((vio)->vioclose)(vio) +#define vio_shutdown(vio,how) ((vio)->shutdown)(vio,how) +#define vio_peer_addr(vio, buf, prt, buflen) (vio)->peer_addr(vio, buf, prt, buflen) +#define vio_io_wait(vio, event, timeout) (vio)->io_wait(vio, event, timeout) +#define vio_is_connected(vio) (vio)->is_connected(vio) +#endif /* !defined(DONT_MAP_VIO) */ + +#ifdef _WIN32 + +/* shutdown(2) flags */ +#ifndef SHUT_RD +#define SHUT_RD SD_RECEIVE +#endif + +#endif + +/* This enumerator is used in parser - should be always visible */ +enum SSL_type +{ + SSL_TYPE_NOT_SPECIFIED= -1, + SSL_TYPE_NONE, + SSL_TYPE_ANY, + SSL_TYPE_X509, + SSL_TYPE_SPECIFIED +}; + +/* HFTODO - hide this if we don't want client in embedded server */ +/* This structure is for every connection on both sides */ +struct st_vio +{ + MYSQL_SOCKET mysql_socket; /* Instrumented socket */ + my_bool localhost; /* Are we from localhost? */ + int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */ + struct sockaddr_storage local; /* Local internet address */ + struct sockaddr_storage remote; /* Remote internet address */ + enum enum_vio_type type; /* Type of connection */ + const char *desc; /* String description */ + char *read_buffer; /* buffer for vio_read_buff */ + char *read_pos; /* start of unfetched data in the + read buffer */ + char *read_end; /* end of unfetched data */ + int read_timeout; /* Timeout value (ms) for read ops. */ + int write_timeout; /* Timeout value (ms) for write ops. */ + /* function pointers. They are similar for socket/SSL/whatever */ + void (*viodelete)(Vio*); + int (*vioerrno)(Vio*); + size_t (*read)(Vio*, uchar *, size_t); + size_t (*write)(Vio*, const uchar *, size_t); + int (*timeout)(Vio*, uint, my_bool); + int (*vioblocking)(Vio*, my_bool, my_bool *); + my_bool (*is_blocking)(Vio*); + int (*viokeepalive)(Vio*, my_bool); + int (*fastsend)(Vio*); + my_bool (*peer_addr)(Vio*, char *, uint16*, size_t); + void (*in_addr)(Vio*, struct sockaddr_storage*); + my_bool (*should_retry)(Vio*); + my_bool (*was_timeout)(Vio*); + int (*vioclose)(Vio*); + my_bool (*is_connected)(Vio*); + int (*shutdown)(Vio *, int); + my_bool (*has_data) (Vio*); + int (*io_wait)(Vio*, enum enum_vio_io_event, int); + my_bool (*connect)(Vio*, struct sockaddr *, socklen_t, int); +#ifdef HAVE_OPENSSL + void *ssl_arg; +#endif +#ifdef _WIN32 + HANDLE hPipe; + OVERLAPPED overlapped; + int shutdown_flag; + void *tp_ctx; /* threadpool context */ +#endif +}; +#endif /* vio_violite_h_ */ diff --git a/include/waiting_threads.h b/include/waiting_threads.h new file mode 100644 index 00000000..5f708f42 --- /dev/null +++ b/include/waiting_threads.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _waiting_threads_h +#define _waiting_threads_h + +#include <my_sys.h> + +#include <lf.h> + +C_MODE_START + +typedef struct st_wt_resource_id WT_RESOURCE_ID; +typedef struct st_wt_resource WT_RESOURCE; + +typedef struct st_wt_resource_type { + my_bool (*compare)(const void *a, const void *b); + const void *(*make_key)(const WT_RESOURCE_ID *id, uint *len); /* not used */ +} WT_RESOURCE_TYPE; + +struct st_wt_resource_id { + ulonglong value; + const WT_RESOURCE_TYPE *type; +}; +/* the below differs from sizeof(WT_RESOURCE_ID) by the amount of padding */ +#define sizeof_WT_RESOURCE_ID (sizeof(ulonglong)+sizeof(void*)) + +#define WT_WAIT_STATS 24 +#define WT_CYCLE_STATS 32 +extern ulonglong wt_wait_table[WT_WAIT_STATS]; +extern uint32 wt_wait_stats[WT_WAIT_STATS+1]; +extern uint32 wt_cycle_stats[2][WT_CYCLE_STATS+1]; +extern uint32 wt_success_stats; + +typedef struct st_wt_thd { + /* + XXX + there's no protection (mutex) against concurrent access of the + dynarray below. it is assumed that a caller will have it anyway + (not to protect this array but to protect its own - caller's - + data structures), and we'll get it for free. A caller needs to + ensure that a blocker won't release a resource before a blocked + thread starts waiting, which is usually done with a mutex. + + If the above assumption is wrong, we'll need to add a mutex here. + */ + DYNAMIC_ARRAY my_resources; + /* + 'waiting_for' is modified under waiting_for->lock, and only by thd itself + 'waiting_for' is read lock-free (using pinning protocol), but a thd object + can read its own 'waiting_for' without any locks or tricks. + */ + WT_RESOURCE *waiting_for; + LF_PINS *pins; + + /* pointers to values */ + const ulong *timeout_short; + const ulong *deadlock_search_depth_short; + const ulong *timeout_long; + const ulong *deadlock_search_depth_long; + + /* + weight relates to the desirability of a transaction being killed if it's + part of a deadlock. In a deadlock situation transactions with lower weights + are killed first. + + Examples of using the weight to implement different selection strategies: + + 1. Latest + Keep all weights equal. + 2. Random + Assign weights at random. + (variant: modify a weight randomly before every lock request) + 3. Youngest + Set weight to -NOW() + 4. Minimum locks + count locks granted in your lock manager, store the value as a weight + 5. Minimum work + depends on the definition of "work". For example, store the number + of rows modifies in this transaction (or a length of REDO log for a + transaction) as a weight. + + It is only statistically relevant and is not protected by any locks. + */ + ulong volatile weight; + /* + 'killed' is indirectly protected by waiting_for->lock because + a killed thread needs to clear its 'waiting_for' and thus needs a lock. + That is a thread needs an exclusive lock to read 'killed' reliably. + But other threads may change 'killed' from 0 to 1, a shared + lock is enough for that. + */ + my_bool killed; +#ifndef DBUG_OFF + const char *name; +#endif +} WT_THD; + +#define WT_TIMEOUT ETIMEDOUT +#define WT_OK 0 +#define WT_DEADLOCK -1 +#define WT_DEPTH_EXCEEDED -2 +#define WT_FREE_TO_GO -3 + +void wt_init(void); +void wt_end(void); +void wt_thd_lazy_init(WT_THD *, const ulong *, const ulong *, const ulong *, const ulong *); +void wt_thd_destroy(WT_THD *); +int wt_thd_will_wait_for(WT_THD *, WT_THD *, const WT_RESOURCE_ID *); +int wt_thd_cond_timedwait(WT_THD *, mysql_mutex_t *); +void wt_thd_release(WT_THD *, const WT_RESOURCE_ID *); +#define wt_thd_release_all(THD) wt_thd_release((THD), 0) +my_bool wt_resource_id_memcmp(const void *, const void *); + +C_MODE_END + +#endif diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h new file mode 100644 index 00000000..22d8d204 --- /dev/null +++ b/include/welcome_copyright_notice.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2011, 2017, Oracle and/or its affiliates. + Copyright (c) 2011, 2017, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef _welcome_copyright_notice_h_ +#define _welcome_copyright_notice_h_ + +#define COPYRIGHT_NOTICE_CURRENT_YEAR "2018" + +/* + This define specifies copyright notice which is displayed by every MySQL + program on start, or on help screen. +*/ +#define ORACLE_WELCOME_COPYRIGHT_NOTICE(first_year) \ + "Copyright (c) " first_year ", " COPYRIGHT_NOTICE_CURRENT_YEAR \ + ", Oracle, MariaDB Corporation Ab and others.\n" + +#endif /* _welcome_copyright_notice_h_ */ diff --git a/include/wqueue.h b/include/wqueue.h new file mode 100644 index 00000000..de7a7170 --- /dev/null +++ b/include/wqueue.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2007, 2008, Sun Microsystems, Inc, + Copyright (c) 2011, 2012, Monty Program Ab + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef WQUEUE_INCLUDED +#define WQUEUE_INCLUDED + +#include <my_pthread.h> + +/* info about requests in a waiting queue */ +typedef struct st_pagecache_wqueue +{ + struct st_my_thread_var *last_thread; /* circular list of waiting + threads */ +} WQUEUE; + +void wqueue_link_into_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); +void wqueue_unlink_from_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); +void wqueue_add_to_queue(WQUEUE *wqueue, struct st_my_thread_var *thread); +void wqueue_add_and_wait(WQUEUE *wqueue, + struct st_my_thread_var *thread, + mysql_mutex_t *lock); +void wqueue_release_queue(WQUEUE *wqueue); +void wqueue_release_one_locktype_from_queue(WQUEUE *wqueue); + +#endif diff --git a/include/wsrep.h b/include/wsrep.h new file mode 100644 index 00000000..e4535dea --- /dev/null +++ b/include/wsrep.h @@ -0,0 +1,74 @@ +/* Copyright 2014 Codership Oy <http://www.codership.com> & SkySQL Ab + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef WSREP_INCLUDED +#define WSREP_INCLUDED + +#include <my_config.h> +#include "log.h" + +#ifdef WITH_WSREP +#define IF_WSREP(A,B) A +#define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A) + +extern ulong wsrep_debug; // wsrep_mysqld.cc +extern void WSREP_LOG(void (*fun)(const char* fmt, ...), const char* fmt, ...); + +#define WSREP_DEBUG(...) \ + if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__) +#define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__) +#define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__) +#define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__) +#define WSREP_UNKNOWN(fmt, ...) WSREP_ERROR("UNKNOWN: " fmt, ##__VA_ARGS__) + +#define WSREP_LOG_CONFLICT_THD(thd, role) \ + WSREP_INFO("%s: \n " \ + " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \ + " SQL: %s", \ + role, \ + thd_get_thread_id(thd), \ + wsrep_thd_client_mode_str(thd), \ + wsrep_thd_client_state_str(thd), \ + wsrep_thd_transaction_state_str(thd), \ + wsrep_thd_trx_seqno(thd), \ + wsrep_thd_query(thd) \ + ); + +#define WSREP_LOG_CONFLICT(bf_thd, victim_thd, bf_abort) \ + if (wsrep_debug || wsrep_log_conflicts) \ + { \ + WSREP_INFO("cluster conflict due to %s for threads:", \ + (bf_abort) ? "high priority abort" : "certification failure" \ + ); \ + if (bf_thd) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \ + if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \ + WSREP_INFO("context: %s:%d", __FILE__, __LINE__); \ + } + + +#else /* !WITH_WSREP */ + +/* These macros are needed to compile MariaDB without WSREP support + * (e.g. embedded) */ + +#define IF_WSREP(A,B) B +//#define DBUG_ASSERT_IF_WSREP(A) +#define WSREP_DEBUG(...) +//#define WSREP_INFO(...) +//#define WSREP_WARN(...) +#define WSREP_ERROR(...) +#endif /* WITH_WSREP */ + +#endif /* WSREP_INCLUDED */ |