mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 10:56:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			225 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* 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));
 | |
| }
 | 
