Merge branch 'v2.x' into v2.x-3504

pull/3505/head
René Cannaò 4 years ago committed by GitHub
commit 4bfe674064
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

5
.gitignore vendored

@ -194,3 +194,8 @@ test/tap/tests/reg_test_3504-change_user_libmysql_helper
test/tap/tests/generate_set_session_csv
test/tap/tests/set_testing-240.csv
local_testing_datadir/
#files generated during CI run
proxysql-save.cfg
test/tap/tests/test_cluster_sync_config/cluster_sync_node_stderr.txt
test/tap/tests/test_cluster_sync_config/proxysql*.pem

@ -35,11 +35,18 @@ struct bio_st {
typedef int CRYPTO_REF_COUNT;
// in libssl 1.1.1
/**
* @brief This is the 'bio_st' struct definition from libssl 3.0.0. NOTE: This is an internal struct from
* OpenSSL library, currently it's used for performing checks on the reads/writes performed on the BIO objects.
* It's extremely important to keep this struct up to date with each OpenSSL dependency update.
*/
struct bio_st {
OSSL_LIB_CTX *libctx;
const BIO_METHOD *method;
/* bio, mode, argp, argi, argl, ret */
#ifndef OPENSSL_NO_DEPRECATED_3_0
BIO_callback_fn callback;
#endif
BIO_callback_fn_ex callback_ex;
char *cb_arg; /* first argument for the callback */
int init;

@ -785,3 +785,53 @@ int create_extra_users(
return EXIT_SUCCESS;
}
std::string tap_curtime() {
time_t __timer;
char lut[30];
struct tm __tm_info;
time(&__timer);
localtime_r(&__timer, &__tm_info);
strftime(lut, 25, "%Y-%m-%d %H:%M:%S", &__tm_info);
std::string s = std::string(lut);
return s;
int get_proxysql_cpu_usage(const CommandLine& cl, uint32_t intv, uint32_t& cpu_usage) {
// check if proxysql process is consuming higher cpu than it should
MYSQL* proxysql_admin = mysql_init(NULL);
if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
return -1;
}
// recover admin variables
std::string set_stats_query { "SET admin-stats_system_cpu=" + std::to_string(intv) };
MYSQL_QUERY(proxysql_admin, set_stats_query.c_str());
MYSQL_QUERY(proxysql_admin, "LOAD ADMIN VARIABLES TO RUNTIME");
// sleep during the required interval + safe threshold
sleep(intv + 2);
MYSQL_QUERY(proxysql_admin, "SELECT * FROM system_cpu ORDER BY timestamp DESC LIMIT 1");
MYSQL_RES* admin_res = mysql_store_result(proxysql_admin);
MYSQL_ROW row = mysql_fetch_row(admin_res);
double s_clk = (1.0 / sysconf(_SC_CLK_TCK)) * 1000;
int utime_ms = atoi(row[1]) * s_clk;
int stime_ms = atoi(row[2]) * s_clk;
int t_ms = utime_ms + stime_ms;
// return the cpu usage
cpu_usage = t_ms;
// free the result
mysql_free_result(admin_res);
// recover admin variables
MYSQL_QUERY(proxysql_admin, "SET admin-stats_system_cpu=60");
MYSQL_QUERY(proxysql_admin, "LOAD ADMIN VARIABLES TO RUNTIME");
mysql_close(proxysql_admin);
return 0;
}

@ -10,6 +10,8 @@
#include <curl/curl.h>
#include "command_line.h"
#define MYSQL_QUERY(mysql, query) \
do { \
if (mysql_query(mysql, query)) { \
@ -227,4 +229,15 @@ int create_extra_users(
MYSQL* proxysql_admin, MYSQL* mysql_server, const std::vector<user_config>& users_config
);
std::string tap_curtime();
/**
* @brief Returns ProxySQL cpu usage in ms.
* @param intv The interval in which the CPU usage of ProxySQL is going
* to be measured.
* @param cpu_usage Output parameter with the cpu usage by ProxySQL in
* 'ms' in the specified interval.
* @return 0 if success, -1 in case of error.
*/
int get_proxysql_cpu_usage(const CommandLine& cl, uint32_t intv, uint32_t& cpu_usage);
#endif // #define UTILS_H

@ -1,5 +1,5 @@
/**
* @file test_simple_ssl_con-t.cpp
* @file reg_test_3273_ssl_con-t.cpp
* @brief This test tries to induce a particular timing condition to replicate issue #70138.
* For testing the issue against admin, supply to the binary "admin" as parameter, otherwise
* the connection will be created as a regular client connection.
@ -64,49 +64,8 @@ static int wait_for_mysql(MYSQL *mysql, int status) {
}
}
/**
* @brief Returns ProxySQL cpu usage in ms.
* @param intv The interval in which the CPU usage of ProxySQL is going
* to be measured.
* @param cpu_usage Output parameter with the cpu usage by ProxySQL in
* 'ms' in the specified interval.
* @return 0 if success, -1 in case of error.
*/
int get_proxysql_cpu_usage(const CommandLine& cl, int intv, int* cpu_usage) {
// check if proxysql process is consuming higher cpu than it should
MYSQL* proxysql_admin = mysql_init(NULL);
if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
return -1;
}
// recover admin variables
std::string set_stats_query { "SET admin-stats_system_cpu=" + std::to_string(intv) };
MYSQL_QUERY(proxysql_admin, set_stats_query.c_str());
MYSQL_QUERY(proxysql_admin, "LOAD ADMIN VARIABLES TO RUNTIME");
// sleep during the required interval + safe threshold
sleep(intv + 2);
MYSQL_QUERY(proxysql_admin, "SELECT * FROM system_cpu ORDER BY timestamp DESC LIMIT 1");
MYSQL_RES* admin_res = mysql_store_result(proxysql_admin);
MYSQL_ROW row = mysql_fetch_row(admin_res);
double s_clk = 1.0 / sysconf(_SC_CLK_TCK);
int utime_ms = atoi(row[1]) / s_clk;
int stime_ms = atoi(row[2]) / s_clk;
int t_ms = utime_ms + stime_ms;
// return the cpu usage
*cpu_usage = t_ms;
// recover admin variables
MYSQL_QUERY(proxysql_admin, "SET admin-stats_system_cpu=60");
MYSQL_QUERY(proxysql_admin, "LOAD ADMIN VARIABLES TO RUNTIME");
return 0;
}
const uint32_t REPORT_INTV_SEC = 5;
const double MAX_ALLOWED_CPU_USAGE = 0.15;
int main(int argc, char** argv) {
CommandLine cl;
@ -125,8 +84,8 @@ int main(int argc, char** argv) {
}
// get ProxySQL idle cpu usage
int idle_cpu_ms = 0;
int idle_err = get_proxysql_cpu_usage(cl, 5, &idle_cpu_ms);
uint32_t idle_cpu_ms = 0;
int idle_err = get_proxysql_cpu_usage(cl, REPORT_INTV_SEC, idle_cpu_ms);
if (idle_err) {
fprintf(stdout, "File %s, line %d, Error: '%s'\n", __FILE__, __LINE__, "Unable to get 'idle_cpu' usage.");
return idle_err;
@ -155,8 +114,7 @@ int main(int argc, char** argv) {
my_socket sockt = mysql_get_socket(proxysql);
int state = 0;
while (status)
{
while (status) {
status = wait_for_mysql(proxysql, status);
if (state == 1) {
std::thread closer {[sockt]() -> void {
@ -187,20 +145,20 @@ int main(int argc, char** argv) {
return exit_status();
}
int final_cpu_ms = 0;
int final_err = get_proxysql_cpu_usage(cl, 5, &final_cpu_ms);
uint32_t final_cpu_ms = 0;
int final_err = get_proxysql_cpu_usage(cl, REPORT_INTV_SEC, final_cpu_ms);
if (final_err) {
fprintf(stdout, "File %s, line %d, Error: '%s'\n", __FILE__, __LINE__, "Unable to get 'idle_cpu' usage.");
return idle_err;
}
// proxysql spent more than one time of CPU in the last 5 seconds when it should be
// idle; something is wrong
// compute the '%' of CPU used during the last interval
uint32_t cpu_usage_ms = final_cpu_ms - idle_cpu_ms;
double cpu_usage_pct = cpu_usage_ms / (REPORT_INTV_SEC * 1000.0);
ok(
final_cpu_ms < (idle_cpu_ms*3),
"ProxySQL shouldn't be taking so much CPU time, idle:'%d', final:'%d'",
idle_cpu_ms,
final_cpu_ms
cpu_usage_pct < MAX_ALLOWED_CPU_USAGE, "ProxySQL CPU usage should be below expected: (Exp: %%%lf, Act: %%%lf)",
MAX_ALLOWED_CPU_USAGE, cpu_usage_pct
);
return exit_status();

@ -0,0 +1,169 @@
/**
* @file reg_test_3765_ssl_pollout-t.cpp
* @brief This test opens multiple connections against ProxySQL with different client flags and checks that
* CPU usage by ProxySQL didn't increase significantly. Tested connections types are: normal, SSL, and
* compression.
* @details The goal of the test is to detect regressions or incompatibilities in the way ProxySQL polling
* operations interacts with OpenSSL library.
*/
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <stdio.h>
#include <unistd.h>
#include <poll.h>
#include <sys/epoll.h>
#include <mysql.h>
#include <thread>
#include "tap.h"
#include "command_line.h"
#include "utils.h"
using std::string;
using std::vector;
struct conn_opts_t {
string host;
string user;
string pass;
int port;
uint64_t client_flags;
};
/**
* @brief TODO: Refactor this into utils, also used in another PR.
*/
int create_connections(const conn_opts_t& conn_opts, uint32_t cons_num, std::vector<MYSQL*>& proxy_conns) {
std::vector<MYSQL*> result {};
for (uint32_t i = 0; i < cons_num; i++) {
const char* host = conn_opts.host.c_str();
const char* user = conn_opts.user.c_str();
const char* pass = conn_opts.pass.c_str();
const int port = conn_opts.port;
MYSQL* proxysql = mysql_init(NULL);
if (conn_opts.client_flags & CLIENT_SSL) {
mysql_ssl_set(proxysql, NULL, NULL, NULL, NULL, NULL);
}
if (!mysql_real_connect(proxysql, host, user, pass, NULL, port, NULL, conn_opts.client_flags)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql));
return EXIT_FAILURE;
} else {
result.push_back(proxysql);
}
}
proxy_conns = result;
return EXIT_SUCCESS;
}
const uint32_t ADMIN_CONN_NUM = 100;
const uint32_t MYSQL_CONN_NUM = 100;
const uint32_t REPORT_INTV_SEC = 5;
const double MAX_ALLOWED_CPU_USAGE = 0.15;
int get_idle_conns_cpu_usage(CommandLine& cl, uint64_t mode, uint32_t& idle_cpu_ms, uint32_t& final_cpu_ms) {
// get ProxySQL idle cpu usage
int idle_err = get_proxysql_cpu_usage(cl, REPORT_INTV_SEC, idle_cpu_ms);
if (idle_err) {
fprintf(stdout, "File %s, line %d, Error: '%s'\n", __FILE__, __LINE__, "Unable to get 'idle_cpu' usage.");
return idle_err;
}
conn_opts_t proxy_conns_opts { "127.0.0.1", cl.username, cl.password, cl.port, mode };
conn_opts_t admin_conns_opts { "127.0.0.1", cl.admin_username, cl.admin_password, cl.admin_port, mode };
// Create 'N' admin and mysql connections without SSL
vector<MYSQL*> v_admin_conns {};
int admin_conns_res = create_connections(admin_conns_opts, ADMIN_CONN_NUM, v_admin_conns);
if (admin_conns_res != EXIT_SUCCESS) {
return EXIT_FAILURE;
}
vector<MYSQL*> v_proxy_conns {};
int mysql_conns_res = create_connections(proxy_conns_opts, MYSQL_CONN_NUM, v_proxy_conns);
if (admin_conns_res != EXIT_SUCCESS) {
return EXIT_FAILURE;
}
int final_err = get_proxysql_cpu_usage(cl, REPORT_INTV_SEC, final_cpu_ms);
if (final_err) {
fprintf(stdout, "File %s, line %d, Error: '%s'\n", __FILE__, __LINE__, "Unable to get 'idle_cpu' usage.");
return idle_err;
}
std::for_each(v_admin_conns.begin(), v_admin_conns.end(), [](MYSQL* conn) -> void { mysql_close(conn); });
std::for_each(v_proxy_conns.begin(), v_proxy_conns.end(), [](MYSQL* conn) -> void { mysql_close(conn); });
return EXIT_SUCCESS;
}
int main(int argc, char** argv) {
CommandLine cl;
if (cl.getEnv()) {
diag("Failed to get the required environmental variables.");
return -1;
}
uint32_t idle_cpu_ms = 0;
uint32_t final_cpu_ms = 0;
MYSQL* proxysql_admin = mysql_init(NULL);
if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
return EXIT_FAILURE;
}
MYSQL_QUERY(proxysql_admin, "SET mysql-have_ssl=1");
MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME");
mysql_close(proxysql_admin);
diag("Testing regular connections...");
int cpu_usage_res = get_idle_conns_cpu_usage(cl, 0, idle_cpu_ms, final_cpu_ms);
if (cpu_usage_res != EXIT_SUCCESS) { return EXIT_FAILURE; }
// compute the '%' of CPU used during the last interval
uint32_t cpu_usage_ms = final_cpu_ms - idle_cpu_ms;
double cpu_usage_pct = cpu_usage_ms / (REPORT_INTV_SEC * 1000.0);
ok(
cpu_usage_pct < MAX_ALLOWED_CPU_USAGE, "ProxySQL CPU usage should be below expected: (Exp: %%%lf, Act: %%%lf)",
MAX_ALLOWED_CPU_USAGE, cpu_usage_pct
);
diag("Testing SSL connections...");
cpu_usage_res = get_idle_conns_cpu_usage(cl, CLIENT_SSL, idle_cpu_ms, final_cpu_ms);
if (cpu_usage_res != EXIT_SUCCESS) { return EXIT_FAILURE; }
// compute the '%' of CPU used during the last interval
cpu_usage_ms = final_cpu_ms - idle_cpu_ms;
cpu_usage_pct = cpu_usage_ms / (REPORT_INTV_SEC * 1000.0);
ok(
cpu_usage_pct < MAX_ALLOWED_CPU_USAGE, "ProxySQL CPU usage should be below expected: (Exp: %%%lf, Act: %%%lf)",
MAX_ALLOWED_CPU_USAGE, cpu_usage_pct
);
diag("Testing SSL and compressed connections...");
cpu_usage_res = get_idle_conns_cpu_usage(cl, CLIENT_SSL|CLIENT_COMPRESS, idle_cpu_ms, final_cpu_ms);
if (cpu_usage_res != EXIT_SUCCESS) { return EXIT_FAILURE; }
// compute the '%' of CPU used during the last interval
cpu_usage_ms = final_cpu_ms - idle_cpu_ms;
cpu_usage_pct = cpu_usage_ms / (REPORT_INTV_SEC * 1000.0);
ok(
cpu_usage_pct < MAX_ALLOWED_CPU_USAGE, "ProxySQL CPU usage should be below expected: (Exp: %%%lf, Act: %%%lf)",
MAX_ALLOWED_CPU_USAGE, cpu_usage_pct
);
return exit_status();
}

@ -40,6 +40,7 @@ int shunn_server(MYSQL* proxysql_admin, uint32_t i, uint32_t j) {
std::string t_simulator_error_query { "PROXYSQL_SIMULATOR mysql_error %d 127.0.0.1:330%d 1234" };
std::string simulator_error_q_i {};
string_format(t_simulator_error_query, simulator_error_q_i, i, j);
diag("%s: running query: %s", tap_curtime().c_str(), simulator_error_q_i.c_str());
MYSQL_QUERY(proxysql_admin, simulator_error_q_i.c_str());
return EXIT_SUCCESS;
@ -63,18 +64,21 @@ int wakup_target_server(MYSQL* proxysql_mysql, uint32_t i) {
string_format(t_simple_do_query, simple_do_query, i);
mysql_query(proxysql_mysql, simple_do_query.c_str());
diag("%s: running query: %s", tap_curtime().c_str(), simple_do_query.c_str());
sleep(SHUN_RECOVERY_TIME * 2);
mysql_query(proxysql_mysql, simple_do_query.c_str());
diag("%s: running query: %s", tap_curtime().c_str(), simple_do_query.c_str());
return EXIT_SUCCESS;
}
int server_status_checker(MYSQL* admin, const string& f_st, const string& n_st, uint32_t i) {
std::string t_server_status_query {
"SELECT status FROM runtime_mysql_servers WHERE port=330%d order by hostgroup_id"
"SELECT status,hostgroup_id FROM runtime_mysql_servers WHERE port=330%d order by hostgroup_id"
};
std::string server_status_query {};
string_format(t_server_status_query, server_status_query, i);
diag("%s: running query: %s", tap_curtime().c_str(), server_status_query.c_str());
MYSQL_QUERY(admin, server_status_query.c_str());
MYSQL_RES* status_res = mysql_store_result(admin);
@ -89,7 +93,8 @@ int server_status_checker(MYSQL* admin, const string& f_st, const string& n_st,
while (( row = mysql_fetch_row(status_res) )) {
std::string status { row[0] };
diag("Status found for server '127.0.0.1:330%d' was '%s'", i, status.c_str());
std::string hgid { row[1] };
diag("Status found for server '%s:127.0.0.1:330%d' was '%s'", hgid.c_str(), i, status.c_str());
if (row_num == 0) {
if (status != f_st) {
unexp_row_value = true;

Loading…
Cancel
Save