PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/database/mysql_common.c

https://github.com/cfenoy/slurm
C | 800 lines | 638 code | 84 blank | 78 comment | 126 complexity | a43ddaf3808992491c6649382483dad9 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * mysql_common.c - common functions for the mysql storage plugin.
  3. *****************************************************************************
  4. *
  5. * Copyright (C) 2004-2007 The Regents of the University of California.
  6. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  7. * Written by Danny Auble <da@llnl.gov>
  8. *
  9. * This file is part of SLURM, a resource management program.
  10. * For details, see <http://www.schedmd.com/slurmdocs/>.
  11. * Please also read the included file: DISCLAIMER.
  12. *
  13. * SLURM is free software; you can redistribute it and/or modify it under
  14. * the terms of the GNU General Public License as published by the Free
  15. * Software Foundation; either version 2 of the License, or (at your option)
  16. * any later version.
  17. *
  18. * In addition, as a special exception, the copyright holders give permission
  19. * to link the code of portions of this program with the OpenSSL library under
  20. * certain conditions as described in each individual source file, and
  21. * distribute linked combinations including the two. You must obey the GNU
  22. * General Public License in all respects for all of the code used other than
  23. * OpenSSL. If you modify file(s) with this exception, you may extend this
  24. * exception to your version of the file(s), but you are not obligated to do
  25. * so. If you do not wish to do so, delete this exception statement from your
  26. * version. If you delete this exception statement from all source files in
  27. * the program, then also delete it here.
  28. *
  29. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  30. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  31. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  32. * details.
  33. *
  34. * You should have received a copy of the GNU General Public License along
  35. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  36. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  37. *
  38. * This file is patterned after jobcomp_linux.c, written by Morris Jette and
  39. * Copyright (C) 2002 The Regents of the University of California.
  40. \*****************************************************************************/
  41. #include "mysql_common.h"
  42. #include "src/common/xstring.h"
  43. #include "src/common/xmalloc.h"
  44. #include "src/common/timers.h"
  45. #include "src/common/slurm_protocol_api.h"
  46. #include "src/common/read_config.h"
  47. static char *table_defs_table = "table_defs_table";
  48. /* NOTE: Insure that mysql_conn->lock is set on function entry */
  49. static int _clear_results(MYSQL *db_conn)
  50. {
  51. MYSQL_RES *result = NULL;
  52. int rc = 0;
  53. do {
  54. /* did current statement return data? */
  55. if ((result = mysql_store_result(db_conn)))
  56. mysql_free_result(result);
  57. /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
  58. if ((rc = mysql_next_result(db_conn)) > 0)
  59. error("Could not execute statement %d %s",
  60. mysql_errno(db_conn),
  61. mysql_error(db_conn));
  62. } while (rc == 0);
  63. if (rc > 0) {
  64. errno = rc;
  65. return SLURM_ERROR;
  66. }
  67. return SLURM_SUCCESS;
  68. }
  69. /* NOTE: Insure that mysql_conn->lock is set on function entry */
  70. static MYSQL_RES *_get_first_result(MYSQL *db_conn)
  71. {
  72. MYSQL_RES *result = NULL;
  73. int rc = 0;
  74. do {
  75. /* did current statement return data? */
  76. if ((result = mysql_store_result(db_conn)))
  77. return result;
  78. /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
  79. if ((rc = mysql_next_result(db_conn)) > 0)
  80. debug3("error: Could not execute statement %d", rc);
  81. } while (rc == 0);
  82. return NULL;
  83. }
  84. /* NOTE: Insure that mysql_conn->lock is set on function entry */
  85. static MYSQL_RES *_get_last_result(MYSQL *db_conn)
  86. {
  87. MYSQL_RES *result = NULL;
  88. MYSQL_RES *last_result = NULL;
  89. int rc = 0;
  90. do {
  91. /* did current statement return data? */
  92. if ((result = mysql_store_result(db_conn))) {
  93. if (last_result)
  94. mysql_free_result(last_result);
  95. last_result = result;
  96. }
  97. /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
  98. if ((rc = mysql_next_result(db_conn)) > 0)
  99. debug3("error: Could not execute statement %d", rc);
  100. } while (rc == 0);
  101. return last_result;
  102. }
  103. /* NOTE: Insure that mysql_conn->lock is set on function entry */
  104. static int _mysql_query_internal(MYSQL *db_conn, char *query)
  105. {
  106. int rc = SLURM_SUCCESS;
  107. if (!db_conn)
  108. fatal("You haven't inited this storage yet.");
  109. /* clear out the old results so we don't get a 2014 error */
  110. _clear_results(db_conn);
  111. if (mysql_query(db_conn, query)) {
  112. const char *err_str = mysql_error(db_conn);
  113. errno = mysql_errno(db_conn);
  114. if (errno == ER_NO_SUCH_TABLE) {
  115. debug4("This could happen often and is expected.\n"
  116. "mysql_query failed: %d %s\n%s",
  117. errno, err_str, query);
  118. errno = 0;
  119. goto end_it;
  120. }
  121. error("mysql_query failed: %d %s\n%s", errno, err_str, query);
  122. if (errno == ER_LOCK_WAIT_TIMEOUT) {
  123. fatal("mysql gave ER_LOCK_WAIT_TIMEOUT as an error. "
  124. "The only way to fix this is restart the "
  125. "calling program");
  126. }
  127. /* FIXME: If we get ER_LOCK_WAIT_TIMEOUT here we need
  128. * to restart the connections, but it appears restarting
  129. * the calling program is the only way to handle this.
  130. * If anyone in the future figures out a way to handle
  131. * this, super. Until then we will need to restart the
  132. * calling program if you ever get this error.
  133. */
  134. rc = SLURM_ERROR;
  135. }
  136. end_it:
  137. return rc;
  138. }
  139. /* NOTE: Insure that mysql_conn->lock is NOT set on function entry */
  140. static int _mysql_make_table_current(mysql_conn_t *mysql_conn, char *table_name,
  141. storage_field_t *fields, char *ending)
  142. {
  143. char *query = NULL;
  144. char *correct_query = NULL;
  145. MYSQL_RES *result = NULL;
  146. MYSQL_ROW row;
  147. int i = 0;
  148. List columns = NULL;
  149. ListIterator itr = NULL;
  150. char *col = NULL;
  151. int adding = 0;
  152. int run_update = 0;
  153. char *primary_key = NULL;
  154. char *unique_index = NULL;
  155. int old_primary = 0;
  156. char *old_index = NULL;
  157. char *temp = NULL;
  158. DEF_TIMERS;
  159. /* figure out the keys in the table */
  160. query = xstrdup_printf("show index from %s", table_name);
  161. if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) {
  162. xfree(query);
  163. return SLURM_ERROR;
  164. }
  165. xfree(query);
  166. while ((row = mysql_fetch_row(result))) {
  167. // row[2] is the key name
  168. if (!strcasecmp(row[2], "PRIMARY"))
  169. old_primary = 1;
  170. else if (!old_index)
  171. old_index = xstrdup(row[2]);
  172. }
  173. mysql_free_result(result);
  174. /* figure out the existing columns in the table */
  175. query = xstrdup_printf("show columns from %s", table_name);
  176. if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) {
  177. xfree(query);
  178. xfree(old_index);
  179. return SLURM_ERROR;
  180. }
  181. xfree(query);
  182. columns = list_create(slurm_destroy_char);
  183. while ((row = mysql_fetch_row(result))) {
  184. col = xstrdup(row[0]); //Field
  185. list_append(columns, col);
  186. }
  187. mysql_free_result(result);
  188. itr = list_iterator_create(columns);
  189. query = xstrdup_printf("alter table %s", table_name);
  190. correct_query = xstrdup_printf("alter table %s", table_name);
  191. START_TIMER;
  192. while (fields[i].name) {
  193. int found = 0;
  194. list_iterator_reset(itr);
  195. while ((col = list_next(itr))) {
  196. if (!strcmp(col, fields[i].name)) {
  197. xstrfmtcat(query, " modify %s %s,",
  198. fields[i].name,
  199. fields[i].options);
  200. xstrfmtcat(correct_query, " modify %s %s,",
  201. fields[i].name,
  202. fields[i].options);
  203. list_delete_item(itr);
  204. found = 1;
  205. break;
  206. }
  207. }
  208. if (!found) {
  209. if (i) {
  210. info("adding column %s after %s in table %s",
  211. fields[i].name,
  212. fields[i-1].name,
  213. table_name);
  214. xstrfmtcat(query, " add %s %s after %s,",
  215. fields[i].name,
  216. fields[i].options,
  217. fields[i-1].name);
  218. xstrfmtcat(correct_query, " modify %s %s,",
  219. fields[i].name,
  220. fields[i].options);
  221. } else {
  222. info("adding column %s at the beginning "
  223. "of table %s",
  224. fields[i].name,
  225. table_name);
  226. xstrfmtcat(query, " add %s %s first,",
  227. fields[i].name,
  228. fields[i].options);
  229. xstrfmtcat(correct_query, " modify %s %s,",
  230. fields[i].name,
  231. fields[i].options);
  232. }
  233. adding = 1;
  234. }
  235. i++;
  236. }
  237. list_iterator_reset(itr);
  238. while ((col = list_next(itr))) {
  239. adding = 1;
  240. info("dropping column %s from table %s", col, table_name);
  241. xstrfmtcat(query, " drop %s,", col);
  242. }
  243. list_iterator_destroy(itr);
  244. list_destroy(columns);
  245. if ((temp = strstr(ending, "primary key ("))) {
  246. int open = 0, close =0;
  247. int end = 0;
  248. while (temp[end++]) {
  249. if (temp[end] == '(')
  250. open++;
  251. else if (temp[end] == ')')
  252. close++;
  253. else
  254. continue;
  255. if (open == close)
  256. break;
  257. }
  258. if (temp[end]) {
  259. end++;
  260. primary_key = xstrndup(temp, end);
  261. if (old_primary) {
  262. xstrcat(query, " drop primary key,");
  263. xstrcat(correct_query, " drop primary key,");
  264. }
  265. xstrfmtcat(query, " add %s,", primary_key);
  266. xstrfmtcat(correct_query, " add %s,", primary_key);
  267. xfree(primary_key);
  268. }
  269. }
  270. if ((temp = strstr(ending, "unique index ("))) {
  271. int open = 0, close =0;
  272. int end = 0;
  273. while (temp[end++]) {
  274. if (temp[end] == '(')
  275. open++;
  276. else if (temp[end] == ')')
  277. close++;
  278. else
  279. continue;
  280. if (open == close)
  281. break;
  282. }
  283. if (temp[end]) {
  284. end++;
  285. unique_index = xstrndup(temp, end);
  286. if (old_index) {
  287. xstrfmtcat(query, " drop index %s,",
  288. old_index);
  289. xstrfmtcat(correct_query, " drop index %s,",
  290. old_index);
  291. }
  292. xstrfmtcat(query, " add %s,", unique_index);
  293. xstrfmtcat(correct_query, " add %s,", unique_index);
  294. xfree(unique_index);
  295. }
  296. }
  297. xfree(old_index);
  298. query[strlen(query)-1] = ';';
  299. correct_query[strlen(correct_query)-1] = ';';
  300. //info("%d query\n%s", __LINE__, query);
  301. /* see if we have already done this definition */
  302. if (!adding) {
  303. char *quoted = slurm_add_slash_to_quotes(query);
  304. char *query2 = xstrdup_printf("select table_name from "
  305. "%s where definition='%s'",
  306. table_defs_table, quoted);
  307. MYSQL_RES *result = NULL;
  308. MYSQL_ROW row;
  309. xfree(quoted);
  310. run_update = 1;
  311. if ((result = mysql_db_query_ret(mysql_conn, query2, 0))) {
  312. if ((row = mysql_fetch_row(result)))
  313. run_update = 0;
  314. mysql_free_result(result);
  315. }
  316. xfree(query2);
  317. if (run_update) {
  318. run_update = 2;
  319. query2 = xstrdup_printf("select table_name from "
  320. "%s where table_name='%s'",
  321. table_defs_table, table_name);
  322. if ((result = mysql_db_query_ret(
  323. mysql_conn, query2, 0))) {
  324. if ((row = mysql_fetch_row(result)))
  325. run_update = 1;
  326. mysql_free_result(result);
  327. }
  328. xfree(query2);
  329. }
  330. }
  331. /* if something has changed run the alter line */
  332. if (run_update || adding) {
  333. time_t now = time(NULL);
  334. char *query2 = NULL;
  335. char *quoted = NULL;
  336. if (run_update == 2)
  337. debug4("Table %s doesn't exist, adding", table_name);
  338. else
  339. debug("Table %s has changed. Updating...", table_name);
  340. if (mysql_db_query(mysql_conn, query)) {
  341. xfree(query);
  342. return SLURM_ERROR;
  343. }
  344. quoted = slurm_add_slash_to_quotes(correct_query);
  345. query2 = xstrdup_printf("insert into %s (creation_time, "
  346. "mod_time, table_name, definition) "
  347. "values (%ld, %ld, '%s', '%s') "
  348. "on duplicate key update "
  349. "definition='%s', mod_time=%ld;",
  350. table_defs_table, now, now,
  351. table_name, quoted,
  352. quoted, now);
  353. xfree(quoted);
  354. if (mysql_db_query(mysql_conn, query2)) {
  355. xfree(query2);
  356. return SLURM_ERROR;
  357. }
  358. xfree(query2);
  359. }
  360. xfree(query);
  361. xfree(correct_query);
  362. query = xstrdup_printf("make table current %s", table_name);
  363. END_TIMER2(query);
  364. xfree(query);
  365. return SLURM_SUCCESS;
  366. }
  367. /* NOTE: Insure that mysql_conn->lock is set on function entry */
  368. static int _create_db(char *db_name, mysql_db_info_t *db_info)
  369. {
  370. char create_line[50];
  371. MYSQL *mysql_db = NULL;
  372. int rc = SLURM_ERROR;
  373. MYSQL *db_ptr = NULL;
  374. char *db_host = NULL;
  375. while (rc == SLURM_ERROR) {
  376. rc = SLURM_SUCCESS;
  377. if (!(mysql_db = mysql_init(mysql_db)))
  378. fatal("mysql_init failed: %s", mysql_error(mysql_db));
  379. db_host = db_info->host;
  380. db_ptr = mysql_real_connect(mysql_db,
  381. db_host, db_info->user,
  382. db_info->pass, NULL,
  383. db_info->port, NULL, 0);
  384. if (!db_ptr && db_info->backup) {
  385. info("Connection failed to host = %s "
  386. "user = %s port = %u",
  387. db_host, db_info->user,
  388. db_info->port);
  389. db_host = db_info->backup;
  390. db_ptr = mysql_real_connect(mysql_db, db_host,
  391. db_info->user,
  392. db_info->pass, NULL,
  393. db_info->port, NULL, 0);
  394. }
  395. if (db_ptr) {
  396. snprintf(create_line, sizeof(create_line),
  397. "create database %s", db_name);
  398. if (mysql_query(mysql_db, create_line)) {
  399. fatal("mysql_real_query failed: %d %s\n%s",
  400. mysql_errno(mysql_db),
  401. mysql_error(mysql_db), create_line);
  402. }
  403. if (mysql_thread_safe())
  404. mysql_thread_end();
  405. mysql_close(mysql_db);
  406. } else {
  407. info("Connection failed to host = %s "
  408. "user = %s port = %u",
  409. db_host, db_info->user,
  410. db_info->port);
  411. error("mysql_real_connect failed: %d %s",
  412. mysql_errno(mysql_db),
  413. mysql_error(mysql_db));
  414. rc = SLURM_ERROR;
  415. }
  416. if (rc == SLURM_ERROR)
  417. sleep(3);
  418. }
  419. return rc;
  420. }
  421. extern mysql_conn_t *create_mysql_conn(int conn_num, bool rollback,
  422. char *cluster_name)
  423. {
  424. mysql_conn_t *mysql_conn = xmalloc(sizeof(mysql_conn_t));
  425. mysql_conn->rollback = rollback;
  426. mysql_conn->conn = conn_num;
  427. mysql_conn->cluster_name = xstrdup(cluster_name);
  428. slurm_mutex_init(&mysql_conn->lock);
  429. mysql_conn->update_list = list_create(slurmdb_destroy_update_object);
  430. return mysql_conn;
  431. }
  432. extern int destroy_mysql_conn(mysql_conn_t *mysql_conn)
  433. {
  434. if (mysql_conn) {
  435. mysql_db_close_db_connection(mysql_conn);
  436. xfree(mysql_conn->pre_commit_query);
  437. xfree(mysql_conn->cluster_name);
  438. slurm_mutex_destroy(&mysql_conn->lock);
  439. list_destroy(mysql_conn->update_list);
  440. xfree(mysql_conn);
  441. }
  442. return SLURM_SUCCESS;
  443. }
  444. extern mysql_db_info_t *create_mysql_db_info(slurm_mysql_plugin_type_t type)
  445. {
  446. mysql_db_info_t *db_info = xmalloc(sizeof(mysql_db_info_t));
  447. switch (type) {
  448. case SLURM_MYSQL_PLUGIN_AS:
  449. db_info->port = slurm_get_accounting_storage_port();
  450. if (!db_info->port) {
  451. db_info->port = DEFAULT_MYSQL_PORT;
  452. slurm_set_accounting_storage_port(db_info->port);
  453. }
  454. db_info->host = slurm_get_accounting_storage_host();
  455. db_info->backup = slurm_get_accounting_storage_backup_host();
  456. db_info->user = slurm_get_accounting_storage_user();
  457. db_info->pass = slurm_get_accounting_storage_pass();
  458. break;
  459. case SLURM_MYSQL_PLUGIN_JC:
  460. db_info->port = slurm_get_jobcomp_port();
  461. if (!db_info->port) {
  462. db_info->port = DEFAULT_MYSQL_PORT;
  463. slurm_set_jobcomp_port(db_info->port);
  464. }
  465. db_info->host = slurm_get_jobcomp_host();
  466. db_info->user = slurm_get_jobcomp_user();
  467. db_info->pass = slurm_get_jobcomp_pass();
  468. break;
  469. default:
  470. xfree(db_info);
  471. fatal("Unknown mysql_db_info %d", type);
  472. }
  473. return db_info;
  474. }
  475. extern int destroy_mysql_db_info(mysql_db_info_t *db_info)
  476. {
  477. if (db_info) {
  478. xfree(db_info->backup);
  479. xfree(db_info->host);
  480. xfree(db_info->user);
  481. xfree(db_info->pass);
  482. xfree(db_info);
  483. }
  484. return SLURM_SUCCESS;
  485. }
  486. extern int mysql_db_get_db_connection(mysql_conn_t *mysql_conn, char *db_name,
  487. mysql_db_info_t *db_info)
  488. {
  489. int rc = SLURM_SUCCESS;
  490. bool storage_init = false;
  491. char *db_host = db_info->host;
  492. xassert(mysql_conn);
  493. slurm_mutex_lock(&mysql_conn->lock);
  494. if (!(mysql_conn->db_conn = mysql_init(mysql_conn->db_conn))) {
  495. slurm_mutex_unlock(&mysql_conn->lock);
  496. fatal("mysql_init failed: %s",
  497. mysql_error(mysql_conn->db_conn));
  498. } else {
  499. unsigned int my_timeout = 30;
  500. #ifdef MYSQL_OPT_RECONNECT
  501. my_bool reconnect = 1;
  502. /* make sure reconnect is on */
  503. mysql_options(mysql_conn->db_conn, MYSQL_OPT_RECONNECT,
  504. &reconnect);
  505. #endif
  506. mysql_options(mysql_conn->db_conn, MYSQL_OPT_CONNECT_TIMEOUT,
  507. (char *)&my_timeout);
  508. while (!storage_init) {
  509. if (!mysql_real_connect(mysql_conn->db_conn, db_host,
  510. db_info->user, db_info->pass,
  511. db_name, db_info->port, NULL,
  512. CLIENT_MULTI_STATEMENTS)) {
  513. int err = mysql_errno(mysql_conn->db_conn);
  514. if (err == ER_BAD_DB_ERROR) {
  515. debug("Database %s not created. "
  516. "Creating", db_name);
  517. rc = _create_db(db_name, db_info);
  518. } else {
  519. const char *err_str = mysql_error(
  520. mysql_conn->db_conn);
  521. error("mysql_real_connect failed: "
  522. "%d %s",
  523. err, err_str);
  524. if ((db_host == db_info->host)
  525. && db_info->backup) {
  526. db_host = db_info->backup;
  527. continue;
  528. }
  529. rc = ESLURM_DB_CONNECTION;
  530. break;
  531. }
  532. } else {
  533. storage_init = true;
  534. }
  535. }
  536. }
  537. slurm_mutex_unlock(&mysql_conn->lock);
  538. errno = rc;
  539. return rc;
  540. }
  541. extern int mysql_db_close_db_connection(mysql_conn_t *mysql_conn)
  542. {
  543. slurm_mutex_lock(&mysql_conn->lock);
  544. if (mysql_conn && mysql_conn->db_conn) {
  545. if (mysql_thread_safe())
  546. mysql_thread_end();
  547. mysql_close(mysql_conn->db_conn);
  548. mysql_conn->db_conn = NULL;
  549. }
  550. slurm_mutex_unlock(&mysql_conn->lock);
  551. return SLURM_SUCCESS;
  552. }
  553. extern int mysql_db_cleanup()
  554. {
  555. debug3("starting mysql cleaning up");
  556. #ifdef mysql_library_end
  557. mysql_library_end();
  558. #else
  559. mysql_server_end();
  560. #endif
  561. debug3("finished mysql cleaning up");
  562. return SLURM_SUCCESS;
  563. }
  564. extern int mysql_db_query(mysql_conn_t *mysql_conn, char *query)
  565. {
  566. int rc = SLURM_SUCCESS;
  567. if (!mysql_conn || !mysql_conn->db_conn)
  568. fatal("You haven't inited this storage yet.");
  569. slurm_mutex_lock(&mysql_conn->lock);
  570. rc = _mysql_query_internal(mysql_conn->db_conn, query);
  571. slurm_mutex_unlock(&mysql_conn->lock);
  572. return rc;
  573. }
  574. extern int mysql_db_ping(mysql_conn_t *mysql_conn)
  575. {
  576. int rc;
  577. if (!mysql_conn->db_conn)
  578. return -1;
  579. /* clear out the old results so we don't get a 2014 error */
  580. slurm_mutex_lock(&mysql_conn->lock);
  581. _clear_results(mysql_conn->db_conn);
  582. rc = mysql_ping(mysql_conn->db_conn);
  583. slurm_mutex_unlock(&mysql_conn->lock);
  584. return rc;
  585. }
  586. extern int mysql_db_commit(mysql_conn_t *mysql_conn)
  587. {
  588. int rc = SLURM_SUCCESS;
  589. if (!mysql_conn->db_conn)
  590. return SLURM_ERROR;
  591. slurm_mutex_lock(&mysql_conn->lock);
  592. /* clear out the old results so we don't get a 2014 error */
  593. _clear_results(mysql_conn->db_conn);
  594. if (mysql_commit(mysql_conn->db_conn)) {
  595. error("mysql_commit failed: %d %s",
  596. mysql_errno(mysql_conn->db_conn),
  597. mysql_error(mysql_conn->db_conn));
  598. errno = mysql_errno(mysql_conn->db_conn);
  599. rc = SLURM_ERROR;
  600. }
  601. slurm_mutex_unlock(&mysql_conn->lock);
  602. return rc;
  603. }
  604. extern int mysql_db_rollback(mysql_conn_t *mysql_conn)
  605. {
  606. int rc = SLURM_SUCCESS;
  607. if (!mysql_conn->db_conn)
  608. return SLURM_ERROR;
  609. slurm_mutex_lock(&mysql_conn->lock);
  610. /* clear out the old results so we don't get a 2014 error */
  611. _clear_results(mysql_conn->db_conn);
  612. if (mysql_rollback(mysql_conn->db_conn)) {
  613. error("mysql_commit failed: %d %s",
  614. mysql_errno(mysql_conn->db_conn),
  615. mysql_error(mysql_conn->db_conn));
  616. errno = mysql_errno(mysql_conn->db_conn);
  617. rc = SLURM_ERROR;
  618. }
  619. slurm_mutex_unlock(&mysql_conn->lock);
  620. return rc;
  621. }
  622. extern MYSQL_RES *mysql_db_query_ret(mysql_conn_t *mysql_conn,
  623. char *query, bool last)
  624. {
  625. MYSQL_RES *result = NULL;
  626. slurm_mutex_lock(&mysql_conn->lock);
  627. if (_mysql_query_internal(mysql_conn->db_conn, query) != SLURM_ERROR) {
  628. if (mysql_errno(mysql_conn->db_conn) == ER_NO_SUCH_TABLE)
  629. goto fini;
  630. else if (last)
  631. result = _get_last_result(mysql_conn->db_conn);
  632. else
  633. result = _get_first_result(mysql_conn->db_conn);
  634. if (!result && mysql_field_count(mysql_conn->db_conn)) {
  635. /* should have returned data */
  636. error("We should have gotten a result: '%m' '%s'",
  637. mysql_error(mysql_conn->db_conn));
  638. }
  639. }
  640. fini:
  641. slurm_mutex_unlock(&mysql_conn->lock);
  642. return result;
  643. }
  644. extern int mysql_db_query_check_after(mysql_conn_t *mysql_conn, char *query)
  645. {
  646. int rc = SLURM_SUCCESS;
  647. slurm_mutex_lock(&mysql_conn->lock);
  648. if ((rc = _mysql_query_internal(
  649. mysql_conn->db_conn, query)) != SLURM_ERROR)
  650. rc = _clear_results(mysql_conn->db_conn);
  651. slurm_mutex_unlock(&mysql_conn->lock);
  652. return rc;
  653. }
  654. extern int mysql_db_insert_ret_id(mysql_conn_t *mysql_conn, char *query)
  655. {
  656. int new_id = 0;
  657. slurm_mutex_lock(&mysql_conn->lock);
  658. if (_mysql_query_internal(mysql_conn->db_conn, query) != SLURM_ERROR) {
  659. new_id = mysql_insert_id(mysql_conn->db_conn);
  660. if (!new_id) {
  661. /* should have new id */
  662. error("We should have gotten a new id: %s",
  663. mysql_error(mysql_conn->db_conn));
  664. }
  665. }
  666. slurm_mutex_unlock(&mysql_conn->lock);
  667. return new_id;
  668. }
  669. extern int mysql_db_create_table(mysql_conn_t *mysql_conn, char *table_name,
  670. storage_field_t *fields, char *ending)
  671. {
  672. char *query = NULL;
  673. int i = 0, rc;
  674. storage_field_t *first_field = fields;
  675. if (!fields || !fields->name) {
  676. error("Not creating an empty table");
  677. return SLURM_ERROR;
  678. }
  679. /* We have an internal table called table_defs_table which
  680. * contains the definition of each table in the database. To
  681. * speed things up we just check against that to see if
  682. * anything has changed.
  683. */
  684. query = xstrdup_printf("create table if not exists %s "
  685. "(creation_time int unsigned not null, "
  686. "mod_time int unsigned default 0 not null, "
  687. "table_name text not null, "
  688. "definition text not null, "
  689. "primary key (table_name(50))) engine='innodb'",
  690. table_defs_table);
  691. if (mysql_db_query(mysql_conn, query) == SLURM_ERROR) {
  692. xfree(query);
  693. return SLURM_ERROR;
  694. }
  695. xfree(query);
  696. query = xstrdup_printf("create table if not exists %s (%s %s",
  697. table_name, fields->name, fields->options);
  698. i = 1;
  699. fields++;
  700. while (fields && fields->name) {
  701. xstrfmtcat(query, ", %s %s", fields->name, fields->options);
  702. fields++;
  703. i++;
  704. }
  705. xstrcat(query, ending);
  706. /* make sure we can do a rollback */
  707. xstrcat(query, " engine='innodb'");
  708. if (mysql_db_query(mysql_conn, query) == SLURM_ERROR) {
  709. xfree(query);
  710. return SLURM_ERROR;
  711. }
  712. xfree(query);
  713. rc = _mysql_make_table_current(
  714. mysql_conn, table_name, first_field, ending);
  715. return rc;
  716. }