check_dbi.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*****************************************************************************
  2. *
  3. * Nagios check_dbi plugin
  4. *
  5. * License: GPL
  6. * Copyright (c) 2011 Nagios Plugins Development Team
  7. * Author: Sebastian 'tokkee' Harl <sh@teamix.net>
  8. *
  9. * Description:
  10. *
  11. * This file contains the check_dbi plugin
  12. *
  13. * Runs an arbitrary (SQL) command and checks the result.
  14. *
  15. *
  16. * This program is free software: you can redistribute it and/or modify
  17. * it under the terms of the GNU General Public License as published by
  18. * the Free Software Foundation, either version 3 of the License, or
  19. * (at your option) any later version.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  28. *
  29. *
  30. *****************************************************************************/
  31. const char *progname = "check_dbi";
  32. const char *copyright = "2011";
  33. const char *email = "nagiosplug-devel@lists.sourceforge.net";
  34. #include "common.h"
  35. #include "utils.h"
  36. #include "netutils.h"
  37. /* required for NAN */
  38. #ifndef _ISOC99_SOURCE
  39. #define _ISOC99_SOURCE
  40. #endif
  41. #include <assert.h>
  42. #include <math.h>
  43. #include <dbi/dbi.h>
  44. #include <stdarg.h>
  45. typedef enum {
  46. METRIC_CONN_TIME,
  47. METRIC_QUERY_RESULT,
  48. METRIC_QUERY_TIME,
  49. } np_dbi_metric_t;
  50. typedef struct {
  51. char *key;
  52. char *value;
  53. } driver_option_t;
  54. char *host = NULL;
  55. int verbose = 0;
  56. char *warning_range = NULL;
  57. char *critical_range = NULL;
  58. thresholds *dbi_thresholds = NULL;
  59. char *expect = NULL;
  60. np_dbi_metric_t metric = METRIC_QUERY_RESULT;
  61. char *np_dbi_driver = NULL;
  62. driver_option_t *np_dbi_options = NULL;
  63. int np_dbi_options_num = 0;
  64. char *np_dbi_database = NULL;
  65. char *np_dbi_query = NULL;
  66. int process_arguments (int, char **);
  67. int validate_arguments (void);
  68. void print_usage (void);
  69. void print_help (void);
  70. double timediff (struct timeval, struct timeval);
  71. void np_dbi_print_error (dbi_conn, char *, ...);
  72. int do_query (dbi_conn, const char **, double *, double *);
  73. int
  74. main (int argc, char **argv)
  75. {
  76. int status = STATE_UNKNOWN;
  77. dbi_driver driver;
  78. dbi_conn conn;
  79. struct timeval start_timeval, end_timeval;
  80. double conn_time = 0.0;
  81. double query_time = 0.0;
  82. const char *query_val_str = NULL;
  83. double query_val = 0.0;
  84. int i;
  85. setlocale (LC_ALL, "");
  86. bindtextdomain (PACKAGE, LOCALEDIR);
  87. textdomain (PACKAGE);
  88. /* Parse extra opts if any */
  89. argv = np_extra_opts (&argc, argv, progname);
  90. if (process_arguments (argc, argv) == ERROR)
  91. usage4 (_("Could not parse arguments"));
  92. /* Set signal handling and alarm */
  93. if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
  94. usage4 (_("Cannot catch SIGALRM"));
  95. }
  96. alarm (timeout_interval);
  97. if (verbose > 2)
  98. printf ("Initializing DBI\n");
  99. if (dbi_initialize (NULL) < 0) {
  100. printf ("UNKNOWN - failed to initialize DBI.\n");
  101. return STATE_UNKNOWN;
  102. }
  103. if (verbose)
  104. printf ("Opening DBI driver '%s'\n", np_dbi_driver);
  105. driver = dbi_driver_open (np_dbi_driver);
  106. if (! driver) {
  107. printf ("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n",
  108. np_dbi_driver);
  109. printf ("Known drivers:\n");
  110. for (driver = dbi_driver_list (NULL); driver; driver = dbi_driver_list (driver)) {
  111. printf (" - %s\n", dbi_driver_get_name (driver));
  112. }
  113. return STATE_UNKNOWN;
  114. }
  115. /* make a connection to the database */
  116. gettimeofday (&start_timeval, NULL);
  117. conn = dbi_conn_open (driver);
  118. if (! conn) {
  119. printf ("UNKNOWN - failed top open connection object.\n");
  120. dbi_conn_close (conn);
  121. return STATE_UNKNOWN;
  122. }
  123. for (i = 0; i < np_dbi_options_num; ++i) {
  124. const char *opt;
  125. if (verbose > 1)
  126. printf ("Setting DBI driver option '%s' to '%s'\n",
  127. np_dbi_options[i].key, np_dbi_options[i].value);
  128. if (! dbi_conn_set_option (conn, np_dbi_options[i].key, np_dbi_options[i].value))
  129. continue;
  130. /* else: status != 0 */
  131. np_dbi_print_error (conn, "UNKNOWN - failed to set option '%s' to '%s'",
  132. np_dbi_options[i].key, np_dbi_options[i].value);
  133. printf ("Known driver options:\n");
  134. for (opt = dbi_conn_get_option_list (conn, NULL); opt;
  135. opt = dbi_conn_get_option_list (conn, opt)) {
  136. printf (" - %s\n", opt);
  137. }
  138. dbi_conn_close (conn);
  139. return STATE_UNKNOWN;
  140. }
  141. if (host) {
  142. if (verbose > 1)
  143. printf ("Setting DBI driver option 'host' to '%s'\n", host);
  144. dbi_conn_set_option (conn, "host", host);
  145. }
  146. if (verbose) {
  147. const char *dbname, *host;
  148. dbname = dbi_conn_get_option (conn, "dbname");
  149. host = dbi_conn_get_option (conn, "host");
  150. if (! dbname)
  151. dbname = "<unspecified>";
  152. if (! host)
  153. host = "<unspecified>";
  154. printf ("Connecting to database '%s' at host '%s'\n",
  155. dbname, host);
  156. }
  157. if (dbi_conn_connect (conn) < 0) {
  158. np_dbi_print_error (conn, "UNKOWN - failed to connect to database");
  159. return STATE_UNKNOWN;
  160. }
  161. gettimeofday (&end_timeval, NULL);
  162. conn_time = timediff (start_timeval, end_timeval);
  163. if (verbose)
  164. printf("Time elapsed: %f\n", conn_time);
  165. if (metric == METRIC_CONN_TIME)
  166. status = get_status (conn_time, dbi_thresholds);
  167. /* select a database */
  168. if (np_dbi_database) {
  169. if (verbose > 1)
  170. printf ("Selecting database '%s'\n", np_dbi_database);
  171. if (dbi_conn_select_db (conn, np_dbi_database)) {
  172. np_dbi_print_error (conn, "UNKOWN - failed to select database '%s'",
  173. np_dbi_database);
  174. return STATE_UNKNOWN;
  175. }
  176. }
  177. if (np_dbi_query) {
  178. /* execute query */
  179. status = do_query (conn, &query_val_str, &query_val, &query_time);
  180. if (status != STATE_OK)
  181. /* do_query prints an error message in this case */
  182. return status;
  183. if (metric == METRIC_QUERY_RESULT) {
  184. if (expect) {
  185. if ((! query_val_str) || strcmp (query_val_str, expect))
  186. status = STATE_CRITICAL;
  187. else
  188. status = STATE_OK;
  189. }
  190. else
  191. status = get_status (query_val, dbi_thresholds);
  192. }
  193. else if (metric == METRIC_QUERY_TIME)
  194. status = get_status (query_time, dbi_thresholds);
  195. }
  196. if (verbose)
  197. printf("Closing connection\n");
  198. dbi_conn_close (conn);
  199. /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error
  200. * which should have been reported and handled (abort) before */
  201. assert ((metric != METRIC_QUERY_RESULT) || (! isnan (query_val)) || expect);
  202. printf ("%s - connection time: %fs", state_text (status), conn_time);
  203. if (np_dbi_query) {
  204. if (expect) {
  205. printf (", '%s' returned '%s' in %fs", np_dbi_query,
  206. query_val_str ? query_val_str : "<nothing>", query_time);
  207. if (status != STATE_OK)
  208. printf (" (expected '%s')", expect);
  209. }
  210. else if (isnan (query_val))
  211. printf (", '%s' query execution time: %fs", np_dbi_query, query_time);
  212. else
  213. printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time);
  214. }
  215. printf (" | conntime=%fs;%s;%s;0;", conn_time,
  216. ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "",
  217. ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "");
  218. if (np_dbi_query) {
  219. if (! isnan (query_val)) /* this is also true when -e is used */
  220. printf (" query=%f;%s;%s;;", query_val,
  221. ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "",
  222. ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : "");
  223. printf (" querytime=%fs;%s;%s;0;", query_time,
  224. ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "",
  225. ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : "");
  226. }
  227. printf ("\n");
  228. return status;
  229. }
  230. /* process command-line arguments */
  231. int
  232. process_arguments (int argc, char **argv)
  233. {
  234. int c;
  235. int option = 0;
  236. static struct option longopts[] = {
  237. STD_LONG_OPTS,
  238. {"expect", required_argument, 0, 'e'},
  239. {"metric", required_argument, 0, 'm'},
  240. {"driver", required_argument, 0, 'd'},
  241. {"option", required_argument, 0, 'o'},
  242. {"query", required_argument, 0, 'q'},
  243. {"database", required_argument, 0, 'D'},
  244. {0, 0, 0, 0}
  245. };
  246. while (1) {
  247. c = getopt_long (argc, argv, "Vvht:c:w:e:m:H:d:o:q:D:",
  248. longopts, &option);
  249. if (c == EOF)
  250. break;
  251. switch (c) {
  252. case '?': /* usage */
  253. usage5 ();
  254. case 'h': /* help */
  255. print_help ();
  256. exit (STATE_OK);
  257. case 'V': /* version */
  258. print_revision (progname, NP_VERSION);
  259. exit (STATE_OK);
  260. case 'c': /* critical range */
  261. critical_range = optarg;
  262. break;
  263. case 'w': /* warning range */
  264. warning_range = optarg;
  265. break;
  266. case 'e':
  267. expect = optarg;
  268. break;
  269. case 'm':
  270. if (! strcasecmp (optarg, "CONN_TIME"))
  271. metric = METRIC_CONN_TIME;
  272. else if (! strcasecmp (optarg, "QUERY_RESULT"))
  273. metric = METRIC_QUERY_RESULT;
  274. else if (! strcasecmp (optarg, "QUERY_TIME"))
  275. metric = METRIC_QUERY_TIME;
  276. else
  277. usage2 (_("Invalid metric"), optarg);
  278. break;
  279. case 't': /* timeout */
  280. if (!is_intnonneg (optarg))
  281. usage2 (_("Timeout interval must be a positive integer"), optarg);
  282. else
  283. timeout_interval = atoi (optarg);
  284. case 'H': /* host */
  285. if (!is_host (optarg))
  286. usage2 (_("Invalid hostname/address"), optarg);
  287. else
  288. host = optarg;
  289. break;
  290. case 'v':
  291. verbose++;
  292. break;
  293. case 'd':
  294. np_dbi_driver = optarg;
  295. break;
  296. case 'o':
  297. {
  298. driver_option_t *new;
  299. char *k, *v;
  300. k = optarg;
  301. v = strchr (k, (int)'=');
  302. if (! v)
  303. usage2 (_("Option must be '<key>=<value>'"), optarg);
  304. *v = '\0';
  305. ++v;
  306. new = realloc (np_dbi_options,
  307. (np_dbi_options_num + 1) * sizeof (*new));
  308. if (! new) {
  309. printf ("UNKOWN - failed to reallocate memory\n");
  310. exit (STATE_UNKNOWN);
  311. }
  312. np_dbi_options = new;
  313. new = np_dbi_options + np_dbi_options_num;
  314. ++np_dbi_options_num;
  315. new->key = k;
  316. new->value = v;
  317. }
  318. break;
  319. case 'q':
  320. np_dbi_query = optarg;
  321. break;
  322. case 'D':
  323. np_dbi_database = optarg;
  324. break;
  325. }
  326. }
  327. set_thresholds (&dbi_thresholds, warning_range, critical_range);
  328. return validate_arguments ();
  329. }
  330. int
  331. validate_arguments ()
  332. {
  333. if (! np_dbi_driver)
  334. usage ("Must specify a DBI driver");
  335. if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME))
  336. && (! np_dbi_query))
  337. usage ("Must specify a query to execute (metric == QUERY_RESULT)");
  338. if ((metric != METRIC_CONN_TIME)
  339. && (metric != METRIC_QUERY_RESULT)
  340. && (metric != METRIC_QUERY_TIME))
  341. usage ("Invalid metric specified");
  342. if (expect && (warning_range || critical_range))
  343. usage ("Do not mix -e and -w/-c");
  344. if (expect && (metric != METRIC_QUERY_RESULT))
  345. usage ("Option -e requires metric QUERY_RESULT");
  346. return OK;
  347. }
  348. void
  349. print_help (void)
  350. {
  351. print_revision (progname, NP_VERSION);
  352. printf (COPYRIGHT, copyright, email);
  353. printf (_("This program connects to an (SQL) database using DBI and checks the\n"
  354. "specified metric against threshold levels. The default metric is\n"
  355. "the result of the specified query.\n"));
  356. printf ("\n\n");
  357. print_usage ();
  358. printf (UT_HELP_VRSN);
  359. /* include this conditionally to avoid 'zero-length printf format string'
  360. * compiler warnings */
  361. #ifdef NP_EXTRA_OPTS
  362. printf (UT_EXTRA_OPTS);
  363. #endif
  364. printf ("\n");
  365. printf (" %s\n", "-d, --driver=STRING");
  366. printf (" %s\n", _("DBI driver to use"));
  367. printf (" %s\n", "-o, --option=STRING");
  368. printf (" %s\n", _("DBI driver options"));
  369. printf (" %s\n", "-q, --query=STRING");
  370. printf (" %s\n", _("query to execute"));
  371. printf ("\n");
  372. printf (UT_WARN_CRIT_RANGE);
  373. printf (" %s\n", "-e, --expect=STRING");
  374. printf (" %s\n", _("String to expect as query result"));
  375. printf (" %s\n", _("Do not mix with -w or -c!"));
  376. printf (" %s\n", "-m, --metric=METRIC");
  377. printf (" %s\n", _("Metric to check thresholds against. Available metrics:"));
  378. printf (" CONN_TIME - %s\n", _("time used for setting up the database connection"));
  379. printf (" QUERY_RESULT - %s\n", _("result (first column of first row) of the query"));
  380. printf (" QUERY_TIME - %s\n", _("time used to execute the query"));
  381. printf (" %s\n", _("(ignore the query result)"));
  382. printf ("\n");
  383. printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
  384. printf (UT_VERBOSE);
  385. printf ("\n");
  386. printf (" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates"));
  387. printf (" %s\n\n", _("on a query, one has to be specified (-q option)."));
  388. printf (" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,"));
  389. printf (" %s\n", _("executes the specified query. The first column of the first row of the"));
  390. printf (" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the"));
  391. printf (" %s\n", _("warning and critical ranges. The result from the query has to be numeric"));
  392. printf (" %s\n\n", _("(strings representing numbers are fine)."));
  393. printf (" %s\n", _("The number and type of required DBI driver options depends on the actual"));
  394. printf (" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/"));
  395. printf (" %s\n\n", _("for details."));
  396. printf (" %s\n", _("Examples:"));
  397. printf (" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n");
  398. printf (" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n");
  399. printf (" Warning if more than five connections; critical if more than ten.\n\n");
  400. printf (" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n");
  401. printf (" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n");
  402. printf (" Warning if less than 5 or more than 20 users are logged in; critical\n");
  403. printf (" if more than 50 users.\n\n");
  404. printf (" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n");
  405. printf (" -m CONN_TIME -w 0.5 -c 2\n");
  406. printf (" Warning if connecting to the database takes more than half of a second;\n");
  407. printf (" critical if it takes more than 2 seconds.\n");
  408. printf (UT_SUPPORT);
  409. }
  410. void
  411. print_usage (void)
  412. {
  413. printf ("%s\n", _("Usage:"));
  414. printf ("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname);
  415. printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n");
  416. printf (" [-e <string>]\n");
  417. }
  418. #define CHECK_IGNORE_ERROR(s) \
  419. do { \
  420. if (metric != METRIC_QUERY_RESULT) \
  421. return (s); \
  422. } while (0)
  423. const char *
  424. get_field_str (dbi_conn conn, dbi_result res, unsigned short field_type)
  425. {
  426. const char *str;
  427. if (field_type != DBI_TYPE_STRING) {
  428. printf ("CRITICAL - result value is not a string\n");
  429. return NULL;
  430. }
  431. str = dbi_result_get_string_idx (res, 1);
  432. if ((! str) || (strcmp (str, "ERROR") == 0)) {
  433. CHECK_IGNORE_ERROR (NULL);
  434. np_dbi_print_error (conn, "CRITICAL - failed to fetch string value");
  435. return NULL;
  436. }
  437. if ((verbose && expect) || (verbose > 2))
  438. printf ("Query returned string '%s'\n", str);
  439. return str;
  440. }
  441. double
  442. get_field (dbi_conn conn, dbi_result res, unsigned short *field_type)
  443. {
  444. double val = NAN;
  445. if (*field_type == DBI_TYPE_INTEGER) {
  446. val = (double)dbi_result_get_longlong_idx (res, 1);
  447. }
  448. else if (*field_type == DBI_TYPE_DECIMAL) {
  449. val = dbi_result_get_double_idx (res, 1);
  450. }
  451. else if (*field_type == DBI_TYPE_STRING) {
  452. const char *val_str;
  453. char *endptr = NULL;
  454. val_str = get_field_str (conn, res, *field_type);
  455. if (! val_str) {
  456. CHECK_IGNORE_ERROR (NAN);
  457. *field_type = DBI_TYPE_ERROR;
  458. return NAN;
  459. }
  460. val = strtod (val_str, &endptr);
  461. if (endptr == val_str) {
  462. CHECK_IGNORE_ERROR (NAN);
  463. printf ("CRITICAL - result value is not a numeric: %s\n", val_str);
  464. *field_type = DBI_TYPE_ERROR;
  465. return NAN;
  466. }
  467. else if ((endptr != NULL) && (*endptr != '\0')) {
  468. if (verbose)
  469. printf ("Garbage after value: %s\n", endptr);
  470. }
  471. }
  472. else {
  473. CHECK_IGNORE_ERROR (NAN);
  474. printf ("CRITICAL - cannot parse value of type %s (%i)\n",
  475. (*field_type == DBI_TYPE_BINARY)
  476. ? "BINARY"
  477. : (*field_type == DBI_TYPE_DATETIME)
  478. ? "DATETIME"
  479. : "<unknown>",
  480. *field_type);
  481. *field_type = DBI_TYPE_ERROR;
  482. return NAN;
  483. }
  484. return val;
  485. }
  486. double
  487. get_query_result (dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val)
  488. {
  489. unsigned short field_type;
  490. double val = NAN;
  491. if (dbi_result_get_numrows (res) == DBI_ROW_ERROR) {
  492. CHECK_IGNORE_ERROR (STATE_OK);
  493. np_dbi_print_error (conn, "CRITICAL - failed to fetch rows");
  494. return STATE_CRITICAL;
  495. }
  496. if (dbi_result_get_numrows (res) < 1) {
  497. CHECK_IGNORE_ERROR (STATE_OK);
  498. printf ("WARNING - no rows returned\n");
  499. return STATE_WARNING;
  500. }
  501. if (dbi_result_get_numfields (res) == DBI_FIELD_ERROR) {
  502. CHECK_IGNORE_ERROR (STATE_OK);
  503. np_dbi_print_error (conn, "CRITICAL - failed to fetch fields");
  504. return STATE_CRITICAL;
  505. }
  506. if (dbi_result_get_numfields (res) < 1) {
  507. CHECK_IGNORE_ERROR (STATE_OK);
  508. printf ("WARNING - no fields returned\n");
  509. return STATE_WARNING;
  510. }
  511. if (dbi_result_first_row (res) != 1) {
  512. CHECK_IGNORE_ERROR (STATE_OK);
  513. np_dbi_print_error (conn, "CRITICAL - failed to fetch first row");
  514. return STATE_CRITICAL;
  515. }
  516. field_type = dbi_result_get_field_type_idx (res, 1);
  517. if (field_type != DBI_TYPE_ERROR) {
  518. if (expect)
  519. /* the value will be freed in dbi_result_free */
  520. *res_val_str = strdup (get_field_str (conn, res, field_type));
  521. else
  522. val = get_field (conn, res, &field_type);
  523. }
  524. *res_val = val;
  525. if (field_type == DBI_TYPE_ERROR) {
  526. CHECK_IGNORE_ERROR (STATE_OK);
  527. np_dbi_print_error (conn, "CRITICAL - failed to fetch data");
  528. return STATE_CRITICAL;
  529. }
  530. dbi_result_free (res);
  531. return STATE_OK;
  532. }
  533. #undef CHECK_IGNORE_ERROR
  534. int
  535. do_query (dbi_conn conn, const char **res_val_str, double *res_val, double *res_time)
  536. {
  537. dbi_result res;
  538. struct timeval timeval_start, timeval_end;
  539. int status = STATE_OK;
  540. assert (np_dbi_query);
  541. if (verbose)
  542. printf ("Executing query '%s'\n", np_dbi_query);
  543. gettimeofday (&timeval_start, NULL);
  544. res = dbi_conn_query (conn, np_dbi_query);
  545. if (! res) {
  546. np_dbi_print_error (conn, "CRITICAL - failed to execute query '%s'", np_dbi_query);
  547. return STATE_CRITICAL;
  548. }
  549. status = get_query_result (conn, res, res_val_str, res_val);
  550. gettimeofday (&timeval_end, NULL);
  551. *res_time = timediff (timeval_start, timeval_end);
  552. if (verbose)
  553. printf ("Time elapsed: %f\n", *res_time);
  554. return status;
  555. }
  556. double
  557. timediff (struct timeval start, struct timeval end)
  558. {
  559. double diff;
  560. while (start.tv_usec > end.tv_usec) {
  561. --end.tv_sec;
  562. end.tv_usec += 1000000;
  563. }
  564. diff = (double)(end.tv_sec - start.tv_sec)
  565. + (double)(end.tv_usec - start.tv_usec) / 1000000.0;
  566. return diff;
  567. }
  568. void
  569. np_dbi_print_error (dbi_conn conn, char *fmt, ...)
  570. {
  571. const char *errmsg = NULL;
  572. va_list ap;
  573. va_start (ap, fmt);
  574. dbi_conn_error (conn, &errmsg);
  575. vprintf (fmt, ap);
  576. printf (": %s\n", errmsg);
  577. va_end (ap);
  578. }