1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
/*
Copyright (c) 2013, 2025, Oracle and/or its affiliates.
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 designed to work 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 either included with
the program or referenced in the documentation.
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-1301 USA
*/
#include "sql/conn_handler/init_net_server_extension.h"
#include <assert.h>
#include <stddef.h>
#include "lex_string.h"
#include "my_compiler.h"
#include "my_psi_config.h"
#include "mysql/components/services/bits/psi_socket_bits.h"
#include "mysql/components/services/bits/psi_statement_bits.h"
#include "mysql/psi/mysql_idle.h" // MYSQL_SOCKET_SET_STATE,
#include "mysql/psi/mysql_socket.h"
#include "mysql/psi/mysql_statement.h"
#include "mysql_com.h"
#include "mysql_com_server.h"
// MYSQL_START_IDLE_WAIT
#include "sql/mysqld.h" // stage_starting
#include "sql/protocol_classic.h"
#include "sql/sql_class.h" // THD
#include "violite.h"
#ifdef HAVE_PSI_STATEMENT_INTERFACE // TODO: << nonconformance with
// HAVE_PSI_INTERFACE
PSI_statement_info stmt_info_new_packet;
#endif
static void net_before_header_psi(NET *net [[maybe_unused]], void *user_data,
size_t /* unused: count */) {
THD *thd;
thd = static_cast<THD *>(user_data);
assert(thd != nullptr);
if (thd->m_server_idle) {
/*
The server is IDLE, waiting for the next command.
Technically, it is a wait on a socket, which may take a long time,
because the call is blocking.
Disable the socket instrumentation, to avoid recording a SOCKET event.
Instead, start explicitly an IDLE event.
*/
MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_IDLE);
MYSQL_START_IDLE_WAIT(thd->m_idle_psi, &thd->m_idle_state);
}
mysql_thread_set_secondary_engine(false);
}
static void net_after_header_psi(NET *net [[maybe_unused]], void *user_data,
size_t /* unused: count */, bool rc) {
THD *thd;
thd = static_cast<THD *>(user_data);
assert(thd != nullptr);
if (thd->m_server_idle) {
/*
The server just got data for a network packet header,
from the network layer.
The IDLE event is now complete, since we now have a message to process.
We need to:
- start a new STATEMENT event
- start a new STAGE event, within this statement,
- start recording SOCKET WAITS events, within this stage.
The proper order is critical to get events numbered correctly,
and nested in the proper parent.
*/
MYSQL_END_IDLE_WAIT(thd->m_idle_psi);
#ifdef HAVE_PSI_THREAD_INTERFACE
PSI_thread *thread = thd_get_psi(thd);
if (thread != nullptr) {
PSI_THREAD_CALL(detect_telemetry)(thread);
}
#endif
if (!rc) {
assert(thd->m_statement_psi == nullptr);
thd->m_statement_psi = MYSQL_START_STATEMENT(
&thd->m_statement_state, stmt_info_new_packet.m_key, thd->db().str,
thd->db().length, thd->charset(), nullptr);
/*
Starts a new stage in performance schema, if compiled in and enabled.
Also sets THD::proc_info (used by SHOW PROCESSLIST, column STATE)
*/
THD_STAGE_INFO(thd, stage_starting);
}
/*
TODO: consider recording a SOCKET event for the bytes just read,
by also passing count here.
*/
MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_ACTIVE);
thd->m_server_idle = false;
}
}
void init_net_server_extension(THD *thd) {
/* Start with a clean state for connection events. */
thd->m_idle_psi = nullptr;
thd->m_statement_psi = nullptr;
thd->m_server_idle = false;
/* Hook up the NET_SERVER callback in the net layer. */
thd->m_net_server_extension.m_user_data = thd;
thd->m_net_server_extension.m_before_header = net_before_header_psi;
thd->m_net_server_extension.m_after_header = net_after_header_psi;
thd->m_net_server_extension.compress_ctx.algorithm = MYSQL_UNCOMPRESSED;
thd->m_net_server_extension.timeout_on_full_packet = false;
/* Activate this private extension for the mysqld server. */
thd->get_protocol_classic()->get_net()->extension =
&thd->m_net_server_extension;
}
|