
See script directory for method. The script to run in the top level MaxScale directory is called maxscale-uncrustify.sh, which uses another script, list-src, from the same directory (so you need to set your PATH). The uncrustify version was 0.66.
511 lines
12 KiB
C++
511 lines
12 KiB
C++
#include "maxscales.h"
|
|
#include <sstream>
|
|
#include <unordered_map>
|
|
|
|
Maxscales::Maxscales(const char* pref, const char* test_cwd, bool verbose)
|
|
{
|
|
strcpy(prefix, pref);
|
|
this->verbose = verbose;
|
|
strcpy(test_dir, test_cwd);
|
|
read_env();
|
|
}
|
|
|
|
int Maxscales::read_env()
|
|
{
|
|
char* env;
|
|
char env_name[64];
|
|
|
|
read_basic_env();
|
|
|
|
if ((N > 0) && (N < 255))
|
|
{
|
|
for (int i = 0; i < N; i++)
|
|
{
|
|
sprintf(env_name, "%s_%03d_cnf", prefix, i);
|
|
env = getenv(env_name);
|
|
if (env == NULL)
|
|
{
|
|
sprintf(env_name, "%s_cnf", prefix);
|
|
env = getenv(env_name);
|
|
}
|
|
if (env != NULL)
|
|
{
|
|
sprintf(maxscale_cnf[i], "%s", env);
|
|
}
|
|
else
|
|
{
|
|
sprintf(maxscale_cnf[i], "/etc/maxscale.cnf");
|
|
}
|
|
|
|
sprintf(env_name, "%s_%03d_log_dir", prefix, i);
|
|
env = getenv(env_name);
|
|
if (env == NULL)
|
|
{
|
|
sprintf(env_name, "%s_log_dir", prefix);
|
|
env = getenv(env_name);
|
|
}
|
|
|
|
if (env != NULL)
|
|
{
|
|
sprintf(maxscale_log_dir[i], "%s", env);
|
|
}
|
|
else
|
|
{
|
|
sprintf(maxscale_log_dir[i], "/var/log/maxscale/");
|
|
}
|
|
|
|
sprintf(env_name, "%s_%03d_binlog_dir", prefix, i);
|
|
env = getenv(env_name);
|
|
if (env == NULL)
|
|
{
|
|
sprintf(env_name, "%s_binlog_dir", prefix);
|
|
env = getenv(env_name);
|
|
}
|
|
if (env != NULL)
|
|
{
|
|
sprintf(maxscale_binlog_dir[i], "%s", env);
|
|
}
|
|
else
|
|
{
|
|
sprintf(maxscale_binlog_dir[i], "/var/lib/maxscale/Binlog_Service/");
|
|
}
|
|
|
|
sprintf(env_name, "%s_%03d_maxadmin_password", prefix, i);
|
|
env = getenv(env_name);
|
|
if (env == NULL)
|
|
{
|
|
sprintf(env_name, "%s_maxadmin_password", prefix);
|
|
env = getenv(env_name);
|
|
}
|
|
if (env != NULL)
|
|
{
|
|
sprintf(maxadmin_password[i], "%s", env);
|
|
}
|
|
else
|
|
{
|
|
sprintf(maxadmin_password[i], "mariadb");
|
|
}
|
|
|
|
rwsplit_port[i] = 4006;
|
|
readconn_master_port[i] = 4008;
|
|
readconn_slave_port[i] = 4009;
|
|
binlog_port[i] = 5306;
|
|
|
|
ports[i][0] = rwsplit_port[i];
|
|
ports[i][1] = readconn_master_port[i];
|
|
ports[i][2] = readconn_slave_port[i];
|
|
|
|
N_ports[0] = 3;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int Maxscales::connect_rwsplit(int m)
|
|
{
|
|
if (use_ipv6)
|
|
{
|
|
conn_rwsplit[m] = open_conn(rwsplit_port[m],
|
|
IP6[m],
|
|
user_name,
|
|
password,
|
|
ssl);
|
|
}
|
|
else
|
|
{
|
|
conn_rwsplit[m] = open_conn(rwsplit_port[m],
|
|
IP[m],
|
|
user_name,
|
|
password,
|
|
ssl);
|
|
}
|
|
routers[m][0] = conn_rwsplit[m];
|
|
|
|
int rc = 0;
|
|
int my_errno = mysql_errno(conn_rwsplit[m]);
|
|
|
|
if (my_errno)
|
|
{
|
|
if (verbose)
|
|
{
|
|
printf("Failed to connect to readwritesplit: %d, %s", my_errno, mysql_error(conn_rwsplit[m]));
|
|
}
|
|
rc = my_errno;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int Maxscales::connect_readconn_master(int m)
|
|
{
|
|
if (use_ipv6)
|
|
{
|
|
conn_master[m] = open_conn(readconn_master_port[m],
|
|
IP6[m],
|
|
user_name,
|
|
password,
|
|
ssl);
|
|
}
|
|
else
|
|
{
|
|
conn_master[m] = open_conn(readconn_master_port[m],
|
|
IP[m],
|
|
user_name,
|
|
password,
|
|
ssl);
|
|
}
|
|
routers[m][1] = conn_master[m];
|
|
|
|
int rc = 0;
|
|
int my_errno = mysql_errno(conn_master[m]);
|
|
|
|
if (my_errno)
|
|
{
|
|
if (verbose)
|
|
{
|
|
printf("Failed to connect to readwritesplit: %d, %s", my_errno, mysql_error(conn_master[m]));
|
|
}
|
|
rc = my_errno;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int Maxscales::connect_readconn_slave(int m)
|
|
{
|
|
if (use_ipv6)
|
|
{
|
|
conn_slave[m] = open_conn(readconn_slave_port[m],
|
|
IP6[m],
|
|
user_name,
|
|
password,
|
|
ssl);
|
|
}
|
|
else
|
|
{
|
|
conn_slave[m] = open_conn(readconn_slave_port[m],
|
|
IP[m],
|
|
user_name,
|
|
password,
|
|
ssl);
|
|
}
|
|
routers[m][2] = conn_slave[m];
|
|
|
|
int rc = 0;
|
|
int my_errno = mysql_errno(conn_slave[m]);
|
|
|
|
if (my_errno)
|
|
{
|
|
if (verbose)
|
|
{
|
|
printf("Failed to connect to readwritesplit: %d, %s", my_errno, mysql_error(conn_slave[m]));
|
|
}
|
|
rc = my_errno;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int Maxscales::connect_maxscale(int m)
|
|
{
|
|
return connect_rwsplit(m)
|
|
+ connect_readconn_master(m)
|
|
+ connect_readconn_slave(m);
|
|
}
|
|
|
|
int Maxscales::close_maxscale_connections(int m)
|
|
{
|
|
mysql_close(conn_master[m]);
|
|
mysql_close(conn_slave[m]);
|
|
mysql_close(conn_rwsplit[m]);
|
|
return 0;
|
|
}
|
|
|
|
int Maxscales::restart_maxscale(int m)
|
|
{
|
|
int res = ssh_node(m, "service maxscale restart", true);
|
|
fflush(stdout);
|
|
return res;
|
|
}
|
|
|
|
int Maxscales::start_maxscale(int m)
|
|
{
|
|
int res = ssh_node(m, "service maxscale start", true);
|
|
fflush(stdout);
|
|
return res;
|
|
}
|
|
|
|
int Maxscales::stop_maxscale(int m)
|
|
{
|
|
int res = ssh_node(m, "service maxscale stop", true);
|
|
fflush(stdout);
|
|
return res;
|
|
}
|
|
|
|
|
|
int Maxscales::execute_maxadmin_command(int m, const char* cmd)
|
|
{
|
|
return ssh_node_f(m, true, "maxadmin %s", cmd);
|
|
}
|
|
int Maxscales::execute_maxadmin_command_print(int m, const char* cmd)
|
|
{
|
|
int exit_code;
|
|
printf("%s\n", ssh_node_output_f(m, true, &exit_code, "maxadmin %s", cmd));
|
|
return exit_code;
|
|
}
|
|
|
|
int Maxscales::check_maxadmin_param(int m, const char* command, const char* param, const char* value)
|
|
{
|
|
char result[1024];
|
|
int rval = 1;
|
|
|
|
if (get_maxadmin_param(m, (char*)command, (char*)param, (char*)result) == 0)
|
|
{
|
|
char* end = strchr(result, '\0') - 1;
|
|
|
|
while (isspace(*end))
|
|
{
|
|
*end-- = '\0';
|
|
}
|
|
|
|
char* start = result;
|
|
|
|
while (isspace(*start))
|
|
{
|
|
start++;
|
|
}
|
|
|
|
if (strcmp(start, value) == 0)
|
|
{
|
|
rval = 0;
|
|
}
|
|
else
|
|
{
|
|
printf("Expected %s, got %s\n", value, start);
|
|
}
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
int Maxscales::get_maxadmin_param(int m, const char* command, const char* param, char* result)
|
|
{
|
|
char* buf;
|
|
int exit_code;
|
|
|
|
buf = ssh_node_output_f(m, true, &exit_code, "maxadmin %s", command);
|
|
|
|
// printf("%s\n", buf);
|
|
|
|
char* x = strstr(buf, param);
|
|
|
|
if (x == NULL)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
x += strlen(param);
|
|
|
|
// Skip any trailing parts of the parameter name
|
|
while (!isspace(*x))
|
|
{
|
|
x++;
|
|
}
|
|
|
|
// Trim leading whitespace
|
|
while (!isspace(*x))
|
|
{
|
|
x++;
|
|
}
|
|
|
|
char* end = strchr(x, '\n');
|
|
|
|
// Trim trailing whitespace
|
|
while (isspace(*end))
|
|
{
|
|
*end-- = '\0';
|
|
}
|
|
|
|
strcpy(result, x);
|
|
|
|
return exit_code;
|
|
}
|
|
|
|
|
|
long unsigned Maxscales::get_maxscale_memsize(int m)
|
|
{
|
|
int exit_code;
|
|
char* ps_out = ssh_node_output(m, "ps -e -o pid,vsz,comm= | grep maxscale", false, &exit_code);
|
|
long unsigned mem = 0;
|
|
pid_t pid;
|
|
sscanf(ps_out, "%d %lu", &pid, &mem);
|
|
return mem;
|
|
}
|
|
|
|
|
|
int Maxscales::find_master_maxadmin(Mariadb_nodes* nodes, int m)
|
|
{
|
|
bool found = false;
|
|
int master = -1;
|
|
|
|
for (int i = 0; i < nodes->N; i++)
|
|
{
|
|
char show_server[256];
|
|
char res[256];
|
|
sprintf(show_server, "show server server%d", i + 1);
|
|
get_maxadmin_param(m, show_server, (char*) "Status", res);
|
|
|
|
if (strstr(res, "Master"))
|
|
{
|
|
if (found)
|
|
{
|
|
master = -1;
|
|
}
|
|
else
|
|
{
|
|
master = i;
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return master;
|
|
}
|
|
|
|
int Maxscales::find_slave_maxadmin(Mariadb_nodes* nodes, int m)
|
|
{
|
|
int slave = -1;
|
|
|
|
for (int i = 0; i < nodes->N; i++)
|
|
{
|
|
char show_server[256];
|
|
char res[256];
|
|
sprintf(show_server, "show server server%d", i + 1);
|
|
get_maxadmin_param(m, show_server, (char*) "Status", res);
|
|
|
|
if (strstr(res, "Slave"))
|
|
{
|
|
slave = i;
|
|
}
|
|
}
|
|
|
|
return slave;
|
|
}
|
|
|
|
StringSet Maxscales::get_server_status(const char* name, int m)
|
|
{
|
|
std::set<std::string> rval;
|
|
int exit_code;
|
|
char* res = ssh_node_output_f(m, true, &exit_code, "maxadmin list servers|grep \'%s\'", name);
|
|
char* pipe = strrchr(res, '|');
|
|
|
|
if (res && pipe)
|
|
{
|
|
pipe++;
|
|
char* tok = strtok(pipe, ",");
|
|
|
|
while (tok)
|
|
{
|
|
char* p = tok;
|
|
char* end = strchr(tok, '\n');
|
|
if (!end)
|
|
{
|
|
end = strchr(tok, '\0');
|
|
}
|
|
|
|
// Trim leading whitespace
|
|
while (p < end && isspace(*p))
|
|
{
|
|
p++;
|
|
}
|
|
|
|
// Trim trailing whitespace
|
|
while (end > tok && isspace(*end))
|
|
{
|
|
*end-- = '\0';
|
|
}
|
|
|
|
rval.insert(p);
|
|
tok = strtok(NULL, ",\n");
|
|
}
|
|
|
|
free(res);
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
int Maxscales::port(enum service type, int m) const
|
|
{
|
|
switch (type)
|
|
{
|
|
case RWSPLIT:
|
|
return rwsplit_port[m];
|
|
|
|
case READCONN_MASTER:
|
|
return readconn_master_port[m];
|
|
|
|
case READCONN_SLAVE:
|
|
return readconn_slave_port[m];
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void Maxscales::wait_for_monitor(int intervals, int m)
|
|
{
|
|
// Helper for getting number of monitor ticks
|
|
auto get_ticks = [&](std::string name) {
|
|
int rc;
|
|
char* ticks = ssh_node_output_f(m,
|
|
false,
|
|
&rc,
|
|
"maxctrl api get monitors/%s data.attributes.ticks",
|
|
name.c_str());
|
|
char* ptr;
|
|
int rval = strtol(ticks, &ptr, 10);
|
|
|
|
if (ptr == ticks || (*ptr != '\0' && !isspace(*ptr)))
|
|
{
|
|
printf("ERROR, invalid monitor tick value: %s\n", ticks);
|
|
rval = -1;
|
|
}
|
|
|
|
free(ticks);
|
|
return rval;
|
|
};
|
|
|
|
int rc = 0;
|
|
|
|
// Get a list of monitor names that are running
|
|
char* monitors = ssh_node_output_f(m, false, &rc, "maxctrl --tsv list monitors|grep Running|cut -f 1");
|
|
std::istringstream is;
|
|
is.str(monitors);
|
|
free(monitors);
|
|
std::string name;
|
|
std::unordered_map<std::string, int> ticks;
|
|
|
|
// For each monitor, store the current monitor tick
|
|
while (std::getline(is, name))
|
|
{
|
|
ticks[name] = get_ticks(name);
|
|
}
|
|
|
|
for (auto a : ticks)
|
|
{
|
|
// Wait a maximum of 60 seconds for a single monitor interval
|
|
for (int i = 0; i < 60; i++)
|
|
{
|
|
int start = a.second;
|
|
int end = get_ticks(a.first);
|
|
|
|
if (start == -1 || end == -1 || end - start >= intervals)
|
|
{
|
|
break;
|
|
}
|
|
sleep(1);
|
|
}
|
|
}
|
|
}
|