diff --git a/include/ProxySQL_Cluster.hpp b/include/ProxySQL_Cluster.hpp index e0b8164d1..03c41ac02 100644 --- a/include/ProxySQL_Cluster.hpp +++ b/include/ProxySQL_Cluster.hpp @@ -51,9 +51,11 @@ class ProxySQL_Node_Address { uint64_t hash; // unused for now char *uuid; char *hostname; + char *admin_mysql_ifaces; uint16_t port; ProxySQL_Node_Address(char *h, uint16_t p) { hostname = strdup(h); + admin_mysql_ifaces = NULL; port = p; uuid = NULL; hash = 0; @@ -61,6 +63,7 @@ class ProxySQL_Node_Address { ~ProxySQL_Node_Address() { if (hostname) free(hostname); if (uuid) free(uuid); + if (admin_mysql_ifaces) free(admin_mysql_ifaces); } }; @@ -237,6 +240,9 @@ class ProxySQL_Cluster { pthread_mutex_t update_mysql_users_mutex; pthread_mutex_t update_mysql_variables_mutex; pthread_mutex_t update_proxysql_servers_mutex; + // this records the interface that Admin is listening to + pthread_mutex_t admin_mysql_ifaces_mutex; + char *admin_mysql_ifaces; int cluster_check_interval_ms; int cluster_check_status_frequency; int cluster_mysql_query_rules_diffs_before_sync; @@ -261,6 +267,7 @@ class ProxySQL_Cluster { void get_credentials(char **, char **); void set_username(char *); void set_password(char *); + void set_admin_mysql_ifaces(char *); bool Update_Node_Metrics(char * _h, uint16_t _p, MYSQL_RES *_r, unsigned long long _response_time) { return nodes.Update_Node_Metrics(_h, _p, _r, _response_time); } diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index c02641920..ee217433d 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -493,7 +493,7 @@ static int http_handler(void *cls, struct MHD_Connection *connection, const char #define ADMIN_SQLITE_TABLE_RUNTIME_PROXYSQL_SERVERS "CREATE TABLE runtime_proxysql_servers (hostname VARCHAR NOT NULL , port INT NOT NULL DEFAULT 6032 , weight INT CHECK (weight >= 0) NOT NULL DEFAULT 0 , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (hostname, port) )" -#define STATS_SQLITE_TABLE_PROXYSQL_SERVERS_CLIENTS_STATUS "CREATE TABLE stats_proxysql_servers_clients_status (uuid VARCHAR NOT NULL , hostname VARCHAR NOT NULL , port INT NOT NULL , last_seen_at INT NOT NULL , PRIMARY KEY (uuid, hostname, port) )" +#define STATS_SQLITE_TABLE_PROXYSQL_SERVERS_CLIENTS_STATUS "CREATE TABLE stats_proxysql_servers_clients_status (uuid VARCHAR NOT NULL , hostname VARCHAR NOT NULL , port INT NOT NULL , admin_mysql_ifaces VARCHAR NOT NULL , last_seen_at INT NOT NULL , PRIMARY KEY (uuid, hostname, port) )" #define STATS_SQLITE_TABLE_PROXYSQL_SERVERS_STATUS "CREATE TABLE stats_proxysql_servers_status (hostname VARCHAR NOT NULL , port INT NOT NULL DEFAULT 6032 , weight INT CHECK (weight >= 0) NOT NULL DEFAULT 0 , master VARCHAR NOT NULL , global_version INT NOT NULL , check_age_us INT NOT NULL , ping_time_us INT NOT NULL, checks_OK INT NOT NULL , checks_ERR INT NOT NULL , PRIMARY KEY (hostname, port) )" @@ -1221,28 +1221,43 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ sess->client_myds->shut_soft(); return false; } - if (query_no_space_length==l+36) { + if (query_no_space_length >= l+36+2) { uuid_t uu; - if (uuid_parse(query_no_space+l, uu)==0) { + char *A_uuid = NULL; + char *B_interface = NULL; + c_split_2(query_no_space+l, " ", &A_uuid, &B_interface); // we split the value + if (uuid_parse(A_uuid, uu)==0 && B_interface && strlen(B_interface)) { proxy_info("Received PROXYSQL CLUSTER_NODE_UUID from %s:%d : %s\n", sess->client_myds->addr.addr, sess->client_myds->addr.port, query_no_space+l); if (sess->proxysql_node_address==NULL) { sess->proxysql_node_address = new ProxySQL_Node_Address(sess->client_myds->addr.addr, sess->client_myds->addr.port); - sess->proxysql_node_address->uuid = strdup(query_no_space+l); - proxy_info("Created new link with Cluster node %s:%d : %s\n", sess->client_myds->addr.addr, sess->client_myds->addr.port, query_no_space+l); + sess->proxysql_node_address->uuid = strdup(A_uuid); + if (sess->proxysql_node_address->admin_mysql_ifaces) { + free(sess->proxysql_node_address->admin_mysql_ifaces); + } + sess->proxysql_node_address->admin_mysql_ifaces = strdup(B_interface); + proxy_info("Created new link with Cluster node %s:%d : %s at interface %s\n", sess->client_myds->addr.addr, sess->client_myds->addr.port, A_uuid, B_interface); SPA->send_MySQL_OK(&sess->client_myds->myprot, NULL); + free(A_uuid); + free(B_interface); return false; } else { - if (strcmp(query_no_space+l, sess->proxysql_node_address->uuid)) { - proxy_error("Cluster node %s:%d is sending a new UUID : %s . Former UUID : %s . Exiting client\n", sess->client_myds->addr.addr, sess->client_myds->addr.port, query_no_space+l, sess->proxysql_node_address->uuid); + if (strcmp(A_uuid, sess->proxysql_node_address->uuid)) { + proxy_error("Cluster node %s:%d is sending a new UUID : %s . Former UUID : %s . Exiting client\n", sess->client_myds->addr.addr, sess->client_myds->addr.port, A_uuid, sess->proxysql_node_address->uuid); SPA->send_MySQL_ERR(&sess->client_myds->myprot, (char *)"Received PROXYSQL CLUSTER_NODE_UUID with a new UUID not matching the previous one"); sess->client_myds->shut_soft(); + free(A_uuid); + free(B_interface); return false; } else { - proxy_info("Cluster node %s:%d is sending again its UUID : %s\n", sess->client_myds->addr.addr, sess->client_myds->addr.port, query_no_space+l); + proxy_info("Cluster node %s:%d is sending again its UUID : %s\n", sess->client_myds->addr.addr, sess->client_myds->addr.port, A_uuid); SPA->send_MySQL_OK(&sess->client_myds->myprot, NULL); + free(A_uuid); + free(B_interface); return false; } } + free(A_uuid); + free(B_interface); return false; } else { proxy_warning("Received PROXYSQL CLUSTER_NODE_UUID from %s:%d with invalid format: %s . Exiting client\n", sess->client_myds->addr.addr, sess->client_myds->addr.port, query_no_space+l); @@ -4802,13 +4817,15 @@ __run_query: if (sess->proxysql_node_address) { if (sess->client_myds->active) { time_t now = time(NULL); - string q = "INSERT OR REPLACE INTO stats_proxysql_servers_clients_status (uuid, hostname, port, last_seen_at) VALUES (\""; + string q = "INSERT OR REPLACE INTO stats_proxysql_servers_clients_status (uuid, hostname, port, admin_mysql_ifaces, last_seen_at) VALUES (\""; q += sess->proxysql_node_address->uuid; q += "\",\""; q += sess->proxysql_node_address->hostname; q += "\","; q += std::to_string(sess->proxysql_node_address->port); - q += ","; + q += ",\""; + q += sess->proxysql_node_address->admin_mysql_ifaces; + q += "\","; q += std::to_string(now) + ")"; SPA->statsdb->execute(q.c_str()); } @@ -7615,6 +7632,7 @@ bool ProxySQL_Admin::set_variable(char *name, char *value) { // this is the pub if (update_creds && variables.mysql_ifaces) { S_amll.update_ifaces(variables.mysql_ifaces, &S_amll.ifaces_mysql); } + GloProxyCluster->set_admin_mysql_ifaces(value); return true; } else { return false; diff --git a/lib/ProxySQL_Cluster.cpp b/lib/ProxySQL_Cluster.cpp index f1bad58e4..fb8fcdc55 100644 --- a/lib/ProxySQL_Cluster.cpp +++ b/lib/ProxySQL_Cluster.cpp @@ -110,6 +110,10 @@ void * ProxySQL_Cluster_Monitor_thread(void *args) { same_version = true; std::string q = "PROXYSQL CLUSTER_NODE_UUID "; q += GloVars.uuid; + q += " "; + pthread_mutex_lock(&GloProxyCluster->admin_mysql_ifaces_mutex); + q += GloProxyCluster->admin_mysql_ifaces; + pthread_mutex_unlock(&GloProxyCluster->admin_mysql_ifaces_mutex); proxy_info("Cluster: sending CLUSTER_NODE_UUID %s to peer %s:%d\n", GloVars.uuid, node->hostname, node->port); rc_query = mysql_query(conn, q.c_str()); } else { @@ -2586,6 +2590,9 @@ ProxySQL_Cluster::ProxySQL_Cluster() { pthread_mutex_init(&update_mysql_servers_mutex,NULL); pthread_mutex_init(&update_mysql_users_mutex,NULL); pthread_mutex_init(&update_proxysql_servers_mutex,NULL); + pthread_mutex_init(&update_mysql_variables_mutex,NULL); + pthread_mutex_init(&admin_mysql_ifaces_mutex,NULL); + admin_mysql_ifaces = strdup((char *)""); // always initialized cluster_username = strdup((char *)""); cluster_password = strdup((char *)""); cluster_check_interval_ms = 1000; @@ -2611,6 +2618,10 @@ ProxySQL_Cluster::~ProxySQL_Cluster() { free(cluster_password); cluster_password = NULL; } + if (admin_mysql_ifaces) { + free(admin_mysql_ifaces); + admin_mysql_ifaces = NULL; + } } // this function returns credentials to the caller, used by monitoring threads @@ -2635,6 +2646,13 @@ void ProxySQL_Cluster::set_password(char *_password) { pthread_mutex_unlock(&mutex); } +void ProxySQL_Cluster::set_admin_mysql_ifaces(char *value) { + pthread_mutex_lock(&admin_mysql_ifaces_mutex); + free(admin_mysql_ifaces); + admin_mysql_ifaces=strdup(value); + pthread_mutex_unlock(&admin_mysql_ifaces_mutex); +} + void ProxySQL_Cluster::print_version() { fprintf(stderr,"Standard ProxySQL Cluster rev. %s -- %s -- %s\n", PROXYSQL_CLUSTER_VERSION, __FILE__, __TIMESTAMP__); };