diff options
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 | |||
@@ -56,18 +56,22 @@ mysqlstat_connect(void) | |||
56 | { | 56 | { |
57 | struct mysqlstat_connection *conn; | 57 | static struct mysqlstat_connection *conn; |
58 | my_bool t = 1; | 58 | my_bool t = 1; |
59 | 59 | ||
60 | conn = xcalloc(1, sizeof(*conn)); | 60 | if (!conn) { |
61 | mysql_init(&conn->mysql); | 61 | conn = xcalloc(1, sizeof(*conn)); |
62 | if (access(config_file, F_OK) == 0) | 62 | mysql_init(&conn->mysql); |
63 | mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_FILE, | 63 | if (access(config_file, F_OK) == 0) |
64 | config_file); | 64 | mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_FILE, |
65 | mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_GROUP, "mysqlstat"); | 65 | config_file); |
66 | mysql_options(&conn->mysql, MYSQL_OPT_RECONNECT, &t); | 66 | mysql_options(&conn->mysql, |
67 | if (!mysql_real_connect(&conn->mysql, NULL, NULL, NULL, NULL, 0, | 67 | MYSQL_READ_DEFAULT_GROUP, "mysqlstat"); |
68 | NULL, 0)) { | 68 | mysql_options(&conn->mysql, MYSQL_OPT_RECONNECT, &t); |
69 | snmp_log(LOG_ERR, "can't connect to MySQL: %s\n", | 69 | if (!mysql_real_connect(&conn->mysql, |
70 | mysql_error(&conn->mysql)); | 70 | NULL, NULL, NULL, NULL, 0, |
71 | free(conn); | 71 | NULL, 0)) { |
72 | conn = NULL; | 72 | snmp_log(LOG_ERR, "can't connect to MySQL: %s\n", |
73 | mysql_error(&conn->mysql)); | ||
74 | free(conn); | ||
75 | conn = NULL; | ||
76 | } | ||
73 | } | 77 | } |
@@ -75,11 +79,2 @@ mysqlstat_connect(void) | |||
75 | } | 79 | } |
76 | |||
77 | void | ||
78 | mysqlstat_disconnect(mysqlstat_connection_t conn) | ||
79 | { | ||
80 | if (!conn) | ||
81 | return; | ||
82 | mysql_close(&conn->mysql); | ||
83 | free(conn); | ||
84 | } | ||
85 | 80 | ||
@@ -103,3 +98,94 @@ unsigned mysqlstat_cache_timeout = CACHE_TIMEOUT; | |||
103 | #define STREQ(pat,str) (strcmp(#pat, str) == 0) | 98 | #define STREQ(pat,str) (strcmp(#pat, str) == 0) |
99 | |||
100 | struct process_list { | ||
101 | time_t ts; | ||
102 | MYSQL_RES *res; | ||
103 | uint32_t total; | ||
104 | uint32_t active; | ||
105 | uint32_t slaves; | ||
106 | uint32_t itr; | ||
107 | }; | ||
108 | |||
109 | enum { | ||
110 | FI_processID, | ||
111 | FI_processUser, | ||
112 | FI_processHost, | ||
113 | FI_processDatabase, | ||
114 | FI_processCommand, | ||
115 | FI_processTime, | ||
116 | FI_processState, | ||
117 | FI_processInfo | ||
118 | }; | ||
104 | 119 | ||
120 | static int | ||
121 | get_process_list(struct process_list **p) | ||
122 | { | ||
123 | static struct process_list plist; | ||
124 | time_t now; | ||
125 | |||
126 | now = time(NULL); | ||
127 | if (!plist.res || now - plist.ts >= mysqlstat_cache_timeout) { | ||
128 | mysqlstat_connection_t conn; | ||
129 | unsigned i; | ||
130 | |||
131 | if (plist.res) { | ||
132 | mysql_free_result(plist.res); | ||
133 | plist.res = NULL; | ||
134 | plist.total = plist.active = plist.slaves = 0; | ||
135 | } | ||
136 | DEBUGMSGTL(("mysqlstat", "Getting process list\n")); | ||
137 | |||
138 | conn = mysqlstat_connect(); | ||
139 | if (!conn) | ||
140 | return SNMP_ERR_GENERR; | ||
141 | |||
142 | if (mysql_query(&conn->mysql, "SHOW PROCESSLIST")) { | ||
143 | snmp_log(LOG_ERR, "can't get slave process list: %s\n", | ||
144 | mysql_error(&conn->mysql)); | ||
145 | return SNMP_ERR_NOSUCHNAME; | ||
146 | } | ||
147 | plist.res = mysql_store_result(&conn->mysql); | ||
148 | plist.ts = now; | ||
149 | |||
150 | plist.total = mysql_num_rows(plist.res); | ||
151 | for (i = 0; i < plist.total; i++) { | ||
152 | MYSQL_ROW row; | ||
153 | |||
154 | mysql_data_seek(plist.res, i); | ||
155 | row = mysql_fetch_row(plist.res); | ||
156 | if (!row[FI_processState] | ||
157 | || STREQ(Sleep, row[FI_processState])) | ||
158 | continue; | ||
159 | if (row[FI_processCommand] | ||
160 | && strcmp(row[FI_processCommand], "Binlog Dump") == 0) | ||
161 | plist.slaves++; | ||
162 | else | ||
163 | plist.active++; | ||
164 | } | ||
165 | } | ||
166 | *p = &plist; | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | MYSQL_ROW | ||
171 | process_next(struct process_list *p) | ||
172 | { | ||
173 | MYSQL_ROW row; | ||
174 | if (p->itr >= p->total) | ||
175 | return NULL; | ||
176 | mysql_data_seek(p->res, p->itr); | ||
177 | ++p->itr; | ||
178 | return mysql_fetch_row(p->res); | ||
179 | } | ||
180 | |||
181 | MYSQL_ROW | ||
182 | process_first(struct process_list **state) | ||
183 | { | ||
184 | struct process_list *p; | ||
185 | if (get_process_list(&p)) | ||
186 | return NULL; | ||
187 | p->itr = 0; | ||
188 | *state = p; | ||
189 | return process_next(p); | ||
190 | } | ||
105 | 191 | ||
@@ -226,3 +312,2 @@ replSlaveStatusTable_load(netsnmp_cache *cache, void *vmagic) | |||
226 | mysql_error(&conn->mysql)); | 312 | mysql_error(&conn->mysql)); |
227 | mysqlstat_disconnect(conn); | ||
228 | return SNMP_ERR_NOSUCHNAME; | 313 | return SNMP_ERR_NOSUCHNAME; |
@@ -232,3 +317,3 @@ replSlaveStatusTable_load(netsnmp_cache *cache, void *vmagic) | |||
232 | if (mysql_num_rows(res) < 1) { | 317 | if (mysql_num_rows(res) < 1) { |
233 | snmp_log(LOG_INFO, "empty slave status\n"); | 318 | /* snmp_log(LOG_INFO, "empty slave status\n"); */ |
234 | return 0; | 319 | return 0; |
@@ -242,3 +327,2 @@ replSlaveStatusTable_load(netsnmp_cache *cache, void *vmagic) | |||
242 | if (!ent) { | 327 | if (!ent) { |
243 | mysqlstat_disconnect(conn); | ||
244 | return SNMP_ERR_GENERR; | 328 | return SNMP_ERR_GENERR; |
@@ -249,3 +333,2 @@ replSlaveStatusTable_load(netsnmp_cache *cache, void *vmagic) | |||
249 | SNMP_FREE(ent); | 333 | SNMP_FREE(ent); |
250 | mysqlstat_disconnect(conn); | ||
251 | return SNMP_ERR_GENERR; | 334 | return SNMP_ERR_GENERR; |
@@ -261,6 +344,5 @@ replSlaveStatusTable_load(netsnmp_cache *cache, void *vmagic) | |||
261 | for (i = 0; i < num_fields; i++) | 344 | for (i = 0; i < num_fields; i++) |
262 | store_slave_status_row (ent, fields[i].name, row[i]); | 345 | store_slave_status_row(ent, fields[i].name, row[i]); |
263 | 346 | ||
264 | mysql_free_result(res); | 347 | mysql_free_result(res); |
265 | mysqlstat_disconnect(conn); | ||
266 | return 0; | 348 | return 0; |
@@ -297,14 +379,2 @@ replSlaveStatusTable_entry_free(void *data) | |||
297 | 379 | ||
298 | |||
299 | enum { | ||
300 | FI_processID, | ||
301 | FI_processUser, | ||
302 | FI_processHost, | ||
303 | FI_processDatabase, | ||
304 | FI_processCommand, | ||
305 | FI_processTime, | ||
306 | FI_processState, | ||
307 | FI_processInfo | ||
308 | }; | ||
309 | |||
310 | static void | 380 | static void |
@@ -329,4 +399,9 @@ process_list_add(netsnmp_tdata *table_data, long idx, MYSQL_ROW mysql_row) | |||
329 | ent->processID = strtol(mysql_row[FI_processID], NULL, 10); | 399 | ent->processID = strtol(mysql_row[FI_processID], NULL, 10); |
400 | |||
330 | ASSIGN_ROW(ent, processUser, mysql_row); | 401 | ASSIGN_ROW(ent, processUser, mysql_row); |
331 | ASSIGN_ROW(ent, processHost, mysql_row); | 402 | |
403 | ent->processHost_len = strcspn(mysql_row[FI_processHost], ":"); | ||
404 | ent->processHost = xmalloc(ent->processHost_len); | ||
405 | memcpy(ent->processHost, mysql_row[FI_processHost], ent->processHost_len); | ||
406 | |||
332 | ASSIGN_ROW(ent, processDatabase, mysql_row); | 407 | ASSIGN_ROW(ent, processDatabase, mysql_row); |
@@ -348,35 +423,10 @@ processListTable_load(netsnmp_cache *cache, void *vmagic) | |||
348 | { | 423 | { |
349 | mysqlstat_connection_t conn; | 424 | struct process_list *p; |
350 | MYSQL_RES *res; | ||
351 | unsigned int num_rows, i; | ||
352 | netsnmp_tdata *table = (netsnmp_tdata *) vmagic; | 425 | netsnmp_tdata *table = (netsnmp_tdata *) vmagic; |
426 | MYSQL_ROW row; | ||
427 | uint32_t i; | ||
353 | 428 | ||
354 | DEBUGMSGTL(("mysqlstat", "Getting process list\n")); | 429 | for (row = process_first(&p), i = 0; row; row = process_next(p), i++) { |
355 | |||
356 | conn = mysqlstat_connect(); | ||
357 | if (!conn) | ||
358 | return SNMP_ERR_GENERR; | ||
359 | |||
360 | if (mysql_query(&conn->mysql, "SHOW PROCESSLIST")) { | ||
361 | snmp_log(LOG_ERR, "can't get slave process list: %s\n", | ||
362 | mysql_error(&conn->mysql)); | ||
363 | mysqlstat_disconnect(conn); | ||
364 | return SNMP_ERR_NOSUCHNAME; | ||
365 | } | ||
366 | |||
367 | res = mysql_store_result(&conn->mysql); | ||
368 | num_rows = mysql_num_rows(res); | ||
369 | |||
370 | for (i = 0; i < num_rows; i++) { | ||
371 | MYSQL_ROW row; | ||
372 | |||
373 | mysql_data_seek(res, i); | ||
374 | row = mysql_fetch_row(res); | ||
375 | |||
376 | process_list_add(table, i, row); | 430 | process_list_add(table, i, row); |
377 | } | 431 | } |
378 | |||
379 | mysql_free_result(res); | ||
380 | mysqlstat_disconnect(conn); | ||
381 | |||
382 | return 0; | 432 | return 0; |
@@ -395,2 +445,30 @@ processListTab |