aboutsummaryrefslogtreecommitdiff
path: root/src/mysqlstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mysqlstat.c')
-rw-r--r--src/mysqlstat.c220
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
77void
78mysqlstat_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
100struct 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
109enum {
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
120static int
121get_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
170MYSQL_ROW
171process_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
181MYSQL_ROW
182process_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
299enum {
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
310static void 380static 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