diff --git a/.gitignore b/.gitignore index 6ecf39937..bd74bb7e8 100644 --- a/.gitignore +++ b/.gitignore @@ -80,7 +80,7 @@ deps/mariadb-client-library/mariadb-connector-c-2.1.0-src/ deps/glib/glib-2.40.0/ #libevent -deps/libevent/libevent-2.0.21-stable/ +deps/libevent/libevent-2.0.22-stable/ #memcached deps/memcached/memcached-1.4.20/ diff --git a/deps/Makefile b/deps/Makefile index e68707702..1383e5689 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -1,6 +1,6 @@ -default: libconfig libdaemon jemalloc mariadb_client re2 libinjection +default: libevent libconfig libdaemon jemalloc mariadb_client re2 libinjection .PHONY: default @@ -12,7 +12,13 @@ libdaemon/libdaemon/libdaemon/.libs/libdaemon.a: libdaemon: libdaemon/libdaemon/libdaemon/.libs/libdaemon.a +libevent/libevent/.libs/libevent.a: + cd libevent && rm -rf libevent-2.0.22-stable + cd libevent && tar -zxf libevent-2.0.22-stable.tar.gz + cd libevent/libevent && ./configure + cd libevent/libevent && make +libevent: libevent/libevent/.libs/libevent.a libinjection/libinjection.a: cd libinjection && make @@ -34,6 +40,7 @@ mariadb-client-library/mariadb_client/include/my_config.h: cd mariadb-client-library && rm -rf mariadb-connector-c-2.1.0-src cd mariadb-client-library && tar -zxf mariadb-connector-c-2.1.0-src.tar.gz cd mariadb-client-library/mariadb_client && cmake . + cd mariadb-client-library/mariadb_client && patch libmariadb/libmariadb.c < ../libmariadb.c.patch cd mariadb-client-library/mariadb_client && make # cd mariadb-client-library/mariadb_client/include && make my_config.h @@ -47,7 +54,6 @@ mariadb_client: mariadb-client-library/mariadb_client/include/my_config.h # #sqlite3: sqlite3/sqlite3/sqlite3.o - libconfig/libconfig/lib/.libs/libconfig++.a: cd libconfig && rm -rf libconfig-1.4.9 cd libconfig && tar -zxf libconfig-1.4.9.tar.gz @@ -73,8 +79,7 @@ cleanall: cd libconfig && rm -rf libconfig-1.4.9 cd re2 && rm -rf re2 cd libinjection && make clean -# cd glib && rm -rf glib-2.40.0 -# cd libevent && rm -rf libevent-2.0.21-stable + cd libevent && rm -rf libevent-2.0.22-stable # cd sqlite3 && rm -rf sqlite-amalgamation-3080403 .PHONY: cleanall diff --git a/deps/libevent/libevent b/deps/libevent/libevent new file mode 120000 index 000000000..99ce3b45f --- /dev/null +++ b/deps/libevent/libevent @@ -0,0 +1 @@ +libevent-2.0.22-stable \ No newline at end of file diff --git a/deps/libevent/libevent-2.0.22-stable.tar.gz b/deps/libevent/libevent-2.0.22-stable.tar.gz new file mode 100644 index 000000000..db88cad47 Binary files /dev/null and b/deps/libevent/libevent-2.0.22-stable.tar.gz differ diff --git a/deps/mariadb-client-library/libmariadb.c.patch b/deps/mariadb-client-library/libmariadb.c.patch new file mode 100644 index 000000000..c8b97bee6 --- /dev/null +++ b/deps/mariadb-client-library/libmariadb.c.patch @@ -0,0 +1,15 @@ +@@ -2192,6 +2192,14 @@ + my_free(mysql->options.extension->ssl_crlpath, MYF(MY_ALLOW_ZERO_PTR)); + if(hash_inited(&mysql->options.extension->connect_attrs)) + hash_free(&mysql->options.extension->connect_attrs); ++ { ++ struct mysql_async_context *ctxt; ++ if ((ctxt = mysql->options.extension->async_context) != 0) ++ { ++ my_context_destroy(&ctxt->async_context); ++ my_free((gptr)ctxt, MYF(0)); ++ } ++ } + } + my_free((gptr)mysql->options.extension, MYF(MY_ALLOW_ZERO_PTR)); + /* clear all pointer */ diff --git a/deps/mariadb-client-library/mariadb-connector-c-2.1.0-src.tar.gz b/deps/mariadb-client-library/mariadb-connector-c-2.1.0-src.tar.gz new file mode 100644 index 000000000..d26e758d2 Binary files /dev/null and b/deps/mariadb-client-library/mariadb-connector-c-2.1.0-src.tar.gz differ diff --git a/deps/mariadb-client-library/mariadb_client b/deps/mariadb-client-library/mariadb_client index 6e9463630..35d1bab54 120000 --- a/deps/mariadb-client-library/mariadb_client +++ b/deps/mariadb-client-library/mariadb_client @@ -1 +1 @@ -mariadb_client-2.0.0-src \ No newline at end of file +mariadb-connector-c-2.1.0-src \ No newline at end of file diff --git a/deps/mariadb-client-library/mariadb_client-2.0.0-src.tar.gz b/deps/mariadb-client-library/mariadb_client-2.0.0-src.tar.gz deleted file mode 100644 index dd6ea31c6..000000000 Binary files a/deps/mariadb-client-library/mariadb_client-2.0.0-src.tar.gz and /dev/null differ diff --git a/include/MySQL_Monitor.hpp b/include/MySQL_Monitor.hpp index 8954da65f..f7fad6336 100644 --- a/include/MySQL_Monitor.hpp +++ b/include/MySQL_Monitor.hpp @@ -1,16 +1,11 @@ #ifndef __CLASS_MYSQL_MONITOR_H #define __CLASS_MYSQL_MONITOR_H +//#include +//#include +//#include "btree_map.h" #include "proxysql.h" #include "cpp.h" - -#define MONITOR_SQLITE_TABLE_MYSQL_SERVERS "CREATE TABLE mysql_servers (\ - hostname VARCHAR NOT NULL,\ - port INT NOT NULL DEFAULT 3306,\ - time_since INT NOT NULL DEFAULT 0,\ - time_until INT NOT NULL DEFAULT 0,\ - PRIMARY KEY (hostname, port))" - #define MONITOR_SQLITE_TABLE_MYSQL_SERVER_CONNECT "CREATE TABLE mysql_server_connect (\ hostname VARCHAR NOT NULL,\ port INT NOT NULL DEFAULT 3306,\ @@ -43,6 +38,25 @@ ping_failure_last INT NOT NULL DEFAULT 0,\ PRIMARY KEY (hostname, port))" +#define MONITOR_SQLITE_TABLE_MYSQL_SERVER_CONNECT_LOG "CREATE TABLE mysql_server_connect_log (\ + hostname VARCHAR NOT NULL,\ + port INT NOT NULL DEFAULT 3306,\ + time_start INT NOT NULL DEFAULT 0,\ + connect_success_time INT DEFAULT 0,\ + connect_error VARCHAR,\ + PRIMARY KEY (hostname, port, time_start))" + +#define MONITOR_SQLITE_TABLE_MYSQL_SERVER_PING_LOG "CREATE TABLE mysql_server_ping_log (\ + hostname VARCHAR NOT NULL,\ + port INT NOT NULL DEFAULT 3306,\ + time_start INT NOT NULL DEFAULT 0,\ + ping_success_time INT DEFAULT 0,\ + ping_error VARCHAR,\ + PRIMARY KEY (hostname, port, time_start))" + + +class MySQL_Monitor_Connection_Pool; + class MySQL_Monitor { private: //unsigned int MySQL_Monitor__thread_MySQL_Thread_Variables_version; @@ -52,7 +66,9 @@ class MySQL_Monitor { void drop_tables_defs(std::vector *tables_defs); void check_and_build_standard_tables(SQLite3DB *db, std::vector *tables_defs); public: + MySQL_Monitor_Connection_Pool *My_Conn_Pool; bool shutdown; + SQLite3DB *admindb; // internal database SQLite3DB *monitordb; // internal database MySQL_Monitor(); ~MySQL_Monitor(); diff --git a/include/MySQL_Thread.h b/include/MySQL_Thread.h index 400c32993..1988d2efd 100644 --- a/include/MySQL_Thread.h +++ b/include/MySQL_Thread.h @@ -235,10 +235,18 @@ class MySQL_Threads_Handler pthread_attr_t attr; rwlock_t rwlock; struct { + int monitor_history; int monitor_connect_interval; int monitor_connect_timeout; int monitor_ping_interval; int monitor_ping_timeout; + int monitor_query_interval; + int monitor_query_timeout; + char * monitor_query_variables; + char * monitor_query_status; + char *monitor_username; + char *monitor_password; + bool monitor_timer_cached; int ping_interval_server; int ping_timeout_server; int connect_timeout_server; diff --git a/include/proxysql_admin.h b/include/proxysql_admin.h index b2594a9ff..73b344ca0 100644 --- a/include/proxysql_admin.h +++ b/include/proxysql_admin.h @@ -84,6 +84,7 @@ class ProxySQL_Admin { SQLite3DB *admindb; // in memory SQLite3DB *statsdb; // in memory SQLite3DB *configdb; // on disk + SQLite3DB *monitordb; // in memory void print_version(); bool init(); void init_users(); diff --git a/include/proxysql_structs.h b/include/proxysql_structs.h index 3b595efcd..a2b67a671 100644 --- a/include/proxysql_structs.h +++ b/include/proxysql_structs.h @@ -632,10 +632,18 @@ __thread bool mysql_thread___servers_stats; __thread bool mysql_thread___commands_stats; /* variables used by the monitoring module */ +__thread int mysql_thread___monitor_history; __thread int mysql_thread___monitor_connect_interval; __thread int mysql_thread___monitor_connect_timeout; __thread int mysql_thread___monitor_ping_interval; __thread int mysql_thread___monitor_ping_timeout; +__thread int mysql_thread___monitor_query_interval; +__thread int mysql_thread___monitor_query_timeout; +__thread char * mysql_thread___monitor_query_variables; +__thread char * mysql_thread___monitor_query_status; +__thread char * mysql_thread___monitor_username; +__thread char * mysql_thread___monitor_password; +__thread bool mysql_thread___monitor_timer_cached; #ifdef DEBUG __thread bool mysql_thread___session_debug; @@ -659,6 +667,21 @@ extern __thread int mysql_thread___poll_timeout_on_failure; extern __thread bool mysql_thread___have_compress; extern __thread bool mysql_thread___servers_stats; extern __thread bool mysql_thread___commands_stats; + +/* variables used by the monitoring module */ +extern __thread int mysql_thread___monitor_history; +extern __thread int mysql_thread___monitor_connect_interval; +extern __thread int mysql_thread___monitor_connect_timeout; +extern __thread int mysql_thread___monitor_ping_interval; +extern __thread int mysql_thread___monitor_ping_timeout; +extern __thread int mysql_thread___monitor_query_interval; +extern __thread int mysql_thread___monitor_query_timeout; +extern __thread char * mysql_thread___monitor_query_variables; +extern __thread char * mysql_thread___monitor_query_status; +extern __thread char * mysql_thread___monitor_username; +extern __thread char * mysql_thread___monitor_password; +extern __thread bool mysql_thread___monitor_timer_cached; + #ifdef DEBUG extern __thread bool mysql_thread___session_debug; #endif /* DEBUG */ diff --git a/lib/Makefile b/lib/Makefile index f1337d943..f3eae7588 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,13 +17,16 @@ LIBCONFIG_IDIR=-I$(LIBCONFIG_PATH)/lib INJECTION_PATH=$(DEPS_PATH)/libinjection INJECTION_IDIR=$(INJECTION_PATH) +LIBEVENT_PATH=$(DEPS_PATH)/libevent/libevent +LIBEVENT_IDIR=$(LIBEVENT_PATH)/include + RE2_PATH=$(DEPS_PATH)/re2/re2 RE2_IDIR=$(RE2_PATH) IDIR=../include -IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -I$(RE2_IDIR) +IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -I$(RE2_IDIR) -I$(LIBEVENT_IDIR) LDIRS=-L$(JEMALLOC_PATH)/lib -L$(RE2_PATH)/obj -L$(INJECTION_PATH) @@ -55,8 +58,8 @@ $(ODIR)/%.o: %.c $(ODIR)/%.oo: %.cpp $(CPP) -fPIC -c -o $@ $< $(CPPFLAGS) -libproxysql.a: $(ODIR) $(OBJ) $(OBJ_CPP) $(INJECTION_PATH)/libinjection.a $(RE2_PATH)/obj/libre2.a - ar rcs $@ $(OBJ) $(OBJ_CPP) $(INJECTION_PATH)/libinjection.a $(RE2_PATH)/obj/libre2.a +libproxysql.a: $(ODIR) $(OBJ) $(OBJ_CPP) $(INJECTION_PATH)/libinjection.a $(RE2_PATH)/obj/libre2.a $(LIBEVENT_PATH)/.libs/libevent.a + ar rcs $@ $(OBJ) $(OBJ_CPP) $(INJECTION_PATH)/libinjection.a $(RE2_PATH)/obj/libre2.a $(LIBEVENT_PATH)/.libs/libevent.a $(ODIR): mkdir $(ODIR) diff --git a/lib/MySQL_Monitor.cpp b/lib/MySQL_Monitor.cpp index 0d0ac2228..6a3e35867 100644 --- a/lib/MySQL_Monitor.cpp +++ b/lib/MySQL_Monitor.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include "proxysql.h" #include "cpp.h" @@ -10,25 +12,406 @@ #endif /* DEBUG */ #define MYSQL_MONITOR_VERSION "0.2.0519" DEB + +#include + extern ProxySQL_Admin *GloAdmin; extern MySQL_Threads_Handler *GloMTH; + +static MySQL_Monitor *GloMyMon; + +#define NEXT_IMMEDIATE(new_st) do { ST= new_st; goto again; } while (0) + +static void state_machine_handler(int fd, short event, void *arg); + + +/* +struct state_data { + int ST; + char *hostname; + int port; + struct event ev_mysql; + MYSQL mysql; + MYSQL_RES *result; + MYSQL *ret; + int err; + MYSQL_ROW row; + struct query_entry *query_element; + int index; +}; +*/ + +static int connect__num_active_connections; +static int total_connect__num_active_connections=0; +static int ping__num_active_connections; +static int total_ping__num_active_connections=0; + + +struct cmp_str { + bool operator()(char const *a, char const *b) + { + return strcmp(a, b) < 0; + } +}; + +class MySQL_Monitor_Connection_Pool { + private: + int size; + //std::map* > my_connections; + std::map* , cmp_str> my_connections; + public: + MySQL_Monitor_Connection_Pool(); + ~MySQL_Monitor_Connection_Pool(); + MYSQL * get_connection(char *hostname, int port); + void put_connection(char *hostname, int port, MYSQL *my); +}; + +MySQL_Monitor_Connection_Pool::MySQL_Monitor_Connection_Pool() { + size=0; +} + +MySQL_Monitor_Connection_Pool::~MySQL_Monitor_Connection_Pool() { +} + +MYSQL * MySQL_Monitor_Connection_Pool::get_connection(char *hostname, int port) { + std::map* >::iterator it; + //it = my_connections.find(std::make_pair(hostname,port)); + char *buf=(char *)malloc(16+strlen(hostname)); + sprintf(buf,"%s:%d",hostname,port); + it = my_connections.find(buf); + free(buf); + if (it != my_connections.end()) { + std::list *lst=it->second; + if (!lst->empty()) { + MYSQL *ret=lst->front(); + lst->pop_front(); + size--; + return ret; + } + } + return NULL; +} + +void MySQL_Monitor_Connection_Pool::put_connection(char *hostname, int port, MYSQL *my) { + size++; + std::map* >::iterator it; + //std::map, std::list* >::iterator it; + char * buf=(char *)malloc(16+strlen(hostname)); + sprintf(buf,"%s:%d",hostname,port); + it = my_connections.find(buf); + //it = my_connections.find(std::make_pair(hostname,port)); + std::list *lst=NULL; + if (it==my_connections.end()) { + lst=new std::list; + //my_connections.insert(std::pair(hostname,port), std::list*>(lst)); + my_connections.insert(my_connections.begin(), std::pair*>(buf,lst)); + } else { + free(buf); + lst=it->second; + } + lst->push_back(my); + if (lst->size()%1000==0) { + fprintf(stderr,"list size=%lu\n", lst->size()); + } +} + +enum MySQL_Monitor_State_Data_Task_Type { + MON_CONNECT, + MON_PING +}; + +class MySQL_Monitor_State_Data { + public: + MySQL_Monitor_State_Data_Task_Type task_id; + struct timeval tv_out; + unsigned long long t1; + unsigned long long t2; + int ST; + char *hostname; + int port; + struct event *ev_mysql; + MYSQL *mysql; +// MYSQL *mysql_ptr; + struct event_base *base; + MYSQL_RES *result; + MYSQL *ret; + int interr; + char * mysql_error_msg; + MYSQL_ROW *row; + MySQL_Monitor_State_Data(char *h, int p, struct event_base *b) { + task_id=MON_CONNECT; + mysql=NULL; + result=NULL; + ret=NULL; + row=NULL; + mysql_error_msg=NULL; + hostname=strdup(h); + port=p; + base=b; + ST=0; + ev_mysql=NULL; + } + ~MySQL_Monitor_State_Data() { + if (hostname) { + free(hostname); + } + assert(mysql==NULL); // if mysql is not NULL, there is a bug + //if (mysql) { + // mysql_close(mysql); + //} + if (mysql_error_msg) { + free(mysql_error_msg); + } + } + void unregister() { + if (ev_mysql) { + event_del(ev_mysql); + event_free(ev_mysql); + } + } + int handler(int fd, short event) { + int status; +again: + //fprintf(stderr, "Status: %s %d %d\n", hostname, port, ST); + switch (ST) { + case 0: + mysql=mysql_init(NULL); + assert(mysql); + mysql_options(mysql, MYSQL_OPT_NONBLOCK, 0); + if (mysql_thread___monitor_timer_cached==true) { + event_base_gettimeofday_cached(base, &tv_out); + } else { + evutil_gettimeofday(&tv_out, NULL); + } + t1=(((unsigned long long) tv_out.tv_sec) * 1000000) + (tv_out.tv_usec); + if (port) { + status= mysql_real_connect_start(&ret, mysql, hostname, mysql_thread___monitor_username, mysql_thread___monitor_password, NULL, port, NULL, 0); + } else { + status= mysql_real_connect_start(&ret, mysql, "localhost", mysql_thread___monitor_username, mysql_thread___monitor_password, NULL, 0, hostname, 0); + } + if (status) + /* Wait for connect to complete. */ + next_event(1, status); + else + NEXT_IMMEDIATE(3); + break; + case 1: + status= mysql_real_connect_cont(&ret, mysql, mysql_status(event)); + if (status) + next_event(1, status); + else + //NEXT_IMMEDIATE(40); + NEXT_IMMEDIATE(3); + break; + + case 3: + if (!ret) { + mysql_error_msg=strdup(mysql_error(mysql)); + mysql_close(mysql); + mysql=NULL; + NEXT_IMMEDIATE(50); + } + switch(task_id) { + case MON_CONNECT: + NEXT_IMMEDIATE(40); + break; + case MON_PING: + NEXT_IMMEDIATE(7); + break; + default: + assert(0); + break; + } + break; + + case 7: + if (mysql_thread___monitor_timer_cached==true) { + event_base_gettimeofday_cached(base, &tv_out); + } else { + evutil_gettimeofday(&tv_out, NULL); + } + t1=(((unsigned long long) tv_out.tv_sec) * 1000000) + (tv_out.tv_usec); + status=mysql_ping_start(&interr,mysql); + if (status) + next_event(8,status); + else + NEXT_IMMEDIATE(9); + break; + + case 8: + status=mysql_ping_cont(&interr,mysql, mysql_status(event)); + if (status) + next_event(8,status); + else + NEXT_IMMEDIATE(9); + break; + + case 9: + if (interr) { + mysql_error_msg=strdup(mysql_error(mysql)); + mysql_close(mysql); + mysql=NULL; + NEXT_IMMEDIATE(50); + } + switch(task_id) { + case MON_PING: + NEXT_IMMEDIATE(39); + break; + default: + assert(0); + break; + } + break; + + + case 39: + if (mysql_thread___monitor_timer_cached==true) { + event_base_gettimeofday_cached(base, &tv_out); + } else { + evutil_gettimeofday(&tv_out, NULL); + } + t2=(((unsigned long long) tv_out.tv_sec) * 1000000) + (tv_out.tv_usec); + GloMyMon->My_Conn_Pool->put_connection(hostname,port,mysql); + mysql=NULL; + return -1; + break; + + case 40: + if (mysql_thread___monitor_timer_cached==true) { + event_base_gettimeofday_cached(base, &tv_out); + } else { + evutil_gettimeofday(&tv_out, NULL); + } + t2=(((unsigned long long) tv_out.tv_sec) * 1000000) + (tv_out.tv_usec); + //fprintf(stderr, "Connect time: %lluus\n", t2-t1); + NEXT_IMMEDIATE(50); // TEMP + status= mysql_close_start(mysql); + if (status) + next_event(41, status); + else + NEXT_IMMEDIATE(50); + break; + + case 41: + status= mysql_close_cont(mysql, mysql_status(event)); + if (status) + next_event(41, status); + else + NEXT_IMMEDIATE(50); + break; + + case 50: + /* We are done! */ + if (mysql) { + mysql_close(mysql); + mysql=NULL; + } + return -1; + break; + + default: + assert(0); + break; + + } + return 0; + } + void next_event(int new_st, int status) { + short wait_event= 0; + struct timeval tv, *ptv; + int fd; + + if (status & MYSQL_WAIT_READ) + wait_event|= EV_READ; + if (status & MYSQL_WAIT_WRITE) + wait_event|= EV_WRITE; + if (wait_event) + fd= mysql_get_socket(mysql); + else + fd= -1; + if (status & MYSQL_WAIT_TIMEOUT) { + //tv.tv_sec= mysql_get_timeout_value(mysql); + //tv.tv_usec= 0; + tv.tv_sec= 0; + tv.tv_usec= 10000; + ptv= &tv; + } else { + ptv= NULL; + } + //event_set(ev_mysql, fd, wait_event, state_machine_handler, this); + if (ev_mysql==NULL) { + ev_mysql=event_new(base, fd, wait_event, state_machine_handler, this); + //event_add(ev_mysql, ptv); + } + //event_del(ev_mysql); + event_assign(ev_mysql, base, fd, wait_event, state_machine_handler, this); + event_add(ev_mysql, ptv); + ST= new_st; + //fprintf(stderr,"FD:%d %d\n", fd, (ptv ? tv.tv_sec : 0)); + } +}; + + + +//static void +//next_event(int new_st, int status, MySQL_Monitor_State_Data *sd) +//{ +//} + + + +static void +state_machine_handler(int fd __attribute__((unused)), short event, void *arg) { + MySQL_Monitor_State_Data *msd=(MySQL_Monitor_State_Data *)arg; + struct event_base *base=msd->base; + int rc=msd->handler(fd, event); + if (rc==-1) { + //delete msd; + msd->unregister(); + switch (msd->task_id) { + case MON_CONNECT: + connect__num_active_connections--; + if (connect__num_active_connections == 0) + event_base_loopbreak(base); + break; + case MON_PING: + ping__num_active_connections--; + if (ping__num_active_connections == 0) + event_base_loopbreak(base); + break; + default: + assert(0); + break; + } + } +} + MySQL_Monitor::MySQL_Monitor() { + GloMyMon = this; + + My_Conn_Pool=new MySQL_Monitor_Connection_Pool(); + shutdown=false; // create new SQLite datatabase monitordb = new SQLite3DB(); monitordb->open((char *)"file:mem_monitordb?mode=memory&cache=shared", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); + admindb=new SQLite3DB(); + admindb->open((char *)"file:mem_admindb?mode=memory&cache=shared", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); // define monitoring tables tables_defs_monitor=new std::vector; - insert_into_tables_defs(tables_defs_monitor,"mysql_servers", MONITOR_SQLITE_TABLE_MYSQL_SERVERS); + //insert_into_tables_defs(tables_defs_monitor,"mysql_servers", MONITOR_SQLITE_TABLE_MYSQL_SERVERS); insert_into_tables_defs(tables_defs_monitor,"mysql_server_connect", MONITOR_SQLITE_TABLE_MYSQL_SERVER_CONNECT); - insert_into_tables_defs(tables_defs_monitor,"mysql_server_ping", MONITOR_SQLITE_TABLE_MYSQL_SERVER_PING); - + insert_into_tables_defs(tables_defs_monitor,"mysql_server_connect_log", MONITOR_SQLITE_TABLE_MYSQL_SERVER_CONNECT_LOG); + insert_into_tables_defs(tables_defs_monitor,"mysql_server_ping", MONITOR_SQLITE_TABLE_MYSQL_SERVER_PING); + insert_into_tables_defs(tables_defs_monitor,"mysql_server_ping_log", MONITOR_SQLITE_TABLE_MYSQL_SERVER_PING_LOG); // create monitoring tables check_and_build_standard_tables(monitordb, tables_defs_monitor); + monitordb->execute("CREATE INDEX IF NOT EXISTS idx_connect_log_time_start ON mysql_server_connect_log (time_start)"); + monitordb->execute("CREATE INDEX IF NOT EXISTS idx_ping_log_time_start ON mysql_server_ping_log (time_start)"); }; @@ -37,6 +420,7 @@ MySQL_Monitor::~MySQL_Monitor() { drop_tables_defs(tables_defs_monitor); delete tables_defs_monitor; delete monitordb; + delete admindb; //delete mysql_thr; fprintf(stderr,"MySQL_Monitor destroyed\n"); }; @@ -82,12 +466,27 @@ void MySQL_Monitor::check_and_build_standard_tables(SQLite3DB *db, std::vectorcurtime=monotonic_time(); MySQL_Monitor__thread_MySQL_Thread_Variables_version=GloMTH->get_global_version(); mysql_thr->refresh_variables(); + unsigned long long t1; + unsigned long long t2; + unsigned long long start_time; while (shutdown==false) { + + t1=monotonic_time(); + + struct timeval tv_out; + evutil_gettimeofday(&tv_out, NULL); + start_time=(((unsigned long long) tv_out.tv_sec) * 1000000) + (tv_out.tv_usec); + + connect__num_active_connections=0; + // create libevent base + libevent_base= event_base_new(); + unsigned int glover=GloMTH->get_global_version(); if (MySQL_Monitor__thread_MySQL_Thread_Variables_version < glover ) { MySQL_Monitor__thread_MySQL_Thread_Variables_version=glover; @@ -99,35 +498,133 @@ void * MySQL_Monitor::monitor_connect() { int cols=0; int affected_rows=0; SQLite3_result *resultset=NULL; - char *query=(char *)"SELECT hostname, port FROM mysql_servers"; + MySQL_Monitor_State_Data **sds=NULL; + char *query=(char *)"SELECT DISTINCT hostname, port FROM mysql_servers"; proxy_debug(PROXY_DEBUG_ADMIN, 4, "%s\n", query); - monitordb->execute_statement(query, &error , &cols , &affected_rows , &resultset); + admindb->execute_statement(query, &error , &cols , &affected_rows , &resultset); + int i=0; + sds=NULL; if (error) { proxy_error("Error on %s : %s\n", query, error); + goto __end_monitor_connect_loop; } else { + if (resultset->rows_count==0) { + goto __end_monitor_connect_loop; + } + sds=(MySQL_Monitor_State_Data **)malloc(resultset->rows_count * sizeof(MySQL_Monitor_State_Data *)); for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { SQLite3_row *r=*it; + //fprintf(stderr,"Host:%s, port:%s\n", r->fields[0], r->fields[1]); + sds[i] = new MySQL_Monitor_State_Data(r->fields[0],atoi(r->fields[1]),libevent_base); + sds[i]->task_id=MON_CONNECT; + connect__num_active_connections++; + total_connect__num_active_connections++; + if (total_connect__num_active_connections%1000==0) { + fprintf(stderr,"total conns: %d\n", total_connect__num_active_connections); + } + state_machine_handler(-1,-1,sds[i]); + i++; } } - fprintf(stderr,"MySQL_Monitor - CONNECT\n"); - usleep(1000000); + + // start libevent loop + event_base_dispatch(libevent_base); + + +__end_monitor_connect_loop: + if (sds) { + sqlite3_stmt *statement; + sqlite3 *mondb=monitordb->get_db(); + int rc; + char *query=NULL; + query=(char *)"DELETE FROM mysql_server_connect_log WHERE time_start < ?1"; + rc=sqlite3_prepare_v2(mondb, query, -1, &statement, 0); + assert(rc==SQLITE_OK); + rc=sqlite3_bind_int64(statement, 1, start_time-mysql_thread___monitor_history*1000); assert(rc==SQLITE_OK); + do { + rc=sqlite3_step(statement); + if (rc!=SQLITE_DONE) { // the execution of the prepared statement failed + fprintf(stderr,"%d %s\n",rc, sqlite3_errmsg(mondb)); + assert(rc==SQLITE_LOCKED); // it is possible that the table was locked because in use, in this case we retry + usleep(1000); + } + } while (rc!=SQLITE_DONE); + rc=sqlite3_clear_bindings(statement); assert(rc==SQLITE_OK); + rc=sqlite3_reset(statement); assert(rc==SQLITE_OK); + sqlite3_finalize(statement); + + query=(char *)"INSERT OR REPLACE INTO mysql_server_connect_log VALUES (?1 , ?2 , ?3 , ?4 , ?5)"; + rc=sqlite3_prepare_v2(mondb, query, -1, &statement, 0); + //fprintf(stderr,"%d %s\n",rc, sqlite3_errmsg(mondb)); + assert(rc==SQLITE_OK); + while (i>0) { + i--; + MySQL_Monitor_State_Data *mmsd=sds[i]; + rc=sqlite3_bind_text(statement, 1, mmsd->hostname, -1, SQLITE_TRANSIENT); assert(rc==SQLITE_OK); + rc=sqlite3_bind_int(statement, 2, mmsd->port); assert(rc==SQLITE_OK); + rc=sqlite3_bind_int64(statement, 3, start_time); assert(rc==SQLITE_OK); + rc=sqlite3_bind_int64(statement, 4, (mmsd->mysql_error_msg ? 0 : mmsd->t2-mmsd->t1)); assert(rc==SQLITE_OK); + rc=sqlite3_bind_text(statement, 5, mmsd->mysql_error_msg, -1, SQLITE_TRANSIENT); assert(rc==SQLITE_OK); + do { + rc=sqlite3_step(statement); + if (rc!=SQLITE_DONE) { // the execution of the prepared statement failed + fprintf(stderr,"%d %s\n",rc, sqlite3_errmsg(mondb)); + assert(rc==SQLITE_LOCKED); // it is possible that the table was locked because in use, in this case we retry + usleep(1000); + } + } while (rc!=SQLITE_DONE); + rc=sqlite3_clear_bindings(statement); assert(rc==SQLITE_OK); + rc=sqlite3_reset(statement); assert(rc==SQLITE_OK); + delete mmsd; + } + sqlite3_finalize(statement); + free(sds); + } + if (resultset) + delete resultset; + + event_base_free(libevent_base); + + t2=monotonic_time(); + + //fprintf(stderr,"%llu %llu %llu\n", t1, t2, mysql_thread___monitor_connect_interval); + if (t1+(1000*mysql_thread___monitor_connect_interval)>t2) { + usleep(t1+(1000*mysql_thread___monitor_connect_interval)-t2); + } + //fprintf(stderr,"MySQL_Monitor - CONNECT\n"); + //usleep(1000); } return NULL; } void * MySQL_Monitor::monitor_ping() { // initialize the MySQL Thread (note: this is not a real thread, just the structures associated with it) + struct event_base *libevent_base; unsigned int MySQL_Monitor__thread_MySQL_Thread_Variables_version; MySQL_Thread * mysql_thr = new MySQL_Thread(); mysql_thr->curtime=monotonic_time(); MySQL_Monitor__thread_MySQL_Thread_Variables_version=GloMTH->get_global_version(); mysql_thr->refresh_variables(); - unsigned int t1; - unsigned int t2; - t1=monotonic_time(); + unsigned long long t1; + unsigned long long t2; + unsigned long long start_time; + //unsigned int t1; + //unsigned int t2; + //t1=monotonic_time(); while (shutdown==false) { + + t1=monotonic_time(); + + struct timeval tv_out; + evutil_gettimeofday(&tv_out, NULL); + start_time=(((unsigned long long) tv_out.tv_sec) * 1000000) + (tv_out.tv_usec); + + ping__num_active_connections=0; + // create libevent base + libevent_base= event_base_new(); + unsigned int glover=GloMTH->get_global_version(); if (MySQL_Monitor__thread_MySQL_Thread_Variables_version < glover ) { MySQL_Monitor__thread_MySQL_Thread_Variables_version=glover; @@ -135,8 +632,113 @@ void * MySQL_Monitor::monitor_ping() { fprintf(stderr,"MySQL_Monitor - PING - refreshing variables\n"); } - fprintf(stderr,"MySQL_Monitor - PING\n"); - usleep(1000000); + char *error=NULL; + int cols=0; + int affected_rows=0; + SQLite3_result *resultset=NULL; + MySQL_Monitor_State_Data **sds=NULL; + char *query=(char *)"SELECT DISTINCT hostname, port FROM mysql_servers"; + proxy_debug(PROXY_DEBUG_ADMIN, 4, "%s\n", query); + admindb->execute_statement(query, &error , &cols , &affected_rows , &resultset); + int i=0; + sds=NULL; + if (error) { + proxy_error("Error on %s : %s\n", query, error); + goto __end_monitor_ping_loop; + } else { + if (resultset->rows_count==0) { + goto __end_monitor_ping_loop; + } + sds=(MySQL_Monitor_State_Data **)malloc(resultset->rows_count * sizeof(MySQL_Monitor_State_Data *)); + for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { + SQLite3_row *r=*it; + //fprintf(stderr,"Host:%s, port:%s\n", r->fields[0], r->fields[1]); + sds[i] = new MySQL_Monitor_State_Data(r->fields[0],atoi(r->fields[1]),libevent_base); + sds[i]->task_id=MON_PING; + ping__num_active_connections++; + total_ping__num_active_connections++; + if (total_ping__num_active_connections%1000==0) { + fprintf(stderr,"total conns: %d\n", total_ping__num_active_connections); + } + MySQL_Monitor_State_Data *_mmsd=sds[i]; + _mmsd->mysql=GloMyMon->My_Conn_Pool->get_connection(_mmsd->hostname, _mmsd->port); + if (_mmsd->mysql==NULL) { + state_machine_handler(-1,-1,_mmsd); + } else { + int fd=mysql_get_socket(_mmsd->mysql); + _mmsd->ST=7; + state_machine_handler(fd,-1,_mmsd); + } + i++; + } + } + + // start libevent loop + event_base_dispatch(libevent_base); + +__end_monitor_ping_loop: + if (sds) { + sqlite3_stmt *statement; + sqlite3 *mondb=monitordb->get_db(); + int rc; + char *query=NULL; + query=(char *)"DELETE FROM mysql_server_ping_log WHERE time_start < ?1"; + rc=sqlite3_prepare_v2(mondb, query, -1, &statement, 0); + assert(rc==SQLITE_OK); + rc=sqlite3_bind_int64(statement, 1, start_time-mysql_thread___monitor_history*1000); assert(rc==SQLITE_OK); + do { + rc=sqlite3_step(statement); + if (rc!=SQLITE_DONE) { // the execution of the prepared statement failed + fprintf(stderr,"%d %s\n",rc, sqlite3_errmsg(mondb)); + assert(rc==SQLITE_LOCKED); // it is possible that the table was locked because in use, in this case we retry + usleep(1000); + } + } while (rc!=SQLITE_DONE); + rc=sqlite3_clear_bindings(statement); assert(rc==SQLITE_OK); + rc=sqlite3_reset(statement); assert(rc==SQLITE_OK); + sqlite3_finalize(statement); + + query=(char *)"INSERT OR REPLACE INTO mysql_server_ping_log VALUES (?1 , ?2 , ?3 , ?4 , ?5)"; + rc=sqlite3_prepare_v2(mondb, query, -1, &statement, 0); + //fprintf(stderr,"%d %s\n",rc, sqlite3_errmsg(mondb)); + assert(rc==SQLITE_OK); + while (i>0) { + i--; + MySQL_Monitor_State_Data *mmsd=sds[i]; + rc=sqlite3_bind_text(statement, 1, mmsd->hostname, -1, SQLITE_TRANSIENT); assert(rc==SQLITE_OK); + rc=sqlite3_bind_int(statement, 2, mmsd->port); assert(rc==SQLITE_OK); + rc=sqlite3_bind_int64(statement, 3, start_time); assert(rc==SQLITE_OK); + rc=sqlite3_bind_int64(statement, 4, (mmsd->mysql_error_msg ? 0 : mmsd->t2-mmsd->t1)); assert(rc==SQLITE_OK); + rc=sqlite3_bind_text(statement, 5, mmsd->mysql_error_msg, -1, SQLITE_TRANSIENT); assert(rc==SQLITE_OK); + do { + rc=sqlite3_step(statement); + if (rc!=SQLITE_DONE) { // the execution of the prepared statement failed + fprintf(stderr,"%d %s\n",rc, sqlite3_errmsg(mondb)); + assert(rc==SQLITE_LOCKED); // it is possible that the table was locked because in use, in this case we retry + usleep(1000); + } + } while (rc!=SQLITE_DONE); + rc=sqlite3_clear_bindings(statement); assert(rc==SQLITE_OK); + rc=sqlite3_reset(statement); assert(rc==SQLITE_OK); + delete mmsd; + } + sqlite3_finalize(statement); + free(sds); + } + + if (resultset) + delete resultset; + + event_base_free(libevent_base); + + t2=monotonic_time(); + + //fprintf(stderr,"%llu %llu %llu\n", t1, t2, mysql_thread___monitor_connect_interval); + if (t1+(1000*mysql_thread___monitor_ping_interval)>t2) { + usleep(t1+(1000*mysql_thread___monitor_ping_interval)-t2); + } + //fprintf(stderr,"MySQL_Monitor - PING\n"); + //usleep(1000000); } return NULL; } diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 2b96a4dcf..8733edb5e 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -114,10 +114,18 @@ static char * mysql_thread_variables_names[]= { (char *)"default_charset", (char *)"have_compress", (char *)"interfaces", + (char *)"monitor_history", (char *)"monitor_connect_interval", (char *)"monitor_connect_timeout", (char *)"monitor_ping_interval", (char *)"monitor_ping_timeout", + (char *)"monitor_username", + (char *)"monitor_password", + (char *)"monitor_query_variables", + (char *)"monitor_query_status", + (char *)"monitor_query_interval", + (char *)"monitor_query_timeout", + (char *)"monitor_timer_cached", (char *)"ping_interval_server", (char *)"ping_timeout_server", (char *)"default_schema", @@ -151,10 +159,18 @@ MySQL_Threads_Handler::MySQL_Threads_Handler() { spinlock_rwlock_init(&rwlock); pthread_attr_init(&attr); variables.connect_timeout_server=10000; + variables.monitor_history=600000; variables.monitor_connect_interval=120000; variables.monitor_connect_timeout=200; variables.monitor_ping_interval=60000; variables.monitor_ping_timeout=100; + variables.monitor_query_interval=60000; + variables.monitor_query_timeout=100; + variables.monitor_username=strdup((char *)"monitor"); + variables.monitor_password=strdup((char *)"monitor"); + variables.monitor_query_variables=strdup((char *)"SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES"); + variables.monitor_query_status=strdup((char *)"SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS"); + variables.monitor_timer_cached=true; variables.ping_interval_server=5000; variables.ping_timeout_server=100; variables.connect_timeout_server_error=strdup((char *)"#2003:Can't connect to MySQL server"); @@ -245,6 +261,12 @@ void MySQL_Threads_Handler::commit() { } char * MySQL_Threads_Handler::get_variable_string(char *name) { + if (!strncasecmp(name,"monitor_",8)) { + if (!strcasecmp(name,"monitor_username")) return strdup(variables.monitor_username); + if (!strcasecmp(name,"monitor_password")) return strdup(variables.monitor_password); + if (!strcasecmp(name,"monitor_query_variables")) return strdup(variables.monitor_query_variables); + if (!strcasecmp(name,"monitor_query_status")) return strdup(variables.monitor_query_status); + } if (!strcasecmp(name,"connect_timeout_server_error")) return strdup(variables.connect_timeout_server_error); if (!strcasecmp(name,"server_version")) return strdup(variables.server_version); if (!strcasecmp(name,"default_schema")) return strdup(variables.default_schema); @@ -270,10 +292,14 @@ int MySQL_Threads_Handler::get_variable_int(char *name) { if (!strcasecmp(name,"session_debug")) return (int)variables.session_debug; #endif /* DEBUG */ if (!strncasecmp(name,"monitor_",8)) { + if (!strcasecmp(name,"monitor_history")) return (int)variables.monitor_history; if (!strcasecmp(name,"monitor_connect_interval")) return (int)variables.monitor_connect_interval; if (!strcasecmp(name,"monitor_connect_timeout")) return (int)variables.monitor_connect_timeout; if (!strcasecmp(name,"monitor_ping_interval")) return (int)variables.monitor_ping_interval; if (!strcasecmp(name,"monitor_ping_timeout")) return (int)variables.monitor_ping_timeout; + if (!strcasecmp(name,"monitor_query_interval")) return (int)variables.monitor_query_interval; + if (!strcasecmp(name,"monitor_query_timeout")) return (int)variables.monitor_query_timeout; + if (!strcasecmp(name,"monitor_timer_cached")) return (int)variables.monitor_timer_cached; } if (!strcasecmp(name,"connect_timeout_server")) return (int)variables.connect_timeout_server; if (!strcasecmp(name,"ping_interval_server")) return (int)variables.ping_interval_server; @@ -302,6 +328,14 @@ char * MySQL_Threads_Handler::get_variable(char *name) { // this is the public f } // monitor variables if (!strncasecmp(name,"monitor_",8)) { + if (!strcasecmp(name,"monitor_username")) return strdup(variables.monitor_username); + if (!strcasecmp(name,"monitor_password")) return strdup(variables.monitor_password); + if (!strcasecmp(name,"monitor_query_variables")) return strdup(variables.monitor_query_variables); + if (!strcasecmp(name,"monitor_query_status")) return strdup(variables.monitor_query_status); + if (!strcasecmp(name,"monitor_history")) { + sprintf(intbuf,"%d",variables.monitor_history); + return strdup(intbuf); + } if (!strcasecmp(name,"monitor_connect_interval")) { sprintf(intbuf,"%d",variables.monitor_connect_interval); return strdup(intbuf); @@ -318,6 +352,17 @@ char * MySQL_Threads_Handler::get_variable(char *name) { // this is the public f sprintf(intbuf,"%d",variables.monitor_ping_timeout); return strdup(intbuf); } + if (!strcasecmp(name,"monitor_query_interval")) { + sprintf(intbuf,"%d",variables.monitor_query_interval); + return strdup(intbuf); + } + if (!strcasecmp(name,"monitor_query_timeout")) { + sprintf(intbuf,"%d",variables.monitor_query_timeout); + return strdup(intbuf); + } + if (!strcasecmp(name,"monitor_timer_cached")) { + return strdup((variables.monitor_timer_cached ? "true" : "false")); + } } if (!strcasecmp(name,"default_charset")) { sprintf(intbuf,"%d",variables.default_charset); @@ -384,9 +429,54 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t // monitor variables if (!strncasecmp(name,"monitor_",8)) { - if (!strcasecmp(name,"monitor_connect_interval")) { + if (!strcasecmp(name,"monitor_username")) { + if (vallen) { + free(variables.monitor_username); + variables.monitor_username=strdup(value); + return true; + } else { + return false; + } + } + if (!strcasecmp(name,"monitor_password")) { + if (vallen) { + free(variables.monitor_password); + variables.monitor_password=strdup(value); + return true; + } else { + return false; + } + } + if (!strcasecmp(name,"monitor_query_variables")) { + if (vallen) { + free(variables.monitor_query_variables); + variables.monitor_query_variables=strdup(value); + return true; + } else { + return false; + } + } + if (!strcasecmp(name,"monitor_query_status")) { + if (vallen) { + free(variables.monitor_query_status); + variables.monitor_query_status=strdup(value); + return true; + } else { + return false; + } + } + if (!strcasecmp(name,"monitor_history")) { int intv=atoi(value); if (intv > 1000 && intv < 7*24*3600*1000) { + variables.monitor_history=intv; + return true; + } else { + return false; + } + } + if (!strcasecmp(name,"monitor_connect_interval")) { + int intv=atoi(value); + if (intv >= 100 && intv < 7*24*3600*1000) { variables.monitor_connect_interval=intv; return true; } else { @@ -395,7 +485,7 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t } if (!strcasecmp(name,"monitor_connect_timeout")) { int intv=atoi(value); - if (intv > 100 && intv < 600*1000) { + if (intv >= 100 && intv < 600*1000) { variables.monitor_connect_timeout=intv; return true; } else { @@ -404,7 +494,7 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t } if (!strcasecmp(name,"monitor_ping_interval")) { int intv=atoi(value); - if (intv > 1000 && intv < 7*24*3600*1000) { + if (intv >= 100 && intv < 7*24*3600*1000) { variables.monitor_ping_interval=intv; return true; } else { @@ -413,13 +503,42 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t } if (!strcasecmp(name,"monitor_ping_timeout")) { int intv=atoi(value); - if (intv > 100 && intv < 600*1000) { + if (intv >= 100 && intv < 600*1000) { variables.monitor_ping_timeout=intv; return true; } else { return false; } } + if (!strcasecmp(name,"monitor_query_interval")) { + int intv=atoi(value); + if (intv >= 100 && intv < 7*24*3600*1000) { + variables.monitor_query_interval=intv; + return true; + } else { + return false; + } + } + if (!strcasecmp(name,"monitor_query_timeout")) { + int intv=atoi(value); + if (intv >= 100 && intv < 600*1000) { + variables.monitor_query_timeout=intv; + return true; + } else { + return false; + } + } + if (!strcasecmp(name,"monitor_timer_cached")) { + if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { + variables.monitor_timer_cached=true; + return true; + } + if (strcasecmp(value,"false")==0 || strcasecmp(value,"0")==0) { + variables.monitor_timer_cached=false; + return true; + } + return false; + } } if (!strcasecmp(name,"ping_interval_server")) { int intv=atoi(value); @@ -1094,6 +1213,24 @@ void MySQL_Thread::refresh_variables() { mysql_thread___connect_timeout_server=GloMTH->get_variable_int((char *)"connect_timeout_server"); if (mysql_thread___connect_timeout_server_error) free(mysql_thread___connect_timeout_server_error); mysql_thread___connect_timeout_server_error=GloMTH->get_variable_string((char *)"connect_timeout_server_error"); + + if (mysql_thread___monitor_username) free(mysql_thread___monitor_username); + mysql_thread___monitor_username=GloMTH->get_variable_string((char *)"monitor_username"); + if (mysql_thread___monitor_password) free(mysql_thread___monitor_password); + mysql_thread___monitor_password=GloMTH->get_variable_string((char *)"monitor_password"); + if (mysql_thread___monitor_query_variables) free(mysql_thread___monitor_query_variables); + mysql_thread___monitor_query_variables=GloMTH->get_variable_string((char *)"monitor_query_variables"); + if (mysql_thread___monitor_query_status) free(mysql_thread___monitor_query_status); + mysql_thread___monitor_query_status=GloMTH->get_variable_string((char *)"monitor_query_status"); + mysql_thread___monitor_timer_cached=(bool)GloMTH->get_variable_int((char *)"monitor_timer_cached"); + mysql_thread___monitor_history=GloMTH->get_variable_int((char *)"monitor_history"); + mysql_thread___monitor_connect_interval=GloMTH->get_variable_int((char *)"monitor_connect_interval"); + mysql_thread___monitor_connect_timeout=GloMTH->get_variable_int((char *)"monitor_connect_timeout"); + mysql_thread___monitor_ping_interval=GloMTH->get_variable_int((char *)"monitor_ping_interval"); + mysql_thread___monitor_ping_timeout=GloMTH->get_variable_int((char *)"monitor_ping_timeout"); + mysql_thread___monitor_query_interval=GloMTH->get_variable_int((char *)"monitor_query_interval"); + mysql_thread___monitor_query_timeout=GloMTH->get_variable_int((char *)"monitor_query_timeout"); + if (mysql_thread___server_version) free(mysql_thread___server_version); mysql_thread___server_version=GloMTH->get_variable_string((char *)"server_version"); if (mysql_thread___default_schema) free(mysql_thread___default_schema); diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index a12840364..f28a4540f 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -1317,6 +1317,8 @@ bool ProxySQL_Admin::init() { configdb=new SQLite3DB(); configdb->open((char *)GloVars.admindb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); + monitordb = new SQLite3DB(); + monitordb->open((char *)"file:mem_monitordb?mode=memory&cache=shared", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); tables_defs_admin=new std::vector; tables_defs_stats=new std::vector; @@ -1349,6 +1351,7 @@ bool ProxySQL_Admin::init() { __attach_db_to_admindb(configdb, (char *)"disk"); __attach_db_to_admindb(statsdb, (char *)"stats"); + __attach_db_to_admindb(monitordb, (char *)"monitor"); #ifdef DEBUG admindb->execute("ATTACH DATABASE 'file:mem_mydb?mode=memory&cache=shared' AS myhgm"); @@ -1426,6 +1429,7 @@ void ProxySQL_Admin::admin_shutdown() { delete admindb; delete statsdb; delete configdb; + delete monitordb; sqlite3_shutdown(); if (main_poll_fds) { for (i=0;i