summaryrefslogtreecommitdiffstats
path: root/include/mysql/psi/mysql_socket.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/mysql/psi/mysql_socket.h')
-rw-r--r--include/mysql/psi/mysql_socket.h1353
1 files changed, 1353 insertions, 0 deletions
diff --git a/include/mysql/psi/mysql_socket.h b/include/mysql/psi/mysql_socket.h
new file mode 100644
index 00000000..95cb02a5
--- /dev/null
+++ b/include/mysql/psi/mysql_socket.h
@@ -0,0 +1,1353 @@
+/* Copyright (c) 2010, 2023, Oracle and/or its affiliates.
+ Copyright (c) 2017, MariaDB Corporation.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License, version 2.0,
+as published by the Free Software Foundation.
+
+This program is also distributed with certain software (including
+but not limited to OpenSSL) that is licensed under separate terms,
+as designated in a particular file or component or in included license
+documentation. The authors of MySQL hereby grant you an additional
+permission to link the program and your derivative works with the
+separately licensed software that they have included with MySQL.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License, version 2.0, for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+02110-1335 USA
+*/
+
+#ifndef MYSQL_SOCKET_H
+#define MYSQL_SOCKET_H
+
+/* For MY_STAT */
+#include <my_dir.h>
+/* For my_chsize */
+#include <my_sys.h>
+/* For socket api */
+#ifdef _WIN32
+ #include <ws2def.h>
+ #include <winsock2.h>
+ #include <MSWSock.h>
+ #define SOCKBUF_T char
+#else
+ #include <netinet/in.h>
+ #define SOCKBUF_T void
+#endif
+/**
+ @file mysql/psi/mysql_socket.h
+[...]
+*/
+
+#include "mysql/psi/psi.h"
+
+#ifndef PSI_SOCKET_CALL
+#define PSI_SOCKET_CALL(M) PSI_DYNAMIC_CALL(M)
+#endif
+
+/**
+ @defgroup Socket_instrumentation Socket Instrumentation
+ @ingroup Instrumentation_interface
+ @{
+*/
+
+/**
+ @def mysql_socket_register(P1, P2, P3)
+ Socket registration.
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_register(P1, P2, P3) \
+ inline_mysql_socket_register(P1, P2, P3)
+#else
+ #define mysql_socket_register(P1, P2, P3) \
+ do {} while (0)
+#endif
+
+/** An instrumented socket. */
+struct st_mysql_socket
+{
+ /** The real socket descriptor. */
+ my_socket fd;
+
+ /** Is this a Unix-domain socket? */
+ char is_unix_domain_socket;
+
+ /** Is this a socket opened for the extra port? */
+ char is_extra_port;
+
+ /** Address family of the socket. (See sa_family from struct sockaddr). */
+ unsigned short address_family;
+
+ /**
+ The instrumentation hook.
+ Note that this hook is not conditionally defined,
+ for binary compatibility of the @c MYSQL_SOCKET interface.
+ */
+ struct PSI_socket *m_psi;
+};
+
+/**
+ An instrumented socket.
+ @c MYSQL_SOCKET is a replacement for @c my_socket.
+*/
+typedef struct st_mysql_socket MYSQL_SOCKET;
+
+
+/**
+ @def MYSQL_INVALID_SOCKET
+ MYSQL_SOCKET initial value.
+*/
+//MYSQL_SOCKET MYSQL_INVALID_SOCKET= {INVALID_SOCKET, NULL};
+#define MYSQL_INVALID_SOCKET mysql_socket_invalid()
+
+/**
+ MYSQL_SOCKET helper. Initialize instrumented socket.
+ @sa mysql_socket_getfd
+ @sa mysql_socket_setfd
+*/
+static inline MYSQL_SOCKET
+mysql_socket_invalid()
+{
+ MYSQL_SOCKET mysql_socket= {INVALID_SOCKET, 0, 0, 0, NULL};
+ return mysql_socket;
+}
+
+/**
+ Set socket descriptor and address.
+ @param socket nstrumented socket
+ @param addr unformatted socket address
+ @param addr_len length of socket address
+*/
+
+static inline void
+mysql_socket_set_address(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ MYSQL_SOCKET socket,
+ const struct sockaddr *addr,
+ socklen_t addr_len
+#else
+ MYSQL_SOCKET socket __attribute__ ((unused)),
+ const struct sockaddr *addr __attribute__ ((unused)),
+ socklen_t addr_len __attribute__ ((unused))
+#endif
+)
+{
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (socket.m_psi != NULL)
+ PSI_SOCKET_CALL(set_socket_info)(socket.m_psi, NULL, addr, addr_len);
+#endif
+}
+
+/**
+ Set socket descriptor and address.
+ @param socket instrumented socket
+*/
+static inline void
+mysql_socket_set_thread_owner(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+MYSQL_SOCKET socket
+#else
+MYSQL_SOCKET socket __attribute__ ((unused))
+#endif
+)
+{
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (socket.m_psi != NULL)
+ PSI_SOCKET_CALL(set_socket_thread_owner)(socket.m_psi);
+#endif
+}
+
+/**
+ MYSQL_SOCKET helper. Get socket descriptor.
+ @param mysql_socket Instrumented socket
+ @sa mysql_socket_getfd
+*/
+static inline my_socket
+mysql_socket_getfd(MYSQL_SOCKET mysql_socket)
+{
+ return mysql_socket.fd;
+}
+
+/**
+ MYSQL_SOCKET helper. Set socket descriptor.
+ @param mysql_socket Instrumented socket
+ @param fd Socket descriptor
+ @sa mysql_socket_setfd
+*/
+static inline void
+mysql_socket_setfd(MYSQL_SOCKET *mysql_socket, my_socket fd)
+{
+ if (likely(mysql_socket != NULL))
+ mysql_socket->fd= fd;
+}
+
+/**
+ @def MYSQL_SOCKET_WAIT_VARIABLES
+ Instrumentation helper for socket waits.
+ This instrumentation declares local variables.
+ Do not use a ';' after this macro
+ @param LOCKER locker
+ @param STATE locker state
+ @sa MYSQL_START_SOCKET_WAIT.
+ @sa MYSQL_END_SOCKET_WAIT.
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE) \
+ struct PSI_socket_locker* LOCKER; \
+ PSI_socket_locker_state STATE;
+#else
+ #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE)
+#endif
+
+/**
+ @def MYSQL_START_SOCKET_WAIT
+ Instrumentation helper for socket waits.
+ This instrumentation marks the start of a wait event.
+ @param LOCKER locker
+ @param STATE locker state
+ @param SOCKET instrumented socket
+ @param OP The socket operation to be performed
+ @param COUNT bytes to be written/read
+ @sa MYSQL_END_SOCKET_WAIT.
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \
+ LOCKER= inline_mysql_start_socket_wait(STATE, SOCKET, OP, COUNT,\
+ __FILE__, __LINE__)
+#else
+ #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \
+ do {} while (0)
+#endif
+
+/**
+ @def MYSQL_END_SOCKET_WAIT
+ Instrumentation helper for socket waits.
+ This instrumentation marks the end of a wait event.
+ @param LOCKER locker
+ @param COUNT actual bytes written/read, or -1
+ @sa MYSQL_START_SOCKET_WAIT.
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \
+ inline_mysql_end_socket_wait(LOCKER, COUNT)
+#else
+ #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \
+ do {} while (0)
+#endif
+
+/**
+ @def MYSQL_SOCKET_SET_STATE
+ Set the state (IDLE, ACTIVE) of an instrumented socket.
+ @param SOCKET the instrumented socket
+ @param STATE the new state
+ @sa PSI_socket_state
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \
+ inline_mysql_socket_set_state(SOCKET, STATE)
+#else
+ #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \
+ do {} while (0)
+#endif
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+/**
+ Instrumentation calls for MYSQL_START_SOCKET_WAIT.
+ @sa MYSQL_START_SOCKET_WAIT.
+*/
+static inline struct PSI_socket_locker*
+inline_mysql_start_socket_wait(PSI_socket_locker_state *state,
+ MYSQL_SOCKET mysql_socket,
+ enum PSI_socket_operation op,
+ size_t byte_count,
+ const char *src_file, uint src_line)
+{
+ struct PSI_socket_locker *locker;
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (state, mysql_socket.m_psi, op, byte_count, src_file, src_line);
+ }
+ else
+ locker= NULL;
+ return locker;
+}
+
+/**
+ Instrumentation calls for MYSQL_END_SOCKET_WAIT.
+ @sa MYSQL_END_SOCKET_WAIT.
+*/
+static inline void
+inline_mysql_end_socket_wait(struct PSI_socket_locker *locker, size_t byte_count)
+{
+ if (psi_likely(locker != NULL))
+ PSI_SOCKET_CALL(end_socket_wait)(locker, byte_count);
+}
+
+/**
+ Set the state (IDLE, ACTIVE) of an instrumented socket.
+ @param socket the instrumented socket
+ @param state the new state
+ @sa PSI_socket_state
+*/
+static inline void
+inline_mysql_socket_set_state(MYSQL_SOCKET socket, enum PSI_socket_state state)
+{
+ if (socket.m_psi != NULL)
+ PSI_SOCKET_CALL(set_socket_state)(socket.m_psi, state);
+}
+#endif /* HAVE_PSI_SOCKET_INTERFACE */
+
+/**
+ @def mysql_socket_fd(K, F)
+ Create a socket.
+ @c mysql_socket_fd is a replacement for @c socket.
+ @param K PSI_socket_key for this instrumented socket
+ @param F File descriptor
+*/
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_fd(K, F) \
+ inline_mysql_socket_fd(K, F)
+#else
+ #define mysql_socket_fd(K, F) \
+ inline_mysql_socket_fd(F)
+#endif
+
+/**
+ @def mysql_socket_socket(K, D, T, P)
+ Create a socket.
+ @c mysql_socket_socket is a replacement for @c socket.
+ @param K PSI_socket_key for this instrumented socket
+ @param D Socket domain
+ @param T Protocol type
+ @param P Transport protocol
+*/
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_socket(K, D, T, P) \
+ inline_mysql_socket_socket(K, D, T, P)
+#else
+ #define mysql_socket_socket(K, D, T, P) \
+ inline_mysql_socket_socket(D, T, P)
+#endif
+
+/**
+ @def mysql_socket_bind(FD, AP, L)
+ Bind a socket to a local port number and IP address
+ @c mysql_socket_bind is a replacement for @c bind.
+ @param FD Instrumented socket descriptor returned by socket()
+ @param AP Pointer to local port number and IP address in sockaddr structure
+ @param L Length of sockaddr structure
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_bind(FD, AP, L) \
+ inline_mysql_socket_bind(__FILE__, __LINE__, FD, AP, L)
+#else
+ #define mysql_socket_bind(FD, AP, L) \
+ inline_mysql_socket_bind(FD, AP, L)
+#endif
+
+/**
+ @def mysql_socket_getsockname(FD, AP, LP)
+ Return port number and IP address of the local host
+ @c mysql_socket_getsockname is a replacement for @c getsockname.
+ @param FD Instrumented socket descriptor returned by socket()
+ @param AP Pointer to returned address of local host in @c sockaddr structure
+ @param LP Pointer to length of @c sockaddr structure
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_getsockname(FD, AP, LP) \
+ inline_mysql_socket_getsockname(__FILE__, __LINE__, FD, AP, LP)
+#else
+ #define mysql_socket_getsockname(FD, AP, LP) \
+ inline_mysql_socket_getsockname(FD, AP, LP)
+#endif
+
+/**
+ @def mysql_socket_connect(FD, AP, L)
+ Establish a connection to a remote host.
+ @c mysql_socket_connect is a replacement for @c connect.
+ @param FD Instrumented socket descriptor returned by socket()
+ @param AP Pointer to target address in sockaddr structure
+ @param L Length of sockaddr structure
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_connect(FD, AP, L) \
+ inline_mysql_socket_connect(__FILE__, __LINE__, FD, AP, L)
+#else
+ #define mysql_socket_connect(FD, AP, L) \
+ inline_mysql_socket_connect(FD, AP, L)
+#endif
+
+/**
+ @def mysql_socket_getpeername(FD, AP, LP)
+ Get port number and IP address of remote host that a socket is connected to.
+ @c mysql_socket_getpeername is a replacement for @c getpeername.
+ @param FD Instrumented socket descriptor returned by socket() or accept()
+ @param AP Pointer to returned address of remote host in sockaddr structure
+ @param LP Pointer to length of sockaddr structure
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_getpeername(FD, AP, LP) \
+ inline_mysql_socket_getpeername(__FILE__, __LINE__, FD, AP, LP)
+#else
+ #define mysql_socket_getpeername(FD, AP, LP) \
+ inline_mysql_socket_getpeername(FD, AP, LP)
+#endif
+
+/**
+ @def mysql_socket_send(FD, B, N, FL)
+ Send data from the buffer, B, to a connected socket.
+ @c mysql_socket_send is a replacement for @c send.
+ @param FD Instrumented socket descriptor returned by socket() or accept()
+ @param B Buffer to send
+ @param N Number of bytes to send
+ @param FL Control flags
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_send(FD, B, N, FL) \
+ inline_mysql_socket_send(__FILE__, __LINE__, FD, B, N, FL)
+#else
+ #define mysql_socket_send(FD, B, N, FL) \
+ inline_mysql_socket_send(FD, B, N, FL)
+#endif
+
+/**
+ @def mysql_socket_recv(FD, B, N, FL)
+ Receive data from a connected socket.
+ @c mysql_socket_recv is a replacement for @c recv.
+ @param FD Instrumented socket descriptor returned by socket() or accept()
+ @param B Buffer to receive to
+ @param N Maximum bytes to receive
+ @param FL Control flags
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_recv(FD, B, N, FL) \
+ inline_mysql_socket_recv(__FILE__, __LINE__, FD, B, N, FL)
+#else
+ #define mysql_socket_recv(FD, B, N, FL) \
+ inline_mysql_socket_recv(FD, B, N, FL)
+#endif
+
+/**
+ @def mysql_socket_sendto(FD, B, N, FL, AP, L)
+ Send data to a socket at the specified address.
+ @c mysql_socket_sendto is a replacement for @c sendto.
+ @param FD Instrumented socket descriptor returned by socket()
+ @param B Buffer to send
+ @param N Number of bytes to send
+ @param FL Control flags
+ @param AP Pointer to destination sockaddr structure
+ @param L Size of sockaddr structure
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_sendto(FD, B, N, FL, AP, L) \
+ inline_mysql_socket_sendto(__FILE__, __LINE__, FD, B, N, FL, AP, L)
+#else
+ #define mysql_socket_sendto(FD, B, N, FL, AP, L) \
+ inline_mysql_socket_sendto(FD, B, N, FL, AP, L)
+#endif
+
+/**
+ @def mysql_socket_recvfrom(FD, B, N, FL, AP, L)
+ Receive data from a socket and return source address information
+ @c mysql_socket_recvfrom is a replacement for @c recvfrom.
+ @param FD Instrumented socket descriptor returned by socket()
+ @param B Buffer to receive to
+ @param N Maximum bytes to receive
+ @param FL Control flags
+ @param AP Pointer to source address in sockaddr_storage structure
+ @param LP Size of sockaddr_storage structure
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \
+ inline_mysql_socket_recvfrom(__FILE__, __LINE__, FD, B, N, FL, AP, LP)
+#else
+ #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \
+ inline_mysql_socket_recvfrom(FD, B, N, FL, AP, LP)
+#endif
+
+/**
+ @def mysql_socket_getsockopt(FD, LV, ON, OP, OL)
+ Get a socket option for the specified socket.
+ @c mysql_socket_getsockopt is a replacement for @c getsockopt.
+ @param FD Instrumented socket descriptor returned by socket()
+ @param LV Protocol level
+ @param ON Option to query
+ @param OP Buffer which will contain the value for the requested option
+ @param OL Pointer to length of OP
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \
+ inline_mysql_socket_getsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL)
+#else
+ #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \
+ inline_mysql_socket_getsockopt(FD, LV, ON, OP, OL)
+#endif
+
+/**
+ @def mysql_socket_setsockopt(FD, LV, ON, OP, OL)
+ Set a socket option for the specified socket.
+ @c mysql_socket_setsockopt is a replacement for @c setsockopt.
+ @param FD Instrumented socket descriptor returned by socket()
+ @param LV Protocol level
+ @param ON Option to modify
+ @param OP Buffer containing the value for the specified option
+ @param OL Pointer to length of OP
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \
+ inline_mysql_socket_setsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL)
+#else
+ #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \
+ inline_mysql_socket_setsockopt(FD, LV, ON, OP, OL)
+#endif
+
+/**
+ @def mysql_sock_set_nonblocking
+ Set socket to non-blocking.
+ @param FD instrumented socket descriptor
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_sock_set_nonblocking(FD) \
+ inline_mysql_sock_set_nonblocking(__FILE__, __LINE__, FD)
+#else
+ #define mysql_sock_set_nonblocking(FD) \
+ inline_mysql_sock_set_nonblocking(FD)
+#endif
+
+/**
+ @def mysql_socket_listen(FD, N)
+ Set socket state to listen for an incoming connection.
+ @c mysql_socket_listen is a replacement for @c listen.
+ @param FD Instrumented socket descriptor, bound and connected
+ @param N Maximum number of pending connections allowed.
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_listen(FD, N) \
+ inline_mysql_socket_listen(__FILE__, __LINE__, FD, N)
+#else
+ #define mysql_socket_listen(FD, N) \
+ inline_mysql_socket_listen(FD, N)
+#endif
+
+/**
+ @def mysql_socket_accept(K, FD, AP, LP)
+ Accept a connection from any remote host; TCP only.
+ @c mysql_socket_accept is a replacement for @c accept.
+ @param K PSI_socket_key for this instrumented socket
+ @param FD Instrumented socket descriptor, bound and placed in a listen state
+ @param AP Pointer to sockaddr structure with returned IP address and port of connected host
+ @param LP Pointer to length of valid information in AP
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_accept(K, FD, AP, LP) \
+ inline_mysql_socket_accept(__FILE__, __LINE__, K, FD, AP, LP)
+#else
+ #define mysql_socket_accept(K, FD, AP, LP) \
+ inline_mysql_socket_accept(FD, AP, LP)
+#endif
+
+/**
+ @def mysql_socket_close(FD)
+ Close a socket and sever any connections.
+ @c mysql_socket_close is a replacement for @c close.
+ @param FD Instrumented socket descriptor returned by socket() or accept()
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_close(FD) \
+ inline_mysql_socket_close(__FILE__, __LINE__, FD)
+#else
+ #define mysql_socket_close(FD) \
+ inline_mysql_socket_close(FD)
+#endif
+
+/**
+ @def mysql_socket_shutdown(FD, H)
+ Disable receives and/or sends on a socket.
+ @c mysql_socket_shutdown is a replacement for @c shutdown.
+ @param FD Instrumented socket descriptor returned by socket() or accept()
+ @param H Specifies which operations to shutdown
+*/
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ #define mysql_socket_shutdown(FD, H) \
+ inline_mysql_socket_shutdown(__FILE__, __LINE__, FD, H)
+#else
+ #define mysql_socket_shutdown(FD, H) \
+ inline_mysql_socket_shutdown(FD, H)
+#endif
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+static inline void inline_mysql_socket_register(
+ const char *category,
+ PSI_socket_info *info,
+ int count)
+{
+ PSI_SOCKET_CALL(register_socket)(category, info, count);
+}
+#endif
+
+/** mysql_socket_fd */
+
+static inline MYSQL_SOCKET
+inline_mysql_socket_fd
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ PSI_socket_key key,
+#endif
+ int fd)
+{
+ MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET;
+ mysql_socket.fd= fd;
+
+ DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET);
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket)
+ (key, (const my_socket*)&mysql_socket.fd, NULL, 0);
+#endif
+ /**
+ Currently systemd socket activation is the user of this
+ function. Its API (man sd_listen_fds) says FD_CLOSE_EXEC
+ is already called. If there becomes another user, we
+ can call it again without detriment.
+
+ If needed later:
+ #if defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
+ (void) fcntl(mysql_socket.fd, F_SETFD, FD_CLOEXEC);
+ #endif
+ */
+
+ return mysql_socket;
+}
+
+/** mysql_socket_socket */
+
+static inline MYSQL_SOCKET
+inline_mysql_socket_socket
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ PSI_socket_key key,
+#endif
+ int domain, int type, int protocol)
+{
+ MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET;
+ mysql_socket.fd= socket(domain, type | SOCK_CLOEXEC, protocol);
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (likely(mysql_socket.fd != INVALID_SOCKET))
+ {
+ mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket)
+ (key, (const my_socket*)&mysql_socket.fd, NULL, 0);
+ }
+#endif
+
+ /* SOCK_CLOEXEC isn't always a number - can't preprocessor compare */
+#if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) && !defined(HAVE_SOCK_CLOEXEC)
+ (void) fcntl(mysql_socket.fd, F_SETFD, FD_CLOEXEC);
+#endif
+
+ return mysql_socket;
+}
+
+/** mysql_socket_bind */
+
+static inline int
+inline_mysql_socket_bind
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, size_t len)
+{
+ int result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker_state state;
+ PSI_socket_locker *locker;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= bind(mysql_socket.fd, addr, (int)len);
+
+ /* Instrumentation end */
+ if (result == 0)
+ PSI_SOCKET_CALL(set_socket_info)(mysql_socket.m_psi, NULL, addr, (socklen_t)len);
+
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= bind(mysql_socket.fd, addr, (int)len);
+ return result;
+}
+
+/** mysql_socket_getsockname */
+
+static inline int
+inline_mysql_socket_getsockname
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len)
+{
+ int result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= getsockname(mysql_socket.fd, addr, len);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= getsockname(mysql_socket.fd, addr, len);
+
+ return result;
+}
+
+/** mysql_socket_connect */
+
+static inline int
+inline_mysql_socket_connect
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, socklen_t len)
+{
+ int result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= connect(mysql_socket.fd, addr, len);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= connect(mysql_socket.fd, addr, len);
+
+ return result;
+}
+
+/** mysql_socket_getpeername */
+
+static inline int
+inline_mysql_socket_getpeername
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len)
+{
+ int result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= getpeername(mysql_socket.fd, addr, len);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= getpeername(mysql_socket.fd, addr, len);
+
+ return result;
+}
+
+/** mysql_socket_send */
+
+static inline ssize_t
+inline_mysql_socket_send
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags)
+{
+ ssize_t result;
+ DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET);
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line);
+
+ /* Instrumented code */
+ result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ {
+ size_t bytes_written= (result > 0) ? (size_t) result : 0;
+ PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written);
+ }
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
+
+ return result;
+}
+
+/** mysql_socket_recv */
+
+static inline ssize_t
+inline_mysql_socket_recv
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags)
+{
+ ssize_t result;
+ DBUG_ASSERT(mysql_socket.fd != INVALID_SOCKET);
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ {
+ size_t bytes_read= (result > 0) ? (size_t) result : 0;
+ PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read);
+ }
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
+
+ return result;
+}
+
+/** mysql_socket_sendto */
+
+static inline ssize_t
+inline_mysql_socket_sendto
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags, const struct sockaddr *addr, socklen_t addr_len)
+{
+ ssize_t result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line);
+
+ /* Instrumented code */
+ result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ {
+ size_t bytes_written = (result > 0) ? (size_t) result : 0;
+ PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written);
+ }
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
+
+ return result;
+}
+
+/** mysql_socket_recvfrom */
+
+static inline ssize_t
+inline_mysql_socket_recvfrom
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags,
+ struct sockaddr *addr, socklen_t *addr_len)
+{
+ ssize_t result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ {
+ size_t bytes_read= (result > 0) ? (size_t) result : 0;
+ PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read);
+ }
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
+
+ return result;
+}
+
+/** mysql_socket_getsockopt */
+
+static inline int
+inline_mysql_socket_getsockopt
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, int level, int optname, SOCKBUF_T *optval, socklen_t *optlen)
+{
+ int result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= getsockopt(mysql_socket.fd, level, optname, optval, optlen);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= getsockopt(mysql_socket.fd, level, optname, optval, optlen);
+
+ return result;
+}
+
+/** mysql_socket_setsockopt */
+
+static inline int
+inline_mysql_socket_setsockopt
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, int level, int optname, const SOCKBUF_T *optval,
+ socklen_t optlen)
+{
+ int result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= setsockopt(mysql_socket.fd, level, optname, optval, optlen);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= setsockopt(mysql_socket.fd, level, optname, optval, optlen);
+
+ return result;
+}
+
+/** set_socket_nonblock */
+static inline int
+set_socket_nonblock(my_socket fd)
+{
+ int ret= 0;
+#ifdef _WIN32
+ {
+ u_long nonblocking= 1;
+ ret= ioctlsocket(fd, FIONBIO, &nonblocking);
+ }
+#else
+ {
+ int fd_flags;
+ fd_flags= fcntl(fd, F_GETFL, 0);
+ if (fd_flags < 0)
+ return errno;
+#if defined(O_NONBLOCK)
+ fd_flags |= O_NONBLOCK;
+#elif defined(O_NDELAY)
+ fd_flags |= O_NDELAY;
+#elif defined(O_FNDELAY)
+ fd_flags |= O_FNDELAY;
+#else
+#error "No definition of non-blocking flag found."
+#endif /* O_NONBLOCK */
+ if (fcntl(fd, F_SETFL, fd_flags) == -1)
+ ret= errno;
+ }
+#endif /* _WIN32 */
+ return ret;
+}
+
+/** mysql_socket_set_nonblocking */
+
+static inline int
+inline_mysql_sock_set_nonblocking
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket
+)
+{
+ int result= 0;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (mysql_socket.m_psi)
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_OPT,
+ (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= set_socket_nonblock(mysql_socket.fd);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= set_socket_nonblock(mysql_socket.fd);
+
+ return result;
+}
+
+/** mysql_socket_listen */
+
+static inline int
+inline_mysql_socket_listen
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, int backlog)
+{
+ int result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= listen(mysql_socket.fd, backlog);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= listen(mysql_socket.fd, backlog);
+
+ return result;
+}
+
+/** mysql_socket_accept */
+
+static inline MYSQL_SOCKET
+inline_mysql_socket_accept
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line, PSI_socket_key key,
+#endif
+ MYSQL_SOCKET socket_listen, struct sockaddr *addr, socklen_t *addr_len)
+{
+#ifdef FD_CLOEXEC
+ int flags __attribute__ ((unused));
+#endif
+
+ MYSQL_SOCKET socket_accept;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (socket_listen.m_psi != NULL)
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, socket_listen.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+#ifdef HAVE_ACCEPT4
+ socket_accept.fd= accept4(socket_listen.fd, addr, addr_len, SOCK_CLOEXEC);
+#else
+ socket_accept.fd= accept(socket_listen.fd, addr, addr_len);
+#ifdef FD_CLOEXEC
+ if (socket_accept.fd != INVALID_SOCKET)
+ {
+ flags= fcntl(socket_accept.fd, F_GETFD);
+ if (flags != -1)
+ {
+ flags |= FD_CLOEXEC;
+ fcntl(socket_accept.fd, F_SETFD, flags);
+ }
+ }
+#endif
+#endif
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+ }
+ else
+#endif
+ {
+ /* Non instrumented code */
+#ifdef HAVE_ACCEPT4
+ socket_accept.fd= accept4(socket_listen.fd, addr, addr_len, SOCK_CLOEXEC);
+#else
+ socket_accept.fd= accept(socket_listen.fd, addr, addr_len);
+#ifdef FD_CLOEXEC
+ if (socket_accept.fd != INVALID_SOCKET)
+ {
+ flags= fcntl(socket_accept.fd, F_GETFD);
+ if (flags != -1)
+ {
+ flags |= FD_CLOEXEC;
+ fcntl(socket_accept.fd, F_SETFD, flags);
+ }
+ }
+#endif
+#endif
+ }
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (likely(socket_accept.fd != INVALID_SOCKET))
+ {
+ /* Initialize the instrument with the new socket descriptor and address */
+ socket_accept.m_psi= PSI_SOCKET_CALL(init_socket)
+ (key, (const my_socket*)&socket_accept.fd, addr, *addr_len);
+ }
+#endif
+
+ return socket_accept;
+}
+
+/** mysql_socket_close */
+
+static inline int
+inline_mysql_socket_close
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket)
+{
+ int result;
+
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ /* Instrumentation start */
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_CLOSE, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+ result= closesocket(mysql_socket.fd);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+ /* Remove the instrumentation for this socket. */
+ if (mysql_socket.m_psi != NULL)
+ PSI_SOCKET_CALL(destroy_socket)(mysql_socket.m_psi);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+ result= closesocket(mysql_socket.fd);
+
+ return result;
+}
+
+/** mysql_socket_shutdown */
+
+static inline int
+inline_mysql_socket_shutdown
+(
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ const char *src_file, uint src_line,
+#endif
+ MYSQL_SOCKET mysql_socket, int how)
+{
+ int result;
+
+#ifdef _WIN32
+ static LPFN_DISCONNECTEX DisconnectEx = NULL;
+ if (DisconnectEx == NULL)
+ {
+ DWORD dwBytesReturned;
+ GUID guidDisconnectEx = WSAID_DISCONNECTEX;
+ WSAIoctl(mysql_socket.fd, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &guidDisconnectEx, sizeof(GUID),
+ &DisconnectEx, sizeof(DisconnectEx),
+ &dwBytesReturned, NULL, NULL);
+ }
+#endif
+
+/* Instrumentation start */
+#ifdef HAVE_PSI_SOCKET_INTERFACE
+ if (psi_likely(mysql_socket.m_psi != NULL))
+ {
+ PSI_socket_locker *locker;
+ PSI_socket_locker_state state;
+ locker= PSI_SOCKET_CALL(start_socket_wait)
+ (&state, mysql_socket.m_psi, PSI_SOCKET_SHUTDOWN, (size_t)0, src_file, src_line);
+
+ /* Instrumented code */
+#ifdef _WIN32
+ if (DisconnectEx)
+ result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL,
+ (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1;
+ else
+#endif
+ result= shutdown(mysql_socket.fd, how);
+
+ /* Instrumentation end */
+ if (locker != NULL)
+ PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
+
+ return result;
+ }
+#endif
+
+ /* Non instrumented code */
+#ifdef _WIN32
+ if (DisconnectEx)
+ result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL,
+ (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1;
+ else
+#endif
+ result= shutdown(mysql_socket.fd, how);
+
+ return result;
+}
+
+/** @} (end of group Socket_instrumentation) */
+
+#endif
+