summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--cmake/systemd.cmake1
-rw-r--r--config.h.cmake1
-rwxr-xr-xdebian/rules2
-rw-r--r--include/my_service_manager.h8
-rw-r--r--include/mysql/psi/mysql_socket.h49
-rw-r--r--sql/mysqld.cc157
-rw-r--r--support-files/CMakeLists.txt19
-rw-r--r--support-files/mariadb-extra.socket.in20
-rw-r--r--support-files/mariadb-extra@.socket.in20
-rw-r--r--support-files/mariadb.socket.in24
-rw-r--r--support-files/mariadb@.socket.in23
12 files changed, 321 insertions, 7 deletions
diff --git a/.gitignore b/.gitignore
index 9eb935f127c..4fee2deaea5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -241,7 +241,11 @@ support-files/config.small.ini
support-files/mariadb.pc
support-files/mariadb.pp
support-files/mariadb.service
+support-files/mariadb.socket
+support-files/mariadb-extra.socket
support-files/mariadb@.service
+support-files/mariadb@.socket
+support-files/mariadb-extra@.socket
support-files/my-huge.cnf
support-files/my-innodb-heavy-4G.cnf
support-files/my-large.cnf
diff --git a/cmake/systemd.cmake b/cmake/systemd.cmake
index 84d0cba94d9..c223716faeb 100644
--- a/cmake/systemd.cmake
+++ b/cmake/systemd.cmake
@@ -37,6 +37,7 @@ MACRO(CHECK_SYSTEMD)
ENDIF()
SET(CMAKE_REQUIRED_LIBRARIES ${LIBSYSTEMD})
CHECK_LIBRARY_EXISTS(systemd sd_listen_fds "" HAVE_SYSTEMD_SD_LISTEN_FDS)
+ CHECK_LIBRARY_EXISTS(systemd sd_listen_fds_with_names "" HAVE_SYSTEMD_SD_LISTEN_FDS_WITH_NAMES)
CHECK_INCLUDE_FILES(systemd/sd-daemon.h HAVE_SYSTEMD_SD_DAEMON_H)
CHECK_FUNCTION_EXISTS(sd_notify HAVE_SYSTEMD_SD_NOTIFY)
CHECK_FUNCTION_EXISTS(sd_notifyf HAVE_SYSTEMD_SD_NOTIFYF)
diff --git a/config.h.cmake b/config.h.cmake
index 2af94f96d9a..698ea65efd5 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -103,6 +103,7 @@
/* Libraries */
#cmakedefine HAVE_LIBWRAP 1
#cmakedefine HAVE_SYSTEMD 1
+#cmakedefine HAVE_SYSTEMD_SD_LISTEN_FDS_WITH_NAMES 1
/* Does "struct timespec" have a "sec" and "nsec" field? */
#cmakedefine HAVE_TIMESPEC_TS_SEC 1
diff --git a/debian/rules b/debian/rules
index a8bd26d43df..758831fcdf6 100755
--- a/debian/rules
+++ b/debian/rules
@@ -190,7 +190,7 @@ override_dh_systemd_enable:
dh_systemd_enable --name=mariadb
dh_systemd_enable --no-enable --name=mariadb@
-# Start mysql at sequence number 19 before 20 where apache, proftpd etc gets
+# Start MariaDB at sequence number 19 before 20 where apache, proftpd etc gets
# started which might depend on a running database server.
override_dh_installinit-arch:
dh_installinit --name=mariadb --no-start -- defaults 19 21
diff --git a/include/my_service_manager.h b/include/my_service_manager.h
index 95b5235e755..3eff1253f20 100644
--- a/include/my_service_manager.h
+++ b/include/my_service_manager.h
@@ -31,8 +31,16 @@
/** INTERVAL in seconds followed by printf style status */
#define service_manager_extend_timeout(INTERVAL, FMTSTR, ...) \
sd_notifyf(0, "STATUS=" FMTSTR "\nEXTEND_TIMEOUT_USEC=%u\n", ##__VA_ARGS__, INTERVAL * 1000000)
+/* sd_listen_fds_with_names added v227 however RHEL/Centos7 has v219, fallback to sd_listen_fds */
+#ifndef HAVE_SYSTEMD_SD_LISTEN_FDS_WITH_NAMES
+#define sd_listen_fds_with_names(FD, NAMES) sd_listen_fds(FD)
+#endif
#else
+#define sd_listen_fds_with_names(FD, NAMES) (0)
+#define sd_is_socket_unix(FD, TYPE, LISTENING, PATH, SIZE) (0)
+#define sd_is_socket_inet(FD, FAMILY, TYPE, LISTENING, PORT) (0)
+#define SD_LISTEN_FDS_START (0)
#define sd_notify(X, Y)
#define sd_notifyf(E, F, ...)
#define service_manager_extend_timeout(I, FMTSTR, ...)
diff --git a/include/mysql/psi/mysql_socket.h b/include/mysql/psi/mysql_socket.h
index 59489fabe25..d70e1c8fc5a 100644
--- a/include/mysql/psi/mysql_socket.h
+++ b/include/mysql/psi/mysql_socket.h
@@ -305,6 +305,22 @@ inline_mysql_socket_set_state(MYSQL_SOCKET socket, enum PSI_socket_state 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.
@@ -578,6 +594,39 @@ static inline void inline_mysql_socket_register(
}
#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
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index adb6ff82662..7a1d56e7ff9 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1346,6 +1346,9 @@ struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD()
Dynamic_array<MYSQL_SOCKET> listen_sockets(PSI_INSTRUMENT_MEM, 0);
bool unix_sock_is_online= false;
+static int systemd_sock_activation; /* systemd socket activation */
+
+
/**
Error reporter that buffer log messages.
@param level log message level
@@ -1690,8 +1693,10 @@ static void close_connections(void)
{
MYSQL_SOCKET *sock= listen_sockets.get_pos(i);
(void) mysql_socket_close(*sock);
- if (sock->is_unix_domain_socket)
+ if (sock->is_unix_domain_socket && !systemd_sock_activation)
+ {
(void) unlink(mysqld_unix_port);
+ }
}
listen_sockets.free_memory();
mysql_mutex_unlock(&LOCK_start_thread);
@@ -2342,6 +2347,144 @@ static void activate_tcp_port(uint port,
DBUG_VOID_RETURN;
}
+
+/**
+ Activate usage of a systemd activated sockets
+ i.e started by mariadb.socket
+*/
+
+static void use_systemd_activated_sockets()
+{
+#ifndef __linux__
+ return;
+#else
+ char **names = NULL;
+ int sd_sockets;
+ DBUG_ENTER("use_systemd_activated_sockets");
+
+ sd_sockets= sd_listen_fds_with_names(0, &names);
+
+ if (!sd_sockets)
+ DBUG_VOID_RETURN;
+
+ DBUG_PRINT("general",("Systemd listen_fds is %d", sd_sockets));
+ while (sd_sockets--)
+ {
+ MYSQL_SOCKET sock;
+ int stype= 0, accepting= 0, getnameinfo_err;
+ socklen_t l;
+ union
+ {
+ struct sockaddr sa;
+ struct sockaddr_storage storage;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_un un;
+ } addr;
+ SOCKET_SIZE_TYPE addrlen= sizeof(addr);
+ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+
+ int fd= SD_LISTEN_FDS_START + sd_sockets;
+
+ if (getsockname(fd, &addr.sa, &addrlen))
+ {
+ sql_print_error("Unable to getsockname on systemd socket activation socket %d,"
+ " errno %d", fd, errno);
+ goto err;
+ }
+
+ l= sizeof(stype);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &stype, &l) < 0)
+ {
+ sql_print_error("Unable to getsockopt(SOL_SOCKET, SO_TYPE) on"
+ " systemd socket activation socket %d,"
+ " errno %d", fd, errno);
+ goto err;
+ }
+
+ if (stype != SOCK_STREAM)
+ {
+ sql_print_error("Unknown systemd socket activation socket %d,"
+ " not of type SOCK_STREAM - type %d", fd, stype);
+ goto err;
+ }
+
+ l= sizeof(accepting);
+ if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
+ {
+ sql_print_error("Unable to getsockopt(SOL_SOCKET, SO_ACCEPTCONN) on"
+ " systemd socket activation socket %d,"
+ " errno %d", fd, errno);
+ goto err;
+ }
+
+ if (!accepting)
+ {
+ sql_print_error("Unknown systemd socket activation socket %d,"
+ " is not listening", fd);
+ goto err;
+ }
+
+ switch (addr.sa.sa_family)
+ {
+ case AF_INET:
+ sock= mysql_socket_fd(key_socket_tcpip, fd);
+ sock.is_unix_domain_socket= 0;
+ mysqld_port= ntohs(addr.in.sin_port);
+ break;
+ case AF_INET6:
+ sock= mysql_socket_fd(key_socket_tcpip, fd);
+ sock.is_unix_domain_socket= 0;
+ mysqld_port= ntohs(addr.in6.sin6_port);
+ break;
+ case AF_UNIX:
+ sock= mysql_socket_fd(key_socket_unix, fd);
+ sock.is_unix_domain_socket= 1;
+ break;
+ default:
+ sql_print_error("Unknown systemd socket activation socket %d,"
+ " not UNIX or INET socket", fd);
+ goto err;
+ }
+
+ getnameinfo_err= getnameinfo(&addr.sa, addrlen, hbuf, sizeof(hbuf), sbuf,
+ sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+ if (getnameinfo_err)
+ sql_print_warning("getnameinfo() on systemd socket activation socket %d"
+ " failed with error %d", fd, getnameinfo_err);
+ else
+ {
+ /*
+ Handle abstract sockets and present them in @ form.
+ We don't just use sbuf because of https://sourceware.org/bugzilla/show_bug.cgi?id=27634.
+ */
+ if (sbuf[0] == '\0')
+ addr.un.sun_path[0] = '@';
+ sql_print_information("Using systemd activated socket %s port %s", hbuf,
+ sbuf[0] == '\0' ? addr.un.sun_path : sbuf);
+ }
+
+ /*
+ We check names!=NULL here because sd_listen_fds_with_names maybe
+ just sd_listen_fds on older pre v227 systemd
+ */
+ sock.is_extra_port= names && strcmp(names[sd_sockets], "extra") == 0;
+ mysql_socket_set_thread_owner(sock);
+ listen_sockets.push(sock);
+ }
+ systemd_sock_activation= 1;
+ free(names);
+
+ DBUG_VOID_RETURN;
+
+err:
+ free(names);
+ unireg_abort(1);
+ DBUG_VOID_RETURN;
+#endif /* __linux__ */
+}
+
+
static void network_init(void)
{
#ifdef HAVE_SYS_UN_H
@@ -2350,6 +2493,8 @@ static void network_init(void)
#endif
DBUG_ENTER("network_init");
+ use_systemd_activated_sockets();
+
if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0))
unireg_abort(1); /* purecov: inspected */
@@ -2366,7 +2511,7 @@ static void network_init(void)
if (!opt_disable_networking)
DBUG_ASSERT(report_port != 0);
#endif
- if (!opt_disable_networking && !opt_bootstrap)
+ if (!opt_disable_networking && !opt_bootstrap && !systemd_sock_activation)
{
if (mysqld_port)
activate_tcp_port(mysqld_port, &listen_sockets,
@@ -2380,7 +2525,7 @@ static void network_init(void)
/*
** Create the UNIX socket
*/
- if (mysqld_unix_port[0] && !opt_bootstrap)
+ if (mysqld_unix_port[0] && !opt_bootstrap && systemd_sock_activation==0)
{
MYSQL_SOCKET unix_sock= MYSQL_INVALID_SOCKET;
size_t port_len;
@@ -5589,7 +5734,8 @@ int mysqld_main(int argc, char **argv)
if (IS_SYSVAR_AUTOSIZE(&server_version_ptr))
sql_print_information(ER_DEFAULT(ER_STARTUP), my_progname, server_version,
- (unix_sock_is_online ? mysqld_unix_port : (char*) ""),
+ (systemd_sock_activation ? "Systemd socket activated ports" :
+ (unix_sock_is_online ? mysqld_unix_port : (char*) "")),
mysqld_port, MYSQL_COMPILATION_COMMENT);
else
{
@@ -5601,7 +5747,8 @@ int mysqld_main(int argc, char **argv)
sql_print_information(ER_DEFAULT(ER_STARTUP), my_progname,
real_server_version,
- (unix_sock_is_online ? mysqld_unix_port : (char*) ""),
+ (systemd_sock_activation ? "Systemd socket activated ports" :
+ (unix_sock_is_online ? mysqld_unix_port : (char*) "")),
mysqld_port, MYSQL_COMPILATION_COMMENT);
}
diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt
index 338ae90cd42..851f0394f4a 100644
--- a/support-files/CMakeLists.txt
+++ b/support-files/CMakeLists.txt
@@ -120,6 +120,10 @@ IF(UNIX AND NOT WITHOUT_SERVER)
IF(HAVE_SYSTEMD)
CONFIGURE_FILE(mariadb.service.in
${CMAKE_CURRENT_BINARY_DIR}/mariadb.service @ONLY)
+ CONFIGURE_FILE(mariadb.socket.in
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb.socket @ONLY)
+ CONFIGURE_FILE(mariadb-extra.socket.in
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb-extra.socket @ONLY)
EXECUTE_PROCESS(
COMMAND ${CMAKE_COMMAND} -E create_symlink ./mariadb.service mysql.service
COMMAND ${CMAKE_COMMAND} -E create_symlink ./mariadb.service mysqld.service
@@ -136,13 +140,24 @@ IF(UNIX AND NOT WITHOUT_SERVER)
IF(NOT CMAKE_VERSION VERSION_LESS 3.3.0 OR NOT RPM)
CONFIGURE_FILE(mariadb@.service.in
${CMAKE_CURRENT_BINARY_DIR}/mariadb@.service @ONLY)
- INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mariadb@.service
+ CONFIGURE_FILE(mariadb@.socket.in
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb@.socket @ONLY)
+ CONFIGURE_FILE(mariadb-extra@.socket.in
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb-extra@.socket @ONLY)
+ INSTALL(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb@.service
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb@.socket
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb-extra@.socket
+ ${CMAKE_CURRENT_BINARY_DIR}/mysql.service
+ ${CMAKE_CURRENT_BINARY_DIR}/mysqld.service
DESTINATION ${inst_location}/systemd COMPONENT SupportFiles)
ENDIF()
IF(INSTALL_SYSTEMD_UNITDIR)
INSTALL(FILES
${CMAKE_CURRENT_BINARY_DIR}/mariadb.service
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb.socket
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb-extra.socket
${CMAKE_CURRENT_BINARY_DIR}/mysql.service
${CMAKE_CURRENT_BINARY_DIR}/mysqld.service
DESTINATION ${INSTALL_SYSTEMD_UNITDIR} COMPONENT Server)
@@ -154,6 +169,8 @@ IF(UNIX AND NOT WITHOUT_SERVER)
"${INSTALL_SYSTEMD_UNITDIR}/mariadb@bootstrap.service.d"
COMPONENT Server)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mariadb@.service
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb@.socket
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb-extra@.socket
DESTINATION ${INSTALL_SYSTEMD_UNITDIR} COMPONENT Server)
ENDIF()
diff --git a/support-files/mariadb-extra.socket.in b/support-files/mariadb-extra.socket.in
new file mode 100644
index 00000000000..f268a0ad2a8
--- /dev/null
+++ b/support-files/mariadb-extra.socket.in
@@ -0,0 +1,20 @@
+
+[Unit]
+
+Description=MariaDB @VERSION@ database server (socket activation extra port)
+Documentation=man:mariadbd(8)
+Documentation=https://mariadb.com/kb/en/library/systemd/
+
+[Socket]
+
+Service=mariadb.service
+
+# An "extra" as a descriptor name that means treat these ListenStreams as
+# the same as an extra_port.
+# Ref: https://mariadb.com/kb/en/thread-pool-system-status-variables/#extra_port
+
+FileDescriptorName=extra
+
+ListenStream=@mariadb-extra
+ListenStream=@MYSQL_UNIX_ADDR@-extra
+
diff --git a/support-files/mariadb-extra@.socket.in b/support-files/mariadb-extra@.socket.in
new file mode 100644
index 00000000000..f33344f2abd
--- /dev/null
+++ b/support-files/mariadb-extra@.socket.in
@@ -0,0 +1,20 @@
+
+[Unit]
+
+Description=MariaDB @VERSION@ database server (socket activation extra port multi-instance %I)
+Documentation=man:mariadbd(8)
+Documentation=https://mariadb.com/kb/en/library/systemd/
+
+[Socket]
+
+Service=mariadb@%i.service
+
+# An "extra" as a descriptor name that means treat these ListenStreams as
+# the same as an extra_port.
+# Ref: https://mariadb.com/kb/en/thread-pool-system-status-variables/#extra_port
+
+FileDescriptorName=extra
+
+ListenStream=@mariadb-extra-%I
+ListenStream=@MYSQL_UNIX_ADDR@-extra-%I
+
diff --git a/support-files/mariadb.socket.in b/support-files/mariadb.socket.in
new file mode 100644
index 00000000000..d99fdee0334
--- /dev/null
+++ b/support-files/mariadb.socket.in
@@ -0,0 +1,24 @@
+
+[Unit]
+Description=MariaDB @VERSION@ database server (socket activation)
+Documentation=man:mariadbd(8)
+Documentation=https://mariadb.com/kb/en/library/systemd/
+
+[Socket]
+
+##############################################################################
+## USERs can override
+##
+##
+## by creating a file in /etc/systemd/system/mariadb.socket.d/MY_SPECIAL.conf
+## and adding/setting the following under [Socket] will override this file's
+## settings.
+
+SocketUser=@MYSQLD_USER@
+SocketMode=777
+
+ListenStream=@mariadb
+ListenStream=@MYSQL_UNIX_ADDR@
+ListenStream=@MYSQL_TCP_PORT@
+
+# Backlog=150
diff --git a/support-files/mariadb@.socket.in b/support-files/mariadb@.socket.in
new file mode 100644
index 00000000000..561a44443c9
--- /dev/null
+++ b/support-files/mariadb@.socket.in
@@ -0,0 +1,23 @@
+
+[Unit]
+Description=MariaDB @VERSION@ database server (socket activation multi-instance %I))
+Documentation=man:mariadbd(8)
+Documentation=https://mariadb.com/kb/en/library/systemd/
+
+[Socket]
+
+##############################################################################
+## USERs can override
+##
+##
+## by creating a file in /etc/systemd/system/mariadb.socket.d/MY_SPECIAL.conf
+## and adding/setting the following under [Socket] will override this file's
+## settings.
+
+SocketUser=@MYSQLD_USER@
+SocketMode=777
+
+ListenStream=@mariadb-%I
+ListenStream=@MYSQL_UNIX_ADDR@-%I
+
+# Backlog=150