static int mysql_drive_session(eventer_t e, int mask, void *closure, struct timeval *now) { const char *dsn, *sql; char sql_buff[8192]; char dsn_buff[512]; mysql_check_info_t *ci = closure; noit_check_t *check = ci->check; struct timeval t1, t2, diff; mtev_hash_table dsn_h = MTEV_HASH_EMPTY; const char *host=NULL; const char *user=NULL; const char *password=NULL; const char *dbname=NULL; const char *port_s=NULL; const char *socket=NULL; const char *sslmode=NULL; u_int32_t port; unsigned long client_flag = CLIENT_IGNORE_SIGPIPE; unsigned int timeout; if(mask & (EVENTER_READ | EVENTER_WRITE)) { /* this case is impossible from the eventer. It is called as * such on the synchronous completion of the event. */ mysql_log_results(ci->self, ci->check); mysql_cleanup(ci->self, ci->check); check->flags &= ~NP_RUNNING; return 0; } switch(mask) { case EVENTER_ASYNCH_WORK: ci->connect_duration = NULL; ci->query_duration = NULL; FETCH_CONFIG_OR(dsn, ""); noit_check_interpolate(dsn_buff, sizeof(dsn_buff), dsn, &ci->attrs, check->config); mysql_parse_dsn(dsn_buff, &dsn_h); mtev_hash_retrieve(&dsn_h, "host", strlen("host"), (void**)&host); mtev_hash_retrieve(&dsn_h, "user", strlen("user"), (void**)&user); mtev_hash_retrieve(&dsn_h, "password", strlen("password"), (void**)&password); mtev_hash_retrieve(&dsn_h, "dbname", strlen("dbname"), (void**)&dbname); mtev_hash_retrieve(&dsn_h, "port", strlen("port"), (void**)&port_s); if(mtev_hash_retrieve(&dsn_h, "sslmode", strlen("sslmode"), (void**)&sslmode) && !strcmp(sslmode, "require")) client_flag |= CLIENT_SSL; port = port_s ? strtol(port_s, NULL, 10) : 3306; mtev_hash_retrieve(&dsn_h, "socket", strlen("socket"), (void**)&socket); ci->conn = mysql_init(NULL); /* allocate us a handle */ if(!ci->conn) AVAIL_BAIL("mysql_init failed"); timeout = check->timeout / 1000; mysql_options(ci->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&timeout); if(!mysql_real_connect(ci->conn, host, user, password, dbname, port, socket, client_flag)) { mtevL(noit_stderr, "error during mysql_real_connect: %s\n", mysql_error(ci->conn)); AVAIL_BAIL(mysql_error(ci->conn)); } if(mysql_ping(ci->conn)) AVAIL_BAIL(mysql_error(ci->conn)); #if MYSQL_VERSION_ID >= 50000 if (sslmode && !strcmp(sslmode, "require")) { /* mysql has a bad habit of silently failing to establish ssl and * falling back to unencrypted, so after making the connection, let's * check that we're actually using SSL by checking for a non-NULL * return value from mysql_get_ssl_cipher(). */ if (mysql_get_ssl_cipher(ci->conn) == NULL) { mtevL(nldeb, "mysql_get_ssl_cipher() returns NULL, but SSL mode required."); AVAIL_BAIL("mysql_get_ssl_cipher() returns NULL, but SSL mode required."); } } #endif gettimeofday(&t1, NULL); sub_timeval(t1, check->last_fire_time, &diff); ci->connect_duration_d = diff.tv_sec * 1000.0 + diff.tv_usec / 1000.0; ci->connect_duration = &ci->connect_duration_d; FETCH_CONFIG_OR(sql, ""); noit_check_interpolate(sql_buff, sizeof(sql_buff), sql, &ci->attrs, check->config); if (mysql_query(ci->conn, sql_buff)) AVAIL_BAIL(mysql_error(ci->conn)); gettimeofday(&t2, NULL); sub_timeval(t2, t1, &diff); ci->query_duration_d = diff.tv_sec * 1000.0 + diff.tv_usec / 1000.0; ci->query_duration = &ci->query_duration_d; ci->result = mysql_store_result(ci->conn); if(!ci->result) AVAIL_BAIL("mysql_store_result failed"); ci->rv = mysql_num_rows(ci->result); mysql_ingest_stats(ci); if(ci->result) { MYSQL_RES *result_swap = ci->result; ci->result = NULL; mysql_free_result(result_swap); } if(ci->conn) { MYSQL *conn_swap = ci->conn; ci->conn = NULL; mysql_close(conn_swap); } ci->timed_out = 0; mtev_hash_destroy(&dsn_h, free, free); return 0; break; case EVENTER_ASYNCH_CLEANUP: /* This sets us up for a completion call. */ e->mask = EVENTER_READ | EVENTER_WRITE; break; default: abort(); } return 0; }
static int postgres_drive_session(eventer_t e, int mask, void *closure, struct timeval *now) { const char *dsn, *sql; char sql_buff[8192]; char dsn_buff[512]; struct timeval t1, t2, diff; postgres_check_info_t *ci = closure; noit_check_t *check = ci->check; if(mask & (EVENTER_READ | EVENTER_WRITE)) { /* this case is impossible from the eventer. It is called as * such on the synchronous completion of the event. */ postgres_log_results(ci->self, ci->check); postgres_cleanup(ci->self, ci->check); check->flags &= ~NP_RUNNING; return 0; } switch(mask) { case EVENTER_ASYNCH_WORK: noit_check_stats_clear(&ci->current); ci->connect_duration = NULL; ci->query_duration = NULL; FETCH_CONFIG_OR(dsn, ""); noit_check_interpolate(dsn_buff, sizeof(dsn_buff), dsn, &ci->attrs, check->config); ci->conn = PQconnectdb(dsn_buff); if(!ci->conn) AVAIL_BAIL("PQconnectdb failed"); if(PQstatus(ci->conn) != CONNECTION_OK) AVAIL_BAIL(PQerrorMessage(ci->conn)); FETCH_CONFIG_OR(sql, ""); noit_check_interpolate(sql_buff, sizeof(sql_buff), sql, &ci->attrs, check->config); gettimeofday(&t1, NULL); sub_timeval(t1, check->last_fire_time, &diff); ci->connect_duration_d = diff.tv_sec * 1000.0 + diff.tv_usec / 1000.0; ci->connect_duration = &ci->connect_duration_d; ci->result = PQexec(ci->conn, sql_buff); gettimeofday(&t2, NULL); sub_timeval(t2, t1, &diff); ci->query_duration_d = diff.tv_sec * 1000.0 + diff.tv_usec / 1000.0; ci->query_duration = &ci->query_duration_d; if(!ci->result) AVAIL_BAIL("PQexec failed"); ci->rv = PQresultStatus(ci->result); switch(ci->rv) { case PGRES_TUPLES_OK: postgres_ingest_stats(ci); case PGRES_COMMAND_OK: break; default: AVAIL_BAIL(PQresultErrorMessage(ci->result)); } if(ci->result) { PGresult *result_swap = ci->result; ci->result = NULL; PQclear(result_swap); } if(ci->conn) { PGconn *conn_swap = ci->conn; ci->conn = NULL; PQfinish(conn_swap); } ci->timed_out = 0; return 0; break; case EVENTER_ASYNCH_CLEANUP: /* This sets us up for a completion call. */ e->mask = EVENTER_READ | EVENTER_WRITE; break; default: abort(); } return 0; }