diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-06-07 08:01:46 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-06-07 08:01:46 +0300 |
commit | 757b835af8984c1fa796aec1789b484bd307bb8a (patch) | |
tree | 7f37eec457262277ff2fe856eb2907155fded780 /src/mysqlstat.c | |
parent | ec36698ad30b99a05104952f011cf471faf83e56 (diff) | |
download | mysqlstat-757b835af8984c1fa796aec1789b484bd307bb8a.tar.gz mysqlstat-757b835af8984c1fa796aec1789b484bd307bb8a.tar.bz2 |
Keep MySQL connection open as long as possible. Implement new OIDs.
* src/MYSQL-STAT-MIB.txt: New OIDs: processTotalCount,
processActiveCount, and processSlaveCount
* src/mysqlstat.c (mysqlstat_connect): Keep connection open.
(mysqlstat_disconnect): Remove.
(get_process_list, process_first, process_next): New functions.
Keep a cached list of processes and iterate through it.
All functions updated.
(process_total_count,process_active_count)
(process_slave_count): New functions.
* src/mysqlstat.h (process_total_count,process_active_count)
(process_slave_count): New protos.
* src/mysqlstat_mib.mib2c (handle_$i): Update.
Diffstat (limited to 'src/mysqlstat.c')
-rw-r--r-- | src/mysqlstat.c | 220 |
1 files changed, 149 insertions, 71 deletions
diff --git a/src/mysqlstat.c b/src/mysqlstat.c index 938439a..2ffd0dd 100644 --- a/src/mysqlstat.c +++ b/src/mysqlstat.c @@ -54,34 +54,29 @@ xstrdup(char const *s) mysqlstat_connection_t mysqlstat_connect(void) { - struct mysqlstat_connection *conn; + static struct mysqlstat_connection *conn; my_bool t = 1; - conn = xcalloc(1, sizeof(*conn)); - mysql_init(&conn->mysql); - if (access(config_file, F_OK) == 0) - mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_FILE, - config_file); - mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_GROUP, "mysqlstat"); - mysql_options(&conn->mysql, MYSQL_OPT_RECONNECT, &t); - if (!mysql_real_connect(&conn->mysql, NULL, NULL, NULL, NULL, 0, - NULL, 0)) { - snmp_log(LOG_ERR, "can't connect to MySQL: %s\n", - mysql_error(&conn->mysql)); - free(conn); - conn = NULL; + if (!conn) { + conn = xcalloc(1, sizeof(*conn)); + mysql_init(&conn->mysql); + if (access(config_file, F_OK) == 0) + mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_FILE, + config_file); + mysql_options(&conn->mysql, + MYSQL_READ_DEFAULT_GROUP, "mysqlstat"); + mysql_options(&conn->mysql, MYSQL_OPT_RECONNECT, &t); + if (!mysql_real_connect(&conn->mysql, + NULL, NULL, NULL, NULL, 0, + NULL, 0)) { + snmp_log(LOG_ERR, "can't connect to MySQL: %s\n", + mysql_error(&conn->mysql)); + free(conn); + conn = NULL; + } } return conn; } - -void -mysqlstat_disconnect(mysqlstat_connection_t conn) -{ - if (!conn) - return; - mysql_close(&conn->mysql); - free(conn); -} unsigned mysqlstat_cache_timeout = CACHE_TIMEOUT; @@ -101,7 +96,98 @@ unsigned mysqlstat_cache_timeout = CACHE_TIMEOUT; #define ASSIGN_ROW(e,m,r) ASSIGN_STRING(e,m,(r)[__cat2__(FI_,m)]) #define STREQ(pat,str) (strcmp(#pat, str) == 0) + +struct process_list { + time_t ts; + MYSQL_RES *res; + uint32_t total; + uint32_t active; + uint32_t slaves; + uint32_t itr; +}; + +enum { + FI_processID, + FI_processUser, + FI_processHost, + FI_processDatabase, + FI_processCommand, + FI_processTime, + FI_processState, + FI_processInfo +}; +static int +get_process_list(struct process_list **p) +{ + static struct process_list plist; + time_t now; + + now = time(NULL); + if (!plist.res || now - plist.ts >= mysqlstat_cache_timeout) { + mysqlstat_connection_t conn; + unsigned i; + + if (plist.res) { + mysql_free_result(plist.res); + plist.res = NULL; + plist.total = plist.active = plist.slaves = 0; + } + DEBUGMSGTL(("mysqlstat", "Getting process list\n")); + + conn = mysqlstat_connect(); + if (!conn) + return SNMP_ERR_GENERR; + + if (mysql_query(&conn->mysql, "SHOW PROCESSLIST")) { + snmp_log(LOG_ERR, "can't get slave process list: %s\n", + mysql_error(&conn->mysql)); + return SNMP_ERR_NOSUCHNAME; + } + plist.res = mysql_store_result(&conn->mysql); + plist.ts = now; + + plist.total = mysql_num_rows(plist.res); + for (i = 0; i < plist.total; i++) { + MYSQL_ROW row; + + mysql_data_seek(plist.res, i); + row = mysql_fetch_row(plist.res); + if (!row[FI_processState] + || STREQ(Sleep, row[FI_processState])) + continue; + if (row[FI_processCommand] + && strcmp(row[FI_processCommand], "Binlog Dump") == 0) + plist.slaves++; + else + plist.active++; + } + } + *p = &plist; + return 0; +} + +MYSQL_ROW +process_next(struct process_list *p) +{ + MYSQL_ROW row; + if (p->itr >= p->total) + return NULL; + mysql_data_seek(p->res, p->itr); + ++p->itr; + return mysql_fetch_row(p->res); +} + +MYSQL_ROW +process_first(struct process_list **state) +{ + struct process_list *p; + if (get_process_list(&p)) + return NULL; + p->itr = 0; + *state = p; + return process_next(p); +} static long val_Slave_IO_Running(char const *val) @@ -224,13 +310,12 @@ replSlaveStatusTable_load(netsnmp_cache *cache, void *vmagic) if (mysql_query(&conn->mysql, "SHOW SLAVE STATUS")) { snmp_log(LOG_ERR, "can't get slave status: %s\n", mysql_error(&conn->mysql)); - mysqlstat_disconnect(conn); return SNMP_ERR_NOSUCHNAME; } res = mysql_store_result(&conn->mysql); if (mysql_num_rows(res) < 1) { - snmp_log(LOG_INFO, "empty slave status\n"); + /* snmp_log(LOG_INFO, "empty slave status\n"); */ return 0; } @@ -240,14 +325,12 @@ replSlaveStatusTable_load(netsnmp_cache *cache, void *vmagic) ent = SNMP_MALLOC_TYPEDEF(struct replSlaveStatusTable_entry); if (!ent) { - mysqlstat_disconnect(conn); return SNMP_ERR_GENERR; } data_row = netsnmp_tdata_create_row(); if (!data_row) { SNMP_FREE(ent); - mysqlstat_disconnect(conn); return SNMP_ERR_GENERR; } data_row->data = ent; @@ -259,10 +342,9 @@ replSlaveStatusTable_load(netsnmp_cache *cache, void *vmagic) netsnmp_tdata_add_row(table, data_row); for (i = 0; i < num_fields; i++) - store_slave_status_row (ent, fields[i].name, row[i]); + store_slave_status_row(ent, fields[i].name, row[i]); mysql_free_result(res); - mysqlstat_disconnect(conn); return 0; } @@ -295,18 +377,6 @@ replSlaveStatusTable_entry_free(void *data) free(ent->replMasterSSLKey); } - -enum { - FI_processID, - FI_processUser, - FI_processHost, - FI_processDatabase, - FI_processCommand, - FI_processTime, - FI_processState, - FI_processInfo -}; - static void process_list_add(netsnmp_tdata *table_data, long idx, MYSQL_ROW mysql_row) { @@ -327,8 +397,13 @@ process_list_add(netsnmp_tdata *table_data, long idx, MYSQL_ROW mysql_row) ent->processIndex = idx; if (mysql_row[FI_processID]) ent->processID = strtol(mysql_row[FI_processID], NULL, 10); + ASSIGN_ROW(ent, processUser, mysql_row); - ASSIGN_ROW(ent, processHost, mysql_row); + + ent->processHost_len = strcspn(mysql_row[FI_processHost], ":"); + ent->processHost = xmalloc(ent->processHost_len); + memcpy(ent->processHost, mysql_row[FI_processHost], ent->processHost_len); + ASSIGN_ROW(ent, processDatabase, mysql_row); ASSIGN_ROW(ent, processCommand, mysql_row); if (mysql_row[FI_processTime]) @@ -346,39 +421,14 @@ process_list_add(netsnmp_tdata *table_data, long idx, MYSQL_ROW mysql_row) int processListTable_load(netsnmp_cache *cache, void *vmagic) { - mysqlstat_connection_t conn; - MYSQL_RES *res; - unsigned int num_rows, i; + struct process_list *p; netsnmp_tdata *table = (netsnmp_tdata *) vmagic; + MYSQL_ROW row; + uint32_t i; - DEBUGMSGTL(("mysqlstat", "Getting process list\n")); - - conn = mysqlstat_connect(); - if (!conn) - return SNMP_ERR_GENERR; - - if (mysql_query(&conn->mysql, "SHOW PROCESSLIST")) { - snmp_log(LOG_ERR, "can't get slave process list: %s\n", - mysql_error(&conn->mysql)); - mysqlstat_disconnect(conn); - return SNMP_ERR_NOSUCHNAME; - } - - res = mysql_store_result(&conn->mysql); - num_rows = mysql_num_rows(res); - - for (i = 0; i < num_rows; i++) { - MYSQL_ROW row; - - mysql_data_seek(res, i); - row = mysql_fetch_row(res); - + for (row = process_first(&p), i = 0; row; row = process_next(p), i++) { process_list_add(table, i, row); } - - mysql_free_result(res); - mysqlstat_disconnect(conn); - return 0; } @@ -393,6 +443,34 @@ processListTable_entry_free(void *data) free(ent->processInfo); } +uint32_t +process_total_count(void) +{ + struct process_list *p; + if (get_process_list(&p)) + return 0; + return p->total; +} + +uint32_t +process_active_count(void) +{ + struct process_list *p; + if (get_process_list(&p)) + return 0; + return p->active; +} + +uint32_t +process_slave_count(void) +{ + struct process_list *p; + if (get_process_list(&p)) + return 0; + return p->slaves; +} + + #if 0 unsigned replSlaveTable_timeout = CACHE_TIMEOUT; |