PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sview/resv_info.c

https://github.com/cfenoy/slurm
C | 1707 lines | 1462 code | 172 blank | 73 comment | 250 complexity | 7e58fefce55ba70c0b7f2296222ea8f1 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * resv_info.c - Functions related to advanced reservation display
  3. * mode of sview.
  4. *****************************************************************************
  5. * Copyright (C) 2009-2011 Lawrence Livermore National Security.
  6. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  7. * Written by Morris Jette <jette@llnl.gov>
  8. * CODE-OCEC-09-009. All rights reserved.
  9. *
  10. * This file is part of SLURM, a resource management program.
  11. * For details, see <http://www.schedmd.com/slurmdocs/>.
  12. * Please also read the included file: DISCLAIMER.
  13. *
  14. * SLURM is free software; you can redistribute it and/or modify it under
  15. * the terms of the GNU General Public License as published by the Free
  16. * Software Foundation; either version 2 of the License, or (at your option)
  17. * any later version.
  18. *
  19. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  20. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  21. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  22. * details.
  23. *
  24. * You should have received a copy of the GNU General Public License along
  25. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  26. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  27. \*****************************************************************************/
  28. #include "src/common/uid.h"
  29. #include "src/sview/sview.h"
  30. #include "src/common/parse_time.h"
  31. #define _DEBUG 0
  32. /* Collection of data for printing reports. Like data is combined here */
  33. typedef struct {
  34. int color_inx;
  35. GtkTreeIter iter_ptr;
  36. bool iter_set;
  37. int pos;
  38. reserve_info_t *resv_ptr;
  39. } sview_resv_info_t;
  40. enum {
  41. EDIT_REMOVE = 1,
  42. EDIT_EDIT
  43. };
  44. /* These need to be in alpha order (except POS and CNT) */
  45. enum {
  46. SORTID_POS = POS_LOC,
  47. SORTID_ACCOUNTS,
  48. SORTID_ACTION,
  49. SORTID_COLOR,
  50. SORTID_COLOR_INX,
  51. SORTID_DURATION,
  52. SORTID_FEATURES,
  53. SORTID_FLAGS,
  54. SORTID_LICENSES,
  55. SORTID_NAME,
  56. SORTID_NODE_CNT,
  57. SORTID_NODELIST,
  58. SORTID_NODE_INX,
  59. SORTID_PARTITION,
  60. SORTID_TIME_END,
  61. SORTID_TIME_START,
  62. SORTID_UPDATED,
  63. SORTID_USERS,
  64. SORTID_CNT
  65. };
  66. /* extra field here is for choosing the type of edit you that will
  67. * take place. If you choose EDIT_MODEL (means only display a set of
  68. * known options) create it in function create_model_*.
  69. */
  70. /*these are the settings to apply for the user
  71. * on the first startup after a fresh slurm install.
  72. * s/b a const probably*/
  73. static char *_initial_page_opts = "Name,Node_Count,NodeList,"
  74. "Time_Start,Time_End";
  75. static display_data_t display_data_resv[] = {
  76. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE,
  77. refresh_resv, create_model_resv, admin_edit_resv},
  78. {G_TYPE_STRING, SORTID_NAME, "Name", FALSE, EDIT_NONE,
  79. refresh_resv, create_model_resv, admin_edit_resv},
  80. {G_TYPE_STRING, SORTID_COLOR, NULL, TRUE, EDIT_COLOR,
  81. refresh_resv, create_model_resv, admin_edit_resv},
  82. {G_TYPE_STRING, SORTID_ACTION, "Action", FALSE, EDIT_MODEL,
  83. refresh_resv, create_model_resv, admin_edit_resv},
  84. {G_TYPE_STRING, SORTID_NODE_CNT, "Node Count", FALSE, EDIT_TEXTBOX,
  85. refresh_resv, create_model_resv, admin_edit_resv},
  86. {G_TYPE_STRING, SORTID_NODELIST,
  87. #ifdef HAVE_BG
  88. "MidplaneList",
  89. #else
  90. "Node List",
  91. #endif
  92. FALSE, EDIT_TEXTBOX, refresh_resv, create_model_resv, admin_edit_resv},
  93. {G_TYPE_STRING, SORTID_TIME_START, "Time Start", FALSE, EDIT_TEXTBOX,
  94. refresh_resv, create_model_resv, admin_edit_resv},
  95. {G_TYPE_STRING, SORTID_TIME_END, "Time End", FALSE, EDIT_TEXTBOX,
  96. refresh_resv, create_model_resv, admin_edit_resv},
  97. {G_TYPE_STRING, SORTID_DURATION, "Duration", FALSE, EDIT_TEXTBOX,
  98. refresh_resv, create_model_resv, admin_edit_resv},
  99. {G_TYPE_STRING, SORTID_ACCOUNTS, "Accounts", FALSE, EDIT_TEXTBOX,
  100. refresh_resv, create_model_resv, admin_edit_resv},
  101. {G_TYPE_STRING, SORTID_LICENSES, "Licenses", TRUE, EDIT_TEXTBOX,
  102. refresh_resv, create_model_resv, admin_edit_resv},
  103. {G_TYPE_STRING, SORTID_USERS, "Users", FALSE, EDIT_TEXTBOX,
  104. refresh_resv, create_model_resv, admin_edit_resv},
  105. {G_TYPE_STRING, SORTID_PARTITION, "Partition", FALSE, EDIT_TEXTBOX,
  106. refresh_resv, create_model_resv, admin_edit_resv},
  107. {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE, EDIT_TEXTBOX,
  108. refresh_resv, create_model_resv, admin_edit_resv},
  109. {G_TYPE_STRING, SORTID_FLAGS, "Flags", FALSE, EDIT_TEXTBOX,
  110. refresh_resv, create_model_resv, admin_edit_resv},
  111. {G_TYPE_POINTER, SORTID_NODE_INX, NULL, FALSE, EDIT_NONE,
  112. refresh_resv, create_model_resv, admin_edit_resv},
  113. {G_TYPE_INT, SORTID_COLOR_INX, NULL, FALSE, EDIT_NONE,
  114. refresh_resv, create_model_resv, admin_edit_resv},
  115. {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, EDIT_NONE,
  116. refresh_resv, create_model_resv, admin_edit_resv},
  117. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  118. };
  119. static display_data_t create_data_resv[] = {
  120. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE,
  121. refresh_resv, create_model_resv, admin_edit_resv},
  122. {G_TYPE_STRING, SORTID_NAME, "Name", FALSE, EDIT_TEXTBOX,
  123. refresh_resv, create_model_resv, admin_edit_resv},
  124. {G_TYPE_STRING, SORTID_NODE_CNT, "Node_Count", FALSE, EDIT_TEXTBOX,
  125. refresh_resv, create_model_resv, admin_edit_resv},
  126. {G_TYPE_STRING, SORTID_NODELIST,
  127. #ifdef HAVE_BG
  128. "Midplane_List",
  129. #else
  130. "Node_List",
  131. #endif
  132. FALSE, EDIT_TEXTBOX,
  133. refresh_resv, create_model_resv, admin_edit_resv},
  134. {G_TYPE_STRING, SORTID_TIME_START, "Time_Start",
  135. FALSE, EDIT_TEXTBOX,
  136. refresh_resv, create_model_resv, admin_edit_resv},
  137. {G_TYPE_STRING, SORTID_TIME_END, "Time_End", FALSE, EDIT_TEXTBOX,
  138. refresh_resv, create_model_resv, admin_edit_resv},
  139. {G_TYPE_STRING, SORTID_DURATION, "Duration", FALSE, EDIT_TEXTBOX,
  140. refresh_resv, create_model_resv, admin_edit_resv},
  141. {G_TYPE_STRING, SORTID_ACCOUNTS, "Accounts", FALSE, EDIT_TEXTBOX,
  142. refresh_resv, create_model_resv, admin_edit_resv},
  143. {G_TYPE_STRING, SORTID_USERS, "Users", FALSE, EDIT_TEXTBOX,
  144. refresh_resv, create_model_resv, admin_edit_resv},
  145. {G_TYPE_STRING, SORTID_PARTITION, "Partition", FALSE, EDIT_TEXTBOX,
  146. refresh_resv, create_model_resv, admin_edit_resv},
  147. {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE, EDIT_TEXTBOX,
  148. refresh_resv, create_model_resv, admin_edit_resv},
  149. {G_TYPE_STRING, SORTID_FLAGS, "Flags", FALSE, EDIT_TEXTBOX,
  150. refresh_resv, create_model_resv, admin_edit_resv},
  151. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  152. };
  153. static display_data_t options_data_resv[] = {
  154. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE},
  155. {G_TYPE_STRING, INFO_PAGE, "Full Info", TRUE, RESV_PAGE},
  156. {G_TYPE_STRING, RESV_PAGE, "Remove Reservation", TRUE, ADMIN_PAGE},
  157. {G_TYPE_STRING, RESV_PAGE, "Edit Reservation", TRUE, ADMIN_PAGE},
  158. {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, RESV_PAGE},
  159. {G_TYPE_STRING, PART_PAGE, "Partitions", TRUE, RESV_PAGE},
  160. #ifdef HAVE_BG
  161. {G_TYPE_STRING, BLOCK_PAGE, "Blocks", TRUE, RESV_PAGE},
  162. {G_TYPE_STRING, NODE_PAGE, "Midplanes", TRUE, RESV_PAGE},
  163. #else
  164. {G_TYPE_STRING, BLOCK_PAGE, NULL, TRUE, RESV_PAGE},
  165. {G_TYPE_STRING, NODE_PAGE, "Nodes", TRUE, RESV_PAGE},
  166. #endif
  167. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  168. };
  169. static display_data_t *local_display_data = NULL;
  170. static char *got_edit_signal = NULL;
  171. static void _admin_resv(GtkTreeModel *model, GtkTreeIter *iter, char *type);
  172. static void _process_each_resv(GtkTreeModel *model, GtkTreePath *path,
  173. GtkTreeIter*iter, gpointer userdata);
  174. /*
  175. * _parse_flags is used to parse the Flags= option. It handles
  176. * daily, weekly, maint, static_nodes and part_nodes optionally
  177. * preceded by + or -, separated by a comma but no spaces.
  178. */
  179. static uint32_t _parse_flags(const char *flagstr)
  180. {
  181. int flip;
  182. uint32_t outflags = 0;
  183. const char *curr = flagstr;
  184. int taglen = 0;
  185. while (*curr != '\0') {
  186. flip = 0;
  187. if (*curr == '+') {
  188. curr++;
  189. } else if (*curr == '-') {
  190. flip = 1;
  191. curr++;
  192. }
  193. taglen = 0;
  194. while (curr[taglen] != ',' && curr[taglen] != '\0')
  195. taglen++;
  196. if (strncasecmp(curr, "Maintenance", MAX(taglen,1)) == 0) {
  197. curr += taglen;
  198. if (flip)
  199. outflags |= RESERVE_FLAG_NO_MAINT;
  200. else
  201. outflags |= RESERVE_FLAG_MAINT;
  202. } else if ((strncasecmp(curr, "Overlap",MAX(taglen,1))
  203. == 0) && (!flip)) {
  204. curr += taglen;
  205. outflags |= RESERVE_FLAG_OVERLAP;
  206. } else if (strncasecmp(curr, "Ignore_Jobs", MAX(taglen,1))
  207. == 0) {
  208. curr += taglen;
  209. if (flip)
  210. outflags |= RESERVE_FLAG_NO_IGN_JOB;
  211. else
  212. outflags |= RESERVE_FLAG_IGN_JOBS;
  213. } else if (strncasecmp(curr, "Daily", MAX(taglen,1)) == 0) {
  214. curr += taglen;
  215. if (flip)
  216. outflags |= RESERVE_FLAG_NO_DAILY;
  217. else
  218. outflags |= RESERVE_FLAG_DAILY;
  219. } else if (strncasecmp(curr, "Weekly", MAX(taglen,1)) == 0) {
  220. curr += taglen;
  221. if (flip)
  222. outflags |= RESERVE_FLAG_NO_WEEKLY;
  223. else
  224. outflags |= RESERVE_FLAG_WEEKLY;
  225. } else if (strncasecmp(curr, "License_Only", MAX(taglen,1))
  226. == 0) {
  227. curr += taglen;
  228. if (flip)
  229. outflags |= RESERVE_FLAG_NO_LIC_ONLY;
  230. else
  231. outflags |= RESERVE_FLAG_LIC_ONLY;
  232. } else if (strncasecmp(curr, "Static_Alloc", MAX(taglen,1))
  233. == 0) {
  234. curr += taglen;
  235. if (flip)
  236. outflags |= RESERVE_FLAG_NO_STATIC;
  237. else
  238. outflags |= RESERVE_FLAG_STATIC;
  239. } else if (strncasecmp(curr, "Part_Nodes", MAX(taglen,1))
  240. == 0) {
  241. curr += taglen;
  242. if (flip)
  243. outflags |= RESERVE_FLAG_NO_PART_NODES;
  244. else
  245. outflags |= RESERVE_FLAG_PART_NODES;
  246. } else {
  247. char *temp = g_strdup_printf("Error parsing flags %s.",
  248. flagstr);
  249. display_edit_note(temp);
  250. g_free(temp);
  251. outflags = (uint32_t)NO_VAL;
  252. break;
  253. }
  254. if (*curr == ',')
  255. curr++;
  256. }
  257. return outflags;
  258. }
  259. static void _set_active_combo_resv(GtkComboBox *combo,
  260. GtkTreeModel *model, GtkTreeIter *iter,
  261. int type)
  262. {
  263. char *temp_char = NULL;
  264. int action = 0;
  265. gtk_tree_model_get(model, iter, type, &temp_char, -1);
  266. if (!temp_char)
  267. goto end_it;
  268. switch(type) {
  269. case SORTID_ACTION:
  270. if (!strcmp(temp_char, "none"))
  271. action = 0;
  272. else if (!strcmp(temp_char, "remove"))
  273. action = 1;
  274. else
  275. action = 0;
  276. break;
  277. default:
  278. break;
  279. }
  280. g_free(temp_char);
  281. end_it:
  282. gtk_combo_box_set_active(combo, action);
  283. }
  284. /* don't free this char */
  285. static const char *_set_resv_msg(resv_desc_msg_t *resv_msg,
  286. const char *new_text,
  287. int column)
  288. {
  289. char *type = "", *temp_str;
  290. char *tmp_text, *last = NULL, *tok;
  291. int block_inx, temp_int = 0;
  292. uint32_t f;
  293. /* need to clear global_edit_error here (just in case) */
  294. global_edit_error = 0;
  295. if (!resv_msg)
  296. return NULL;
  297. switch(column) {
  298. case SORTID_ACCOUNTS:
  299. resv_msg->accounts = xstrdup(new_text);
  300. type = "accounts";
  301. break;
  302. case SORTID_ACTION:
  303. xfree(got_edit_signal);
  304. if (!strcasecmp(new_text, "None"))
  305. got_edit_signal = NULL;
  306. else
  307. got_edit_signal = xstrdup(new_text);
  308. break;
  309. case SORTID_DURATION:
  310. temp_int = time_str2mins((char *)new_text);
  311. if (temp_int <= 0)
  312. goto return_error;
  313. resv_msg->duration = temp_int;
  314. type = "duration";
  315. break;
  316. case SORTID_TIME_END:
  317. resv_msg->end_time = parse_time((char *)new_text, 0);
  318. type = "end time";
  319. break;
  320. case SORTID_FEATURES:
  321. resv_msg->features = xstrdup(new_text);
  322. type = "features";
  323. break;
  324. case SORTID_FLAGS:
  325. f = _parse_flags(new_text);
  326. type = "flags";
  327. if (f == (uint32_t)NO_VAL)
  328. goto return_error;
  329. resv_msg->flags = f;
  330. break;
  331. case SORTID_LICENSES:
  332. resv_msg->licenses = xstrdup(new_text);
  333. type = "licenses";
  334. break;
  335. case SORTID_NAME:
  336. resv_msg->name = xstrdup(new_text);
  337. type = "name";
  338. break;
  339. case SORTID_NODE_CNT:
  340. type = "Node Count";
  341. block_inx = 0;
  342. tmp_text = xstrdup(new_text);
  343. tok = strtok_r(tmp_text, ",", &last);
  344. while (tok) {
  345. temp_int = strtol(tok, &temp_str, 10);
  346. if ((temp_str[0] == 'k') || (temp_str[0] == 'k'))
  347. temp_int *= 1024;
  348. if ((temp_str[0] == 'm') || (temp_str[0] == 'm'))
  349. temp_int *= (1024 * 1024);
  350. xrealloc(resv_msg->node_cnt,
  351. (sizeof(uint32_t) * (block_inx + 2)));
  352. resv_msg->node_cnt[block_inx++] = temp_int;
  353. if (temp_int <= 0) {
  354. xfree(tmp_text);
  355. xfree(resv_msg->node_cnt);
  356. goto return_error;
  357. }
  358. tok = strtok_r(NULL, ",", &last);
  359. }
  360. xfree(tmp_text);
  361. break;
  362. case SORTID_NODELIST:
  363. resv_msg->node_list = xstrdup(new_text);
  364. type = "node list";
  365. break;
  366. case SORTID_PARTITION:
  367. resv_msg->partition = xstrdup(new_text);
  368. type = "partition";
  369. break;
  370. case SORTID_TIME_START:
  371. resv_msg->start_time = parse_time((char *)new_text, 0);
  372. type = "start time";
  373. break;
  374. case SORTID_USERS:
  375. resv_msg->users = xstrdup(new_text);
  376. type = "users";
  377. break;
  378. default:
  379. type = "unknown";
  380. break;
  381. }
  382. if (strcmp(type, "unknown"))
  383. global_send_update_msg = 1;
  384. return type;
  385. return_error:
  386. global_edit_error = 1;
  387. return type;
  388. }
  389. static void _resv_info_list_del(void *object)
  390. {
  391. sview_resv_info_t *sview_resv_info = (sview_resv_info_t *)object;
  392. if (sview_resv_info) {
  393. xfree(sview_resv_info);
  394. }
  395. }
  396. static void _admin_edit_combo_box_resv(GtkComboBox *combo,
  397. resv_desc_msg_t *resv_msg)
  398. {
  399. GtkTreeModel *model = NULL;
  400. GtkTreeIter iter;
  401. int column = 0;
  402. char *name = NULL;
  403. if (!resv_msg)
  404. return;
  405. if (!gtk_combo_box_get_active_iter(combo, &iter)) {
  406. g_print("nothing selected\n");
  407. return;
  408. }
  409. model = gtk_combo_box_get_model(combo);
  410. if (!model) {
  411. g_print("nothing selected\n");
  412. return;
  413. }
  414. gtk_tree_model_get(model, &iter, 0, &name, -1);
  415. gtk_tree_model_get(model, &iter, 1, &column, -1);
  416. _set_resv_msg(resv_msg, name, column);
  417. g_free(name);
  418. }
  419. static gboolean _admin_focus_out_resv(GtkEntry *entry,
  420. GdkEventFocus *event,
  421. resv_desc_msg_t *resv_msg)
  422. {
  423. if (global_entry_changed) {
  424. const char *col_name = NULL;
  425. int type = gtk_entry_get_max_length(entry);
  426. const char *name = gtk_entry_get_text(entry);
  427. type -= DEFAULT_ENTRY_LENGTH;
  428. col_name = _set_resv_msg(resv_msg, name, type);
  429. if (global_edit_error) {
  430. if (global_edit_error_msg)
  431. g_free(global_edit_error_msg);
  432. global_edit_error_msg = g_strdup_printf(
  433. "Reservation %s %s can't be set to %s",
  434. resv_msg->name,
  435. col_name,
  436. name);
  437. }
  438. global_entry_changed = 0;
  439. }
  440. return false;
  441. }
  442. static GtkWidget *_admin_full_edit_resv(resv_desc_msg_t *resv_msg,
  443. GtkTreeModel *model, GtkTreeIter *iter)
  444. {
  445. GtkScrolledWindow *window = create_scrolled_window();
  446. GtkBin *bin = NULL;
  447. GtkViewport *view = NULL;
  448. GtkTable *table = NULL;
  449. int i = 0, row = 0;
  450. display_data_t *display_data = display_data_resv;
  451. gtk_scrolled_window_set_policy(window,
  452. GTK_POLICY_NEVER,
  453. GTK_POLICY_AUTOMATIC);
  454. bin = GTK_BIN(&window->container);
  455. view = GTK_VIEWPORT(bin->child);
  456. bin = GTK_BIN(&view->bin);
  457. table = GTK_TABLE(bin->child);
  458. gtk_table_resize(table, SORTID_CNT, 2);
  459. gtk_table_set_homogeneous(table, FALSE);
  460. for(i = 0; i < SORTID_CNT; i++) {
  461. while (display_data++) {
  462. if (display_data->id == -1)
  463. break;
  464. if (!display_data->name)
  465. continue;
  466. if (display_data->id != i)
  467. continue;
  468. display_admin_edit(
  469. table, resv_msg, &row, model, iter,
  470. display_data,
  471. G_CALLBACK(_admin_edit_combo_box_resv),
  472. G_CALLBACK(_admin_focus_out_resv),
  473. _set_active_combo_resv);
  474. break;
  475. }
  476. display_data = display_data_resv;
  477. }
  478. gtk_table_resize(table, row, 2);
  479. return GTK_WIDGET(window);
  480. }
  481. static void _layout_resv_record(GtkTreeView *treeview,
  482. sview_resv_info_t *sview_resv_info,
  483. int update)
  484. {
  485. GtkTreeIter iter;
  486. char time_buf[20];
  487. reserve_info_t *resv_ptr = sview_resv_info->resv_ptr;
  488. char *temp_char = NULL;
  489. GtkTreeStore *treestore =
  490. GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
  491. add_display_treestore_line(update, treestore, &iter,
  492. find_col_name(display_data_resv,
  493. SORTID_ACCOUNTS),
  494. resv_ptr->accounts);
  495. secs2time_str((uint32_t)difftime(resv_ptr->end_time,
  496. resv_ptr->start_time),
  497. time_buf, sizeof(time_buf));
  498. add_display_treestore_line(update, treestore, &iter,
  499. find_col_name(display_data_resv,
  500. SORTID_DURATION),
  501. time_buf);
  502. add_display_treestore_line(update, treestore, &iter,
  503. find_col_name(display_data_resv,
  504. SORTID_FEATURES),
  505. resv_ptr->features);
  506. temp_char = reservation_flags_string(resv_ptr->flags);
  507. add_display_treestore_line(update, treestore, &iter,
  508. find_col_name(display_data_resv,
  509. SORTID_FLAGS),
  510. temp_char);
  511. xfree(temp_char);
  512. add_display_treestore_line(update, treestore, &iter,
  513. find_col_name(display_data_resv,
  514. SORTID_LICENSES),
  515. resv_ptr->licenses);
  516. /* NOTE: node_cnt in reservation info from slurmctld ONE number */
  517. convert_num_unit((float)resv_ptr->node_cnt,
  518. time_buf, sizeof(time_buf), UNIT_NONE);
  519. add_display_treestore_line(update, treestore, &iter,
  520. find_col_name(display_data_resv,
  521. SORTID_NODE_CNT),
  522. time_buf);
  523. add_display_treestore_line(update, treestore, &iter,
  524. find_col_name(display_data_resv,
  525. SORTID_NODELIST),
  526. resv_ptr->node_list);
  527. add_display_treestore_line(update, treestore, &iter,
  528. find_col_name(display_data_resv,
  529. SORTID_PARTITION),
  530. resv_ptr->partition);
  531. slurm_make_time_str((time_t *)&resv_ptr->end_time, time_buf,
  532. sizeof(time_buf));
  533. add_display_treestore_line(update, treestore, &iter,
  534. find_col_name(display_data_resv,
  535. SORTID_TIME_END),
  536. time_buf);
  537. slurm_make_time_str((time_t *)&resv_ptr->start_time, time_buf,
  538. sizeof(time_buf));
  539. add_display_treestore_line(update, treestore, &iter,
  540. find_col_name(display_data_resv,
  541. SORTID_TIME_START),
  542. time_buf);
  543. add_display_treestore_line(update, treestore, &iter,
  544. find_col_name(display_data_resv,
  545. SORTID_USERS),
  546. resv_ptr->users);
  547. }
  548. static void _update_resv_record(sview_resv_info_t *sview_resv_info_ptr,
  549. GtkTreeStore *treestore)
  550. {
  551. char tmp_duration[40], tmp_end[40], tmp_nodes[40], tmp_start[40];
  552. char *tmp_flags;
  553. reserve_info_t *resv_ptr = sview_resv_info_ptr->resv_ptr;
  554. secs2time_str((uint32_t)difftime(resv_ptr->end_time,
  555. resv_ptr->start_time),
  556. tmp_duration, sizeof(tmp_duration));
  557. slurm_make_time_str((time_t *)&resv_ptr->end_time, tmp_end,
  558. sizeof(tmp_end));
  559. tmp_flags = reservation_flags_string(resv_ptr->flags);
  560. convert_num_unit((float)resv_ptr->node_cnt,
  561. tmp_nodes, sizeof(tmp_nodes), UNIT_NONE);
  562. slurm_make_time_str((time_t *)&resv_ptr->start_time, tmp_start,
  563. sizeof(tmp_start));
  564. /* Combining these records provides a slight performance improvement */
  565. gtk_tree_store_set(treestore, &sview_resv_info_ptr->iter_ptr,
  566. SORTID_ACCOUNTS, resv_ptr->accounts,
  567. SORTID_COLOR,
  568. sview_colors[sview_resv_info_ptr->color_inx],
  569. SORTID_COLOR_INX, sview_resv_info_ptr->color_inx,
  570. SORTID_DURATION, tmp_duration,
  571. SORTID_FEATURES, resv_ptr->features,
  572. SORTID_FLAGS, tmp_flags,
  573. SORTID_LICENSES, resv_ptr->licenses,
  574. SORTID_NAME, resv_ptr->name,
  575. SORTID_NODE_CNT, tmp_nodes,
  576. SORTID_NODE_INX, resv_ptr->node_inx,
  577. SORTID_NODELIST, resv_ptr->node_list,
  578. SORTID_PARTITION, resv_ptr->partition,
  579. SORTID_TIME_START, tmp_start,
  580. SORTID_TIME_END, tmp_end,
  581. SORTID_UPDATED, 1,
  582. SORTID_USERS, resv_ptr->users,
  583. -1);
  584. xfree(tmp_flags);
  585. return;
  586. }
  587. static void _append_resv_record(sview_resv_info_t *sview_resv_info_ptr,
  588. GtkTreeStore *treestore)
  589. {
  590. gtk_tree_store_append(treestore, &sview_resv_info_ptr->iter_ptr, NULL);
  591. gtk_tree_store_set(treestore, &sview_resv_info_ptr->iter_ptr,
  592. SORTID_POS, sview_resv_info_ptr->pos, -1);
  593. _update_resv_record(sview_resv_info_ptr, treestore);
  594. }
  595. static void _update_info_resv(List info_list,
  596. GtkTreeView *tree_view)
  597. {
  598. GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  599. static GtkTreeModel *last_model = NULL;
  600. reserve_info_t *resv_ptr = NULL;
  601. char *name = NULL;
  602. ListIterator itr = NULL;
  603. sview_resv_info_t *sview_resv_info = NULL;
  604. set_for_update(model, SORTID_UPDATED);
  605. itr = list_iterator_create(info_list);
  606. while ((sview_resv_info = (sview_resv_info_t*) list_next(itr))) {
  607. resv_ptr = sview_resv_info->resv_ptr;
  608. /* This means the tree_store changed (added new column
  609. or something). */
  610. if (last_model != model)
  611. sview_resv_info->iter_set = false;
  612. if (sview_resv_info->iter_set) {
  613. gtk_tree_model_get(model, &sview_resv_info->iter_ptr,
  614. SORTID_NAME, &name, -1);
  615. if (strcmp(name, resv_ptr->name)) { /* Bad pointer */
  616. sview_resv_info->iter_set = false;
  617. //g_print("bad resv iter pointer\n");
  618. }
  619. g_free(name);
  620. }
  621. if (sview_resv_info->iter_set) {
  622. _update_resv_record(sview_resv_info,
  623. GTK_TREE_STORE(model));
  624. } else {
  625. GtkTreePath *path = gtk_tree_path_new_first();
  626. /* get the iter, or find out the list is empty
  627. * goto add */
  628. if (gtk_tree_model_get_iter(
  629. model, &sview_resv_info->iter_ptr, path)) {
  630. do {
  631. /* search for the jobid and
  632. check to see if it is in
  633. the list */
  634. gtk_tree_model_get(
  635. model,
  636. &sview_resv_info->iter_ptr,
  637. SORTID_NAME,
  638. &name, -1);
  639. if (!strcmp(name, resv_ptr->name)) {
  640. /* update with new info */
  641. g_free(name);
  642. _update_resv_record(
  643. sview_resv_info,
  644. GTK_TREE_STORE(model));
  645. sview_resv_info->iter_set = 1;
  646. break;
  647. }
  648. g_free(name);
  649. } while (gtk_tree_model_iter_next(
  650. model,
  651. &sview_resv_info->iter_ptr));
  652. }
  653. if (!sview_resv_info->iter_set) {
  654. _append_resv_record(sview_resv_info,
  655. GTK_TREE_STORE(model));
  656. sview_resv_info->iter_set = true;
  657. }
  658. gtk_tree_path_free(path);
  659. }
  660. }
  661. list_iterator_destroy(itr);
  662. /* remove all old reservations */
  663. remove_old(model, SORTID_UPDATED);
  664. last_model = model;
  665. }
  666. static int _sview_resv_sort_aval_dec(sview_resv_info_t* rec_a,
  667. sview_resv_info_t* rec_b)
  668. {
  669. int size_a = rec_a->resv_ptr->node_cnt;
  670. int size_b = rec_b->resv_ptr->node_cnt;
  671. if (size_a < size_b)
  672. return -1;
  673. else if (size_a > size_b)
  674. return 1;
  675. if (rec_a->resv_ptr->node_list && rec_b->resv_ptr->node_list) {
  676. size_a = strcmp(rec_a->resv_ptr->node_list,
  677. rec_b->resv_ptr->node_list);
  678. if (size_a < 0)
  679. return -1;
  680. else if (size_a > 0)
  681. return 1;
  682. }
  683. return 0;
  684. }
  685. static List _create_resv_info_list(reserve_info_msg_t *resv_info_ptr)
  686. {
  687. static List info_list = NULL;
  688. int i = 0;
  689. static reserve_info_msg_t *last_resv_info_ptr = NULL;
  690. sview_resv_info_t *sview_resv_info_ptr = NULL;
  691. reserve_info_t *resv_ptr = NULL;
  692. if (info_list && (resv_info_ptr == last_resv_info_ptr))
  693. goto update_color;
  694. last_resv_info_ptr = resv_info_ptr;
  695. if (info_list)
  696. list_flush(info_list);
  697. else
  698. info_list = list_create(_resv_info_list_del);
  699. if (!info_list) {
  700. g_print("malloc error\n");
  701. return NULL;
  702. }
  703. for(i=0; i<resv_info_ptr->record_count; i++) {
  704. resv_ptr = &(resv_info_ptr->reservation_array[i]);
  705. sview_resv_info_ptr = xmalloc(sizeof(sview_resv_info_t));
  706. sview_resv_info_ptr->pos = i;
  707. sview_resv_info_ptr->resv_ptr = resv_ptr;
  708. sview_resv_info_ptr->color_inx = i % sview_colors_cnt;
  709. list_append(info_list, sview_resv_info_ptr);
  710. }
  711. list_sort(info_list,
  712. (ListCmpF)_sview_resv_sort_aval_dec);
  713. update_color:
  714. return info_list;
  715. }
  716. static void _display_info_resv(List info_list, popup_info_t *popup_win)
  717. {
  718. specific_info_t *spec_info = popup_win->spec_info;
  719. char *name = (char *)spec_info->search_info->gchar_data;
  720. int found = 0;
  721. reserve_info_t *resv_ptr = NULL;
  722. GtkTreeView *treeview = NULL;
  723. ListIterator itr = NULL;
  724. sview_resv_info_t *sview_resv_info = NULL;
  725. int update = 0;
  726. int j = 0;
  727. if (!spec_info->search_info->gchar_data) {
  728. //info = xstrdup("No pointer given!");
  729. goto finished;
  730. }
  731. need_refresh:
  732. if (!spec_info->display_widget) {
  733. treeview = create_treeview_2cols_attach_to_table(
  734. popup_win->table);
  735. spec_info->display_widget =
  736. gtk_widget_ref(GTK_WIDGET(treeview));
  737. } else {
  738. treeview = GTK_TREE_VIEW(spec_info->display_widget);
  739. update = 1;
  740. }
  741. itr = list_iterator_create(info_list);
  742. while ((sview_resv_info = (sview_resv_info_t*) list_next(itr))) {
  743. resv_ptr = sview_resv_info->resv_ptr;
  744. if (!strcmp(resv_ptr->name, name)) {
  745. j=0;
  746. while (resv_ptr->node_inx[j] >= 0) {
  747. change_grid_color(
  748. popup_win->grid_button_list,
  749. resv_ptr->node_inx[j],
  750. resv_ptr->node_inx[j+1],
  751. sview_resv_info->color_inx,
  752. true, 0);
  753. j += 2;
  754. }
  755. _layout_resv_record(treeview, sview_resv_info, update);
  756. found = 1;
  757. break;
  758. }
  759. }
  760. list_iterator_destroy(itr);
  761. post_setup_popup_grid_list(popup_win);
  762. if (!found) {
  763. if (!popup_win->not_found) {
  764. char *temp = "RESERVATION DOESN'T EXSIST\n";
  765. GtkTreeIter iter;
  766. GtkTreeModel *model = NULL;
  767. /* only time this will be run so no update */
  768. model = gtk_tree_view_get_model(treeview);
  769. add_display_treestore_line(0,
  770. GTK_TREE_STORE(model),
  771. &iter,
  772. temp, "");
  773. }
  774. popup_win->not_found = true;
  775. } else {
  776. if (popup_win->not_found) {
  777. popup_win->not_found = false;
  778. gtk_widget_destroy(spec_info->display_widget);
  779. goto need_refresh;
  780. }
  781. }
  782. gtk_widget_show(spec_info->display_widget);
  783. finished:
  784. return;
  785. }
  786. extern GtkWidget *create_resv_entry(resv_desc_msg_t *resv_msg,
  787. GtkTreeModel *model, GtkTreeIter *iter)
  788. {
  789. GtkScrolledWindow *window = create_scrolled_window();
  790. GtkBin *bin = NULL;
  791. GtkViewport *view = NULL;
  792. GtkTable *table = NULL;
  793. int i = 0, row = 0;
  794. display_data_t *display_data = create_data_resv;
  795. gtk_scrolled_window_set_policy(window,
  796. GTK_POLICY_NEVER,
  797. GTK_POLICY_AUTOMATIC);
  798. bin = GTK_BIN(&window->container);
  799. view = GTK_VIEWPORT(bin->child);
  800. bin = GTK_BIN(&view->bin);
  801. table = GTK_TABLE(bin->child);
  802. gtk_table_resize(table, SORTID_CNT, 2);
  803. gtk_table_set_homogeneous(table, FALSE);
  804. for (i = 0; i < SORTID_CNT; i++) {
  805. while (display_data++) {
  806. if (display_data->id == -1)
  807. break;
  808. if (!display_data->name)
  809. continue;
  810. if (display_data->id != i)
  811. continue;
  812. display_admin_edit(
  813. table, resv_msg, &row, model, iter,
  814. display_data,
  815. G_CALLBACK(_admin_edit_combo_box_resv),
  816. G_CALLBACK(_admin_focus_out_resv),
  817. _set_active_combo_resv);
  818. break;
  819. }
  820. display_data = create_data_resv;
  821. }
  822. gtk_table_resize(table, row, 2);
  823. return GTK_WIDGET(window);
  824. }
  825. extern void refresh_resv(GtkAction *action, gpointer user_data)
  826. {
  827. popup_info_t *popup_win = (popup_info_t *)user_data;
  828. xassert(popup_win);
  829. xassert(popup_win->spec_info);
  830. xassert(popup_win->spec_info->title);
  831. popup_win->force_refresh = 1;
  832. specific_info_resv(popup_win);
  833. }
  834. extern int get_new_info_resv(reserve_info_msg_t **info_ptr,
  835. int force)
  836. {
  837. static reserve_info_msg_t *new_resv_ptr = NULL;
  838. int error_code = SLURM_NO_CHANGE_IN_DATA;
  839. time_t now = time(NULL);
  840. static time_t last;
  841. static bool changed = 0;
  842. if (g_resv_info_ptr && !force
  843. && ((now - last) < working_sview_config.refresh_delay)) {
  844. if (*info_ptr != g_resv_info_ptr)
  845. error_code = SLURM_SUCCESS;
  846. *info_ptr = g_resv_info_ptr;
  847. if (changed)
  848. error_code = SLURM_SUCCESS;
  849. goto end_it;
  850. }
  851. last = now;
  852. if (g_resv_info_ptr) {
  853. error_code = slurm_load_reservations(
  854. g_resv_info_ptr->last_update, &new_resv_ptr);
  855. if (error_code == SLURM_SUCCESS) {
  856. slurm_free_reservation_info_msg(g_resv_info_ptr);
  857. changed = 1;
  858. } else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) {
  859. error_code = SLURM_NO_CHANGE_IN_DATA;
  860. new_resv_ptr = g_resv_info_ptr;
  861. changed = 0;
  862. }
  863. } else {
  864. new_resv_ptr = NULL;
  865. error_code = slurm_load_reservations((time_t) NULL,
  866. &new_resv_ptr);
  867. changed = 1;
  868. }
  869. g_resv_info_ptr = new_resv_ptr;
  870. if (g_resv_info_ptr && (*info_ptr != g_resv_info_ptr))
  871. error_code = SLURM_SUCCESS;
  872. *info_ptr = g_resv_info_ptr;
  873. end_it:
  874. return error_code;
  875. }
  876. extern GtkListStore *create_model_resv(int type)
  877. {
  878. GtkListStore *model = NULL;
  879. GtkTreeIter iter;
  880. switch(type) {
  881. case SORTID_ACTION:
  882. model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
  883. gtk_list_store_append(model, &iter);
  884. gtk_list_store_set(model, &iter,
  885. 1, SORTID_ACTION,
  886. 0, "None",
  887. -1);
  888. gtk_list_store_append(model, &iter);
  889. gtk_list_store_set(model, &iter,
  890. 1, SORTID_ACTION,
  891. 0, "Remove Reservation",
  892. -1);
  893. break;
  894. default:
  895. break;
  896. }
  897. return model;
  898. }
  899. extern void admin_edit_resv(GtkCellRendererText *cell,
  900. const char *path_string,
  901. const char *new_text,
  902. gpointer data)
  903. {
  904. GtkTreeStore *treestore = GTK_TREE_STORE(data);
  905. GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
  906. GtkTreeIter iter;
  907. resv_desc_msg_t *resv_msg = xmalloc(sizeof(resv_desc_msg_t));
  908. char *temp = NULL;
  909. char *old_text = NULL;
  910. const char *type = NULL;
  911. int column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell),
  912. "column"));
  913. if (!new_text || !strcmp(new_text, ""))
  914. goto no_input;
  915. gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), &iter, path);
  916. slurm_init_resv_desc_msg(resv_msg);
  917. gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter,
  918. SORTID_NAME, &temp,
  919. column, &old_text,
  920. -1);
  921. resv_msg->name = xstrdup(temp);
  922. g_free(temp);
  923. type = _set_resv_msg(resv_msg, new_text, column);
  924. if (global_edit_error)
  925. goto print_error;
  926. if (got_edit_signal) {
  927. temp = got_edit_signal;
  928. got_edit_signal = NULL;
  929. _admin_resv(GTK_TREE_MODEL(treestore), &iter, temp);
  930. xfree(temp);
  931. goto no_input;
  932. }
  933. if (old_text && !strcmp(old_text, new_text)) {
  934. temp = g_strdup_printf("No change in value.");
  935. } else if (slurm_update_reservation(resv_msg)
  936. == SLURM_SUCCESS) {
  937. gtk_tree_store_set(treestore, &iter, column, new_text, -1);
  938. temp = g_strdup_printf("Reservation %s %s changed to %s",
  939. resv_msg->name,
  940. type,
  941. new_text);
  942. } else if (errno == ESLURM_DISABLED) {
  943. temp = g_strdup_printf(
  944. "Can only edit %s on reservations not yet started.",
  945. type);
  946. } else {
  947. print_error:
  948. temp = g_strdup_printf("Reservation %s %s can't be "
  949. "set to %s",
  950. resv_msg->name,
  951. type,
  952. new_text);
  953. }
  954. display_edit_note(temp);
  955. g_free(temp);
  956. no_input:
  957. slurm_free_resv_desc_msg(resv_msg);
  958. gtk_tree_path_free (path);
  959. g_free(old_text);
  960. g_static_mutex_unlock(&sview_mutex);
  961. }
  962. extern void get_info_resv(GtkTable *table, display_data_t *display_data)
  963. {
  964. int error_code = SLURM_SUCCESS;
  965. List info_list = NULL;
  966. static int view = -1;
  967. static reserve_info_msg_t *resv_info_ptr = NULL;
  968. char error_char[100];
  969. GtkWidget *label = NULL;
  970. GtkTreeView *tree_view = NULL;
  971. static GtkWidget *display_widget = NULL;
  972. int j=0;
  973. ListIterator itr = NULL;
  974. sview_resv_info_t *sview_resv_info_ptr = NULL;
  975. reserve_info_t *resv_ptr = NULL;
  976. time_t now = time(NULL);
  977. GtkTreePath *path = NULL;
  978. static bool set_opts = FALSE;
  979. if (!set_opts)
  980. set_page_opts(RESV_PAGE, display_data_resv,
  981. SORTID_CNT, _initial_page_opts);
  982. set_opts = TRUE;
  983. /* reset */
  984. if (!table && !display_data) {
  985. if (display_widget)
  986. gtk_widget_destroy(display_widget);
  987. display_widget = NULL;
  988. resv_info_ptr = NULL;
  989. goto reset_curs;
  990. }
  991. if (display_data)
  992. local_display_data = display_data;
  993. if (!table) {
  994. display_data_resv->set_menu = local_display_data->set_menu;
  995. goto reset_curs;
  996. }
  997. if (display_widget && toggled) {
  998. gtk_widget_destroy(display_widget);
  999. display_widget = NULL;
  1000. goto display_it;
  1001. }
  1002. error_code = get_new_info_resv(&resv_info_ptr, force_refresh);
  1003. if (error_code == SLURM_NO_CHANGE_IN_DATA) {
  1004. } else if (error_code != SLURM_SUCCESS) {
  1005. if (view == ERROR_VIEW)
  1006. goto end_it;
  1007. if (display_widget)
  1008. gtk_widget_destroy(display_widget);
  1009. view = ERROR_VIEW;
  1010. sprintf(error_char, "slurm_load_reservations: %s",
  1011. slurm_strerror(slurm_get_errno()));
  1012. label = gtk_label_new(error_char);
  1013. gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
  1014. gtk_widget_show(label);
  1015. display_widget = gtk_widget_ref(GTK_WIDGET(label));
  1016. goto end_it;
  1017. }
  1018. display_it:
  1019. info_list = _create_resv_info_list(resv_info_ptr);
  1020. if (!info_list)
  1021. goto reset_curs;
  1022. /* set up the grid */
  1023. if (display_widget && GTK_IS_TREE_VIEW(display_widget)
  1024. && gtk_tree_selection_count_selected_rows(
  1025. gtk_tree_view_get_selection(
  1026. GTK_TREE_VIEW(display_widget)))) {
  1027. GtkTreeViewColumn *focus_column = NULL;
  1028. /* highlight the correct nodes from the last selection */
  1029. gtk_tree_view_get_cursor(GTK_TREE_VIEW(display_widget),
  1030. &path, &focus_column);
  1031. }
  1032. if (!path) {
  1033. itr = list_iterator_create(info_list);
  1034. while ((sview_resv_info_ptr = list_next(itr))) {
  1035. resv_ptr = sview_resv_info_ptr->resv_ptr;
  1036. if ((resv_ptr->start_time > now) ||
  1037. (resv_ptr->end_time < now))
  1038. continue;/* only map current reservations */
  1039. j=0;
  1040. while (resv_ptr->node_inx[j] >= 0) {
  1041. change_grid_color(grid_button_list,
  1042. resv_ptr->node_inx[j],
  1043. resv_ptr->node_inx[j+1],
  1044. sview_resv_info_ptr->
  1045. color_inx,
  1046. true, 0);
  1047. j += 2;
  1048. }
  1049. }
  1050. list_iterator_destroy(itr);
  1051. change_grid_color(grid_button_list, -1, -1,
  1052. MAKE_WHITE, true, 0);
  1053. } else
  1054. highlight_grid(GTK_TREE_VIEW(display_widget),
  1055. SORTID_NODE_INX, SORTID_COLOR_INX,
  1056. grid_button_list);
  1057. if (view == ERROR_VIEW && display_widget) {
  1058. gtk_widget_destroy(display_widget);
  1059. display_widget = NULL;
  1060. }
  1061. if (!display_widget) {
  1062. tree_view = create_treeview(local_display_data,
  1063. &grid_button_list);
  1064. gtk_tree_selection_set_mode(
  1065. gtk_tree_view_get_selection(tree_view),
  1066. GTK_SELECTION_MULTIPLE);
  1067. display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
  1068. gtk_table_attach_defaults(table,
  1069. GTK_WIDGET(tree_view),
  1070. 0, 1, 0, 1);
  1071. /* since this function sets the model of the tree_view
  1072. to the treestore we don't really care about
  1073. the return value */
  1074. create_treestore(tree_view, display_data_resv,
  1075. SORTID_CNT, SORTID_TIME_START, SORTID_COLOR);
  1076. }
  1077. view = INFO_VIEW;
  1078. _update_info_resv(info_list, GTK_TREE_VIEW(display_widget));
  1079. end_it:
  1080. toggled = FALSE;
  1081. force_refresh = FALSE;
  1082. reset_curs:
  1083. if (main_window && main_window->window)
  1084. gdk_window_set_cursor(main_window->window, NULL);
  1085. return;
  1086. }
  1087. extern void specific_info_resv(popup_info_t *popup_win)
  1088. {
  1089. int resv_error_code = SLURM_SUCCESS;
  1090. static reserve_info_msg_t *resv_info_ptr = NULL;
  1091. static reserve_info_t *resv_ptr = NULL;
  1092. specific_info_t *spec_info = popup_win->spec_info;
  1093. sview_search_info_t *search_info = spec_info->search_info;
  1094. char error_char[100];
  1095. GtkWidget *label = NULL;
  1096. GtkTreeView *tree_view = NULL;
  1097. List resv_list = NULL;
  1098. List send_resv_list = NULL;
  1099. sview_resv_info_t *sview_resv_info_ptr = NULL;
  1100. int j=0, i=-1;
  1101. hostset_t hostset = NULL;
  1102. ListIterator itr = NULL;
  1103. if (!spec_info->display_widget) {
  1104. setup_popup_info(popup_win, display_data_resv, SORTID_CNT);
  1105. }
  1106. if (spec_info->display_widget && popup_win->toggled) {
  1107. gtk_widget_destroy(spec_info->display_widget);
  1108. spec_info->display_widget = NULL;
  1109. goto display_it;
  1110. }
  1111. if ((resv_error_code =
  1112. get_new_info_resv(&resv_info_ptr, popup_win->force_refresh))
  1113. == SLURM_NO_CHANGE_IN_DATA) {
  1114. if (!spec_info->display_widget || spec_info->view == ERROR_VIEW)
  1115. goto display_it;
  1116. } else if (resv_error_code != SLURM_SUCCESS) {
  1117. if (spec_info->view == ERROR_VIEW)
  1118. goto end_it;
  1119. spec_info->view = ERROR_VIEW;
  1120. if (spec_info->display_widget)
  1121. gtk_widget_destroy(spec_info->display_widget);
  1122. sprintf(error_char, "get_new_info_resv: %s",
  1123. slurm_strerror(slurm_get_errno()));
  1124. label = gtk_label_new(error_char);
  1125. gtk_table_attach_defaults(popup_win->table,
  1126. label,
  1127. 0, 1, 0, 1);
  1128. gtk_widget_show(label);
  1129. spec_info->display_widget = gtk_widget_ref(label);
  1130. goto end_it;
  1131. }
  1132. display_it:
  1133. resv_list = _create_resv_info_list(resv_info_ptr);
  1134. if (!resv_list)
  1135. return;
  1136. if (spec_info->view == ERROR_VIEW && spec_info->display_widget) {
  1137. gtk_widget_destroy(spec_info->display_widget);
  1138. spec_info->display_widget = NULL;
  1139. }
  1140. if (spec_info->type != INFO_PAGE && !spec_info->display_widget) {
  1141. tree_view = create_treeview(local_display_data,
  1142. &popup_win->grid_button_list);
  1143. gtk_tree_selection_set_mode(
  1144. gtk_tree_view_get_selection(tree_view),
  1145. GTK_SELECTION_MULTIPLE);
  1146. spec_info->display_widget =
  1147. gtk_widget_ref(GTK_WIDGET(tree_view));
  1148. gtk_table_attach_defaults(popup_win->table,
  1149. GTK_WIDGET(tree_view),
  1150. 0, 1, 0, 1);
  1151. /* since this function sets the model of the tree_view
  1152. to the treestore we don't really care about
  1153. the return value */
  1154. create_treestore(tree_view, popup_win->display_data,
  1155. SORTID_CNT, SORTID_TIME_START, SORTID_COLOR);
  1156. }
  1157. setup_popup_grid_list(popup_win);
  1158. spec_info->view = INFO_VIEW;
  1159. if (spec_info->type == INFO_PAGE) {
  1160. _display_info_resv(resv_list, popup_win);
  1161. goto end_it;
  1162. }
  1163. /* just linking to another list, don't free the inside, just
  1164. the list */
  1165. send_resv_list = list_create(NULL);
  1166. itr = list_iterator_create(resv_list);
  1167. i = -1;
  1168. while ((sview_resv_info_ptr = list_next(itr))) {
  1169. i++;
  1170. resv_ptr = sview_resv_info_ptr->resv_ptr;
  1171. switch(spec_info->type) {
  1172. case PART_PAGE:
  1173. case BLOCK_PAGE:
  1174. case NODE_PAGE:
  1175. if (!resv_ptr->node_list)
  1176. continue;
  1177. if (!(hostset = hostset_create(
  1178. search_info->gchar_data)))
  1179. continue;
  1180. if (!hostset_intersects(hostset, resv_ptr->node_list)) {
  1181. hostset_destroy(hostset);
  1182. continue;
  1183. }
  1184. hostset_destroy(hostset);
  1185. break;
  1186. case JOB_PAGE:
  1187. if (strcmp(resv_ptr->name,
  1188. search_info->gchar_data))
  1189. continue;
  1190. break;
  1191. case RESV_PAGE:
  1192. switch(search_info->search_type) {
  1193. case SEARCH_RESERVATION_NAME:
  1194. if (!search_info->gchar_data)
  1195. continue;
  1196. if (strcmp(resv_ptr->name,
  1197. search_info->gchar_data))
  1198. continue;
  1199. break;
  1200. default:
  1201. continue;
  1202. }
  1203. break;
  1204. default:
  1205. g_print("Unknown type %d\n", spec_info->type);
  1206. continue;
  1207. }
  1208. list_push(send_resv_list, sview_resv_info_ptr);
  1209. j=0;
  1210. while (resv_ptr->node_inx[j] >= 0) {
  1211. change_grid_color(
  1212. popup_win->grid_button_list,
  1213. resv_ptr->node_inx[j],
  1214. resv_ptr->node_inx[j+1],
  1215. sview_resv_info_ptr->color_inx,
  1216. true, 0);
  1217. j += 2;
  1218. }
  1219. }
  1220. list_iterator_destroy(itr);
  1221. post_setup_popup_grid_list(popup_win);
  1222. _update_info_resv(send_resv_list,
  1223. GTK_TREE_VIEW(spec_info->display_widget));
  1224. list_destroy(send_resv_list);
  1225. end_it:
  1226. popup_win->toggled = 0;
  1227. popup_win->force_refresh = 0;
  1228. return;
  1229. }
  1230. extern void set_menus_resv(void *arg, void *arg2, GtkTreePath *path, int type)
  1231. {
  1232. GtkTreeView *tree_view = (GtkTreeView *)arg;
  1233. popup_info_t *popup_win = (popup_info_t *)arg;
  1234. GtkMenu *menu = (GtkMenu *)arg2;
  1235. List button_list = (List)arg2;
  1236. switch(type) {
  1237. case TAB_CLICKED:
  1238. make_fields_menu(NULL, menu, display_data_resv, SORTID_CNT);
  1239. break;
  1240. case ROW_CLICKED:
  1241. make_options_menu(tree_view, path, menu, options_data_resv);
  1242. break;
  1243. case ROW_LEFT_CLICKED:
  1244. highlight_grid(tree_view, SORTID_NODE_INX,
  1245. SORTID_COLOR_INX, button_list);
  1246. break;
  1247. case FULL_CLICKED:
  1248. {
  1249. GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  1250. GtkTreeIter iter;
  1251. if (!gtk_tree_model_get_iter(model, &iter, path)) {
  1252. g_error("error getting iter from model\n");
  1253. break;
  1254. }
  1255. popup_all_resv(model, &iter, INFO_PAGE);
  1256. break;
  1257. }
  1258. case POPUP_CLICKED:
  1259. make_fields_menu(popup_win, menu,
  1260. popup_win->display_data, SORTID_CNT);
  1261. break;
  1262. default:
  1263. g_error("UNKNOWN type %d given to set_fields\n", type);
  1264. }
  1265. }
  1266. extern void popup_all_resv(GtkTreeModel *model, GtkTreeIter *iter, int id)
  1267. {
  1268. char *name = NULL;
  1269. char title[100];
  1270. ListIterator itr = NULL;
  1271. popup_info_t *popup_win = NULL;
  1272. GError *error = NULL;
  1273. gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
  1274. switch(id) {
  1275. case PART_PAGE:
  1276. snprintf(title, 100, "Partition(s) with reservation %s", name);
  1277. break;
  1278. case JOB_PAGE:
  1279. snprintf(title, 100, "Job(s) in reservation %s", name);
  1280. break;
  1281. case NODE_PAGE:
  1282. if (cluster_flags & CLUSTER_FLAG_BG)
  1283. snprintf(title, 100,
  1284. "Midplane(s) in reservation %s",
  1285. name);
  1286. else
  1287. snprintf(title, 100, "Node(s) in reservation %s ",
  1288. name);
  1289. break;
  1290. case BLOCK_PAGE:
  1291. snprintf(title, 100, "Block(s) in reservation %s", name);
  1292. break;
  1293. case SUBMIT_PAGE:
  1294. snprintf(title, 100, "Submit job in reservation %s", name);
  1295. break;
  1296. case INFO_PAGE:
  1297. snprintf(title, 100, "Full info for reservation %s", name);
  1298. break;
  1299. default:
  1300. g_print("resv got %d\n", id);
  1301. }
  1302. itr = list_iterator_create(popup_list);
  1303. while ((popup_win = list_next(itr))) {
  1304. if (popup_win->spec_info)
  1305. if (!strcmp(popup_win->spec_info->title, title)) {
  1306. break;
  1307. }
  1308. }
  1309. list_iterator_destroy(itr);
  1310. if (!popup_win) {
  1311. if (id == INFO_PAGE)
  1312. popup_win = create_popup_info(id, RESV_PAGE, title);
  1313. else
  1314. popup_win = create_popup_info(RESV_PAGE, id, title);
  1315. } else {
  1316. g_free(name);
  1317. gtk_window_present(GTK_WINDOW(popup_win->popup));
  1318. return;
  1319. }
  1320. /* Pass the model and the structs from the iter so we can always get
  1321. the current node_inx.
  1322. */
  1323. popup_win->model = model;
  1324. popup_win->iter = *iter;
  1325. popup_win->node_inx_id = SORTID_NODE_INX;
  1326. switch(id) {
  1327. case JOB_PAGE:
  1328. case INFO_PAGE:
  1329. popup_win->spec_info->search_info->gchar_data = name;
  1330. //specific_info_job(popup_win);
  1331. break;
  1332. case BLOCK_PAGE:
  1333. case NODE_PAGE:
  1334. case PART_PAGE:
  1335. g_free(name);
  1336. gtk_tree_model_get(model, iter, SORTID_NODELIST, &name, -1);
  1337. popup_win->spec_info->search_info->gchar_data = name;
  1338. popup_win->spec_info->search_info->search_type =
  1339. SEARCH_NODE_NAME;
  1340. //specific_info_node(popup_win);
  1341. break;
  1342. case SUBMIT_PAGE:
  1343. break;
  1344. default:
  1345. g_print("resv got unknown type %d\n", id);
  1346. }
  1347. if (!sview_thread_new((gpointer)popup_thr, popup_win, FALSE, &error)) {
  1348. g_printerr ("Failed to create resv popup thread: %s\n",
  1349. error->message);
  1350. return;
  1351. }
  1352. }
  1353. static void _process_each_resv(GtkTreeModel *model, GtkTreePath *path,
  1354. GtkTreeIter*iter, gpointer userdata)
  1355. {
  1356. char *type = userdata;
  1357. if (_DEBUG)
  1358. g_print("process_each_resv: global_multi_error = %d\n",
  1359. global_multi_error);
  1360. if (!global_multi_error) {
  1361. _admin_resv(model, iter, type);
  1362. }
  1363. }
  1364. extern void select_admin_resv(GtkTreeModel *model, GtkTreeIter *iter,
  1365. display_data_t *display_data,
  1366. GtkTreeView *treeview)
  1367. {
  1368. if (treeview) {
  1369. if (display_data->extra & EXTRA_NODES) {
  1370. select_admin_nodes(model, iter, display_data,
  1371. SORTID_NODELIST, treeview);
  1372. return;
  1373. }
  1374. global_multi_error = FALSE;
  1375. gtk_tree_selection_selected_foreach(
  1376. gtk_tree_view_get_selection(treeview),
  1377. _process_each_resv, display_data->name);
  1378. }
  1379. }
  1380. static void _admin_resv(GtkTreeModel *model, GtkTreeIter *iter, char *type)
  1381. {
  1382. resv_desc_msg_t *resv_msg = xmalloc(sizeof(resv_desc_msg_t));
  1383. reservation_name_msg_t resv_name_msg;
  1384. char *resvid = NULL;
  1385. char tmp_char[100];
  1386. char *temp = NULL;
  1387. int edit_type = 0;
  1388. int response = 0;
  1389. GtkWidget *label = NULL;
  1390. GtkWidget *entry = NULL;
  1391. GtkWidget *popup = gtk_dialog_new_with_buttons(
  1392. type,
  1393. GTK_WINDOW(main_window),
  1394. GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
  1395. NULL);
  1396. gtk_window_set_transient_for(GTK_WINDOW(popup), NULL);
  1397. gtk_tree_model_get(model, iter, SORTID_NAME, &resvid, -1);
  1398. slurm_init_resv_desc_msg(resv_msg);
  1399. memset(&resv_name_msg, 0, sizeof(reservation_name_msg_t));
  1400. resv_msg->name = xstrdup(resvid);
  1401. if (!strcasecmp("Remove Reservation", type)) {
  1402. resv_name_msg.name = resvid;
  1403. label = gtk_dialog_add_button(GTK_DIALOG(popup),
  1404. GTK_STOCK_YES, GTK_RESPONSE_OK);
  1405. gtk_window_set_default(GTK_WINDOW(popup), label);
  1406. gtk_dialog_add_button(GTK_DIALOG(popup),
  1407. GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  1408. snprintf(tmp_char, sizeof(tmp_char),
  1409. "Are you sure you want to remove "
  1410. "reservation %s?",
  1411. resvid);
  1412. label = gtk_label_new(tmp_char);
  1413. edit_type = EDIT_REMOVE;
  1414. } else {
  1415. label = gtk_dialog_add_button(GTK_DIALOG(popup),
  1416. GTK_STOCK_OK, GTK_RESPONSE_OK);
  1417. gtk_window_set_default(GTK_WINDOW(popup), label);
  1418. gtk_dialog_add_button(GTK_DIALOG(popup),
  1419. GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  1420. gtk_window_set_default_size(GTK_WINDOW(popup), 200, 400);
  1421. snprintf(tmp_char, sizeof(tmp_char),
  1422. "Editing reservation %s think before you type",
  1423. resvid);
  1424. label = gtk_label_new(tmp_char);
  1425. edit_type = EDIT_EDIT;
  1426. entry = _admin_full_edit_resv(resv_msg, model, iter);
  1427. }
  1428. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
  1429. label, FALSE, FALSE, 0);
  1430. if (entry)
  1431. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
  1432. entry, TRUE, TRUE, 0);
  1433. gtk_widget_show_all(popup);
  1434. response = gtk_dialog_run (GTK_DIALOG(popup));
  1435. if (response == GTK_RESPONSE_OK) {
  1436. switch(edit_type) {
  1437. case EDIT_REMOVE:
  1438. if (slurm_delete_reservation(&resv_name_msg)
  1439. == SLURM_SUCCESS) {
  1440. temp = g_strdup_printf(
  1441. "Reservation %s removed successfully",
  1442. resvid);
  1443. } else {
  1444. temp = g_strdup_printf(
  1445. "Problem removing reservation %s.",
  1446. resvid);
  1447. }
  1448. display_edit_note(temp);
  1449. g_free(temp);
  1450. break;
  1451. case EDIT_EDIT:
  1452. if (got_edit_signal)
  1453. goto end_it;
  1454. if (!global_send_update_msg) {
  1455. temp = g_strdup_printf("No change detected.");
  1456. } else if (slurm_update_reservation(resv_msg)
  1457. == SLURM_SUCCESS) {
  1458. temp = g_strdup_printf(
  1459. "Reservation %s updated successfully",
  1460. resvid);
  1461. } else {
  1462. temp = g_strdup_printf(
  1463. "Problem updating reservation %s.",
  1464. resvid);
  1465. }
  1466. display_edit_note(temp);
  1467. g_free(temp);
  1468. break;
  1469. default:
  1470. break;
  1471. }
  1472. }
  1473. end_it:
  1474. g_free(resvid);
  1475. global_entry_changed = 0;
  1476. slurm_free_resv_desc_msg(resv_msg);
  1477. gtk_widget_destroy(popup);
  1478. if (got_edit_signal) {
  1479. type = got_edit_signal;
  1480. got_edit_signal = NULL;
  1481. _admin_resv(model, iter, type);
  1482. xfree(type);
  1483. }
  1484. return;
  1485. }
  1486. extern void cluster_change_resv(void)
  1487. {
  1488. display_data_t *display_data = display_data_resv;
  1489. while (display_data++) {
  1490. if (display_data->id == -1)
  1491. break;
  1492. if (cluster_flags & CLUSTER_FLAG_BG) {
  1493. switch(display_data->id) {
  1494. case SORTID_NODELIST:
  1495. display_data->name = "MidplaneList";
  1496. break;
  1497. default:
  1498. break;
  1499. }
  1500. } else {
  1501. switch(display_data->id) {
  1502. case SORTID_NODELIST:
  1503. display_data->name = "NodeList";
  1504. break;
  1505. default:
  1506. break;
  1507. }
  1508. }
  1509. }
  1510. display_data = options_data_resv;
  1511. while (display_data++) {
  1512. if (display_data->id == -1)
  1513. break;
  1514. if (cluster_flags & CLUSTER_FLAG_BG) {
  1515. switch(display_data->id) {
  1516. case BLOCK_PAGE:
  1517. display_data->name = "Blocks";
  1518. break;
  1519. case NODE_PAGE:
  1520. display_data->name = "Midplanes";
  1521. break;
  1522. }
  1523. } else {
  1524. switch(display_data->id) {
  1525. case BLOCK_PAGE:
  1526. display_data->name = NULL;
  1527. break;
  1528. case NODE_PAGE:
  1529. display_data->name = "Nodes";
  1530. break;
  1531. }
  1532. }
  1533. }
  1534. get_info_resv(NULL, NULL);
  1535. }