diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
commit | 3f619478f796eddbba6e39502fe941b285dd97b1 (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /storage/perfschema/pfs_global.cc | |
parent | Initial commit. (diff) | |
download | mariadb-upstream.tar.xz mariadb-upstream.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/perfschema/pfs_global.cc')
-rw-r--r-- | storage/perfschema/pfs_global.cc | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/storage/perfschema/pfs_global.cc b/storage/perfschema/pfs_global.cc new file mode 100644 index 00000000..8860be79 --- /dev/null +++ b/storage/perfschema/pfs_global.cc @@ -0,0 +1,225 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights + reserved. + Copyright (c) 2022, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file storage/perfschema/pfs_global.cc + Miscellaneous global dependencies (implementation). +*/ + +#include <my_global.h> +#include "pfs_global.h" +#include "pfs_builtin_memory.h" +#include "log.h" +#include "aligned.h" +#include "assume_aligned.h" + +#include <stdlib.h> +#include <string.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef _WIN32 +#include <winsock2.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +bool pfs_initialized= false; + +/** + Memory allocation for the performance schema. + The memory used internally in the performance schema implementation. + It is allocated at startup, or during runtime with scalable buffers. +*/ +void *pfs_malloc(PFS_builtin_memory_class *klass, size_t size, myf flags) +{ + assert(klass != NULL); + assert(size > 0); + + const size_t aligned_size= MY_ALIGN(size, CPU_LEVEL1_DCACHE_LINESIZE); + + void *ptr= aligned_malloc(aligned_size, CPU_LEVEL1_DCACHE_LINESIZE); + if (unlikely(ptr == NULL)) + return NULL; + + klass->count_alloc(size); + + if (flags & MY_ZEROFILL) + memset_aligned<CPU_LEVEL1_DCACHE_LINESIZE>(ptr, 0, aligned_size); + return ptr; +} + +void pfs_free(PFS_builtin_memory_class *klass, size_t size, void *ptr) +{ + if (ptr == NULL) + return; + + aligned_free(ptr); + klass->count_free(size); +} + +/** + Array allocation for the performance schema. + Checks for overflow of n * size before allocating. + @param klass performance schema memory class + @param n number of array elements + @param size element size + @param flags malloc flags + @return pointer to memory on success, else NULL +*/ +void *pfs_malloc_array(PFS_builtin_memory_class *klass, size_t n, size_t size, myf flags) +{ + assert(klass != NULL); + assert(n > 0); + assert(size > 0); + void *ptr= NULL; + size_t array_size= n * size; + /* Check for overflow before allocating. */ + if (is_overflow(array_size, n, size)) + { + sql_print_warning("Failed to allocate memory for %zu chunks each of size " + "%zu for buffer '%s' due to overflow", n, size, + klass->m_class.m_name); + return NULL; + } + + if(NULL == (ptr= pfs_malloc(klass, array_size, flags))) + { + sql_print_warning("Failed to allocate %zu bytes for buffer '%s' due to " + "out-of-memory", array_size, klass->m_class.m_name); + } + return ptr; +} + +/** + Free array allocated by @sa pfs_malloc_array. + @param klass performance schema memory class + @param n number of array elements + @param size element size + @param ptr pointer to memory +*/ +void pfs_free_array(PFS_builtin_memory_class *klass, size_t n, size_t size, void *ptr) +{ + if (ptr == NULL) + return; + size_t array_size= n * size; + /* Overflow should have been detected by pfs_malloc_array. */ + assert(!is_overflow(array_size, n, size)); + return pfs_free(klass, array_size, ptr); +} + +/** + Detect multiplication overflow. + @param product multiplication product + @param n1 operand + @param n2 operand + @return true if multiplication caused an overflow. +*/ +bool is_overflow(size_t product, size_t n1, size_t n2) +{ + if (n1 != 0 && (product / n1 != n2)) + return true; + else + return false; +} + +void pfs_print_error(const char *format, ...) +{ + va_list args; + va_start(args, format); + /* + Printing to anything else, like the error log, would generate even more + recursive calls to the performance schema implementation + (file io is instrumented), so that could lead to catastrophic results. + Printing to something safe, and low level: stderr only. + */ + vfprintf(stderr, format, args); + va_end(args); + fflush(stderr); +} + + +/** Convert raw ip address into readable format. Do not do a reverse DNS lookup. */ + +uint pfs_get_socket_address(char *host, + uint host_len, + uint *port, + const struct sockaddr_storage *src_addr, + socklen_t src_len) +{ + assert(host); + assert(src_addr); + assert(port); + + memset(host, 0, host_len); + *port= 0; + + switch (src_addr->ss_family) + { + case AF_INET: + { + if (host_len < INET_ADDRSTRLEN+1) + return 0; + struct sockaddr_in *sa4= (struct sockaddr_in *)(src_addr); + #ifdef _WIN32 + /* Older versions of Windows do not support inet_ntop() */ + getnameinfo((struct sockaddr *)sa4, sizeof(struct sockaddr_in), + host, host_len, NULL, 0, NI_NUMERICHOST); + #else + inet_ntop(AF_INET, &(sa4->sin_addr), host, INET_ADDRSTRLEN); + #endif + *port= ntohs(sa4->sin_port); + } + break; + +#ifdef HAVE_IPV6 + case AF_INET6: + { + if (host_len < INET6_ADDRSTRLEN+1) + return 0; + struct sockaddr_in6 *sa6= (struct sockaddr_in6 *)(src_addr); + #ifdef _WIN32 + /* Older versions of Windows do not support inet_ntop() */ + getnameinfo((struct sockaddr *)sa6, sizeof(struct sockaddr_in6), + host, host_len, NULL, 0, NI_NUMERICHOST); + #else + inet_ntop(AF_INET6, &(sa6->sin6_addr), host, INET6_ADDRSTRLEN); + #endif + *port= ntohs(sa6->sin6_port); + } + break; +#endif + + default: + break; + } + + /* Return actual IP address string length */ + return ((uint)strlen((const char*)host)); +} |