diff options
Diffstat (limited to 'include')
50 files changed, 1189 insertions, 547 deletions
diff --git a/include/aria_backup.h b/include/aria_backup.h new file mode 100644 index 00000000000..1a1c437d0b9 --- /dev/null +++ b/include/aria_backup.h @@ -0,0 +1,37 @@ +/* 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 */ + +/* 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; + my_bool checksum; + my_bool transactional; + /* This is true if the table can be copied without any locks */ + my_bool online_backup_safe; +} 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/atomic/gcc_sync.h b/include/atomic/gcc_sync.h deleted file mode 100644 index 82eea35b2ce..00000000000 --- a/include/atomic/gcc_sync.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef GCC_SYNC_INCLUDED -#define GCC_SYNC_INCLUDED - -/* Copyright (c) 2008, 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-1301 USA */ - -/* Old GCC __sync builtins introduced in GCC 4.1 */ - -static inline int my_atomic_cas32(int32 volatile *a, int32 *cmp, int32 set) -{ - int32 cmp_val= *cmp; - int32 sav= __sync_val_compare_and_swap(a, cmp_val, set); - int ret= (sav == cmp_val); - if (!ret) - *cmp = sav; - return ret; -} - -static inline int my_atomic_cas64(int64 volatile *a, int64 *cmp, int64 set) -{ - int64 cmp_val= *cmp; - int64 sav= __sync_val_compare_and_swap(a, cmp_val, set); - int ret= (sav == cmp_val); - if (!ret) - *cmp = sav; - return ret; -} - -static inline int my_atomic_casptr(void * volatile *a, void **cmp, void *set) -{ - void *cmp_val= *cmp; - void *sav= __sync_val_compare_and_swap(a, cmp_val, set); - int ret= (sav == cmp_val); - if (!ret) - *cmp = sav; - return ret; -} - -static inline int32 my_atomic_add32(int32 volatile *a, int32 v) -{ - return __sync_fetch_and_add(a, v); -} - -static inline int64 my_atomic_add64(int64 volatile *a, int64 v) -{ - return __sync_fetch_and_add(a, v); -} - -static inline int32 my_atomic_fas32(int32 volatile *a, int32 v) -{ - return __sync_lock_test_and_set(a, v); -} - -static inline int64 my_atomic_fas64(int64 volatile *a, int64 v) -{ - return __sync_lock_test_and_set(a, v); -} - -static inline void * my_atomic_fasptr(void * volatile *a, void * v) -{ - return __sync_lock_test_and_set(a, v); -} - -static inline int32 my_atomic_load32(int32 volatile *a) -{ - return __sync_fetch_and_or(a, 0); -} - -static inline int64 my_atomic_load64(int64 volatile *a) -{ - return __sync_fetch_and_or(a, 0); -} - -static inline void* my_atomic_loadptr(void * volatile *a) -{ - return __sync_fetch_and_or(a, 0); -} - -static inline void my_atomic_store32(int32 volatile *a, int32 v) -{ - (void) __sync_lock_test_and_set(a, v); -} - -static inline void my_atomic_store64(int64 volatile *a, int64 v) -{ - (void) __sync_lock_test_and_set(a, v); -} - -static inline void my_atomic_storeptr(void * volatile *a, void *v) -{ - (void) __sync_lock_test_and_set(a, v); -} - -#endif /* GCC_SYNC_INCLUDED */ diff --git a/include/ilist.h b/include/ilist.h index f0d15054ab8..6e7219937dd 100644 --- a/include/ilist.h +++ b/include/ilist.h @@ -16,7 +16,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ -#pragma once +#ifndef ILIST_H +#define ILIST_H #include "my_dbug.h" @@ -26,14 +27,17 @@ // Derive your class from this struct to insert to a linked list. template <class Tag= void> struct ilist_node { - ilist_node() + ilist_node() noexcept #ifndef DBUG_OFF : next(NULL), prev(NULL) #endif { } - ilist_node(ilist_node *next, ilist_node *prev) : next(next), prev(prev) {} + ilist_node(ilist_node *next, ilist_node *prev) noexcept + : next(next), prev(prev) + { + } ilist_node *next; ilist_node *prev; @@ -71,42 +75,43 @@ public: typedef T *pointer; typedef T &reference; - Iterator(ListNode *node) : node_(node) { DBUG_ASSERT(node_ != NULL); } + Iterator(ListNode *node) noexcept : node_(node) + { DBUG_ASSERT(node_ != nullptr); } - Iterator &operator++() + Iterator &operator++() noexcept { node_= node_->next; - DBUG_ASSERT(node_ != NULL); + DBUG_ASSERT(node_ != nullptr); return *this; } - Iterator operator++(int) + Iterator operator++(int) noexcept { Iterator tmp(*this); operator++(); return tmp; } - Iterator &operator--() + Iterator &operator--() noexcept { node_= node_->prev; DBUG_ASSERT(node_); return *this; } - Iterator operator--(int) + Iterator operator--(int) noexcept { Iterator tmp(*this); operator--(); return tmp; } - reference operator*() { return *static_cast<pointer>(node_); } - pointer operator->() { return static_cast<pointer>(node_); } + reference operator*() noexcept { return *static_cast<pointer>(node_); } + pointer operator->() noexcept { return static_cast<pointer>(node_); } - friend bool operator==(const Iterator &lhs, const Iterator &rhs) + friend bool operator==(const Iterator &lhs, const Iterator &rhs) noexcept { return lhs.node_ == rhs.node_; } - friend bool operator!=(const Iterator &lhs, const Iterator &rhs) + friend bool operator!=(const Iterator &lhs, const Iterator &rhs) noexcept { return !(lhs == rhs); } @@ -117,30 +122,36 @@ public: friend class ilist; }; - ilist() : sentinel_(&sentinel_, &sentinel_) {} + ilist() noexcept : sentinel_(&sentinel_, &sentinel_) {} - reference front() { return *begin(); } - reference back() { return *--end(); } - const_reference front() const { return *begin(); } - const_reference back() const { return *--end(); } + 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() { return iterator(sentinel_.next); } - const_iterator begin() const + iterator begin() noexcept { return iterator(sentinel_.next); } + const_iterator begin() const noexcept { return iterator(const_cast<ListNode *>(sentinel_.next)); } - iterator end() { return iterator(&sentinel_); } - const_iterator end() const + iterator end() noexcept { return iterator(&sentinel_); } + const_iterator end() const noexcept { return iterator(const_cast<ListNode *>(&sentinel_)); } - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const { return reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return reverse_iterator(begin()); } + 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 { return sentinel_.next == &sentinel_; } + bool empty() const noexcept { return sentinel_.next == &sentinel_; } // Not implemented because it's O(N) // size_type size() const @@ -148,13 +159,13 @@ public: // return static_cast<size_type>(std::distance(begin(), end())); // } - void clear() + void clear() noexcept { sentinel_.next= &sentinel_; sentinel_.prev= &sentinel_; } - iterator insert(iterator pos, reference value) + iterator insert(iterator pos, reference value) noexcept { ListNode *curr= pos.node_; ListNode *prev= pos.node_->prev; @@ -168,7 +179,7 @@ public: return iterator(&value); } - iterator erase(iterator pos) + iterator erase(iterator pos) noexcept { ListNode *prev= pos.node_->prev; ListNode *next= pos.node_->next; @@ -178,22 +189,22 @@ public: #ifndef DBUG_OFF ListNode *curr= pos.node_; - curr->prev= NULL; - curr->next= NULL; + curr->prev= nullptr; + curr->next= nullptr; #endif return next; } - void push_back(reference value) { insert(end(), value); } - void pop_back() { erase(end()); } + void push_back(reference value) noexcept { insert(end(), value); } + void pop_back() noexcept { erase(end()); } - void push_front(reference value) { insert(begin(), value); } - void pop_front() { erase(begin()); } + 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) { erase(iterator(&value)); } + void remove(reference value) noexcept { erase(iterator(&value)); } private: ListNode sentinel_; @@ -219,36 +230,38 @@ public: typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const iterator> const_reverse_iterator; - sized_ilist() : size_(0) {} + sized_ilist() noexcept : size_(0) {} - size_type size() const { return size_; } + size_type size() const noexcept { return size_; } - void clear() + void clear() noexcept { BASE::clear(); size_= 0; } - iterator insert(iterator pos, reference value) + iterator insert(iterator pos, reference value) noexcept { ++size_; return BASE::insert(pos, value); } - iterator erase(iterator pos) + iterator erase(iterator pos) noexcept { --size_; return BASE::erase(pos); } - void push_back(reference value) { insert(BASE::end(), value); } - void pop_back() { erase(BASE::end()); } + void push_back(reference value) noexcept { insert(BASE::end(), value); } + void pop_back() noexcept { erase(BASE::end()); } - void push_front(reference value) { insert(BASE::begin(), value); } - void pop_front() { erase(BASE::begin()); } + void push_front(reference value) noexcept { insert(BASE::begin(), value); } + void pop_front() noexcept { erase(BASE::begin()); } - void remove(reference value) { erase(iterator(&value)); } + 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 index fed85b516d9..b6add6d13a3 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -174,11 +174,11 @@ enum json_value_types { JSON_VALUE_OBJECT=1, JSON_VALUE_ARRAY=2, - JSON_VALUE_STRING, - JSON_VALUE_NUMBER, - JSON_VALUE_TRUE, - JSON_VALUE_FALSE, - JSON_VALUE_NULL + JSON_VALUE_STRING=3, + JSON_VALUE_NUMBER=4, + JSON_VALUE_TRUE=5, + JSON_VALUE_FALSE=6, + JSON_VALUE_NULL=7 }; @@ -423,10 +423,15 @@ int json_path_parts_compare( int json_path_compare(const json_path_t *a, const json_path_t *b, enum json_value_types vt); +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); #ifdef __cplusplus } #endif #endif /* JSON_LIB_INCLUDED */ - diff --git a/include/lf.h b/include/lf.h index 10a60c5c949..88ac644c349 100644 --- a/include/lf.h +++ b/include/lf.h @@ -17,7 +17,6 @@ #define INCLUDE_LF_INCLUDED #include <my_atomic.h> -#include <my_cpu.h> C_MODE_START @@ -166,6 +165,8 @@ void *lf_hash_search_using_hash_value(LF_HASH *hash, LF_PINS *pins, 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() diff --git a/include/m_ctype.h b/include/m_ctype.h index 1cdff1f54cc..0f6e6a11666 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -362,7 +362,6 @@ 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; -extern MY_COLLATION_HANDLER my_collation_ucs2_uca_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 *, @@ -872,14 +871,6 @@ 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_strnxfrm_unicode(CHARSET_INFO *, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags); - -size_t my_strnxfrm_unicode_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 *, diff --git a/include/m_string.h b/include/m_string.h index e967f140dc4..2747a9a7a9f 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -99,7 +99,7 @@ extern char *strmake(char *dst,const char *src,size_t length); #define strmake_buf(D,S) strmake(D, S, sizeof(D) - 1) #else #define strmake_buf(D,S) ({ \ - typeof (D) __x __attribute__((unused)) = { 2 }; \ + __typeof__ (D) __x __attribute__((unused)) = { 2 }; \ strmake(D, S, sizeof(D) - 1); \ }) #endif diff --git a/include/maria.h b/include/maria.h index 880b7367c0b..a946363c57b 100644 --- a/include/maria.h +++ b/include/maria.h @@ -305,7 +305,7 @@ extern int maria_rsame_with_pos(MARIA_HA *file, uchar *record, int inx, MARIA_RECORD_POS pos); extern int maria_update(MARIA_HA *file, const uchar *old, const uchar *new_record); -extern int maria_write(MARIA_HA *file, uchar *buff); +extern int maria_write(MARIA_HA *file, const uchar *buff); extern MARIA_RECORD_POS maria_position(MARIA_HA *file); extern int maria_status(MARIA_HA *info, MARIA_INFO *x, uint flag); extern int maria_lock_database(MARIA_HA *file, int lock_type); @@ -396,6 +396,7 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves); void maria_versioning(MARIA_HA *info, my_bool versioning); void maria_ignore_trids(MARIA_HA *info); uint maria_max_key_length(void); +my_bool maria_too_big_key_for_sort(MARIA_KEYDEF *key, ha_rows rows); #define maria_max_key_segments() HA_MAX_KEY_SEG /* fulltext functions */ diff --git a/include/my_atomic.h b/include/my_atomic.h index 19983daed04..81da9e35cf9 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -2,6 +2,7 @@ #define MY_ATOMIC_INCLUDED /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2018, 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 @@ -112,8 +113,6 @@ #include "atomic/solaris.h" #elif defined(HAVE_GCC_C11_ATOMICS) #include "atomic/gcc_builtins.h" -#elif defined(HAVE_GCC_ATOMIC_BUILTINS) -#include "atomic/gcc_sync.h" #endif #if SIZEOF_LONG == 4 @@ -170,5 +169,4 @@ #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 00000000000..64835e30ca7 --- /dev/null +++ b/include/my_atomic_wrapper.h @@ -0,0 +1,60 @@ +/* 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 */ + +#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() {} + + operator Type() const { return m.load(std::memory_order_relaxed); } + Type operator=(const Type val) + { m.store(val, std::memory_order_relaxed); return val; } + Type operator=(const Atomic_relaxed<Type> &rhs) { return *this= Type{rhs}; } + 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); } + 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_base.h b/include/my_base.h index 4c5b00649cc..44af7b45075 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -99,7 +99,8 @@ enum ha_key_alg { 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_FULLTEXT= 4, /* FULLTEXT (MyISAM tables) */ + HA_KEY_ALG_LONG_HASH= 5 /* long BLOB keys */ }; /* Storage media types */ @@ -631,7 +632,13 @@ 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) */ - uint range_flag; /* key range flags see above */ + /* + 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; diff --git a/include/my_bit.h b/include/my_bit.h index 74469b5b899..7a408bd0535 100644 --- a/include/my_bit.h +++ b/include/my_bit.h @@ -122,6 +122,14 @@ 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 ((2U << used) - 1); +} C_MODE_END #endif /* MY_BIT_INCLUDED */ diff --git a/include/my_compare.h b/include/my_compare.h index bd1a7bd1f34..9ae6c9582fb 100644 --- a/include/my_compare.h +++ b/include/my_compare.h @@ -127,30 +127,32 @@ extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, const uchar *a); #endif /** - Return values of index_cond_func_xxx functions. - - 0=ICP_NO_MATCH - index tuple doesn't satisfy the pushed index condition (the - engine should discard the tuple and go to the next one) - 1=ICP_MATCH - index tuple satisfies the pushed index condition (the - engine should fetch and return the record) - 2=ICP_OUT_OF_RANGE - index tuple is out range that we're scanning, e.g. this - if we're scanning "t.key BETWEEN 10 AND 20" and got a - "t.key=21" tuple (the engine should stop scanning and - return HA_ERR_END_OF_FILE right away). - 3=ICP_ABORTED_BY_USER - engine must stop scanning and should return - HA_ERR_ABORTED_BY_USER right away - -1= ICP_ERROR - Reserved for internal errors in engines. Should not be - returned by index_cond_func_xxx + 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 statisfied. 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 icp_result { - ICP_ERROR=-1, - ICP_NO_MATCH=0, - ICP_MATCH=1, - ICP_OUT_OF_RANGE=2, - ICP_ABORTED_BY_USER=3 -} ICP_RESULT; - -typedef ICP_RESULT (*index_cond_func_t)(void *param); +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_counter.h b/include/my_counter.h new file mode 100644 index 00000000000..c5cbe296df0 --- /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() {} + + 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 index 0e37eafe60e..b7d7008a8e3 100644 --- a/include/my_cpu.h +++ b/include/my_cpu.h @@ -1,6 +1,6 @@ #ifndef MY_CPU_INCLUDED #define MY_CPU_INCLUDED -/* Copyright (c) 2013, MariaDB foundation Ab and SkySQL +/* 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 @@ -50,6 +50,13 @@ # define HAVE_PAUSE_INSTRUCTION /* added in Intel Pentium 4 */ #endif +#ifdef _WIN32 +#elif defined HAVE_PAUSE_INSTRUCTION +#elif defined(_ARCH_PWR8) +#else +# include "my_atomic.h" +#endif + static inline void MY_RELAX_CPU(void) { #ifdef _WIN32 diff --git a/include/my_getopt.h b/include/my_getopt.h index 72ce03d5654..f0cefb35b87 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -106,6 +106,7 @@ 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 int handle_options (int *argc, char ***argv, diff --git a/include/my_global.h b/include/my_global.h index b96a04f4566..ae8835a2a50 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -133,11 +133,6 @@ #define F_UNLCK 3 #define F_TO_EOF 0x3FFFFFFF -/* Shared memory and named pipe connections are supported. */ -#define HAVE_SMEM 1 -#define HAVE_NAMED_PIPE 1 -#define shared_memory_buffer_length 16000 -#define default_shared_memory_base_name "MYSQL" #endif /* _WIN32*/ @@ -1001,7 +996,6 @@ typedef struct st_mysql_lex_string LEX_STRING; #if defined(__WIN__) #define socket_errno WSAGetLastError() #define SOCKET_EINTR WSAEINTR -#define SOCKET_EAGAIN WSAEINPROGRESS #define SOCKET_ETIMEDOUT WSAETIMEDOUT #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK #define SOCKET_EADDRINUSE WSAEADDRINUSE @@ -1196,8 +1190,6 @@ typedef struct { const char *dli_fname, dli_fbase; } Dl_info; /* 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_SMEM /* No shared memory */ - #else #define HAVE_REPLICATION #define HAVE_EXTERNAL_CLIENT diff --git a/include/my_pthread.h b/include/my_pthread.h index bff36072b71..81dd63ee331 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -23,8 +23,6 @@ #define ETIME ETIMEDOUT /* For FreeBSD */ #endif -#include <my_atomic.h> - #ifdef __cplusplus #define EXTERNC extern "C" extern "C" { @@ -191,7 +189,19 @@ extern int my_pthread_create_detached; int sigwait(sigset_t *set, int *sig); #endif -#define my_sigwait(A,B) sigwait((A),(B)) +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 +#define SI_KERNEL 128 + *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)) @@ -806,26 +816,6 @@ extern uint thd_lib_detected; #define statistic_sub(V,C,L) (V)-=(C) #endif /* SAFE_STATISTICS */ -static inline void thread_safe_increment32(int32 *value) -{ - (void) my_atomic_add32_explicit(value, 1, MY_MEMORY_ORDER_RELAXED); -} - -static inline void thread_safe_decrement32(int32 *value) -{ - (void) my_atomic_add32_explicit(value, -1, MY_MEMORY_ORDER_RELAXED); -} - -static inline void thread_safe_increment64(int64 *value) -{ - (void) my_atomic_add64_explicit(value, 1, MY_MEMORY_ORDER_RELAXED); -} - -static inline void thread_safe_decrement64(int64 *value) -{ - (void) my_atomic_add64_explicit(value, -1, MY_MEMORY_ORDER_RELAXED); -} - /* No locking needed, the counter is owned by the thread */ diff --git a/include/my_rdtsc.h b/include/my_rdtsc.h index df421225f4f..33d722764d4 100644 --- a/include/my_rdtsc.h +++ b/include/my_rdtsc.h @@ -1,5 +1,5 @@ /* Copyright (c) 2008 MySQL AB, 2009 Sun Microsystems, Inc. - Use is subject to license terms. + 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 @@ -23,6 +23,20 @@ #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. */ @@ -62,12 +76,113 @@ 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 + guarenteed to be active. + + 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 + --------- + 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. */ -ulonglong my_timer_cycles(void); +static inline ulonglong my_timer_cycles(void) +{ +# if __has_builtin(__builtin_readcyclecounter) && !defined (__aarch64__) + return __builtin_readcyclecounter(); +# elif defined _WIN32 || defined __i386__ || defined __x86_64__ + return __rdtsc(); +# elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) + return (ulonglong) __getReg(_IA64_REG_AR_ITC); /* (3116) */ +#elif defined(__GNUC__) && defined(__ia64__) + { + ulonglong result; + __asm __volatile__ ("mov %0=ar.itc" : "=r" (result)); + return result; + } +#elif defined __GNUC__ && defined __powerpc__ + return __builtin_ppc_get_timebase(); +#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) + { + ulonglong result; + __asm __volatile__ ("rd %%tick,%0" : "=r" (result)); + return result; + } +#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) + { + 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__) + /* covers both s390 and s390x */ + { + ulonglong result; + __asm__ __volatile__ ("stck %0" : "=Q" (result) : : "cc"); + return result; + } +#elif defined(__GNUC__) && defined (__aarch64__) + { + ulonglong result; + __asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (result)); + return result; + } +#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) + /* gethrtime may appear as either cycle or nanosecond counter */ + return (ulonglong) gethrtime(); +#else + return 0; +#endif +} /** - A namoseconds timer. + A nanosecond timer. @return the current timer value, in nanoseconds. */ ulonglong my_timer_nanoseconds(void); @@ -98,34 +213,24 @@ void my_timer_init(MY_TIMER_INFO *mti); C_MODE_END -#define MY_TIMER_ROUTINE_ASM_X86 1 -#define MY_TIMER_ROUTINE_ASM_X86_64 2 -#define MY_TIMER_ROUTINE_RDTSCLL 3 -#define MY_TIMER_ROUTINE_ASM_X86_WIN 4 #define MY_TIMER_ROUTINE_RDTSC 5 #define MY_TIMER_ROUTINE_ASM_IA64 6 -#define MY_TIMER_ROUTINE_ASM_PPC 7 -#define MY_TIMER_ROUTINE_SGI_CYCLE 8 +#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_NXGETTIME 12 #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_PPC64 19 -#define MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC64 20 -#define MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC32 21 -#define MY_TIMER_ROUTINE_ASM_SUNPRO_I386 22 #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_SUNPRO_X86_64 27 #define MY_TIMER_ROUTINE_ASM_S390 28 +#define MY_TIMER_ROUTINE_AARCH64 29 #endif diff --git a/include/my_sys.h b/include/my_sys.h index 60f5613eec1..d3fdc3657a9 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -104,13 +104,12 @@ typedef struct my_aio_result { #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_WAITTANG 0 /* Wait for a user action */ -#define ME_NOREFRESH 64U /* Write the error message to error log */ -#define ME_NOINPUT 0 /* Don't use the input library */ -#define ME_JUST_INFO 1024U /**< not error but just info */ -#define ME_JUST_WARNING 2048U /**< not error but just warning */ -#define ME_FATALERROR 4096U /* Fatal statement error */ +#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' */ @@ -331,7 +330,7 @@ typedef struct st_record_cache /* Used when caching records */ enum file_type { UNOPEN = 0, FILE_BY_OPEN, FILE_BY_CREATE, STREAM_BY_FOPEN, STREAM_BY_FDOPEN, - FILE_BY_MKSTEMP, FILE_BY_DUP + FILE_BY_O_TMPFILE, FILE_BY_MKSTEMP, FILE_BY_DUP }; struct st_my_file_info @@ -911,6 +910,7 @@ static inline char *safe_strdup_root(MEM_ROOT *root, const char *str) } 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, @@ -996,6 +996,16 @@ 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() @@ -1062,13 +1072,6 @@ extern void thd_increment_net_big_packet_count(void *thd, size_t length); #ifdef __WIN__ extern my_bool have_tcpip; /* Is set if tcpip is used */ -/* implemented in my_windac.c */ - -int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror, - DWORD owner_rights, DWORD everybody_rights); - -void my_security_attr_free(SECURITY_ATTRIBUTES *sa); - /* implemented in my_conio.c */ char* my_cgets(char *string, size_t clen, size_t* plen); diff --git a/include/my_time.h b/include/my_time.h index 7c8f3ce909b..b7b54db5586 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -27,7 +27,7 @@ C_MODE_START -extern ulonglong log_10_int[20]; +extern MYSQL_PLUGIN_IMPORT ulonglong log_10_int[20]; extern uchar days_in_month[]; #define MY_TIME_T_MAX LONG_MAX @@ -57,22 +57,20 @@ extern uchar days_in_month[]; /* Flags to str_to_datetime */ -/* - TIME_FUZZY_DATES is used for the result will only be used for comparison - purposes. Conversion is as relaxed as possible. -*/ -#define TIME_FUZZY_DATES 1U -#define TIME_DATETIME_ONLY 2U -#define TIME_TIME_ONLY 4U -#define TIME_NO_ZERO_IN_DATE (1UL << 23) /* == MODE_NO_ZERO_IN_DATE */ -#define TIME_NO_ZERO_DATE (1UL << 24) /* == MODE_NO_ZERO_DATE */ -#define TIME_INVALID_DATES (1UL << 25) /* == MODE_INVALID_DATES */ +#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) +#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) @@ -81,6 +79,16 @@ extern uchar days_in_month[]; /* 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 @@ -100,35 +108,46 @@ 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_time(const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong flag, MYSQL_TIME_STATUS *status); -my_bool str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong flags, MYSQL_TIME_STATUS *status); -longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res, - ulonglong flags, int *was_cut); - -static inline -longlong double_to_datetime(double nr, MYSQL_TIME *ltime, ulonglong flags, int *cut) -{ - if (nr < 0 || nr > (double)LONGLONG_MAX) - nr= (double)LONGLONG_MAX; - return number_to_datetime((longlong) floor(nr), - (ulong)((nr-floor(nr))*TIME_SECOND_PART_FACTOR), - ltime, flags, 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); -int number_to_time(my_bool neg, ulonglong nr, ulong sec_part, - MYSQL_TIME *ltime, 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 *); @@ -191,6 +210,7 @@ void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type); #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); @@ -213,9 +233,16 @@ 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; } static inline void my_timeval_trunc(struct timeval *tv, uint decimals) { diff --git a/include/myisam.h b/include/myisam.h index 3138dc832f7..f2e31bb9f60 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -276,7 +276,7 @@ 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,uchar *buff); +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); @@ -430,6 +430,7 @@ 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 } diff --git a/include/myisammrg.h b/include/myisammrg.h index fe229a85cb0..76286000ff5 100644 --- a/include/myisammrg.h +++ b/include/myisammrg.h @@ -106,7 +106,7 @@ 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,uchar *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, diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index e084b6becec..484287db98d 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -75,7 +75,7 @@ typedef struct st_mysql_xid MYSQL_XID; #define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104 /* MariaDB plugin interface version */ -#define MARIA_PLUGIN_INTERFACE_VERSION 0x010d +#define MARIA_PLUGIN_INTERFACE_VERSION 0x010e /* The allowable types of plugins diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 89f7dcc36c4..c5ae678e82a 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +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); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_auth.h b/include/mysql/plugin_auth.h index 6741283d5bd..ae9c9368f15 100644 --- a/include/mysql/plugin_auth.h +++ b/include/mysql/plugin_auth.h @@ -27,7 +27,7 @@ #include <mysql/plugin.h> -#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0201 +#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0202 #include <mysql/plugin_auth_common.h> @@ -60,7 +60,8 @@ typedef struct st_mysql_server_auth_info /** A corresponding column value from the mysql.user table for the - matching account name + matching account name or the preprocessed value, if preprocess_hash + method is not NULL */ const char *auth_string; @@ -130,6 +131,47 @@ struct st_mysql_auth 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. + */ + 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 diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index e515699cad6..41cb7d075c4 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +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); struct st_mysql_xid { long formatID; long gtrid_length; @@ -561,4 +606,8 @@ 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_encryption.h.pp b/include/mysql/plugin_encryption.h.pp index 7defe0aec2c..6597decfbef 100644 --- a/include/mysql/plugin_encryption.h.pp +++ b/include/mysql/plugin_encryption.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +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); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index a36f51e74e1..bd1cfc7b68b 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +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); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_password_validation.h b/include/mysql/plugin_password_validation.h index ddc9387c72e..23d2c884012 100644 --- a/include/mysql/plugin_password_validation.h +++ b/include/mysql/plugin_password_validation.h @@ -42,8 +42,8 @@ struct st_mariadb_password_validation Function provided by the plugin which should perform password validation and return 0 if the password has passed the validation. */ - int (*validate_password)(MYSQL_CONST_LEX_STRING *username, - MYSQL_CONST_LEX_STRING *password); + int (*validate_password)(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password); }; #ifdef __cplusplus diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp index 9701ad1b92f..2f9d2299c1f 100644 --- a/include/mysql/plugin_password_validation.h.pp +++ b/include/mysql/plugin_password_validation.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +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); struct st_mysql_xid { long formatID; long gtrid_length; @@ -531,6 +576,6 @@ void thd_wakeup_subsequent_commits(void* thd, int wakeup_error); struct st_mariadb_password_validation { int interface_version; - int (*validate_password)(MYSQL_CONST_LEX_STRING *username, - MYSQL_CONST_LEX_STRING *password); + int (*validate_password)(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password); }; diff --git a/include/mysql/service_json.h b/include/mysql/service_json.h new file mode 100644 index 00000000000..141b76279a5 --- /dev/null +++ b/include/mysql/service_json.h @@ -0,0 +1,117 @@ +/* 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 + + Esports JSON parsing methods for plugins to use. + + Fuctions of the service: + js_type - returns the type of the JSON argument, + and the parsed value if it's scalar (not object or array) + + js_get_array_item - expecs JSON array as an argument, + and returns the n_item's item's type and value + Returns JSV_NOTHING type if the array is shorter + than n_item and the actual length of the array in v_len. + + js_get_object_key - expects JSON object as an argument, + searches for a key in the object, return it's type and value. + JSV_NOTHING if no such key found, the number of keys + in v_len. + + js_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_my_crypt.h b/include/mysql/service_my_crypt.h index de4a8bb69da..930d12a7dd1 100644 --- a/include/mysql/service_my_crypt.h +++ b/include/mysql/service_my_crypt.h @@ -45,7 +45,7 @@ extern "C" { /* The max key length of all supported algorithms */ #define MY_AES_MAX_KEY_LENGTH 32 -#define MY_AES_CTX_SIZE 512 +#define MY_AES_CTX_SIZE 640 enum my_aes_mode { MY_AES_ECB, MY_AES_CBC diff --git a/include/mysql/service_my_print_error.h b/include/mysql/service_my_print_error.h index 64e875d83ca..74ba6a2adb8 100644 --- a/include/mysql/service_my_print_error.h +++ b/include/mysql/service_my_print_error.h @@ -32,10 +32,11 @@ extern "C" { #include <stdlib.h> #endif -#define ME_ERROR_LOG 64 /* Write the message to the error log */ -#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 */ +#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, ...); @@ -50,11 +51,9 @@ extern struct my_print_error_service_st { #define my_printv_error(A,B,C,D) my_print_error_service->my_printv_error_func(A,B,C,D) #else -#ifndef MY_ERROR_DEFINED 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 /* MY_ERROR_DEFINED */ #endif /* MYSQL_DYNAMIC_PLUGIN */ #ifdef __cplusplus diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index a08349cd3cf..0a06445de00 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -1,5 +1,20 @@ #ifndef MYSQL_SERVICE_WSREP_INCLUDED -/* Copyright (c) 2015 MariaDB Corporation Ab +#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 @@ -21,162 +36,101 @@ Interface to WSREP functionality in the server. For engines that want to support galera. */ - +#include <my_pthread.h> #ifdef __cplusplus -extern "C" { #endif -enum wsrep_conflict_state { - NO_CONFLICT, - MUST_ABORT, - ABORTING, - ABORTED, - MUST_REPLAY, - REPLAYING, - RETRY_AUTOCOMMIT, - CERT_FAILURE, -}; - -enum wsrep_exec_mode { - /* Transaction processing before replication. */ - LOCAL_STATE, - /* Slave thread applying write sets from other nodes or replaying thread. */ - REPL_RECV, - /* Total-order-isolation mode. */ - TOTAL_ORDER, - /* - Transaction procession after it has been replicated in prepare stage and - has passed certification. - */ - LOCAL_COMMIT -}; - -enum wsrep_query_state { - QUERY_IDLE, - QUERY_EXEC, - QUERY_COMMITTING, - QUERY_EXITING, - QUERY_ROLLINGBACK, -}; - -enum wsrep_trx_status { - WSREP_TRX_OK, - WSREP_TRX_CERT_FAIL, /* certification failure, must abort */ - WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */ - WSREP_TRX_ERROR, /* native mysql error */ -}; - struct xid_t; -struct wsrep; 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 { - struct wsrep * (*get_wsrep_func)(); - my_bool (*get_wsrep_certify_nonPK_func)(); - my_bool (*get_wsrep_debug_func)(); - my_bool (*get_wsrep_drupal_282555_workaround_func)(); my_bool (*get_wsrep_recovery_func)(); - my_bool (*get_wsrep_load_data_splitting_func)(); - my_bool (*get_wsrep_log_conflicts_func)(); - long (*get_wsrep_protocol_version_func)(); - my_bool (*wsrep_aborting_thd_contains_func)(THD *thd); - void (*wsrep_aborting_thd_enqueue_func)(THD *thd); - bool (*wsrep_consistency_check_func)(THD *thd); - int (*wsrep_is_wsrep_xid_func)(const struct xid_t *xid); + 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); - void (*wsrep_lock_rollback_func)(); - int (*wsrep_on_func)(MYSQL_THD); - void (*wsrep_post_commit_func)(THD* thd, bool all); - bool (*wsrep_prepare_key_func)(const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*); - enum wsrep_trx_status (*wsrep_run_wsrep_commit_func)(THD *thd, bool all); - void (*wsrep_thd_LOCK_func)(THD *thd); - void (*wsrep_thd_UNLOCK_func)(THD *thd); - void (*wsrep_thd_awake_func)(THD *thd, my_bool signal); - enum wsrep_conflict_state (*wsrep_thd_conflict_state_func)(MYSQL_THD, my_bool); - const char * (*wsrep_thd_conflict_state_str_func)(THD *thd); - enum wsrep_exec_mode (*wsrep_thd_exec_mode_func)(THD *thd); - const char * (*wsrep_thd_exec_mode_str_func)(THD *thd); - enum wsrep_conflict_state (*wsrep_thd_get_conflict_state_func)(MYSQL_THD); - my_bool (*wsrep_thd_is_BF_func)(MYSQL_THD , my_bool); - my_bool (*wsrep_thd_is_wsrep_func)(MYSQL_THD thd); - const char * (*wsrep_thd_query_func)(THD *thd); - enum wsrep_query_state (*wsrep_thd_query_state_func)(THD *thd); - const char * (*wsrep_thd_query_state_str_func)(THD *thd); - int (*wsrep_thd_retry_counter_func)(THD *thd); - void (*wsrep_thd_set_conflict_state_func)(THD *thd, enum wsrep_conflict_state state); - bool (*wsrep_thd_ignore_table_func)(THD *thd); - long long (*wsrep_thd_trx_seqno_func)(THD *thd); - struct wsrep_ws_handle * (*wsrep_thd_ws_handle_func)(THD *thd); + 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); + 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); void (*wsrep_thd_auto_increment_variables_func)(THD *thd, unsigned long long *offset, unsigned long long *increment); - void (*wsrep_set_load_multi_commit_func)(THD *thd, bool split); - bool (*wsrep_is_load_multi_commit_func)(THD *thd); - int (*wsrep_trx_is_aborting_func)(MYSQL_THD thd); - int (*wsrep_trx_order_before_func)(MYSQL_THD, MYSQL_THD); - void (*wsrep_unlock_rollback_func)(); + 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_applier_func)(MYSQL_THD); + 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); + 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); + bool (*wsrep_thd_set_wsrep_aborter_func)(MYSQL_THD bf_thd, MYSQL_THD thd); } *wsrep_service; +#define MYSQL_SERVICE_WSREP_INCLUDED +#endif + #ifdef MYSQL_DYNAMIC_PLUGIN -#define get_wsrep() wsrep_service->get_wsrep_func() -#define get_wsrep_certify_nonPK() wsrep_service->get_wsrep_certify_nonPK_func() -#define get_wsrep_debug() wsrep_service->get_wsrep_debug_func() -#define get_wsrep_drupal_282555_workaround() wsrep_service->get_wsrep_drupal_282555_workaround_func() + +#define MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED #define get_wsrep_recovery() wsrep_service->get_wsrep_recovery_func() -#define get_wsrep_load_data_splitting() wsrep_service->get_wsrep_load_data_splitting_func() -#define get_wsrep_log_conflicts() wsrep_service->get_wsrep_log_conflicts_func() -#define get_wsrep_protocol_version() wsrep_service->get_wsrep_protocol_version_func() -#define wsrep_aborting_thd_contains(T) wsrep_service->wsrep_aborting_thd_contains_func(T) -#define wsrep_aborting_thd_enqueue(T) wsrep_service->wsrep_aborting_thd_enqueue_func(T) #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_lock_rollback() wsrep_service->wsrep_lock_rollback_func() -#define wsrep_on(X) wsrep_service->wsrep_on_func(X) -#define wsrep_post_commit(T,A) wsrep_service->wsrep_post_commit_func(T,A) -#define wsrep_prepare_key(A,B,C,D,E,F) wsrep_service->wsrep_prepare_key_func(A,B,C,D,E,F) -#define wsrep_run_wsrep_commit(T,A) wsrep_service->wsrep_run_wsrep_commit_func(T,A) +#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_UNLOCK(T) wsrep_service->wsrep_thd_UNLOCK_func(T) -#define wsrep_thd_awake(T,S) wsrep_service->wsrep_thd_awake_func(T,S) -#define wsrep_thd_conflict_state(T,S) wsrep_service->wsrep_thd_conflict_state_func(T,S) -#define wsrep_thd_conflict_state_str(T) wsrep_service->wsrep_thd_conflict_state_str_func(T) -#define wsrep_thd_exec_mode(T) wsrep_service->wsrep_thd_exec_mode_func(T) -#define wsrep_thd_exec_mode_str(T) wsrep_service->wsrep_thd_exec_mode_str_func(T) -#define wsrep_thd_get_conflict_state(T) wsrep_service->wsrep_thd_get_conflict_state_func(T) -#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S) -#define wsrep_thd_is_wsrep(T) wsrep_service->wsrep_thd_is_wsrep_func(T) #define wsrep_thd_query(T) wsrep_service->wsrep_thd_query_func(T) -#define wsrep_thd_query_state(T) wsrep_service->wsrep_thd_query_state_func(T) -#define wsrep_thd_query_state_str(T) wsrep_service->wsrep_thd_query_state_str_func(T) #define wsrep_thd_retry_counter(T) wsrep_service->wsrep_thd_retry_counter_func(T) -#define wsrep_thd_set_conflict_state(T,S) wsrep_service->wsrep_thd_set_conflict_state_func(T,S) #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_thd_ws_handle(T) wsrep_service->wsrep_thd_ws_handle_func(T) #define wsrep_thd_auto_increment_variables(T,O,I) wsrep_service->wsrep_thd_auto_increment_variables_func(T,O,I) -#define wsrep_set_load_multi_commit(T,S) wsrep_service->wsrep_set_load_multi_commit_func(T,S) -#define wsrep_is_load_multi_commit(T) wsrep_service->wsrep_is_load_multi_commit_func(T) -#define wsrep_trx_is_aborting(T) wsrep_service->wsrep_trx_is_aborting_func(T) -#define wsrep_trx_order_before(T1,T2) wsrep_service->wsrep_trx_order_before_func(T1,T2) -#define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func() #define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A) -#define wsrep_thd_is_applier(T) wsrep_service->wsrep_thd_is_applier_func(T) - -#define wsrep_debug get_wsrep_debug() -#define wsrep_log_conflicts get_wsrep_log_conflicts() -#define wsrep_certify_nonPK get_wsrep_certify_nonPK() -#define wsrep_load_data_splitting get_wsrep_load_data_splitting() -#define wsrep_drupal_282555_workaround get_wsrep_drupal_282555_workaround() -#define wsrep_recovery get_wsrep_recovery() -#define wsrep_protocol_version get_wsrep_protocol_version() +#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_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_thd_set_wsrep_aborter(T) wsrep_service->wsrep_thd_set_wsrep_aborter_func(T1, T2) #else -extern my_bool wsrep_debug; +#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; @@ -184,57 +138,89 @@ extern my_bool wsrep_drupal_282555_workaround; extern my_bool wsrep_recovery; extern long wsrep_protocol_version; -bool wsrep_consistency_check(THD *thd); -bool wsrep_prepare_key(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); -const char *wsrep_thd_query(THD *thd); -const char *wsrep_thd_conflict_state_str(THD *thd); -const char *wsrep_thd_exec_mode_str(THD *thd); -const char *wsrep_thd_query_state_str(THD *thd); -enum wsrep_conflict_state wsrep_thd_conflict_state(MYSQL_THD thd, my_bool sync); -enum wsrep_conflict_state wsrep_thd_get_conflict_state(MYSQL_THD thd); -enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); -enum wsrep_query_state wsrep_thd_query_state(THD *thd); -enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, bool all); -int wsrep_is_wsrep_xid(const struct xid_t* xid); -long long wsrep_xid_seqno(const struct xid_t* xid); +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); -int wsrep_on(MYSQL_THD thd); -int wsrep_thd_retry_counter(THD *thd); -int wsrep_trx_is_aborting(MYSQL_THD thd); -int wsrep_trx_order_before(MYSQL_THD thd1, MYSQL_THD thd2); -long get_wsrep_protocol_version(); -long long wsrep_thd_trx_seqno(THD *thd); -my_bool get_wsrep_certify_nonPK(); -my_bool get_wsrep_debug(); -my_bool get_wsrep_drupal_282555_workaround(); +extern "C" long long wsrep_thd_trx_seqno(const MYSQL_THD thd); my_bool get_wsrep_recovery(); -my_bool get_wsrep_load_data_splitting(); -my_bool get_wsrep_log_conflicts(); -my_bool wsrep_aborting_thd_contains(THD *thd); -my_bool wsrep_thd_is_BF(MYSQL_THD thd, my_bool sync); -my_bool wsrep_thd_is_wsrep(MYSQL_THD thd); -struct wsrep *get_wsrep(); -struct wsrep_ws_handle *wsrep_thd_ws_handle(THD *thd); void wsrep_thd_auto_increment_variables(THD *thd, unsigned long long *offset, unsigned long long *increment); -void wsrep_set_load_multi_commit(THD *thd, bool split); -bool wsrep_is_load_multi_commit(THD *thd); -void wsrep_aborting_thd_enqueue(THD *thd); -void wsrep_lock_rollback(); -void wsrep_post_commit(THD* thd, bool all); -void wsrep_thd_LOCK(THD *thd); -void wsrep_thd_UNLOCK(THD *thd); -void wsrep_thd_awake(THD *thd, my_bool signal); -void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state); -bool wsrep_thd_ignore_table(THD *thd); -void wsrep_unlock_rollback(); +bool wsrep_thd_ignore_table(MYSQL_THD thd); void wsrep_set_data_home_dir(const char *data_dir); -my_bool wsrep_thd_is_applier(MYSQL_THD thd); -#endif -#ifdef __cplusplus -} -#endif +/* 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); +/* Unlock thd wsrep lock */ +extern "C" void wsrep_thd_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); +/* set wsrep_aborter for the target THD */ +extern "C" bool wsrep_thd_set_wsrep_aborter(MYSQL_THD bf_thd, MYSQL_THD victim_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 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" bool wsrep_thd_set_wsrep_aborter(MYSQL_THD bf_thd, MYSQL_THD victim_thd); -#define MYSQL_SERVICE_WSREP_INCLUDED #endif - +#endif /* MYSQL_SERVICE_WSREP_INCLUDED */ diff --git a/include/mysql/services.h b/include/mysql/services.h index 986d430dbf1..2c3a0ae421b 100644 --- a/include/mysql/services.h +++ b/include/mysql/services.h @@ -39,6 +39,7 @@ extern "C" { #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>*/ #ifdef __cplusplus diff --git a/include/mysql_com.h b/include/mysql_com.h index 77b98294f87..9e5215f29b3 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -203,6 +203,8 @@ enum enum_indicator_type #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 REFRESH_GRANT (1ULL << 0) /* Refresh grant tables */ #define REFRESH_LOG (1ULL << 1) /* Start on new log file */ @@ -231,6 +233,7 @@ enum enum_indicator_type #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 */ @@ -332,12 +335,8 @@ enum enum_indicator_type CLIENT_DEPRECATE_EOF |\ CLIENT_CONNECT_ATTRS |\ MARIADB_CLIENT_COM_MULTI |\ - MARIADB_CLIENT_STMT_BULK_OPERATIONS) - -/* - To be added later: - CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS -*/ + MARIADB_CLIENT_STMT_BULK_OPERATIONS |\ + CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS) /* Switch off the flags that are optional and depending on build flags diff --git a/include/mysql_embed.h b/include/mysql_embed.h index e9cbdb6a275..775040ac9d1 100644 --- a/include/mysql_embed.h +++ b/include/mysql_embed.h @@ -25,7 +25,6 @@ /* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */ #undef HAVE_DLOPEN /* No udf functions */ -#undef HAVE_SMEM /* No shared memory */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_EMBED_INCLUDED */ diff --git a/include/mysql_version.h.in b/include/mysql_version.h.in index 59df2b7c086..ad719634335 100644 --- a/include/mysql_version.h.in +++ b/include/mysql_version.h.in @@ -14,6 +14,7 @@ #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@ diff --git a/include/mysqld_default_groups.h b/include/mysqld_default_groups.h index 3bc82359787..cf6e92e3bc1 100644 --- a/include/mysqld_default_groups.h +++ b/include/mysqld_default_groups.h @@ -1,6 +1,7 @@ const char *load_default_groups[]= { "mysqld", "server", MYSQL_BASE_VERSION, "mariadb", MARIADB_BASE_VERSION, +"mariadbd", MARIADBD_BASE_VERSION, "client-server", #ifdef WITH_WSREP "galera", diff --git a/include/scope.h b/include/scope.h new file mode 100644 index 00000000000..b9e2e96ae5c --- /dev/null +++ b/include/scope.h @@ -0,0 +1,66 @@ +/* + 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)); +} diff --git a/include/service_versions.h b/include/service_versions.h index 6e138fab5a4..16d21ac40d3 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -42,3 +42,4 @@ #define VERSION_thd_timezone 0x0100 #define VERSION_thd_wait 0x0100 #define VERSION_wsrep 0x0202 +#define VERSION_json 0x0100 diff --git a/include/ssl_compat.h b/include/ssl_compat.h index c94b9671d5f..8cc0e6a9a2b 100644 --- a/include/ssl_compat.h +++ b/include/ssl_compat.h @@ -17,11 +17,7 @@ #include <openssl/opensslv.h> /* OpenSSL version specific definitions */ -#if !defined(HAVE_YASSL) && defined(OPENSSL_VERSION_NUMBER) - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) -#define HAVE_X509_check_host 1 -#endif +#if defined(OPENSSL_VERSION_NUMBER) #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) #define HAVE_OPENSSL11 1 @@ -49,30 +45,44 @@ #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_ERR_remove_thread_state +#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 -#elif defined(HAVE_YASSL) -#define SSL_LIBRARY "YaSSL " YASSL_VERSION -#define BN_free(X) do { } while(0) -#endif /* !defined(HAVE_YASSL) */ +#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 + #define OPENSSL_init_ssl(X,Y) SSL_library_init() #define DH_set0_pqg(D,P,Q,G) ((D)->p= (P), (D)->g= (G)) #define EVP_CIPHER_CTX_buf_noconst(ctx) ((ctx)->buf) #define EVP_CIPHER_CTX_encrypting(ctx) ((ctx)->encrypt) #define EVP_CIPHER_CTX_SIZE sizeof(EVP_CIPHER_CTX) -#define EVP_MD_CTX_SIZE sizeof(EVP_MD_CTX) +#ifndef HAVE_WOLFSSL #define EVP_MD_CTX_reset(X) EVP_MD_CTX_cleanup(X) #define EVP_CIPHER_CTX_reset(X) EVP_CIPHER_CTX_cleanup(X) +#endif #define X509_get0_notBefore(X) X509_get_notBefore(X) #define X509_get0_notAfter(X) X509_get_notAfter(X) #endif diff --git a/include/sslopt-case.h b/include/sslopt-case.h index fe83051c275..72881a266ab 100644 --- a/include/sslopt-case.h +++ b/include/sslopt-case.h @@ -29,8 +29,8 @@ One can disable SSL later by using --skip-ssl or --ssl=0 */ opt_use_ssl= 1; - /* crl has no effect in yaSSL */ -#if defined (HAVE_YASSL) && (!defined (_WIN32) || defined (MYSQL_SERVER)) +#if defined (HAVE_WOLFSSL) && (!defined (_WIN32) || defined (MYSQL_SERVER)) + /* CRL does not work with WolfSSL */ opt_ssl_crl= NULL; opt_ssl_crlpath= NULL; #endif diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index be64e7f6590..d0278a1645d 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -46,6 +46,11 @@ "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 " diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index c65aa693b76..e28f19b919d 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -30,6 +30,7 @@ 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 diff --git a/include/thr_lock.h b/include/thr_lock.h index 35db9ef981b..2873d40c58a 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -168,9 +168,9 @@ 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)(void *, my_bool); - typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool); - typedef int (* wsrep_on_fun)(void *); + 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); diff --git a/include/thread_pool_priv.h b/include/thread_pool_priv.h index f7d2da0b082..47f281192e9 100644 --- a/include/thread_pool_priv.h +++ b/include/thread_pool_priv.h @@ -61,9 +61,6 @@ void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var); my_socket thd_get_fd(THD *thd); int thd_store_globals(THD* thd); -THD *first_global_thread(); -THD *next_global_thread(THD *thd); - /* Print to the MySQL error log */ void sql_print_error(const char *format, ...); diff --git a/include/violite.h b/include/violite.h index bb3fd8f6b6c..f0fc53e4d6e 100644 --- a/include/violite.h +++ b/include/violite.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2012, 2017, MariaDB Corporation. + 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 @@ -38,7 +38,7 @@ typedef struct st_vio Vio; enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE, - VIO_TYPE_SSL, VIO_TYPE_SHARED_MEMORY + VIO_TYPE_SSL }; /** @@ -59,6 +59,11 @@ struct vio_keepalive_opts }; +#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 */ @@ -68,13 +73,6 @@ 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 __WIN__ Vio* vio_new_win32pipe(HANDLE hPipe); -Vio* vio_new_win32shared_memory(HANDLE handle_file_map, - HANDLE handle_map, - HANDLE event_server_wrote, - HANDLE event_server_read, - HANDLE event_client_wrote, - HANDLE event_client_read, - HANDLE event_conn_closed); #else #define HANDLE void * #endif /* __WIN__ */ @@ -89,6 +87,7 @@ 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); @@ -145,7 +144,9 @@ int vio_getnameinfo(const struct sockaddr *sa, /* 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 @@ -155,7 +156,8 @@ 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_LASTERR + SSL_INITERR_MEMFAIL, SSL_INITERR_DH, SSL_INITERR_PROTOCOL, + SSL_INITERR_LASTERR }; const char* sslGetErrString(enum enum_ssl_init_error err); @@ -167,6 +169,8 @@ struct st_VioSSLFd 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, @@ -176,7 +180,8 @@ 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); + const char *crl_file, const char *crl_path, + ulonglong tls_version); void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd); #endif /* HAVE_OPENSSL */ @@ -265,22 +270,9 @@ struct st_vio #ifdef HAVE_OPENSSL void *ssl_arg; #endif -#ifdef HAVE_SMEM - HANDLE handle_file_map; - char *handle_map; - HANDLE event_server_wrote; - HANDLE event_server_read; - HANDLE event_client_wrote; - HANDLE event_client_read; - HANDLE event_conn_closed; - size_t shared_memory_remain; - char *shared_memory_pos; -#endif /* HAVE_SMEM */ #ifdef _WIN32 HANDLE hPipe; OVERLAPPED overlapped; - DWORD read_timeout_ms; - DWORD write_timeout_ms; int shutdown_flag; #endif }; diff --git a/include/wsrep.h b/include/wsrep.h index a3a58324f3e..fde5c5226e7 100644 --- a/include/wsrep.h +++ b/include/wsrep.h @@ -13,11 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ -#include <my_config.h> - #ifndef WSREP_INCLUDED #define WSREP_INCLUDED +#include <my_config.h> + #ifdef WITH_WSREP #define IF_WSREP(A,B) A #define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A) @@ -28,12 +28,14 @@ goto wsrep_error_label; #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) \ - if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, \ - table_list_, alter_info_)) \ + if (WSREP(thd) && wsrep_thd_is_local(thd) && \ + wsrep_to_isolation_begin(thd, db_, table_, \ + table_list_, alter_info_)) \ goto wsrep_error_label; -#define WSREP_TO_ISOLATION_END \ - if (WSREP_ON && (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER))) \ +#define WSREP_TO_ISOLATION_END \ + if ((WSREP(thd) && wsrep_thd_is_local_toi(thd)) || \ + wsrep_thd_is_in_rsu(thd)) \ wsrep_to_isolation_end(thd); /* @@ -50,24 +52,26 @@ #define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__) #define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__) -#define WSREP_SYNC_WAIT(thd_, before_) \ - do { if (WSREP_CLIENT(thd_) && \ - wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; } while(0) -#define WSREP_ERROR_LABEL wsrep_error_label -#else +#define WSREP_SYNC_WAIT(thd_, before_) \ + { if (WSREP_CLIENT(thd_) && \ + wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; } + +#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 DBUG_ASSERT_IF_WSREP(A) #define WSREP_DEBUG(...) -#define WSREP_INFO(...) -#define WSREP_WARN(...) +//#define WSREP_INFO(...) +//#define WSREP_WARN(...) #define WSREP_ERROR(...) -#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0) #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) #define WSREP_TO_ISOLATION_END #define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) -#define WSREP_SYNC_WAIT(thd_, before_) do { } while(0) -#define WSREP_ERROR_LABEL goto wsrep_error_label; wsrep_error_label - +#define WSREP_SYNC_WAIT(thd_, before_) #endif /* WITH_WSREP */ #endif /* WSREP_INCLUDED */ |