PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/src/sview/part_info.c

https://github.com/cfenoy/slurm
C | 3056 lines | 2691 code | 257 blank | 108 comment | 527 complexity | 2a273b760446c62347919e7a7a07d294 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. /*****************************************************************************\
  2. * part_info.c - Functions related to partition display
  3. * mode of sview.
  4. *****************************************************************************
  5. * Copyright (C) 2004-2007 The Regents of the University of California.
  6. * Copyright (C) 2008-2010 Lawrence Livermore National Security.
  7. * Portions Copyright (C) 2010 SchedMD <http://www.schedmd.com>.
  8. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  9. * Written by Danny Auble <da@llnl.gov>
  10. *
  11. * CODE-OCEC-09-009. All rights reserved.
  12. *
  13. * This file is part of SLURM, a resource management program.
  14. * For details, see <http://www.schedmd.com/slurmdocs/>.
  15. * Please also read the included file: DISCLAIMER.
  16. *
  17. * SLURM is free software; you can redistribute it and/or modify it under
  18. * the terms of the GNU General Public License as published by the Free
  19. * Software Foundation; either version 2 of the License, or (at your option)
  20. * any later version.
  21. *
  22. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  23. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  24. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  25. * details.
  26. *
  27. * You should have received a copy of the GNU General Public License along
  28. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  29. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  30. \*****************************************************************************/
  31. #include "src/sview/sview.h"
  32. #include "src/common/parse_time.h"
  33. #include <grp.h>
  34. #define _DEBUG 0
  35. static GtkListStore *_create_model_part2(int type);
  36. typedef struct {
  37. uint32_t cpu_alloc_cnt;
  38. uint32_t cpu_error_cnt;
  39. uint32_t cpu_idle_cnt;
  40. uint32_t disk_total;
  41. char *features;
  42. hostlist_t hl;
  43. uint32_t mem_total;
  44. uint32_t node_cnt;
  45. List node_ptr_list;
  46. uint16_t node_state;
  47. partition_info_t* part_ptr;
  48. char *reason;
  49. } sview_part_sub_t;
  50. /* Collection of data for printing reports. Like data is combined here */
  51. typedef struct {
  52. int color_inx;
  53. GtkTreeIter iter_ptr;
  54. bool iter_set;
  55. /* part_info contains partition, avail, max_time, job_size,
  56. * root, share, groups */
  57. partition_info_t* part_ptr;
  58. int pos;
  59. List sub_list;
  60. sview_part_sub_t sub_part_total;
  61. } sview_part_info_t;
  62. enum {
  63. EDIT_PART_STATE = 1,
  64. EDIT_REMOVE_PART,
  65. EDIT_EDIT
  66. };
  67. /* These need to be in alpha order (except POS and CNT) */
  68. enum {
  69. SORTID_POS = POS_LOC,
  70. SORTID_ALTERNATE,
  71. SORTID_COLOR,
  72. SORTID_COLOR_INX,
  73. SORTID_CPUS,
  74. SORTID_DEFAULT,
  75. SORTID_FEATURES,
  76. SORTID_GRACE_TIME,
  77. SORTID_GROUPS,
  78. SORTID_HIDDEN,
  79. SORTID_JOB_SIZE,
  80. SORTID_MEM,
  81. #ifdef HAVE_BG
  82. SORTID_NODELIST,
  83. SORTID_NODES_ALLOWED,
  84. #endif
  85. SORTID_NAME,
  86. #ifndef HAVE_BG
  87. SORTID_NODELIST,
  88. SORTID_NODES_ALLOWED,
  89. #endif
  90. SORTID_NODE_INX,
  91. SORTID_NODE_STATE,
  92. SORTID_NODE_STATE_NUM,
  93. SORTID_NODES,
  94. SORTID_NODES_MAX,
  95. SORTID_NODES_MIN,
  96. SORTID_ONLY_LINE,
  97. SORTID_PART_STATE,
  98. SORTID_PREEMPT_MODE,
  99. SORTID_PRIORITY,
  100. SORTID_REASON,
  101. SORTID_ROOT,
  102. SORTID_SHARE,
  103. SORTID_TMP_DISK,
  104. SORTID_TIMELIMIT,
  105. SORTID_UPDATED,
  106. SORTID_CNT
  107. };
  108. /*these are the settings to apply for the user
  109. * on the first startup after a fresh slurm install.*/
  110. static char *_initial_page_opts = "Partition,Default,Part_State,"
  111. "Time_Limit,Node_Count,Node_State,NodeList";
  112. static display_data_t display_data_part[] = {
  113. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE, refresh_part},
  114. {G_TYPE_STRING, SORTID_NAME, "Partition", FALSE,
  115. EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
  116. {G_TYPE_STRING, SORTID_COLOR, NULL, TRUE, EDIT_COLOR, refresh_part,
  117. create_model_part, admin_edit_part},
  118. {G_TYPE_STRING, SORTID_ALTERNATE, "Alternate", FALSE,
  119. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  120. {G_TYPE_STRING, SORTID_DEFAULT, "Default", FALSE,
  121. EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
  122. {G_TYPE_STRING, SORTID_GRACE_TIME, "GraceTime", FALSE,
  123. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  124. {G_TYPE_STRING, SORTID_HIDDEN, "Hidden", FALSE,
  125. EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
  126. {G_TYPE_STRING, SORTID_PART_STATE, "Part State", FALSE,
  127. EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
  128. {G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", FALSE,
  129. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  130. {G_TYPE_STRING, SORTID_NODES, "Node Count", FALSE,
  131. EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
  132. {G_TYPE_STRING, SORTID_CPUS, "CPU Count", FALSE,
  133. EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
  134. {G_TYPE_STRING, SORTID_NODE_STATE, "Node State", FALSE,
  135. EDIT_MODEL, refresh_part,
  136. create_model_part, admin_edit_part},
  137. {G_TYPE_STRING, SORTID_JOB_SIZE, "Job Size", FALSE,
  138. EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
  139. {G_TYPE_STRING, SORTID_PREEMPT_MODE, "PreemptMode", FALSE,
  140. EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
  141. {G_TYPE_STRING, SORTID_PRIORITY, "Priority", FALSE,
  142. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  143. {G_TYPE_STRING, SORTID_NODES_MIN, "Nodes Min", FALSE,
  144. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  145. {G_TYPE_STRING, SORTID_NODES_MAX, "Nodes Max", FALSE,
  146. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  147. {G_TYPE_STRING, SORTID_ROOT, "Root", FALSE, EDIT_MODEL, refresh_part,
  148. create_model_part, admin_edit_part},
  149. {G_TYPE_STRING, SORTID_SHARE, "Share", FALSE, EDIT_MODEL, refresh_part,
  150. create_model_part, admin_edit_part},
  151. {G_TYPE_STRING, SORTID_GROUPS, "Groups Allowed", FALSE,
  152. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  153. {G_TYPE_STRING, SORTID_NODES_ALLOWED, "Nodes Allowed Allocating", FALSE,
  154. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  155. {G_TYPE_STRING, SORTID_TMP_DISK, "Temp Disk", FALSE,
  156. EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
  157. {G_TYPE_STRING, SORTID_MEM, "Memory", FALSE, EDIT_NONE, refresh_part,
  158. create_model_part, admin_edit_part},
  159. {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE,
  160. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  161. {G_TYPE_STRING, SORTID_REASON, "Reason", FALSE,
  162. EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
  163. #ifdef HAVE_BG
  164. {G_TYPE_STRING, SORTID_NODELIST, "MidplaneList", FALSE,
  165. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  166. #else
  167. {G_TYPE_STRING, SORTID_NODELIST, "NodeList", FALSE,
  168. EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
  169. #endif
  170. {G_TYPE_INT, SORTID_NODE_STATE_NUM, NULL, FALSE,
  171. EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
  172. {G_TYPE_INT, SORTID_ONLY_LINE, NULL, FALSE, EDIT_NONE, refresh_part,
  173. create_model_part, admin_edit_part},
  174. {G_TYPE_INT, SORTID_COLOR_INX, NULL, FALSE, EDIT_NONE, refresh_part,
  175. create_model_part, admin_edit_part},
  176. {G_TYPE_POINTER, SORTID_NODE_INX, NULL, FALSE, EDIT_NONE,
  177. refresh_part, create_model_part, admin_edit_part},
  178. {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, EDIT_NONE, refresh_part,
  179. create_model_part, admin_edit_part},
  180. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  181. };
  182. static display_data_t create_data_part[] = {
  183. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE, refresh_part},
  184. {G_TYPE_STRING, SORTID_NAME, "Name", FALSE,
  185. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  186. {G_TYPE_STRING, SORTID_ALTERNATE, "Alternate", FALSE,
  187. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  188. {G_TYPE_STRING, SORTID_DEFAULT, "Default", FALSE,
  189. EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
  190. {G_TYPE_STRING, SORTID_GRACE_TIME, "GraceTime", FALSE,
  191. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  192. {G_TYPE_STRING, SORTID_HIDDEN, "Hidden", FALSE,
  193. EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
  194. {G_TYPE_STRING, SORTID_PART_STATE, "State", FALSE,
  195. EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
  196. {G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", FALSE,
  197. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  198. {G_TYPE_STRING, SORTID_PREEMPT_MODE, "PreemptMode", FALSE,
  199. EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
  200. {G_TYPE_STRING, SORTID_PRIORITY, "Priority", FALSE,
  201. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  202. {G_TYPE_STRING, SORTID_NODES_MIN, "Nodes Min", FALSE,
  203. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  204. {G_TYPE_STRING, SORTID_NODES_MAX, "Nodes Max", FALSE,
  205. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  206. {G_TYPE_STRING, SORTID_ROOT, "Root", FALSE,
  207. EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
  208. {G_TYPE_STRING, SORTID_SHARE, "Share", FALSE,
  209. EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
  210. {G_TYPE_STRING, SORTID_GROUPS, "Groups Allowed", FALSE,
  211. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  212. {G_TYPE_STRING, SORTID_NODES_ALLOWED, "Nodes Allowed Allocating", FALSE,
  213. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  214. {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE,
  215. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  216. {G_TYPE_STRING, SORTID_REASON, "Reason", FALSE,
  217. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  218. #ifdef HAVE_BG
  219. {G_TYPE_STRING, SORTID_NODELIST, "MidplaneList", FALSE,
  220. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  221. #else
  222. {G_TYPE_STRING, SORTID_NODELIST, "NodeList", FALSE,
  223. EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
  224. #endif
  225. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  226. };
  227. static display_data_t options_data_part[] = {
  228. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE},
  229. {G_TYPE_STRING, INFO_PAGE, "Full Info", TRUE, PART_PAGE},
  230. {G_TYPE_STRING, PART_PAGE, "Edit Partition", TRUE, ADMIN_PAGE},
  231. {G_TYPE_STRING, PART_PAGE, "Remove Partition", TRUE, ADMIN_PAGE},
  232. #ifdef HAVE_BG
  233. {G_TYPE_STRING, PART_PAGE, "Drain Midplanes",
  234. TRUE, ADMIN_PAGE | EXTRA_NODES},
  235. {G_TYPE_STRING, PART_PAGE, "Resume Midplanes",
  236. TRUE, ADMIN_PAGE | EXTRA_NODES},
  237. {G_TYPE_STRING, PART_PAGE, "Put Midplanes Down",
  238. TRUE, ADMIN_PAGE | EXTRA_NODES},
  239. {G_TYPE_STRING, PART_PAGE, "Make Midplanes Idle",
  240. TRUE, ADMIN_PAGE | EXTRA_NODES},
  241. {G_TYPE_STRING, PART_PAGE, "Update Midplane Features",
  242. TRUE, ADMIN_PAGE | EXTRA_NODES},
  243. #else
  244. {G_TYPE_STRING, PART_PAGE, "Drain Nodes",
  245. TRUE, ADMIN_PAGE | EXTRA_NODES},
  246. {G_TYPE_STRING, PART_PAGE, "Resume Nodes",
  247. TRUE, ADMIN_PAGE | EXTRA_NODES},
  248. {G_TYPE_STRING, PART_PAGE, "Put Nodes Down",
  249. TRUE, ADMIN_PAGE | EXTRA_NODES},
  250. {G_TYPE_STRING, PART_PAGE, "Make Nodes Idle",
  251. TRUE, ADMIN_PAGE | EXTRA_NODES},
  252. {G_TYPE_STRING, PART_PAGE, "Update Node Features",
  253. TRUE, ADMIN_PAGE | EXTRA_NODES},
  254. #endif
  255. {G_TYPE_STRING, PART_PAGE, "Change Partition State",
  256. TRUE, ADMIN_PAGE},
  257. {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, PART_PAGE},
  258. #ifdef HAVE_BG
  259. {G_TYPE_STRING, BLOCK_PAGE, "Blocks", TRUE, PART_PAGE},
  260. {G_TYPE_STRING, NODE_PAGE, "Midplanes", TRUE, PART_PAGE},
  261. #else
  262. {G_TYPE_STRING, BLOCK_PAGE, NULL, TRUE, PART_PAGE},
  263. {G_TYPE_STRING, NODE_PAGE, "Nodes", TRUE, PART_PAGE},
  264. #endif
  265. //{G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", FALSE, PART_PAGE},
  266. {G_TYPE_STRING, RESV_PAGE, "Reservations", TRUE, PART_PAGE},
  267. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  268. };
  269. static display_data_t *local_display_data = NULL;
  270. static char *got_edit_signal = NULL;
  271. static char *got_features_edit_signal = NULL;
  272. static void _append_part_sub_record(sview_part_sub_t *sview_part_sub,
  273. GtkTreeStore *treestore, GtkTreeIter *iter,
  274. int line);
  275. static void _update_part_sub_record(sview_part_sub_t *sview_part_sub,
  276. GtkTreeStore *treestore,
  277. GtkTreeIter *iter);
  278. static int _build_min_max_32_string(char *buffer, int buf_size,
  279. uint32_t min, uint32_t max, bool range)
  280. {
  281. char tmp_min[8];
  282. char tmp_max[8];
  283. convert_num_unit((float)min, tmp_min, sizeof(tmp_min), UNIT_NONE);
  284. convert_num_unit((float)max, tmp_max, sizeof(tmp_max), UNIT_NONE);
  285. if (max == min)
  286. return snprintf(buffer, buf_size, "%s", tmp_max);
  287. else if (range) {
  288. if (max == (uint32_t) INFINITE)
  289. return snprintf(buffer, buf_size, "%s-infinite",
  290. tmp_min);
  291. else
  292. return snprintf(buffer, buf_size, "%s-%s",
  293. tmp_min, tmp_max);
  294. } else
  295. return snprintf(buffer, buf_size, "%s+", tmp_min);
  296. }
  297. static void _set_active_combo_part(GtkComboBox *combo,
  298. GtkTreeModel *model, GtkTreeIter *iter,
  299. int type)
  300. {
  301. char *temp_char = NULL;
  302. int action = 0;
  303. int i = 0, unknown_found = 0;
  304. char *upper = NULL;
  305. if (model)
  306. gtk_tree_model_get(model, iter, type, &temp_char, -1);
  307. if (!temp_char)
  308. goto end_it;
  309. switch(type) {
  310. case SORTID_DEFAULT:
  311. case SORTID_HIDDEN:
  312. case SORTID_ROOT:
  313. if (!strcmp(temp_char, "yes"))
  314. action = 0;
  315. else if (!strcmp(temp_char, "no"))
  316. action = 1;
  317. else
  318. action = 0;
  319. break;
  320. case SORTID_SHARE:
  321. if (!strncmp(temp_char, "force", 5))
  322. action = 0;
  323. else if (!strcmp(temp_char, "no"))
  324. action = 1;
  325. else if (!strncmp(temp_char, "yes", 3))
  326. action = 2;
  327. else if (!strcmp(temp_char, "exclusive"))
  328. action = 3;
  329. else
  330. action = 0;
  331. break;
  332. case SORTID_PART_STATE:
  333. if (!strcmp(temp_char, "up"))
  334. action = 0;
  335. else if (!strcmp(temp_char, "down"))
  336. action = 1;
  337. else if (!strcmp(temp_char, "inactive"))
  338. action = 2;
  339. else if (!strcmp(temp_char, "drain"))
  340. action = 3;
  341. else
  342. action = 0;
  343. break;
  344. case SORTID_NODE_STATE:
  345. if (!strcasecmp(temp_char, "drain"))
  346. action = 0;
  347. else if (!strcasecmp(temp_char, "resume"))
  348. action = 1;
  349. else
  350. for(i = 0; i < NODE_STATE_END; i++) {
  351. upper = node_state_string(i);
  352. if (!strcmp(upper, "UNKNOWN")) {
  353. unknown_found++;
  354. continue;
  355. }
  356. if (!strcasecmp(temp_char, upper)) {
  357. action = i + 2 - unknown_found;
  358. break;
  359. }
  360. }
  361. break;
  362. case SORTID_PREEMPT_MODE:
  363. if (!strcasecmp(temp_char, "cancel"))
  364. action = 0;
  365. else if (!strcasecmp(temp_char, "checkpoint"))
  366. action = 1;
  367. else if (!strcasecmp(temp_char, "off"))
  368. action = 2;
  369. else if (!strcasecmp(temp_char, "requeue"))
  370. action = 3;
  371. else if (!strcasecmp(temp_char, "suspend"))
  372. action = 4;
  373. else
  374. action = 2; /* off */
  375. break;
  376. default:
  377. break;
  378. }
  379. g_free(temp_char);
  380. end_it:
  381. gtk_combo_box_set_active(combo, action);
  382. }
  383. static uint16_t _set_part_share_popup()
  384. {
  385. GtkWidget *table = gtk_table_new(1, 2, FALSE);
  386. GtkWidget *label = NULL;
  387. GtkObject *adjustment = gtk_adjustment_new(4,
  388. 1, 1000,
  389. 1, 60,
  390. 0);
  391. GtkWidget *spin_button =
  392. gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 1, 0);
  393. GtkWidget *popup = gtk_dialog_new_with_buttons(
  394. "Count",
  395. GTK_WINDOW (main_window),
  396. GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
  397. NULL);
  398. int response = 0;
  399. uint16_t count = 4;
  400. label = gtk_dialog_add_button(GTK_DIALOG(popup),
  401. GTK_STOCK_OK, GTK_RESPONSE_OK);
  402. gtk_window_set_default(GTK_WINDOW(popup), label);
  403. label = gtk_label_new("Shared Job Count ");
  404. gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  405. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
  406. table, FALSE, FALSE, 0);
  407. gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
  408. gtk_table_attach_defaults(GTK_TABLE(table), spin_button, 1, 2, 0, 1);
  409. gtk_widget_show_all(popup);
  410. response = gtk_dialog_run (GTK_DIALOG(popup));
  411. if (response == GTK_RESPONSE_OK) {
  412. count = gtk_spin_button_get_value_as_int(
  413. GTK_SPIN_BUTTON(spin_button));
  414. }
  415. gtk_widget_destroy(popup);
  416. return count;
  417. }
  418. /* don't free this char */
  419. static const char *_set_part_msg(update_part_msg_t *part_msg,
  420. const char *new_text,
  421. int column)
  422. {
  423. char *type = "", *temp_char;
  424. int temp_int = 0;
  425. global_edit_error = 0;
  426. if (!part_msg)
  427. return NULL;
  428. switch(column) {
  429. case SORTID_ALTERNATE:
  430. type = "alternate";
  431. part_msg->alternate = xstrdup(new_text);
  432. break;
  433. case SORTID_DEFAULT:
  434. if (!strcasecmp(new_text, "yes")) {
  435. part_msg->flags |= PART_FLAG_DEFAULT;
  436. part_msg->flags &= (~PART_FLAG_DEFAULT_CLR);
  437. } else if (!strcasecmp(new_text, "no")) {
  438. part_msg->flags &= (~PART_FLAG_DEFAULT);
  439. part_msg->flags |= PART_FLAG_DEFAULT_CLR;
  440. }
  441. type = "default";
  442. break;
  443. case SORTID_GRACE_TIME:
  444. temp_int = time_str2mins((char *)new_text);
  445. type = "grace_time";
  446. if (temp_int <= 0)
  447. goto return_error;
  448. /* convert to seconds */
  449. part_msg->grace_time = (uint32_t)(temp_int * 60);
  450. break;
  451. case SORTID_HIDDEN:
  452. if (!strcasecmp(new_text, "yes")) {
  453. part_msg->flags |= PART_FLAG_HIDDEN;
  454. part_msg->flags &= (~PART_FLAG_HIDDEN_CLR);
  455. } else if (!strcasecmp(new_text, "no")) {
  456. part_msg->flags &= (~PART_FLAG_HIDDEN);
  457. part_msg->flags |= PART_FLAG_HIDDEN_CLR;
  458. }
  459. type = "hidden";
  460. break;
  461. case SORTID_TIMELIMIT:
  462. if ((strcasecmp(new_text, "infinite") == 0))
  463. temp_int = INFINITE;
  464. else
  465. temp_int = time_str2mins((char *)new_text);
  466. type = "timelimit";
  467. if ((temp_int <= 0) && (temp_int != INFINITE))
  468. goto return_error;
  469. part_msg->max_time = (uint32_t)temp_int;
  470. break;
  471. case SORTID_PREEMPT_MODE:
  472. if (!strcasecmp(new_text, "cancel"))
  473. part_msg->preempt_mode = PREEMPT_MODE_CANCEL;
  474. else if (!strcasecmp(new_text, "checkpoint"))
  475. part_msg->preempt_mode = PREEMPT_MODE_CHECKPOINT;
  476. else if (!strcasecmp(new_text, "off"))
  477. part_msg->preempt_mode = PREEMPT_MODE_OFF;
  478. else if (!strcasecmp(new_text, "requeue"))
  479. part_msg->preempt_mode = PREEMPT_MODE_REQUEUE;
  480. else if (!strcasecmp(new_text, "suspend"))
  481. part_msg->preempt_mode = PREEMPT_MODE_SUSPEND;
  482. type = "preempt_mode";
  483. break;
  484. case SORTID_PRIORITY:
  485. temp_int = strtol(new_text, (char **)NULL, 10);
  486. type = "priority";
  487. part_msg->priority = (uint16_t)temp_int;
  488. break;
  489. case SORTID_NAME:
  490. type = "name";
  491. part_msg->name = xstrdup(new_text);
  492. break;
  493. case SORTID_NODES_MIN:
  494. temp_int = strtol(new_text, (char **)NULL, 10);
  495. type = "min_nodes";
  496. if (temp_int <= 0)
  497. goto return_error;
  498. part_msg->min_nodes = (uint32_t)temp_int;
  499. break;
  500. case SORTID_NODES_MAX:
  501. if (!strcasecmp(new_text, "infinite")) {
  502. temp_int = INFINITE;
  503. } else {
  504. temp_int = strtol(new_text, &temp_char, 10);
  505. if ((temp_char[0] == 'k') || (temp_char[0] == 'K'))
  506. temp_int *= 1024;
  507. if ((temp_char[0] == 'm') || (temp_char[0] == 'M'))
  508. temp_int *= (1024 * 1024);
  509. }
  510. type = "max_nodes";
  511. if ((temp_int <= 0) && (temp_int != INFINITE))
  512. goto return_error;
  513. part_msg->max_nodes = (uint32_t)temp_int;
  514. break;
  515. case SORTID_ROOT:
  516. if (!strcasecmp(new_text, "yes")) {
  517. part_msg->flags |= PART_FLAG_ROOT_ONLY;
  518. part_msg->flags &= (~PART_FLAG_ROOT_ONLY_CLR);
  519. } else if (!strcasecmp(new_text, "no")) {
  520. part_msg->flags &= (~PART_FLAG_ROOT_ONLY);
  521. part_msg->flags |= PART_FLAG_ROOT_ONLY_CLR;
  522. }
  523. type = "root";
  524. break;
  525. case SORTID_SHARE:
  526. if (!strcasecmp(new_text, "yes")) {
  527. part_msg->max_share = _set_part_share_popup();
  528. } else if (!strcasecmp(new_text, "exclusive")) {
  529. part_msg->max_share = 0;
  530. } else if (!strcasecmp(new_text, "force")) {
  531. part_msg->max_share =
  532. _set_part_share_popup() | SHARED_FORCE;
  533. } else if (!strcasecmp(new_text, "no"))
  534. part_msg->max_share = 1;
  535. else
  536. goto return_error;
  537. type = "share";
  538. break;
  539. case SORTID_GROUPS:
  540. type = "groups";
  541. part_msg->allow_groups = xstrdup(new_text);
  542. break;
  543. case SORTID_NODES_ALLOWED:
  544. type = "allowed alloc nodes";
  545. part_msg->allow_alloc_nodes = xstrdup(new_text);
  546. break;
  547. case SORTID_NODELIST:
  548. part_msg->nodes = xstrdup(new_text);
  549. type = "nodelist";
  550. break;
  551. case SORTID_PART_STATE:
  552. if (!strcasecmp(new_text, "up"))
  553. part_msg->state_up = PARTITION_UP;
  554. else if (!strcasecmp(new_text, "down"))
  555. part_msg->state_up = PARTITION_DOWN;
  556. else if (!strcasecmp(new_text, "inactive"))
  557. part_msg->state_up = PARTITION_INACTIVE;
  558. else if (!strcasecmp(new_text, "drain"))
  559. part_msg->state_up = PARTITION_DRAIN;
  560. else
  561. goto return_error;
  562. type = "availability";
  563. break;
  564. case SORTID_NODE_STATE:
  565. type = (char *)new_text;
  566. got_edit_signal = xstrdup(new_text);
  567. break;
  568. case SORTID_FEATURES:
  569. type = "Update Features";
  570. got_features_edit_signal = xstrdup(new_text);
  571. break;
  572. default:
  573. type = "unknown";
  574. break;
  575. }
  576. if (strcmp(type, "unknown"))
  577. global_send_update_msg = 1;
  578. return type;
  579. return_error:
  580. global_edit_error = 1;
  581. return type;
  582. }
  583. static void _admin_edit_combo_box_part(GtkComboBox *combo,
  584. update_part_msg_t *part_msg)
  585. {
  586. GtkTreeModel *model = NULL;
  587. GtkTreeIter iter;
  588. int column = 0;
  589. char *name = NULL;
  590. if (!part_msg)
  591. return;
  592. if (!gtk_combo_box_get_active_iter(combo, &iter)) {
  593. g_print("nothing selected\n");
  594. return;
  595. }
  596. model = gtk_combo_box_get_model(combo);
  597. if (!model) {
  598. g_print("nothing selected\n");
  599. return;
  600. }
  601. gtk_tree_model_get(model, &iter, 0, &name, -1);
  602. gtk_tree_model_get(model, &iter, 1, &column, -1);
  603. (void) _set_part_msg(part_msg, name, column);
  604. if (name)
  605. g_free(name);
  606. }
  607. static gboolean _admin_focus_out_part(GtkEntry *entry,
  608. GdkEventFocus *event,
  609. update_part_msg_t *part_msg)
  610. {
  611. if (global_entry_changed) {
  612. const char *col_name = NULL;
  613. int type = gtk_entry_get_max_length(entry);
  614. const char *name = gtk_entry_get_text(entry);
  615. type -= DEFAULT_ENTRY_LENGTH;
  616. col_name = _set_part_msg(part_msg, name, type);
  617. if (global_edit_error) {
  618. if (global_edit_error_msg)
  619. g_free(global_edit_error_msg);
  620. global_edit_error_msg = g_strdup_printf(
  621. "Partition %s %s can't be set to %s",
  622. part_msg->name,
  623. col_name,
  624. name);
  625. }
  626. global_entry_changed = 0;
  627. }
  628. return false;
  629. }
  630. static GtkWidget *_admin_full_edit_part(update_part_msg_t *part_msg,
  631. GtkTreeModel *model, GtkTreeIter *iter)
  632. {
  633. GtkScrolledWindow *window = create_scrolled_window();
  634. GtkBin *bin = NULL;
  635. GtkViewport *view = NULL;
  636. GtkTable *table = NULL;
  637. int i = 0, row = 0;
  638. display_data_t *display_data = display_data_part;
  639. gtk_scrolled_window_set_policy(window,
  640. GTK_POLICY_NEVER,
  641. GTK_POLICY_AUTOMATIC);
  642. bin = GTK_BIN(&window->container);
  643. view = GTK_VIEWPORT(bin->child);
  644. bin = GTK_BIN(&view->bin);
  645. table = GTK_TABLE(bin->child);
  646. gtk_table_resize(table, SORTID_CNT, 2);
  647. gtk_table_set_homogeneous(table, FALSE);
  648. for(i = 0; i < SORTID_CNT; i++) {
  649. while (display_data++) {
  650. if (display_data->id == -1)
  651. break;
  652. if (!display_data->name)
  653. continue;
  654. if (display_data->id != i)
  655. continue;
  656. display_admin_edit(
  657. table, part_msg, &row, model, iter,
  658. display_data,
  659. G_CALLBACK(_admin_edit_combo_box_part),
  660. G_CALLBACK(_admin_focus_out_part),
  661. _set_active_combo_part);
  662. break;
  663. }
  664. display_data = display_data_part;
  665. }
  666. gtk_table_resize(table, row, 2);
  667. return GTK_WIDGET(window);
  668. }
  669. static void _subdivide_part(sview_part_info_t *sview_part_info,
  670. GtkTreeModel *model,
  671. GtkTreeIter *sub_iter,
  672. GtkTreeIter *iter)
  673. {
  674. GtkTreeIter first_sub_iter;
  675. ListIterator itr = NULL;
  676. int i = 0, line = 0;
  677. sview_part_sub_t *sview_part_sub = NULL;
  678. int set = 0;
  679. memset(&first_sub_iter, 0, sizeof(GtkTreeIter));
  680. /* make sure all the steps are still here */
  681. if (sub_iter) {
  682. first_sub_iter = *sub_iter;
  683. while (1) {
  684. gtk_tree_store_set(GTK_TREE_STORE(model), sub_iter,
  685. SORTID_UPDATED, 0, -1);
  686. if (!gtk_tree_model_iter_next(model, sub_iter)) {
  687. break;
  688. }
  689. }
  690. memcpy(sub_iter, &first_sub_iter, sizeof(GtkTreeIter));
  691. set = 1;
  692. }
  693. itr = list_iterator_create(sview_part_info->sub_list);
  694. if (list_count(sview_part_info->sub_list) == 1) {
  695. gtk_tree_store_set(GTK_TREE_STORE(model), iter,
  696. SORTID_ONLY_LINE, 1, -1);
  697. sview_part_sub = list_next(itr);
  698. _update_part_sub_record(sview_part_sub,
  699. GTK_TREE_STORE(model),
  700. iter);
  701. } else {
  702. while ((sview_part_sub = list_next(itr))) {
  703. if (!sub_iter) {
  704. i = NO_VAL;
  705. goto adding;
  706. } else {
  707. memcpy(sub_iter, &first_sub_iter,
  708. sizeof(GtkTreeIter));
  709. }
  710. line = 0;
  711. while (1) {
  712. int state;
  713. /* Search for the state number and
  714. check to see if it is in the
  715. list. Here we need to pass an int
  716. for system where endian is an
  717. issue passing a uint16_t may seg
  718. fault. */
  719. gtk_tree_model_get(model, sub_iter,
  720. SORTID_NODE_STATE_NUM,
  721. &state, -1);
  722. if ((uint16_t)state
  723. == sview_part_sub->node_state) {
  724. /* update with new info */
  725. _update_part_sub_record(
  726. sview_part_sub,
  727. GTK_TREE_STORE(model),
  728. sub_iter);
  729. goto found;
  730. }
  731. line++;
  732. if (!gtk_tree_model_iter_next(model,
  733. sub_iter)) {
  734. break;
  735. }
  736. }
  737. adding:
  738. _append_part_sub_record(sview_part_sub,
  739. GTK_TREE_STORE(model),
  740. iter, line);
  741. /* if (i == NO_VAL) */
  742. /* line++; */
  743. found:
  744. ;
  745. }
  746. }
  747. list_iterator_destroy(itr);
  748. if (set) {
  749. sub_iter = &first_sub_iter;
  750. /* clear all steps that aren't active */
  751. while (1) {
  752. gtk_tree_model_get(model, sub_iter,
  753. SORTID_UPDATED, &i, -1);
  754. if (!i) {
  755. if (!gtk_tree_store_remove(
  756. GTK_TREE_STORE(model),
  757. sub_iter))
  758. break;
  759. else
  760. continue;
  761. }
  762. if (!gtk_tree_model_iter_next(model, sub_iter)) {
  763. break;
  764. }
  765. }
  766. }
  767. return;
  768. }
  769. static void _layout_part_record(GtkTreeView *treeview,
  770. sview_part_info_t *sview_part_info,
  771. int update)
  772. {
  773. GtkTreeIter iter;
  774. char time_buf[20], tmp_buf[20];
  775. char tmp_cnt[8];
  776. char tmp_cnt1[8];
  777. char tmp_cnt2[8];
  778. partition_info_t *part_ptr = sview_part_info->part_ptr;
  779. sview_part_sub_t *sview_part_sub = NULL;
  780. char ind_cnt[1024];
  781. char *temp_char = NULL;
  782. uint16_t temp_uint16 = 0;
  783. int i;
  784. int yes_no = -1;
  785. int up_down = -1;
  786. uint32_t limit_set = NO_VAL;
  787. GtkTreeStore *treestore =
  788. GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
  789. convert_num_unit((float)sview_part_info->sub_part_total.cpu_alloc_cnt
  790. / cpus_per_node,
  791. tmp_cnt, sizeof(tmp_cnt), UNIT_NONE);
  792. convert_num_unit((float)sview_part_info->sub_part_total.cpu_idle_cnt
  793. / cpus_per_node,
  794. tmp_cnt1, sizeof(tmp_cnt1), UNIT_NONE);
  795. convert_num_unit((float)sview_part_info->sub_part_total.cpu_error_cnt
  796. / cpus_per_node,
  797. tmp_cnt2, sizeof(tmp_cnt2), UNIT_NONE);
  798. snprintf(ind_cnt, sizeof(ind_cnt), "%s/%s/%s",
  799. tmp_cnt, tmp_cnt1, tmp_cnt2);
  800. for (i = 0; i < SORTID_CNT; i++) {
  801. switch (i) {
  802. case SORTID_PART_STATE:
  803. switch(part_ptr->state_up) {
  804. case PARTITION_UP:
  805. temp_char = "up";
  806. break;
  807. case PARTITION_DOWN:
  808. temp_char = "down";
  809. break;
  810. case PARTITION_INACTIVE:
  811. temp_char = "inactive";
  812. break;
  813. case PARTITION_DRAIN:
  814. temp_char = "drain";
  815. break;
  816. default:
  817. temp_char = "unknown";
  818. break;
  819. }
  820. break;
  821. case SORTID_ALTERNATE:
  822. if (part_ptr->alternate)
  823. temp_char = part_ptr->alternate;
  824. else
  825. temp_char = "";
  826. break;
  827. case SORTID_CPUS:
  828. convert_num_unit((float)part_ptr->total_cpus,
  829. tmp_cnt, sizeof(tmp_cnt),
  830. UNIT_NONE);
  831. temp_char = tmp_cnt;
  832. break;
  833. case SORTID_DEFAULT:
  834. if (part_ptr->flags & PART_FLAG_DEFAULT)
  835. yes_no = 1;
  836. else
  837. yes_no = 0;
  838. break;
  839. case SORTID_FEATURES:
  840. if (sview_part_sub)
  841. temp_char = sview_part_sub->features;
  842. else
  843. temp_char = "";
  844. break;
  845. case SORTID_GRACE_TIME:
  846. limit_set = part_ptr->grace_time;
  847. break;
  848. case SORTID_GROUPS:
  849. if (part_ptr->allow_groups)
  850. temp_char = part_ptr->allow_groups;
  851. else
  852. temp_char = "all";
  853. break;
  854. case SORTID_HIDDEN:
  855. if (part_ptr->flags & PART_FLAG_HIDDEN)
  856. yes_no = 1;
  857. else
  858. yes_no = 0;
  859. break;
  860. case SORTID_JOB_SIZE:
  861. _build_min_max_32_string(time_buf, sizeof(time_buf),
  862. part_ptr->min_nodes,
  863. part_ptr->max_nodes, true);
  864. temp_char = time_buf;
  865. break;
  866. case SORTID_MEM:
  867. convert_num_unit((float)sview_part_info->
  868. sub_part_total.mem_total,
  869. tmp_cnt, sizeof(tmp_cnt),
  870. UNIT_MEGA);
  871. temp_char = tmp_cnt;
  872. break;
  873. case SORTID_NODELIST:
  874. temp_char = part_ptr->nodes;
  875. break;
  876. case SORTID_NODES_ALLOWED:
  877. temp_char = part_ptr->allow_alloc_nodes;
  878. break;
  879. case SORTID_NODES:
  880. if (cluster_flags & CLUSTER_FLAG_BG)
  881. convert_num_unit((float)part_ptr->total_nodes,
  882. tmp_cnt,
  883. sizeof(tmp_cnt), UNIT_NONE);
  884. else
  885. sprintf(tmp_cnt, "%u", part_ptr->total_nodes);
  886. temp_char = tmp_cnt;
  887. break;
  888. case SORTID_NODES_MAX:
  889. limit_set = part_ptr->max_nodes;
  890. break;
  891. case SORTID_NODES_MIN:
  892. limit_set = part_ptr->min_nodes;
  893. break;
  894. case SORTID_NODE_INX:
  895. break;
  896. case SORTID_ONLY_LINE:
  897. break;
  898. case SORTID_PREEMPT_MODE:
  899. temp_uint16 = part_ptr->preempt_mode;
  900. if (temp_uint16 == (uint16_t) NO_VAL)
  901. temp_uint16 = slurm_get_preempt_mode();
  902. temp_char = preempt_mode_string(temp_uint16);
  903. break;
  904. case SORTID_PRIORITY:
  905. convert_num_unit((float)part_ptr->priority,
  906. time_buf, sizeof(time_buf), UNIT_NONE);
  907. temp_char = time_buf;
  908. break;
  909. case SORTID_REASON:
  910. sview_part_sub = list_peek(sview_part_info->sub_list);
  911. if (sview_part_sub)
  912. temp_char = sview_part_sub->reason;
  913. else
  914. temp_char = "";
  915. break;
  916. case SORTID_ROOT:
  917. if (part_ptr->flags & PART_FLAG_ROOT_ONLY)
  918. yes_no = 1;
  919. else
  920. yes_no = 0;
  921. break;
  922. case SORTID_SHARE:
  923. if (part_ptr->max_share & SHARED_FORCE) {
  924. snprintf(tmp_buf, sizeof(tmp_buf), "force:%u",
  925. (part_ptr->max_share
  926. & ~(SHARED_FORCE)));
  927. temp_char = tmp_buf;
  928. } else if (part_ptr->max_share == 0)
  929. temp_char = "exclusive";
  930. else if (part_ptr->max_share > 1) {
  931. snprintf(tmp_buf, sizeof(tmp_buf), "yes:%u",
  932. part_ptr->max_share);
  933. temp_char = tmp_buf;
  934. } else
  935. temp_char = "no";
  936. break;
  937. case SORTID_TMP_DISK:
  938. convert_num_unit(
  939. (float)sview_part_info->sub_part_total.
  940. disk_total,
  941. time_buf, sizeof(time_buf), UNIT_NONE);
  942. temp_char = time_buf;
  943. break;
  944. case SORTID_TIMELIMIT:
  945. limit_set = part_ptr->max_time;
  946. break;
  947. default:
  948. break;
  949. }
  950. if (up_down != -1) {
  951. if (up_down)
  952. temp_char = "up";
  953. else
  954. temp_char = "down";
  955. up_down = -1;
  956. } if (yes_no != -1) {
  957. if (yes_no)
  958. temp_char = "yes";
  959. else
  960. temp_char = "no";
  961. yes_no = -1;
  962. } else if (limit_set != NO_VAL) {
  963. if (limit_set == (uint32_t) INFINITE)
  964. temp_char = "infinite";
  965. else {
  966. convert_num_unit(
  967. (float)limit_set,
  968. time_buf, sizeof(time_buf), UNIT_NONE);
  969. temp_char = time_buf;
  970. }
  971. limit_set = NO_VAL;
  972. }
  973. if (temp_char) {
  974. add_display_treestore_line(
  975. update, treestore, &iter,
  976. find_col_name(display_data_part,
  977. i),
  978. temp_char);
  979. if (i == SORTID_NODES) {
  980. add_display_treestore_line(
  981. update, treestore, &iter,
  982. "Nodes (Allocated/Idle/Other)",
  983. ind_cnt);
  984. }
  985. temp_char = NULL;
  986. }
  987. }
  988. }
  989. static void _update_part_record(sview_part_info_t *sview_part_info,
  990. GtkTreeStore *treestore)
  991. {
  992. char tmp_prio[40], tmp_size[40], tmp_share_buf[40], tmp_time[40];
  993. char tmp_max_nodes[40], tmp_min_nodes[40], tmp_grace[40];
  994. char tmp_cpu_cnt[40], tmp_node_cnt[40];
  995. char *tmp_alt, *tmp_default, *tmp_groups, *tmp_hidden;
  996. char *tmp_root, *tmp_share, *tmp_state;
  997. uint16_t tmp_preempt;
  998. partition_info_t *part_ptr = sview_part_info->part_ptr;
  999. GtkTreeIter sub_iter;
  1000. if (part_ptr->alternate)
  1001. tmp_alt = part_ptr->alternate;
  1002. else
  1003. tmp_alt = "";
  1004. if (cluster_flags & CLUSTER_FLAG_BG)
  1005. convert_num_unit((float)part_ptr->total_cpus, tmp_cpu_cnt,
  1006. sizeof(tmp_cpu_cnt), UNIT_NONE);
  1007. else
  1008. sprintf(tmp_cpu_cnt, "%u", part_ptr->total_cpus);
  1009. if (part_ptr->flags & PART_FLAG_DEFAULT)
  1010. tmp_default = "yes";
  1011. else
  1012. tmp_default = "no";
  1013. if (part_ptr->allow_groups)
  1014. tmp_groups = part_ptr->allow_groups;
  1015. else
  1016. tmp_groups = "all";
  1017. if (part_ptr->flags & PART_FLAG_HIDDEN)
  1018. tmp_hidden = "yes";
  1019. else
  1020. tmp_hidden = "no";
  1021. if (part_ptr->grace_time == (uint32_t) NO_VAL)
  1022. snprintf(tmp_grace, sizeof(tmp_grace), "none");
  1023. else {
  1024. secs2time_str(part_ptr->grace_time,
  1025. tmp_grace, sizeof(tmp_grace));
  1026. }
  1027. if (part_ptr->max_nodes == (uint32_t) INFINITE)
  1028. snprintf(tmp_max_nodes, sizeof(tmp_max_nodes), "infinite");
  1029. else {
  1030. convert_num_unit((float)part_ptr->max_nodes,
  1031. tmp_max_nodes, sizeof(tmp_max_nodes),
  1032. UNIT_NONE);
  1033. }
  1034. if (part_ptr->min_nodes == (uint32_t) INFINITE)
  1035. snprintf(tmp_min_nodes, sizeof(tmp_min_nodes), "infinite");
  1036. else {
  1037. convert_num_unit((float)part_ptr->min_nodes,
  1038. tmp_min_nodes, sizeof(tmp_min_nodes), UNIT_NONE);
  1039. }
  1040. if (cluster_flags & CLUSTER_FLAG_BG)
  1041. convert_num_unit((float)part_ptr->total_nodes, tmp_node_cnt,
  1042. sizeof(tmp_node_cnt), UNIT_NONE);
  1043. else
  1044. sprintf(tmp_node_cnt, "%u", part_ptr->total_nodes);
  1045. if (part_ptr->flags & PART_FLAG_ROOT_ONLY)
  1046. tmp_root = "yes";
  1047. else
  1048. tmp_root = "no";
  1049. if (part_ptr->state_up == PARTITION_UP)
  1050. tmp_state = "up";
  1051. else if (part_ptr->state_up == PARTITION_DOWN)
  1052. tmp_state = "down";
  1053. else if (part_ptr->state_up == PARTITION_INACTIVE)
  1054. tmp_state = "inact";
  1055. else if (part_ptr->state_up == PARTITION_DRAIN)
  1056. tmp_state = "drain";
  1057. else
  1058. tmp_state = "unk";
  1059. _build_min_max_32_string(tmp_size, sizeof(tmp_size),
  1060. part_ptr->min_nodes,
  1061. part_ptr->max_nodes, true);
  1062. tmp_preempt = part_ptr->preempt_mode;
  1063. if (tmp_preempt == (uint16_t) NO_VAL)
  1064. tmp_preempt = slurm_get_preempt_mode(); /* use cluster param */
  1065. convert_num_unit((float)part_ptr->priority,
  1066. tmp_prio, sizeof(tmp_prio), UNIT_NONE);
  1067. if (part_ptr->max_share & SHARED_FORCE) {
  1068. snprintf(tmp_share_buf, sizeof(tmp_share_buf), "force:%u",
  1069. (part_ptr->max_share & ~(SHARED_FORCE)));
  1070. tmp_share = tmp_share_buf;
  1071. } else if (part_ptr->max_share == 0) {
  1072. tmp_share = "exclusive";
  1073. } else if (part_ptr->max_share > 1) {
  1074. snprintf(tmp_share_buf, sizeof(tmp_share_buf), "yes:%u",
  1075. part_ptr->max_share);
  1076. tmp_share = tmp_share_buf;
  1077. } else
  1078. tmp_share = "no";
  1079. if (part_ptr->max_time == INFINITE)
  1080. snprintf(tmp_time, sizeof(tmp_time), "infinite");
  1081. else {
  1082. secs2time_str((part_ptr->max_time * 60),
  1083. tmp_time, sizeof(tmp_time));
  1084. }
  1085. /* Combining these records provides a slight performance improvement
  1086. * NOTE: Some of these fields are cleared here and filled in based upon
  1087. * the configuration of nodes within this partition. */
  1088. gtk_tree_store_set(treestore, &sview_part_info->iter_ptr,
  1089. SORTID_ALTERNATE, tmp_alt,
  1090. SORTID_COLOR,
  1091. sview_colors[sview_part_info->color_inx],
  1092. SORTID_COLOR_INX, sview_part_info->color_inx,
  1093. SORTID_CPUS, tmp_cpu_cnt,
  1094. SORTID_DEFAULT, tmp_default,
  1095. SORTID_FEATURES, "",
  1096. SORTID_GRACE_TIME, tmp_grace,
  1097. SORTID_GROUPS, tmp_groups,
  1098. SORTID_HIDDEN, tmp_hidden,
  1099. SORTID_JOB_SIZE, tmp_size,
  1100. SORTID_MEM, "",
  1101. SORTID_NAME, part_ptr->name,
  1102. SORTID_NODE_INX, part_ptr->node_inx,
  1103. SORTID_NODE_STATE, "",
  1104. SORTID_NODE_STATE_NUM, -1,
  1105. SORTID_NODES, tmp_node_cnt,
  1106. SORTID_NODES_MAX, tmp_max_nodes,
  1107. SORTID_NODES_MIN, tmp_min_nodes,
  1108. SORTID_NODELIST, part_ptr->nodes,
  1109. SORTID_ONLY_LINE, 0,
  1110. SORTID_PART_STATE, tmp_state,
  1111. SORTID_PREEMPT_MODE,
  1112. preempt_mode_string(tmp_preempt),
  1113. SORTID_PRIORITY, tmp_prio,
  1114. SORTID_REASON, "",
  1115. SORTID_ROOT, tmp_root,
  1116. SORTID_SHARE, tmp_share,
  1117. SORTID_TIMELIMIT, tmp_time,
  1118. SORTID_TMP_DISK, "",
  1119. SORTID_UPDATED, 1,
  1120. -1);
  1121. if (gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore),
  1122. &sub_iter,
  1123. &sview_part_info->iter_ptr))
  1124. _subdivide_part(sview_part_info,
  1125. GTK_TREE_MODEL(treestore), &sub_iter,
  1126. &sview_part_info->iter_ptr);
  1127. else
  1128. _subdivide_part(sview_part_info,
  1129. GTK_TREE_MODEL(treestore), NULL,
  1130. &sview_part_info->iter_ptr);
  1131. return;
  1132. }
  1133. static void _update_part_sub_record(sview_part_sub_t *sview_part_sub,
  1134. GtkTreeStore *treestore, GtkTreeIter *iter)
  1135. {
  1136. partition_info_t *part_ptr = sview_part_sub->part_ptr;
  1137. char *tmp_cpus = NULL, *tmp_nodes = NULL, *tmp_nodelist;
  1138. char *tmp_state_lower, *tmp_state_upper;
  1139. char tmp_cnt[40], tmp_disk[40], tmp_mem[40];
  1140. tmp_state_upper = node_state_string(sview_part_sub->node_state);
  1141. tmp_state_lower = str_tolower(tmp_state_upper);
  1142. if ((sview_part_sub->node_state & NODE_STATE_BASE)
  1143. == NODE_STATE_MIXED) {
  1144. if (sview_part_sub->cpu_alloc_cnt) {
  1145. convert_num_unit((float)sview_part_sub->cpu_alloc_cnt,
  1146. tmp_cnt,
  1147. sizeof(tmp_cnt), UNIT_NONE);
  1148. xstrfmtcat(tmp_cpus, "Alloc:%s", tmp_cnt);
  1149. if (cluster_flags & CLUSTER_FLAG_BG) {
  1150. convert_num_unit(
  1151. (float)(sview_part_sub->cpu_alloc_cnt
  1152. / cpus_per_node),
  1153. tmp_cnt,
  1154. sizeof(tmp_cnt), UNIT_NONE);
  1155. xstrfmtcat(tmp_nodes, "Alloc:%s", tmp_cnt);
  1156. }
  1157. }
  1158. if (sview_part_sub->cpu_error_cnt) {
  1159. convert_num_unit((float)sview_part_sub->cpu_error_cnt,
  1160. tmp_cnt,
  1161. sizeof(tmp_cnt), UNIT_NONE);
  1162. if (tmp_cpus)
  1163. xstrcat(tmp_cpus, " ");
  1164. xstrfmtcat(tmp_cpus, "Err:%s", tmp_cnt);
  1165. if (cluster_flags & CLUSTER_FLAG_BG) {
  1166. convert_num_unit(
  1167. (float)(sview_part_sub->cpu_error_cnt
  1168. / cpus_per_node),
  1169. tmp_cnt,
  1170. sizeof(tmp_cnt), UNIT_NONE);
  1171. if (tmp_nodes)
  1172. xstrcat(tmp_nodes, " ");
  1173. xstrfmtcat(tmp_nodes, "Err:%s", tmp_cnt);
  1174. }
  1175. }
  1176. if (sview_part_sub->cpu_idle_cnt) {
  1177. convert_num_unit((float)sview_part_sub->cpu_idle_cnt,
  1178. tmp_cnt,
  1179. sizeof(tmp_cnt), UNIT_NONE);
  1180. if (tmp_cpus)
  1181. xstrcat(tmp_cpus, " ");
  1182. xstrfmtcat(tmp_cpus, "Idle:%s", tmp_cnt);
  1183. if (cluster_flags & CLUSTER_FLAG_BG) {
  1184. convert_num_unit(
  1185. (float)(sview_part_sub->cpu_idle_cnt
  1186. / cpus_per_node),
  1187. tmp_cnt,
  1188. sizeof(tmp_cnt), UNIT_NONE);
  1189. if (tmp_nodes)
  1190. xstrcat(tmp_nodes, " ");
  1191. xstrfmtcat(tmp_nodes, "Idle:%s", tmp_cnt);
  1192. }
  1193. }
  1194. } else {
  1195. tmp_cpus = xmalloc(20);
  1196. convert_num_unit((float)sview_part_sub->cpu_idle_cnt,
  1197. tmp_cpus, 20, UNIT_NONE);
  1198. }
  1199. if (!tmp_nodes) {
  1200. convert_num_unit((float)sview_part_sub->node_cnt, tmp_cnt,
  1201. sizeof(tmp_cnt), UNIT_NONE);
  1202. tmp_nodes = xstrdup(tmp_cnt);
  1203. }
  1204. convert_num_unit((float)sview_part_sub->disk_total, tmp_disk,
  1205. sizeof(tmp_disk), UNIT_NONE);
  1206. convert_num_unit((float)sview_part_sub->mem_total, tmp_mem,
  1207. sizeof(tmp_mem), UNIT_MEGA);
  1208. tmp_nodelist = hostlist_ranged_string_xmalloc(sview_part_sub->hl);
  1209. gtk_tree_store_set(treestore, iter,
  1210. SORTID_CPUS, tmp_cpus,
  1211. SORTID_FEATURES, sview_part_sub->features,
  1212. SORTID_MEM, tmp_mem,
  1213. SORTID_NAME, part_ptr->name,
  1214. SORTID_NODE_STATE_NUM, sview_part_sub->node_state,
  1215. SORTID_NODELIST, tmp_nodelist,
  1216. SORTID_NODES, tmp_nodes,
  1217. SORTID_NODE_STATE, tmp_state_lower,
  1218. SORTID_REASON, sview_part_sub->reason,
  1219. SORTID_TMP_DISK, tmp_disk,
  1220. SORTID_UPDATED, 1,
  1221. -1);
  1222. xfree(tmp_cpus);
  1223. xfree(tmp_nodelist);
  1224. xfree(tmp_nodes);
  1225. xfree(tmp_state_lower);
  1226. return;
  1227. }
  1228. static void _append_part_record(sview_part_info_t *sview_part_info,
  1229. GtkTreeStore *treestore)
  1230. {
  1231. gtk_tree_store_append(treestore, &sview_part_info->iter_ptr, NULL);
  1232. gtk_tree_store_set(treestore, &sview_part_info->iter_ptr,
  1233. SORTID_POS, sview_part_info->pos, -1);
  1234. _update_part_record(sview_part_info, treestore);
  1235. }
  1236. static void _append_part_sub_record(sview_part_sub_t *sview_part_sub,
  1237. GtkTreeStore *treestore, GtkTreeIter *iter,
  1238. int line)
  1239. {
  1240. GtkTreeIter sub_iter;
  1241. gtk_tree_store_append(treestore, &sub_iter, iter);
  1242. gtk_tree_store_set(treestore, &sub_iter, SORTID_POS, line, -1);
  1243. _update_part_sub_record(sview_part_sub, treestore, &sub_iter);
  1244. }
  1245. static void _update_info_part(List info_list,
  1246. GtkTreeView *tree_view)
  1247. {
  1248. GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  1249. static GtkTreeModel *last_model = NULL;
  1250. partition_info_t *part_ptr = NULL;
  1251. char *name = NULL;
  1252. ListIterator itr = NULL;
  1253. sview_part_info_t *sview_part_info = NULL;
  1254. set_for_update(model, SORTID_UPDATED);
  1255. itr = list_iterator_create(info_list);
  1256. while ((sview_part_info = (sview_part_info_t*) list_next(itr))) {
  1257. part_ptr = sview_part_info->part_ptr;
  1258. /* This means the tree_store changed (added new column
  1259. or something). */
  1260. if (last_model != model)
  1261. sview_part_info->iter_set = false;
  1262. if (sview_part_info->iter_set) {
  1263. gtk_tree_model_get(model, &sview_part_info->iter_ptr,
  1264. SORTID_NAME, &name, -1);
  1265. if (strcmp(name, part_ptr->name)) /* Bad pointer */
  1266. sview_part_info->iter_set = false;
  1267. g_free(name);
  1268. }
  1269. if (sview_part_info->iter_set)
  1270. _update_part_record(sview_part_info,
  1271. GTK_TREE_STORE(model));
  1272. else {
  1273. GtkTreePath *path = gtk_tree_path_new_first();
  1274. /* get the iter, or find out the list is empty
  1275. * goto add */
  1276. if (gtk_tree_model_get_iter(
  1277. model, &sview_part_info->iter_ptr, path)) {
  1278. do {
  1279. /* search for the jobid and
  1280. check to see if it is in
  1281. the list */
  1282. gtk_tree_model_get(
  1283. model,
  1284. &sview_part_info->iter_ptr,
  1285. SORTID_NAME,
  1286. &name, -1);
  1287. if (!strcmp(name, part_ptr->name)) {
  1288. /* update with new info */
  1289. g_free(name);
  1290. _update_part_record(
  1291. sview_part_info,
  1292. GTK_TREE_STORE(model));
  1293. sview_part_info->iter_set = 1;
  1294. break;
  1295. }
  1296. g_free(name);
  1297. } while (gtk_tree_model_iter_next(
  1298. model,
  1299. &sview_part_info->iter_ptr));
  1300. }
  1301. if (!sview_part_info->iter_set) {
  1302. _append_part_record(sview_part_info,
  1303. GTK_TREE_STORE(model));
  1304. sview_part_info->iter_set = true;
  1305. }
  1306. gtk_tree_path_free(path);
  1307. }
  1308. }
  1309. list_iterator_destroy(itr);
  1310. /* remove all old partitions */
  1311. remove_old(model, SORTID_UPDATED);
  1312. last_model = model;
  1313. return;
  1314. }
  1315. static void _part_info_list_del(void *object)
  1316. {
  1317. sview_part_info_t *sview_part_info = (sview_part_info_t *)object;
  1318. if (sview_part_info) {
  1319. if (sview_part_info->sub_list)
  1320. list_destroy(sview_part_info->sub_list);
  1321. xfree(sview_part_info);
  1322. }
  1323. }
  1324. static void _destroy_part_sub(void *object)
  1325. {
  1326. sview_part_sub_t *sview_part_sub = (sview_part_sub_t *)object;
  1327. if (sview_part_sub) {
  1328. xfree(sview_part_sub->features);
  1329. xfree(sview_part_sub->reason);
  1330. if (sview_part_sub->hl)
  1331. hostlist_destroy(sview_part_sub->hl);
  1332. if (sview_part_sub->node_ptr_list)
  1333. list_destroy(sview_part_sub->node_ptr_list);
  1334. xfree(sview_part_sub);
  1335. }
  1336. }
  1337. static void _update_sview_part_sub(sview_part_sub_t *sview_part_sub,
  1338. node_info_t *node_ptr,
  1339. int node_scaling)
  1340. {
  1341. int cpus_per_node = 1;
  1342. int idle_cpus = node_ptr->cpus;
  1343. uint16_t err_cpus = 0, alloc_cpus = 0;
  1344. if (node_scaling)
  1345. cpus_per_node = node_ptr->cpus / node_scaling;
  1346. xassert(sview_part_sub);
  1347. xassert(sview_part_sub->node_ptr_list);
  1348. xassert(sview_part_sub->hl);
  1349. if (sview_part_sub->node_cnt == 0) { /* first node added */
  1350. sview_part_sub->node_state = node_ptr->node_state;
  1351. sview_part_sub->features = xstrdup(node_ptr->features);
  1352. sview_part_sub->reason = xstrdup(node_ptr->reason);
  1353. } else if (hostlist_find(sview_part_sub->hl, node_ptr->name) != -1) {
  1354. /* we already have this node in this record,
  1355. * just return, don't duplicate */
  1356. g_print("already been here\n");
  1357. return;
  1358. }
  1359. if ((sview_part_sub->node_state & NODE_STATE_BASE)
  1360. == NODE_STATE_MIXED) {
  1361. slurm_get_select_nodeinfo(node_ptr->select_nodeinfo,
  1362. SELECT_NODEDATA_SUBCNT,
  1363. NODE_STATE_ALLOCATED,
  1364. &alloc_cpus);
  1365. if (cluster_flags & CLUSTER_FLAG_BG) {
  1366. if (!alloc_cpus
  1367. && (IS_NODE_ALLOCATED(node_ptr)
  1368. || IS_NODE_COMPLETING(node_ptr)))
  1369. alloc_cpus = node_ptr->cpus;
  1370. else
  1371. alloc_cpus *= cpus_per_node;
  1372. }
  1373. idle_cpus -= alloc_cpus;
  1374. slurm_get_select_nodeinfo(node_ptr->select_nodeinfo,
  1375. SELECT_NODEDATA_SUBCNT,
  1376. NODE_STATE_ERROR,
  1377. &err_cpus);
  1378. if (cluster_flags & CLUSTER_FLAG_BG)
  1379. err_cpus *= cpus_per_node;
  1380. idle_cpus -= err_cpus;
  1381. } else if (sview_part_sub->node_state == NODE_STATE_ALLOCATED) {
  1382. alloc_cpus = idle_cpus;
  1383. idle_cpus = 0;
  1384. } else if (sview_part_sub->node_state != NODE_STATE_IDLE) {
  1385. err_cpus = idle_cpus;
  1386. idle_cpus = 0;
  1387. }
  1388. sview_part_sub->cpu_alloc_cnt += alloc_cpus;
  1389. sview_part_sub->cpu_error_cnt += err_cpus;
  1390. sview_part_sub->cpu_idle_cnt += idle_cpus;
  1391. sview_part_sub->disk_total += node_ptr->tmp_disk;
  1392. sview_part_sub->mem_total += node_ptr->real_memory;
  1393. sview_part_sub->node_cnt += node_scaling;
  1394. list_append(sview_part_sub->node_ptr_list, node_ptr);
  1395. hostlist_push(sview_part_sub->hl, node_ptr->name);
  1396. }
  1397. /*
  1398. * _create_sview_part_sub - create an sview_part_sub record for
  1399. * the given partition
  1400. * sview_part_sub OUT - ptr to an inited sview_part_sub_t
  1401. */
  1402. static sview_part_sub_t *_create_sview_part_sub(partition_info_t *part_ptr,
  1403. node_info_t *node_ptr,
  1404. int node_scaling)
  1405. {
  1406. sview_part_sub_t *sview_part_sub_ptr =
  1407. xmalloc(sizeof(sview_part_sub_t));
  1408. if (!part_ptr) {
  1409. g_print("got no part_ptr!\n");
  1410. xfree(sview_part_sub_ptr);
  1411. return NULL;
  1412. }
  1413. if (!node_ptr) {
  1414. g_print("got no node_ptr!\n");
  1415. xfree(sview_part_sub_ptr);
  1416. return NULL;
  1417. }
  1418. sview_part_sub_ptr->part_ptr = part_ptr;
  1419. sview_part_sub_ptr->hl = hostlist_create("");
  1420. sview_part_sub_ptr->node_ptr_list = list_create(NULL);
  1421. _update_sview_part_sub(sview_part_sub_ptr, node_ptr, node_scaling);
  1422. return sview_part_sub_ptr;
  1423. }
  1424. static int _insert_sview_part_sub(sview_part_info_t *sview_part_info,
  1425. partition_info_t *part_ptr,
  1426. node_info_t *node_ptr,
  1427. int node_scaling)
  1428. {
  1429. sview_part_sub_t *sview_part_sub = NULL;
  1430. ListIterator itr = list_iterator_create(sview_part_info->sub_list);
  1431. while ((sview_part_sub = list_next(itr))) {
  1432. if (sview_part_sub->node_state
  1433. == node_ptr->node_state) {
  1434. _update_sview_part_sub(sview_part_sub,
  1435. node_ptr,
  1436. node_scaling);
  1437. break;
  1438. }
  1439. }
  1440. list_iterator_destroy(itr);
  1441. if (!sview_part_sub) {
  1442. if ((sview_part_sub = _create_sview_part_sub(
  1443. part_ptr, node_ptr, node_scaling)))
  1444. list_push(sview_part_info->sub_list,
  1445. sview_part_sub);
  1446. }
  1447. return SLURM_SUCCESS;
  1448. }
  1449. /*
  1450. * _create_sview_part_info - create an sview_part_info record for
  1451. * the given partition
  1452. * part_ptr IN - pointer to partition record to add
  1453. * sview_part_info OUT - ptr to an inited sview_part_info_t
  1454. */
  1455. static sview_part_info_t *_create_sview_part_info(partition_info_t* part_ptr)
  1456. {
  1457. sview_part_info_t *sview_part_info =
  1458. xmalloc(sizeof(sview_part_info_t));
  1459. sview_part_info->part_ptr = part_ptr;
  1460. sview_part_info->sub_list = list_create(_destroy_part_sub);
  1461. return sview_part_info;
  1462. }
  1463. static int _sview_part_sort_aval_dec(sview_part_info_t* rec_a,
  1464. sview_part_info_t* rec_b)
  1465. {
  1466. int size_a = rec_a->part_ptr->total_nodes;
  1467. int size_b = rec_b->part_ptr->total_nodes;
  1468. if (size_a < size_b)
  1469. return -1;
  1470. else if (size_a > size_b)
  1471. return 1;
  1472. if (rec_a->part_ptr->nodes && rec_b->part_ptr->nodes) {
  1473. size_a = strcmp(rec_a->part_ptr->nodes, rec_b->part_ptr->nodes);
  1474. if (size_a < 0)
  1475. return -1;
  1476. else if (size_a > 0)
  1477. return 1;
  1478. }
  1479. return 0;
  1480. }
  1481. static int _sview_sub_part_sort(sview_part_sub_t* rec_a,
  1482. sview_part_sub_t* rec_b)
  1483. {
  1484. int size_a = rec_a->node_state & NODE_STATE_BASE;
  1485. int size_b = rec_b->node_state & NODE_STATE_BASE;
  1486. if (size_a < size_b)
  1487. return -1;
  1488. else if (size_a > size_b)
  1489. return 1;
  1490. return 0;
  1491. }
  1492. static List _create_part_info_list(partition_info_msg_t *part_info_ptr,
  1493. node_info_msg_t *node_info_ptr)
  1494. {
  1495. sview_part_info_t *sview_part_info = NULL;
  1496. partition_info_t *part_ptr = NULL;
  1497. static node_info_msg_t *last_node_info_ptr = NULL;
  1498. static partition_info_msg_t *last_part_info_ptr = NULL;
  1499. node_info_t *node_ptr = NULL;
  1500. static List info_list = NULL;
  1501. int i, j2;
  1502. sview_part_sub_t *sview_part_sub = NULL;
  1503. ListIterator itr;
  1504. if (info_list && (node_info_ptr == last_node_info_ptr)
  1505. && (part_info_ptr == last_part_info_ptr))
  1506. return info_list;
  1507. last_node_info_ptr = node_info_ptr;
  1508. last_part_info_ptr = part_info_ptr;
  1509. if (info_list)
  1510. list_flush(info_list);
  1511. else
  1512. info_list = list_create(_part_info_list_del);
  1513. if (!info_list) {
  1514. g_print("malloc error\n");
  1515. return NULL;
  1516. }
  1517. for (i=0; i<part_info_ptr->record_count; i++) {
  1518. part_ptr = &(part_info_ptr->partition_array[i]);
  1519. /* don't include configured excludes */
  1520. if (!working_sview_config.show_hidden &&
  1521. part_ptr->flags & PART_FLAG_HIDDEN)
  1522. continue;
  1523. sview_part_info = _create_sview_part_info(part_ptr);
  1524. sview_part_info->pos = i;
  1525. list_append(info_list, sview_part_info);
  1526. sview_part_info->color_inx = i % sview_colors_cnt;
  1527. j2 = 0;
  1528. while (part_ptr->node_inx[j2] >= 0) {
  1529. int i2 = 0;
  1530. for(i2 = part_ptr->node_inx[j2];
  1531. i2 <= part_ptr->node_inx[j2+1];
  1532. i2++) {
  1533. node_ptr = &(node_info_ptr->node_array[i2]);
  1534. _insert_sview_part_sub(sview_part_info,
  1535. part_ptr,
  1536. node_ptr,
  1537. g_node_scaling);
  1538. }
  1539. j2 += 2;
  1540. }
  1541. list_sort(sview_part_info->sub_list,
  1542. (ListCmpF)_sview_sub_part_sort);
  1543. /* Need to do this after the fact so we deal with
  1544. complete sub parts.
  1545. */
  1546. itr = list_iterator_create(sview_part_info->sub_list);
  1547. while ((sview_part_sub = list_next(itr))) {
  1548. sview_part_info->sub_part_total.node_cnt +=
  1549. sview_part_sub->node_cnt;
  1550. sview_part_info->sub_part_total.cpu_alloc_cnt +=
  1551. sview_part_sub->cpu_alloc_cnt;
  1552. sview_part_info->sub_part_total.cpu_error_cnt +=
  1553. sview_part_sub->cpu_error_cnt;
  1554. sview_part_info->sub_part_total.cpu_idle_cnt +=
  1555. sview_part_sub->cpu_idle_cnt;
  1556. sview_part_info->sub_part_total.disk_total +=
  1557. sview_part_sub->disk_total;
  1558. sview_part_info->sub_part_total.mem_total +=
  1559. sview_part_sub->mem_total;
  1560. if (!sview_part_info->sub_part_total.features) {
  1561. /* store features and reasons
  1562. in the others group */
  1563. sview_part_info->sub_part_total.features
  1564. = sview_part_sub->features;
  1565. sview_part_info->sub_part_total.reason
  1566. = sview_part_sub->reason;
  1567. }
  1568. hostlist_sort(sview_part_sub->hl);
  1569. }
  1570. list_iterator_destroy(itr);
  1571. }
  1572. list_sort(info_list, (ListCmpF)_sview_part_sort_aval_dec);
  1573. return info_list;
  1574. }
  1575. static void _display_info_part(List info_list, popup_info_t *popup_win)
  1576. {
  1577. specific_info_t *spec_info = popup_win->spec_info;
  1578. char *name = (char *)spec_info->searc

Large files files are truncated, but you can click here to view the full file