Пример #1
0
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;
}
Пример #2
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;
}