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-2016 SchedMD <https://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 <https://slurm.schedmd.com/>.
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  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
30 \*****************************************************************************/
31 
32 #include "src/sview/sview.h"
33 #include "src/common/parse_time.h"
34 #include <grp.h>
35 
36 #define _DEBUG 0
37 
38 static GtkListStore *_create_model_part2(int type);
39 
40 typedef struct {
41 	uint32_t cpu_cnt;
42 	uint32_t cpu_alloc_cnt;
43 	uint32_t cpu_idle_cnt;
44 	uint32_t disk_total;
45 	char *features;
46 	char *features_act;
47 	hostlist_t hl;
48 	uint64_t mem_total;
49 	uint32_t node_cnt;
50 	uint32_t node_alloc_cnt;
51 	uint32_t node_error_cnt;
52 	uint32_t node_idle_cnt;
53 	List node_ptr_list;
54 	uint32_t node_state;
55 	partition_info_t* part_ptr;
56 	char *reason;
57 } sview_part_sub_t;
58 
59 /* Collection of data for printing reports. Like data is combined here */
60 typedef struct {
61 	int color_inx;
62 	GtkTreeIter iter_ptr;
63 	bool iter_set;
64 	char *part_name;
65 	char *cluster_name;
66 	/* part_info contains partition, avail, max_time, job_size,
67 	 * root, share, groups */
68 	partition_info_t* part_ptr;
69 	int pos;
70 	List sub_list;
71 	sview_part_sub_t sub_part_total;
72 } sview_part_info_t;
73 
74 enum {
75 	EDIT_PART_STATE = 1,
76 	EDIT_REMOVE_PART,
77 	EDIT_EDIT
78 };
79 
80 /* These need to be in alpha order (except POS and CNT) */
81 enum {
82 	SORTID_POS = POS_LOC,
83 	SORTID_ALLOW_ACCOUNTS,
84 	SORTID_ALLOW_GROUPS,
85 	SORTID_ALLOW_QOS,
86 	SORTID_ALTERNATE,
87 	SORTID_CLUSTER_NAME,
88 	SORTID_COLOR,
89 	SORTID_COLOR_INX,
90 	SORTID_CPUS,
91 	SORTID_DEFAULT,
92 	SORTID_DENY_ACCOUNTS,
93 	SORTID_DENY_QOS,
94 	SORTID_EXCLUSIVE_USER,
95 	SORTID_FEATURES,
96 	SORTID_FEATURES_ACT,
97 	SORTID_GRACE_TIME,
98 	SORTID_HIDDEN,
99 	SORTID_JOB_DEFAULTS,
100 	SORTID_JOB_SIZE,
101 	SORTID_MAX_CPUS_PER_NODE,
102 	SORTID_MEM,
103 	SORTID_NAME,
104 	SORTID_NODELIST,
105 	SORTID_NODES_ALLOWED,
106 	SORTID_NODE_INX,
107 	SORTID_NODE_STATE,
108 	SORTID_NODE_STATE_NUM,
109 	SORTID_NODES,
110 	SORTID_NODES_MAX,
111 	SORTID_NODES_MIN,
112 	SORTID_ONLY_LINE,
113 	SORTID_OVER_SUBSCRIBE,
114 	SORTID_OVER_TIME_LIMIT,
115 	SORTID_PART_STATE,
116 	SORTID_PREEMPT_MODE,
117 	SORTID_PRIORITY_JOB_FACTOR,
118 	SORTID_PRIORITY_TIER,
119 	SORTID_QOS_CHAR,
120 	SORTID_REASON,
121 	SORTID_ROOT,
122 	SORTID_TMP_DISK,
123 	SORTID_TIMELIMIT,
124 	SORTID_UPDATED,
125 	SORTID_CNT
126 };
127 
128 /*
129  * These are the settings to apply for the user
130  * on the first startup after a fresh slurm install.
131  */
132 static char *_initial_page_opts = "Partition,Default,Part_State,Time_Limit,"
133 	"Node_Count,Node_State,NodeList";
134 
135 static display_data_t display_data_part[] = {
136 	{G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE, refresh_part},
137 	{G_TYPE_STRING, SORTID_CLUSTER_NAME, "ClusterName", false,
138 	 EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
139 	{G_TYPE_STRING, SORTID_NAME, "Partition", false,
140 	 EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
141 	{G_TYPE_STRING, SORTID_COLOR, NULL, true, EDIT_COLOR, refresh_part,
142 	 create_model_part, admin_edit_part},
143 	{G_TYPE_STRING, SORTID_ALTERNATE, "Alternate", false,
144 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
145 	{G_TYPE_STRING, SORTID_DEFAULT, "Default", false,
146 	 EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
147 	{G_TYPE_STRING, SORTID_EXCLUSIVE_USER, "ExclusiveUser", false,
148 	 EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
149 	{G_TYPE_STRING, SORTID_GRACE_TIME, "GraceTime", false,
150 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
151 	{G_TYPE_STRING, SORTID_HIDDEN, "Hidden", false,
152 	 EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
153 	{G_TYPE_STRING, SORTID_PART_STATE, "Part State", false,
154 	 EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
155 	{G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", false,
156 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
157 	{G_TYPE_STRING, SORTID_NODES, "Node Count", false,
158 	 EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
159 	{G_TYPE_STRING, SORTID_CPUS, "CPU Count", false,
160 	 EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
161 	{G_TYPE_STRING, SORTID_NODE_STATE, "Node State", false,
162 	 EDIT_MODEL, refresh_part,
163 	 create_model_part, admin_edit_part},
164 	{G_TYPE_STRING, SORTID_JOB_DEFAULTS, "Job Defaults", false,
165 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
166 	{G_TYPE_STRING, SORTID_JOB_SIZE, "Job Size", false,
167 	 EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
168 	{G_TYPE_STRING, SORTID_PREEMPT_MODE, "PreemptMode", false,
169 	 EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
170 	{G_TYPE_STRING, SORTID_PRIORITY_JOB_FACTOR, "PriorityJobFactor", false,
171 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
172 	{G_TYPE_STRING, SORTID_PRIORITY_TIER, "PriorityTier", false,
173 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
174 	{G_TYPE_STRING, SORTID_NODES_MIN, "Nodes (minimum)", false,
175 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
176 	{G_TYPE_STRING, SORTID_NODES_MAX, "Nodes Max", false,
177 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
178 	{G_TYPE_STRING, SORTID_MAX_CPUS_PER_NODE, "Max CPUs Per Node", false,
179 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
180 	{G_TYPE_STRING, SORTID_OVER_SUBSCRIBE, "OverSubscribe", false,
181 	 EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
182 	{G_TYPE_STRING, SORTID_OVER_TIME_LIMIT, "OverTimeLimit", false,
183 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
184 	{G_TYPE_STRING, SORTID_ROOT, "Root", false, EDIT_MODEL, refresh_part,
185 	 create_model_part, admin_edit_part},
186 	{G_TYPE_STRING, SORTID_QOS_CHAR, "Qos", false,
187 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
188 	{G_TYPE_STRING, SORTID_ALLOW_ACCOUNTS, "Allowed Accounts", false,
189 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
190 	{G_TYPE_STRING, SORTID_ALLOW_GROUPS, "Allowed Groups", false,
191 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
192 	{G_TYPE_STRING, SORTID_ALLOW_QOS, "Allowed Qos", false,
193 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
194 	{G_TYPE_STRING, SORTID_DENY_ACCOUNTS, "Denied Accounts", false,
195 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
196 	{G_TYPE_STRING, SORTID_DENY_QOS, "Denied Qos", false,
197 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
198 	{G_TYPE_STRING, SORTID_NODES_ALLOWED, "Nodes Allowed Allocating", false,
199 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
200 	{G_TYPE_STRING, SORTID_TMP_DISK, "Temp Disk", false,
201 	 EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
202 	{G_TYPE_STRING, SORTID_MEM, "Memory", false, EDIT_NONE, refresh_part,
203 	 create_model_part, admin_edit_part},
204 	{G_TYPE_STRING, SORTID_FEATURES, "Available Features", false,
205 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
206 	{G_TYPE_STRING, SORTID_FEATURES_ACT, "Active Features", false,
207 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
208 	{G_TYPE_STRING, SORTID_REASON, "Reason", false,
209 	 EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
210 	{G_TYPE_STRING, SORTID_NODELIST, "NodeList", false,
211 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
212 	{G_TYPE_INT, SORTID_NODE_STATE_NUM, NULL, false,
213 	 EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
214 	{G_TYPE_INT, SORTID_ONLY_LINE, NULL, false, EDIT_NONE, refresh_part,
215 	 create_model_part, admin_edit_part},
216 	{G_TYPE_INT, SORTID_COLOR_INX, NULL, false, EDIT_NONE, refresh_part,
217 	 create_model_part, admin_edit_part},
218 	{G_TYPE_POINTER, SORTID_NODE_INX, NULL, false, EDIT_NONE,
219 	 refresh_part, create_model_part, admin_edit_part},
220 	{G_TYPE_INT, SORTID_UPDATED, NULL, false, EDIT_NONE, refresh_part,
221 	 create_model_part, admin_edit_part},
222 	{G_TYPE_NONE, -1, NULL, false, EDIT_NONE}
223 };
224 
225 static display_data_t create_data_part[] = {
226 	{G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE, refresh_part},
227 	{G_TYPE_STRING, SORTID_CLUSTER_NAME, "ClusterName", false,
228 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
229 	{G_TYPE_STRING, SORTID_NAME, "Name", false,
230 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
231 	{G_TYPE_STRING, SORTID_ALTERNATE, "Alternate", false,
232 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
233 	{G_TYPE_STRING, SORTID_DEFAULT, "Default", false,
234 	 EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
235 	{G_TYPE_STRING, SORTID_EXCLUSIVE_USER, "ExclusiveUser", false,
236 	 EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
237 	{G_TYPE_STRING, SORTID_GRACE_TIME, "GraceTime", false,
238 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
239 	{G_TYPE_STRING, SORTID_HIDDEN, "Hidden", false,
240 	 EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
241 	{G_TYPE_STRING, SORTID_JOB_DEFAULTS, "Job Defaults", false,
242 	 EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
243 	{G_TYPE_STRING, SORTID_PART_STATE, "State", false,
244 	 EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
245 	{G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", false,
246 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
247 	{G_TYPE_STRING, SORTID_PREEMPT_MODE, "PreemptMode", false,
248 	 EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
249 	{G_TYPE_STRING, SORTID_PRIORITY_JOB_FACTOR, "PriorityJobFactor", false,
250 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
251 	{G_TYPE_STRING, SORTID_PRIORITY_TIER, "PriorityTier", false,
252 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
253 	{G_TYPE_STRING, SORTID_NODES_MIN, "Nodes (minimum)", false,
254 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
255 	{G_TYPE_STRING, SORTID_NODES_MAX, "Nodes Max", false,
256 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
257 	{G_TYPE_STRING, SORTID_MAX_CPUS_PER_NODE, "Max CPUs Per Node", false,
258 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
259 	{G_TYPE_STRING, SORTID_ROOT, "Root", false,
260 	 EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
261 	{G_TYPE_STRING, SORTID_OVER_SUBSCRIBE, "OverSubscribe", false,
262 	 EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part},
263 	{G_TYPE_STRING, SORTID_OVER_TIME_LIMIT, "OverTimeLimit", false,
264 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
265 	{G_TYPE_STRING, SORTID_ALLOW_ACCOUNTS, "Accounts Allowed", false,
266 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
267 	{G_TYPE_STRING, SORTID_ALLOW_GROUPS, "Groups Allowed", false,
268 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
269 	{G_TYPE_STRING, SORTID_ALLOW_QOS, "Qos Allowed", false,
270 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
271 	{G_TYPE_STRING, SORTID_DENY_ACCOUNTS, "Accounts Denied", false,
272 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
273 	{G_TYPE_STRING, SORTID_DENY_QOS, "Qos Denied", false,
274 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
275 	{G_TYPE_STRING, SORTID_NODES_ALLOWED, "Nodes Allowed Allocating", false,
276 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
277 	{G_TYPE_STRING, SORTID_FEATURES, "Available Features", false,
278 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
279 	{G_TYPE_STRING, SORTID_FEATURES_ACT, "Active Features", false,
280 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
281 	{G_TYPE_NONE, SORTID_REASON, "Reason", false,
282 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
283 	{G_TYPE_STRING, SORTID_NODELIST, "NodeList", false,
284 	 EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part},
285 	{G_TYPE_NONE, -1, NULL, false, EDIT_NONE}
286 };
287 
288 static display_data_t options_data_part[] = {
289 	{G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE},
290 	{G_TYPE_STRING, INFO_PAGE, "Full Info", true, PART_PAGE},
291 	{G_TYPE_STRING, PART_PAGE, "Edit Partition", true, ADMIN_PAGE},
292 	{G_TYPE_STRING, PART_PAGE, "Remove Partition", true, ADMIN_PAGE},
293 	{G_TYPE_STRING, PART_PAGE, "Drain Nodes",
294 	 true, ADMIN_PAGE | EXTRA_NODES},
295 	{G_TYPE_STRING, PART_PAGE, "Resume Nodes",
296 	 true, ADMIN_PAGE | EXTRA_NODES},
297 	{G_TYPE_STRING, PART_PAGE, "Put Nodes Down",
298 	 true, ADMIN_PAGE | EXTRA_NODES},
299 	{G_TYPE_STRING, PART_PAGE, "Make Nodes Idle",
300 	 true, ADMIN_PAGE | EXTRA_NODES},
301 	{G_TYPE_STRING, PART_PAGE, "Update Node Features",
302 	 true, ADMIN_PAGE | EXTRA_NODES},
303 	{G_TYPE_STRING, PART_PAGE, "Change Partition State",
304 	 true, ADMIN_PAGE},
305 	{G_TYPE_STRING, JOB_PAGE, "Jobs", true, PART_PAGE},
306 	{G_TYPE_STRING, NODE_PAGE, "Nodes", true, PART_PAGE},
307 	//{G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", false, PART_PAGE},
308 	{G_TYPE_STRING, RESV_PAGE, "Reservations", true, PART_PAGE},
309 	{G_TYPE_NONE, -1, NULL, false, EDIT_NONE}
310 };
311 
312 static display_data_t *local_display_data = NULL;
313 static char *got_edit_signal = NULL;
314 static char *got_features_edit_signal = NULL;
315 static GtkTreeModel *last_model = NULL;
316 
317 static void _append_part_sub_record(sview_part_sub_t *sview_part_sub,
318 				    GtkTreeStore *treestore, GtkTreeIter *iter,
319 				    int line);
320 static void _update_part_sub_record(sview_part_sub_t *sview_part_sub,
321 				    GtkTreeStore *treestore,
322 				    GtkTreeIter *iter);
323 
_build_min_max_32_string(char * buffer,int buf_size,uint32_t min,uint32_t max,bool range)324 static int _build_min_max_32_string(char *buffer, int buf_size,
325 				    uint32_t min, uint32_t max, bool range)
326 {
327 	char tmp_min[8];
328 	char tmp_max[8];
329 	convert_num_unit((float)min, tmp_min, sizeof(tmp_min), UNIT_NONE,
330 			 NO_VAL, working_sview_config.convert_flags);
331 	convert_num_unit((float)max, tmp_max, sizeof(tmp_max), UNIT_NONE,
332 			 NO_VAL, working_sview_config.convert_flags);
333 
334 	if (max == min)
335 		return snprintf(buffer, buf_size, "%s", tmp_max);
336 	else if (range) {
337 		if (max == INFINITE)
338 			return snprintf(buffer, buf_size, "%s-infinite",
339 					tmp_min);
340 		else
341 			return snprintf(buffer, buf_size, "%s-%s",
342 					tmp_min, tmp_max);
343 	} else
344 		return snprintf(buffer, buf_size, "%s+", tmp_min);
345 }
346 
_set_active_combo_part(GtkComboBox * combo,GtkTreeModel * model,GtkTreeIter * iter,int type)347 static void _set_active_combo_part(GtkComboBox *combo,
348 				   GtkTreeModel *model, GtkTreeIter *iter,
349 				   int type)
350 {
351 	char *temp_char = NULL;
352 	int action = 0;
353 	int i = 0, unknown_found = 0;
354 	char *upper = NULL;
355 
356 	if (model)
357 		gtk_tree_model_get(model, iter, type, &temp_char, -1);
358 	if (!temp_char)
359 		goto end_it;
360 	switch(type) {
361 	case SORTID_DEFAULT:
362 	case SORTID_EXCLUSIVE_USER:
363 	case SORTID_HIDDEN:
364 	case SORTID_ROOT:
365 		if (!xstrcmp(temp_char, "yes"))
366 			action = 0;
367 		else if (!xstrcmp(temp_char, "no"))
368 			action = 1;
369 		else
370 			action = 0;
371 
372 		break;
373 	case SORTID_OVER_SUBSCRIBE:
374 		if (!xstrncmp(temp_char, "force", 5))
375 			action = 0;
376 		else if (!xstrcmp(temp_char, "no"))
377 			action = 1;
378 		else if (!xstrncmp(temp_char, "yes", 3))
379 			action = 2;
380 		else if (!xstrcmp(temp_char, "exclusive"))
381 			action = 3;
382 		else
383 			action = 0;
384 		break;
385 	case SORTID_PART_STATE:
386 		if (!xstrcmp(temp_char, "up"))
387 			action = 0;
388 		else if (!xstrcmp(temp_char, "down"))
389 			action = 1;
390 		else if (!xstrcmp(temp_char, "inactive"))
391 			action = 2;
392 		else if (!xstrcmp(temp_char, "drain"))
393 			action = 3;
394 		else
395 			action = 0;
396 		break;
397 	case SORTID_NODE_STATE:
398 		if (!xstrcasecmp(temp_char, "drain"))
399 			action = 0;
400 		else if (!xstrcasecmp(temp_char, "resume"))
401 			action = 1;
402 		else
403 			for(i = 0; i < NODE_STATE_END; i++) {
404 				upper = node_state_string(i);
405 				if (!xstrcmp(upper, "UNKNOWN")) {
406 					unknown_found++;
407 					continue;
408 				}
409 
410 				if (!xstrcasecmp(temp_char, upper)) {
411 					action = i + 2 - unknown_found;
412 					break;
413 				}
414 			}
415 
416 		break;
417 	case SORTID_PREEMPT_MODE:
418 		if (!xstrcasecmp(temp_char, "cancel"))
419 			action = 0;
420 		else if (!xstrcasecmp(temp_char, "off"))
421 			action = 2;
422 		else if (!xstrcasecmp(temp_char, "requeue"))
423 			action = 3;
424 		else if (!xstrcasecmp(temp_char, "suspend"))
425 			action = 4;
426 		else
427 			action = 2;	/* off */
428 		break;
429 	default:
430 		break;
431 	}
432 	g_free(temp_char);
433 end_it:
434 	gtk_combo_box_set_active(combo, action);
435 
436 }
437 
_set_part_over_subscribe_popup(void)438 static uint16_t _set_part_over_subscribe_popup(void)
439 {
440 	GtkWidget *table = gtk_table_new(1, 2, false);
441 	GtkWidget *label = NULL;
442 	GtkObject *adjustment = gtk_adjustment_new(4,
443 						   1, 1000,
444 						   1, 60,
445 						   0);
446 	GtkWidget *spin_button =
447 		gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 1, 0);
448 	GtkWidget *popup = gtk_dialog_new_with_buttons(
449 		"Count",
450 		GTK_WINDOW (main_window),
451 		GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
452 		NULL);
453 	int response = 0;
454 	uint16_t count = 4;
455 
456 	gtk_window_set_type_hint(GTK_WINDOW(popup),
457 				 GDK_WINDOW_TYPE_HINT_NORMAL);
458 
459 	label = gtk_dialog_add_button(GTK_DIALOG(popup),
460 				      GTK_STOCK_OK, GTK_RESPONSE_OK);
461 	gtk_window_set_default(GTK_WINDOW(popup), label);
462 
463 	label = gtk_label_new("OverSubscribe Job Count ");
464 
465 	gtk_container_set_border_width(GTK_CONTAINER(table), 10);
466 
467 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
468 			   table, false, false, 0);
469 
470 	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
471 	gtk_table_attach_defaults(GTK_TABLE(table), spin_button, 1, 2, 0, 1);
472 
473 	gtk_widget_show_all(popup);
474 	response = gtk_dialog_run (GTK_DIALOG(popup));
475 
476 	if (response == GTK_RESPONSE_OK) {
477 		count = gtk_spin_button_get_value_as_int(
478 			GTK_SPIN_BUTTON(spin_button));
479 	}
480 
481 	gtk_widget_destroy(popup);
482 
483 	return count;
484 }
485 
486 /* don't free this char */
_set_part_msg(update_part_msg_t * part_msg,const char * new_text,int column)487 static const char *_set_part_msg(update_part_msg_t *part_msg,
488 				 const char *new_text,
489 				 int column)
490 {
491 	char *type = "", *temp_char;
492 	int temp_int = 0;
493 
494 	global_edit_error = 0;
495 
496 	if (!part_msg)
497 		return NULL;
498 
499 	switch(column) {
500 	case SORTID_ALTERNATE:
501 		type = "alternate";
502 		part_msg->alternate = xstrdup(new_text);
503 		break;
504 	case SORTID_DEFAULT:
505 		if (!xstrcasecmp(new_text, "yes")) {
506 			part_msg->flags |= PART_FLAG_DEFAULT;
507 			part_msg->flags &= (~PART_FLAG_DEFAULT_CLR);
508 		} else if (!xstrcasecmp(new_text, "no")) {
509 			part_msg->flags &= (~PART_FLAG_DEFAULT);
510 			part_msg->flags |= PART_FLAG_DEFAULT_CLR;
511 		}
512 		type = "default";
513 		break;
514 	case SORTID_EXCLUSIVE_USER:
515 		if (!xstrcasecmp(new_text, "yes")) {
516 			part_msg->flags |= PART_FLAG_EXCLUSIVE_USER;
517 			part_msg->flags &= (~PART_FLAG_EXC_USER_CLR);
518 		} else if (!xstrcasecmp(new_text, "no")) {
519 			part_msg->flags &= (~PART_FLAG_EXCLUSIVE_USER);
520 			part_msg->flags |= PART_FLAG_EXC_USER_CLR;
521 		}
522 		type = "hidden";
523 		break;
524 	case SORTID_GRACE_TIME:
525 		temp_int = time_str2mins((char *)new_text);
526 		type = "grace_time";
527 		if (temp_int <= 0)
528 			goto return_error;
529 		/* convert to seconds */
530 		part_msg->grace_time = (uint32_t)(temp_int * 60);
531 		break;
532 	case SORTID_HIDDEN:
533 		if (!xstrcasecmp(new_text, "yes")) {
534 			part_msg->flags |= PART_FLAG_HIDDEN;
535 			part_msg->flags &= (~PART_FLAG_HIDDEN_CLR);
536 		} else if (!xstrcasecmp(new_text, "no")) {
537 			part_msg->flags &= (~PART_FLAG_HIDDEN);
538 			part_msg->flags |= PART_FLAG_HIDDEN_CLR;
539 		}
540 		type = "hidden";
541 		break;
542 	case SORTID_JOB_DEFAULTS:
543 		type = "job_defaults";
544 		part_msg->job_defaults_str = xstrdup(new_text);
545 		break;
546 	case SORTID_TIMELIMIT:
547 		if ((xstrcasecmp(new_text, "infinite") == 0))
548 			temp_int = INFINITE;
549 		else
550 			temp_int = time_str2mins((char *)new_text);
551 
552 		type = "timelimit";
553 		if ((temp_int <= 0) && (temp_int != INFINITE))
554 			goto return_error;
555 		part_msg->max_time = (uint32_t)temp_int;
556 		break;
557 	case SORTID_PREEMPT_MODE:
558 		if (!xstrcasecmp(new_text, "cancel"))
559 			part_msg->preempt_mode = PREEMPT_MODE_CANCEL;
560 		else if (!xstrcasecmp(new_text, "off"))
561 			part_msg->preempt_mode = PREEMPT_MODE_OFF;
562 		else if (!xstrcasecmp(new_text, "requeue"))
563 			part_msg->preempt_mode = PREEMPT_MODE_REQUEUE;
564 		else if (!xstrcasecmp(new_text, "suspend"))
565 			part_msg->preempt_mode = PREEMPT_MODE_SUSPEND;
566 		type = "preempt_mode";
567 		break;
568 	case SORTID_PRIORITY_JOB_FACTOR:
569 		temp_int = strtol(new_text, (char **)NULL, 10);
570 		type = "priority_job_factor";
571 		part_msg->priority_job_factor = (uint16_t)temp_int;
572 		break;
573 	case SORTID_PRIORITY_TIER:
574 		temp_int = strtol(new_text, (char **)NULL, 10);
575 		type = "priority_tier";
576 		part_msg->priority_tier = (uint16_t)temp_int;
577 		break;
578 	case SORTID_NAME:
579 		type = "name";
580 		part_msg->name = xstrdup(new_text);
581 		break;
582 	case SORTID_MAX_CPUS_PER_NODE:
583 		temp_int = strtol(new_text, (char **)NULL, 10);
584 		type = "max_cpus_per_node";
585 
586 		if (temp_int <= 0)
587 			goto return_error;
588 		part_msg->max_cpus_per_node = temp_int;
589 		break;
590 	case SORTID_NODES_MIN:
591 		temp_int = strtol(new_text, (char **)NULL, 10);
592 		type = "min_nodes";
593 
594 		if (temp_int <= 0)
595 			goto return_error;
596 		part_msg->min_nodes = (uint32_t)temp_int;
597 		break;
598 	case SORTID_NODES_MAX:
599 		if (!xstrcasecmp(new_text, "infinite")) {
600 			temp_int = INFINITE;
601 		} else {
602 			temp_int = strtol(new_text, &temp_char, 10);
603 			if ((temp_char[0] == 'k') || (temp_char[0] == 'K'))
604 				temp_int *= 1024;
605 			if ((temp_char[0] == 'm') || (temp_char[0] == 'M'))
606 				temp_int *= (1024 * 1024);
607 		}
608 
609 		type = "max_nodes";
610 		if ((temp_int <= 0) && (temp_int != INFINITE))
611 			goto return_error;
612 		part_msg->max_nodes = (uint32_t)temp_int;
613 		break;
614 	case SORTID_ROOT:
615 		if (!xstrcasecmp(new_text, "yes")) {
616 			part_msg->flags |= PART_FLAG_ROOT_ONLY;
617 			part_msg->flags &= (~PART_FLAG_ROOT_ONLY_CLR);
618 		} else if (!xstrcasecmp(new_text, "no")) {
619 			part_msg->flags &= (~PART_FLAG_ROOT_ONLY);
620 			part_msg->flags |= PART_FLAG_ROOT_ONLY_CLR;
621 		}
622 
623 		type = "root";
624 		break;
625 	case SORTID_OVER_SUBSCRIBE:
626 		if (!xstrcasecmp(new_text, "yes")) {
627 			part_msg->max_share = _set_part_over_subscribe_popup();
628 		} else if (!xstrcasecmp(new_text, "exclusive")) {
629 			part_msg->max_share = 0;
630 		} else if (!xstrcasecmp(new_text, "force")) {
631 			part_msg->max_share = _set_part_over_subscribe_popup()
632 					      | SHARED_FORCE;
633 		} else if (!xstrcasecmp(new_text, "no"))
634 			part_msg->max_share = 1;
635 		else
636 			goto return_error;
637 		type = "oversubscribe";
638 		break;
639 	case SORTID_OVER_TIME_LIMIT:
640 		if (!xstrcasecmp(new_text, "INFINITE") ||
641 		    !xstrcasecmp(new_text, "UNLIMITED")) {
642 			part_msg->over_time_limit = INFINITE16;
643 		} else if (new_text[0] >= '0' && new_text[0] <= '9')
644 			part_msg->over_time_limit = atoi(new_text);
645 		else
646 			goto return_error;
647 		type = "overtimelimit";
648 		break;
649 	case SORTID_ALLOW_ACCOUNTS:
650 		type = "accounts";
651 		part_msg->allow_accounts = xstrdup(new_text);
652 		break;
653 	case SORTID_ALLOW_GROUPS:
654 		type = "groups";
655 		part_msg->allow_groups = xstrdup(new_text);
656 		break;
657 	case SORTID_ALLOW_QOS:
658 		type = "qos";
659 		part_msg->allow_qos = xstrdup(new_text);
660 		break;
661 	case SORTID_DENY_ACCOUNTS:
662 		type = "deny account";
663 		part_msg->deny_accounts = xstrdup(new_text);
664 		break;
665 	case SORTID_DENY_QOS:
666 		type = "deny qos";
667 		part_msg->deny_qos = xstrdup(new_text);
668 		break;
669 	case SORTID_NODES_ALLOWED:
670 		type = "allowed alloc nodes";
671 		part_msg->allow_alloc_nodes = xstrdup(new_text);
672 		break;
673 	case SORTID_NODELIST:
674 		part_msg->nodes = xstrdup(new_text);
675 		type = "nodelist";
676 		break;
677 	case SORTID_PART_STATE:
678 		if (!xstrcasecmp(new_text, "up"))
679 			part_msg->state_up = PARTITION_UP;
680 		else if (!xstrcasecmp(new_text, "down"))
681 			part_msg->state_up = PARTITION_DOWN;
682 		else if (!xstrcasecmp(new_text, "inactive"))
683 			part_msg->state_up = PARTITION_INACTIVE;
684 		else if (!xstrcasecmp(new_text, "drain"))
685 			part_msg->state_up = PARTITION_DRAIN;
686 		else
687 			goto return_error;
688 		type = "availability";
689 
690 		break;
691 	case SORTID_NODE_STATE:
692 		type = (char *)new_text;
693 		got_edit_signal = xstrdup(new_text);
694 		break;
695 	case SORTID_FEATURES:
696 		type = "Update Features";
697 		got_features_edit_signal = xstrdup(new_text);
698 		break;
699 	case SORTID_QOS_CHAR:
700 		type = "QOS Char";
701 		part_msg->qos_char = xstrdup(new_text);
702 		break;
703 	default:
704 		type = "unknown";
705 		break;
706 	}
707 
708 	if (xstrcmp(type, "unknown"))
709 		global_send_update_msg = 1;
710 
711 	return type;
712 
713 return_error:
714 	global_edit_error = 1;
715 	return type;
716 
717 }
718 
_admin_edit_combo_box_part(GtkComboBox * combo,update_part_msg_t * part_msg)719 static void _admin_edit_combo_box_part(GtkComboBox *combo,
720 				       update_part_msg_t *part_msg)
721 {
722 	GtkTreeModel *model = NULL;
723 	GtkTreeIter iter;
724 	int column = 0;
725 	char *name = NULL;
726 
727 	if (!part_msg)
728 		return;
729 
730 	if (!gtk_combo_box_get_active_iter(combo, &iter)) {
731 		g_print("nothing selected\n");
732 		return;
733 	}
734 	model = gtk_combo_box_get_model(combo);
735 	if (!model) {
736 		g_print("nothing selected\n");
737 		return;
738 	}
739 
740 	gtk_tree_model_get(model, &iter, 0, &name, -1);
741 	gtk_tree_model_get(model, &iter, 1, &column, -1);
742 
743 	(void) _set_part_msg(part_msg, name, column);
744 	if (name)
745 		g_free(name);
746 }
747 
_admin_focus_out_part(GtkEntry * entry,GdkEventFocus * event,update_part_msg_t * part_msg)748 static gboolean _admin_focus_out_part(GtkEntry *entry,
749 				      GdkEventFocus *event,
750 				      update_part_msg_t *part_msg)
751 {
752 	if (global_entry_changed) {
753 		const char *col_name = NULL;
754 		int type = gtk_entry_get_max_length(entry);
755 		const char *name = gtk_entry_get_text(entry);
756 		type -= DEFAULT_ENTRY_LENGTH;
757 		col_name = _set_part_msg(part_msg, name, type);
758 		if (global_edit_error) {
759 			if (global_edit_error_msg)
760 				g_free(global_edit_error_msg);
761 			global_edit_error_msg = g_strdup_printf(
762 				"Partition %s %s can't be set to %s",
763 				part_msg->name,
764 				col_name,
765 				name);
766 		}
767 
768 		global_entry_changed = 0;
769 	}
770 	return false;
771 }
772 
_admin_full_edit_part(update_part_msg_t * part_msg,GtkTreeModel * model,GtkTreeIter * iter)773 static GtkWidget *_admin_full_edit_part(update_part_msg_t *part_msg,
774 					GtkTreeModel *model, GtkTreeIter *iter)
775 {
776 	GtkScrolledWindow *window = create_scrolled_window();
777 	GtkBin *bin = NULL;
778 	GtkViewport *view = NULL;
779 	GtkTable *table = NULL;
780 	int i = 0, row = 0;
781 	display_data_t *display_data = display_data_part;
782 
783 	gtk_scrolled_window_set_policy(window,
784 				       GTK_POLICY_NEVER,
785 				       GTK_POLICY_AUTOMATIC);
786 	bin = GTK_BIN(&window->container);
787 	view = GTK_VIEWPORT(bin->child);
788 	bin = GTK_BIN(&view->bin);
789 	table = GTK_TABLE(bin->child);
790 	gtk_table_resize(table, SORTID_CNT, 2);
791 
792 	gtk_table_set_homogeneous(table, false);
793 
794 	for (i = 0; i < SORTID_CNT; i++) {
795 		while (display_data++) {
796 			if (display_data->id == -1)
797 				break;
798 			if (!display_data->name)
799 				continue;
800 			if (display_data->id != i)
801 				continue;
802 			display_admin_edit(
803 				table, part_msg, &row, model, iter,
804 				display_data,
805 				G_CALLBACK(_admin_edit_combo_box_part),
806 				G_CALLBACK(_admin_focus_out_part),
807 				_set_active_combo_part);
808 			break;
809 		}
810 		display_data = display_data_part;
811 	}
812 	gtk_table_resize(table, row, 2);
813 
814 	return GTK_WIDGET(window);
815 }
816 
_subdivide_part(sview_part_info_t * sview_part_info,GtkTreeModel * model,GtkTreeIter * sub_iter,GtkTreeIter * iter)817 static void _subdivide_part(sview_part_info_t *sview_part_info,
818 			    GtkTreeModel *model,
819 			    GtkTreeIter *sub_iter,
820 			    GtkTreeIter *iter)
821 {
822 	GtkTreeIter first_sub_iter;
823 	ListIterator itr = NULL;
824 	int i = 0, line = 0;
825 	sview_part_sub_t *sview_part_sub = NULL;
826 	int set = 0;
827 
828 	memset(&first_sub_iter, 0, sizeof(GtkTreeIter));
829 
830 	/* make sure all the steps are still here */
831 	if (sub_iter) {
832 		first_sub_iter = *sub_iter;
833 		while (1) {
834 			gtk_tree_store_set(GTK_TREE_STORE(model), sub_iter,
835 					   SORTID_UPDATED, 0, -1);
836 			if (!gtk_tree_model_iter_next(model, sub_iter)) {
837 				break;
838 			}
839 		}
840 		memcpy(sub_iter, &first_sub_iter, sizeof(GtkTreeIter));
841 		set = 1;
842 	}
843 	itr = list_iterator_create(sview_part_info->sub_list);
844 	if ((list_count(sview_part_info->sub_list) == 1) &&
845 	    (sview_part_sub = list_next(itr))) {
846 		gtk_tree_store_set(GTK_TREE_STORE(model), iter,
847 				   SORTID_ONLY_LINE, 1, -1);
848 		_update_part_sub_record(sview_part_sub,
849 					GTK_TREE_STORE(model),
850 					iter);
851 	} else {
852 		while ((sview_part_sub = list_next(itr))) {
853 			if (!sub_iter) {
854 				i = NO_VAL;
855 				goto adding;
856 			} else {
857 				memcpy(sub_iter, &first_sub_iter,
858 				       sizeof(GtkTreeIter));
859 			}
860 			line = 0;
861 			while (1) {
862 				int state;
863 				/* Search for the state number and
864 				   check to see if it is in the
865 				   list.  Here we need to pass an int
866 				   for system where endian is an
867 				   issue passing a uint16_t may seg
868 				   fault. */
869 				gtk_tree_model_get(model, sub_iter,
870 						   SORTID_NODE_STATE_NUM,
871 						   &state, -1);
872 				if ((uint16_t)state
873 				    == sview_part_sub->node_state) {
874 					/* update with new info */
875 					_update_part_sub_record(
876 						sview_part_sub,
877 						GTK_TREE_STORE(model),
878 						sub_iter);
879 					goto found;
880 				}
881 
882 				line++;
883 				if (!gtk_tree_model_iter_next(model,
884 							      sub_iter)) {
885 					break;
886 				}
887 			}
888 		adding:
889 			_append_part_sub_record(sview_part_sub,
890 						GTK_TREE_STORE(model),
891 						iter, line);
892 /* 			if (i == NO_VAL) */
893 /* 				line++; */
894 		found:
895 			;
896 		}
897 	}
898 	list_iterator_destroy(itr);
899 
900 	if (set) {
901 		sub_iter = &first_sub_iter;
902 		/* clear all steps that aren't active */
903 		while (1) {
904 			gtk_tree_model_get(model, sub_iter,
905 					   SORTID_UPDATED, &i, -1);
906 			if (!i) {
907 				if (!gtk_tree_store_remove(
908 					    GTK_TREE_STORE(model),
909 					    sub_iter))
910 					break;
911 				else
912 					continue;
913 			}
914 			if (!gtk_tree_model_iter_next(model, sub_iter)) {
915 				break;
916 			}
917 		}
918 	}
919 	return;
920 }
921 
_layout_part_record(GtkTreeView * treeview,sview_part_info_t * sview_part_info,int update)922 static void _layout_part_record(GtkTreeView *treeview,
923 				sview_part_info_t *sview_part_info,
924 				int update)
925 {
926 	GtkTreeIter iter;
927 	char time_buf[20], tmp_buf[20];
928 	char tmp_cnt[8];
929 	char tmp_cnt1[8];
930 	char tmp_cnt2[8];
931 	partition_info_t *part_ptr = sview_part_info->part_ptr;
932 	sview_part_sub_t *sview_part_sub = NULL;
933 	char ind_cnt[1024];
934 	const char *job_def_str = NULL, *temp_char = NULL;
935 	uint16_t temp_uint16 = 0;
936 	int i;
937 	int yes_no = -1;
938 	uint32_t limit_set = NO_VAL;
939 	GtkTreeStore *treestore =
940 		GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
941 
942 	convert_num_unit((float)sview_part_info->sub_part_total.node_alloc_cnt,
943 			 tmp_cnt, sizeof(tmp_cnt), UNIT_NONE, NO_VAL,
944 			 working_sview_config.convert_flags);
945 	convert_num_unit((float)sview_part_info->sub_part_total.node_idle_cnt,
946 			 tmp_cnt1, sizeof(tmp_cnt1), UNIT_NONE, NO_VAL,
947 			 working_sview_config.convert_flags);
948 	convert_num_unit((float)sview_part_info->sub_part_total.node_error_cnt,
949 			 tmp_cnt2, sizeof(tmp_cnt2), UNIT_NONE, NO_VAL,
950 			 working_sview_config.convert_flags);
951 	snprintf(ind_cnt, sizeof(ind_cnt), "%s/%s/%s",
952 		 tmp_cnt, tmp_cnt1, tmp_cnt2);
953 
954 	for (i = 0; i < SORTID_CNT; i++) {
955 		switch (i) {
956 		case SORTID_PART_STATE:
957 			switch (part_ptr->state_up) {
958 			case PARTITION_UP:
959 				temp_char = "up";
960 				break;
961 			case PARTITION_DOWN:
962 				temp_char = "down";
963 				break;
964 			case PARTITION_INACTIVE:
965 				temp_char = "inactive";
966 				break;
967 			case PARTITION_DRAIN:
968 				temp_char = "drain";
969 				break;
970 			default:
971 				temp_char = "unknown";
972 				break;
973 			}
974 			break;
975 		case SORTID_ALTERNATE:
976 			if (part_ptr->alternate)
977 				temp_char = part_ptr->alternate;
978 			else
979 				temp_char = "";
980 			break;
981 		case SORTID_CPUS:
982 			convert_num_unit((float)part_ptr->total_cpus,
983 					 tmp_cnt, sizeof(tmp_cnt),
984 					 UNIT_NONE, NO_VAL,
985 					 working_sview_config.convert_flags);
986 			temp_char = tmp_cnt;
987 			break;
988 		case SORTID_DEFAULT:
989 			if (part_ptr->flags & PART_FLAG_DEFAULT)
990 				yes_no = 1;
991 			else
992 				yes_no = 0;
993 			break;
994 		case SORTID_FEATURES:
995 			if (sview_part_sub)
996 				temp_char = sview_part_sub->features;
997 			else
998 				temp_char = "";
999 			break;
1000 		case SORTID_GRACE_TIME:
1001 			limit_set = part_ptr->grace_time;
1002 			break;
1003 		case SORTID_ALLOW_ACCOUNTS:
1004 			if (part_ptr->allow_accounts)
1005 				temp_char = part_ptr->allow_accounts;
1006 			else
1007 				temp_char = "all";
1008 			break;
1009 		case SORTID_ALLOW_GROUPS:
1010 			if (part_ptr->allow_groups)
1011 				temp_char = part_ptr->allow_groups;
1012 			else
1013 				temp_char = "all";
1014 			break;
1015 		case SORTID_ALLOW_QOS:
1016 			if (part_ptr->allow_qos)
1017 				temp_char = part_ptr->allow_qos;
1018 			else
1019 				temp_char = "all";
1020 			break;
1021 		case SORTID_CLUSTER_NAME:
1022 			if (part_ptr->cluster_name)
1023 				temp_char = part_ptr->cluster_name;
1024 			break;
1025 		case SORTID_DENY_ACCOUNTS:
1026 			if (part_ptr->deny_accounts)
1027 				temp_char = part_ptr->deny_accounts;
1028 			else
1029 				temp_char = "none";
1030 			break;
1031 		case SORTID_DENY_QOS:
1032 			if (part_ptr->deny_qos)
1033 				temp_char = part_ptr->deny_qos;
1034 			else
1035 				temp_char = "none";
1036 			break;
1037 		case SORTID_EXCLUSIVE_USER:
1038 			if (part_ptr->flags & PART_FLAG_EXCLUSIVE_USER)
1039 				yes_no = 1;
1040 			else
1041 				yes_no = 0;
1042 			break;
1043 		case SORTID_HIDDEN:
1044 			if (part_ptr->flags & PART_FLAG_HIDDEN)
1045 				yes_no = 1;
1046 			else
1047 				yes_no = 0;
1048 			break;
1049 		case SORTID_JOB_DEFAULTS:
1050 			job_def_str =
1051 				job_defaults_str(part_ptr->job_defaults_list);
1052 			temp_char = job_def_str;
1053 			break;
1054 		case SORTID_JOB_SIZE:
1055 			_build_min_max_32_string(time_buf, sizeof(time_buf),
1056 						 part_ptr->min_nodes,
1057 						 part_ptr->max_nodes, true);
1058 			temp_char = time_buf;
1059 			break;
1060 		case SORTID_MEM:
1061 			convert_num_unit((float)sview_part_info->
1062 					 sub_part_total.mem_total,
1063 					 tmp_cnt, sizeof(tmp_cnt),
1064 					 UNIT_MEGA, NO_VAL,
1065 					 working_sview_config.convert_flags);
1066 			temp_char = tmp_cnt;
1067 			break;
1068 		case SORTID_NODELIST:
1069 			temp_char = part_ptr->nodes;
1070 			break;
1071 		case SORTID_NODES_ALLOWED:
1072 			temp_char = part_ptr->allow_alloc_nodes;
1073 			break;
1074 		case SORTID_NODES:
1075 			sprintf(tmp_cnt, "%u", part_ptr->total_nodes);
1076 			temp_char = tmp_cnt;
1077 			break;
1078 		case SORTID_NODES_MAX:
1079 			limit_set = part_ptr->max_nodes;
1080 			break;
1081 		case SORTID_NODES_MIN:
1082 			limit_set = part_ptr->min_nodes;
1083 			break;
1084 		case SORTID_MAX_CPUS_PER_NODE:
1085 			limit_set = part_ptr->max_cpus_per_node;
1086 			break;
1087 		case SORTID_NODE_INX:
1088 			break;
1089 		case SORTID_ONLY_LINE:
1090 			break;
1091 		case SORTID_PREEMPT_MODE:
1092 			temp_uint16 = part_ptr->preempt_mode;
1093 			if (temp_uint16 == NO_VAL16)
1094 				temp_uint16 =  slurm_get_preempt_mode();
1095 			temp_char = preempt_mode_string(temp_uint16);
1096 			break;
1097 		case SORTID_PRIORITY_JOB_FACTOR:
1098 			convert_num_unit((float)part_ptr->priority_job_factor,
1099 					 time_buf, sizeof(time_buf), UNIT_NONE,
1100 					 NO_VAL,
1101 					 working_sview_config.convert_flags);
1102 			temp_char = time_buf;
1103 			break;
1104 		case SORTID_PRIORITY_TIER:
1105 			convert_num_unit((float)part_ptr->priority_tier,
1106 					 time_buf, sizeof(time_buf), UNIT_NONE,
1107 					 NO_VAL,
1108 					 working_sview_config.convert_flags);
1109 			temp_char = time_buf;
1110 			break;
1111 		case SORTID_REASON:
1112 			sview_part_sub = list_peek(sview_part_info->sub_list);
1113 			if (sview_part_sub)
1114 				temp_char = sview_part_sub->reason;
1115 			else
1116 				temp_char = "";
1117 			break;
1118 		case SORTID_ROOT:
1119 			if (part_ptr->flags & PART_FLAG_ROOT_ONLY)
1120 				yes_no = 1;
1121 			else
1122 				yes_no = 0;
1123 			break;
1124 		case SORTID_OVER_SUBSCRIBE:
1125 			if (part_ptr->max_share & SHARED_FORCE) {
1126 				snprintf(tmp_buf, sizeof(tmp_buf), "force:%u",
1127 					 (part_ptr->max_share
1128 					  & ~(SHARED_FORCE)));
1129 				temp_char = tmp_buf;
1130 			} else if (part_ptr->max_share == 0)
1131 				temp_char = "exclusive";
1132 			else if (part_ptr->max_share > 1) {
1133 				snprintf(tmp_buf, sizeof(tmp_buf), "yes:%u",
1134 					 part_ptr->max_share);
1135 				temp_char = tmp_buf;
1136 			} else
1137 				temp_char = "no";
1138 			break;
1139 		case SORTID_OVER_TIME_LIMIT:
1140 			if (part_ptr->over_time_limit == INFINITE16) {
1141 				temp_char = "UNLIMITED";
1142 			} else if (part_ptr->over_time_limit == NO_VAL16) {
1143 				temp_char = "N/A";
1144 			} else {
1145 				snprintf(tmp_buf, sizeof(tmp_buf), "%u",
1146 					 part_ptr->over_time_limit);
1147 				temp_char = tmp_buf;
1148 			}
1149 			break;
1150 		case SORTID_TMP_DISK:
1151 			convert_num_unit(
1152 				(float)sview_part_info->sub_part_total.
1153 				disk_total,
1154 				time_buf, sizeof(time_buf), UNIT_NONE, NO_VAL,
1155 				working_sview_config.convert_flags);
1156 			temp_char = time_buf;
1157 			break;
1158 		case SORTID_TIMELIMIT:
1159 			limit_set = part_ptr->max_time;
1160 			break;
1161 		case SORTID_QOS_CHAR:
1162 			if (part_ptr->qos_char)
1163 				temp_char = part_ptr->qos_char;
1164 			else
1165 				temp_char = "N/A";
1166 			break;
1167 		default:
1168 			break;
1169 		}
1170 
1171 		if (yes_no != -1) {
1172 			if (yes_no)
1173 				temp_char = "yes";
1174 			else
1175 				temp_char = "no";
1176 			yes_no = -1;
1177 		} else if (limit_set != NO_VAL) {
1178 			if (limit_set == INFINITE)
1179 				temp_char = "infinite";
1180 			else {
1181 				convert_num_unit(
1182 					(float)limit_set, time_buf,
1183 					sizeof(time_buf), UNIT_NONE, NO_VAL,
1184 					working_sview_config.convert_flags);
1185 				temp_char = time_buf;
1186 			}
1187 			limit_set = NO_VAL;
1188 		}
1189 
1190 		if (temp_char) {
1191 			add_display_treestore_line(
1192 				update, treestore, &iter,
1193 				find_col_name(display_data_part,
1194 					      i),
1195 				temp_char);
1196 			if (i == SORTID_NODES) {
1197 				add_display_treestore_line(
1198 					update, treestore, &iter,
1199 					"Nodes (Allocated/Idle/Other)",
1200 					ind_cnt);
1201 			}
1202 			temp_char = NULL;
1203 		}
1204 		xfree(job_def_str);
1205 	}
1206 }
1207 
_update_part_record(sview_part_info_t * sview_part_info,GtkTreeStore * treestore)1208 static void _update_part_record(sview_part_info_t *sview_part_info,
1209 				GtkTreeStore *treestore)
1210 {
1211 	char tmp_prio_job_factor[40], tmp_prio_tier[40];
1212 	char tmp_size[40], tmp_over_subscribe_buf[40], tmp_time[40];
1213 	char tmp_max_nodes[40], tmp_min_nodes[40], tmp_grace[40];
1214 	char tmp_over_time_limit_buf[40];
1215 	char tmp_cpu_cnt[40], tmp_node_cnt[40], tmp_max_cpus_per_node[40];
1216 	char *tmp_alt, *tmp_default, *tmp_accounts, *tmp_groups, *tmp_hidden;
1217 	char *tmp_deny_accounts, *tmp_qos_char, *tmp_exc_user;
1218 	char *tmp_qos, *tmp_deny_qos, *job_def_str = NULL;
1219 	char *tmp_root, *tmp_over_subscribe, *tmp_over_time_limit, *tmp_state;
1220 	uint16_t tmp_preempt;
1221 	partition_info_t *part_ptr = sview_part_info->part_ptr;
1222 	GtkTreeIter sub_iter;
1223 
1224 	if (part_ptr->alternate)
1225 		tmp_alt = part_ptr->alternate;
1226 	else
1227 		tmp_alt = "";
1228 
1229 	sprintf(tmp_cpu_cnt, "%u", part_ptr->total_cpus);
1230 
1231 	if (part_ptr->flags & PART_FLAG_DEFAULT)
1232 		tmp_default = "yes";
1233 	else
1234 		tmp_default = "no";
1235 
1236 	if (part_ptr->allow_accounts)
1237 		tmp_accounts = part_ptr->allow_accounts;
1238 	else
1239 		tmp_accounts = "all";
1240 
1241 	if (part_ptr->allow_groups)
1242 		tmp_groups = part_ptr->allow_groups;
1243 	else
1244 		tmp_groups = "all";
1245 
1246 	if (part_ptr->allow_qos)
1247 		tmp_qos = part_ptr->allow_qos;
1248 	else
1249 		tmp_qos = "all";
1250 
1251 	if (part_ptr->deny_accounts)
1252 		tmp_deny_accounts = part_ptr->deny_accounts;
1253 	else
1254 		tmp_deny_accounts = "none";
1255 
1256 	if (part_ptr->deny_qos)
1257 		tmp_deny_qos = part_ptr->deny_qos;
1258 	else
1259 		tmp_deny_qos = "none";
1260 
1261 	if (part_ptr->flags & PART_FLAG_EXCLUSIVE_USER)
1262 		tmp_exc_user = "yes";
1263 	else
1264 		tmp_exc_user = "no";
1265 
1266 	if (part_ptr->flags & PART_FLAG_HIDDEN)
1267 		tmp_hidden = "yes";
1268 	else
1269 		tmp_hidden = "no";
1270 
1271 	if (part_ptr->grace_time == NO_VAL)
1272 		snprintf(tmp_grace, sizeof(tmp_grace), "none");
1273 	else {
1274 		secs2time_str(part_ptr->grace_time,
1275 			      tmp_grace, sizeof(tmp_grace));
1276 	}
1277 
1278 	job_def_str = job_defaults_str(part_ptr->job_defaults_list);
1279 
1280 	if (part_ptr->max_nodes == INFINITE)
1281 		snprintf(tmp_max_nodes, sizeof(tmp_max_nodes), "infinite");
1282 	else {
1283 		convert_num_unit((float)part_ptr->max_nodes, tmp_max_nodes,
1284 				 sizeof(tmp_max_nodes), UNIT_NONE, NO_VAL,
1285 				 working_sview_config.convert_flags);
1286 	}
1287 
1288 	if (part_ptr->min_nodes == INFINITE)
1289 		snprintf(tmp_min_nodes, sizeof(tmp_min_nodes), "infinite");
1290 	else {
1291 		convert_num_unit((float)part_ptr->min_nodes, tmp_min_nodes,
1292 				 sizeof(tmp_min_nodes), UNIT_NONE, NO_VAL,
1293 				 working_sview_config.convert_flags);
1294 	}
1295 
1296 	if (part_ptr->max_cpus_per_node == INFINITE) {
1297 		sprintf(tmp_max_cpus_per_node, "UNLIMITED");
1298 	} else {
1299 		sprintf(tmp_max_cpus_per_node, "%u",
1300 			part_ptr->max_cpus_per_node);
1301 	}
1302 
1303 	sprintf(tmp_node_cnt, "%u", part_ptr->total_nodes);
1304 
1305 	if (part_ptr->flags & PART_FLAG_ROOT_ONLY)
1306 		tmp_root = "yes";
1307 	else
1308 		tmp_root = "no";
1309 
1310 	if (part_ptr->state_up == PARTITION_UP)
1311 		tmp_state = "up";
1312 	else if (part_ptr->state_up == PARTITION_DOWN)
1313 		tmp_state = "down";
1314 	else if (part_ptr->state_up == PARTITION_INACTIVE)
1315 		tmp_state = "inact";
1316 	else if (part_ptr->state_up == PARTITION_DRAIN)
1317 		tmp_state = "drain";
1318 	else
1319 		tmp_state = "unk";
1320 
1321 	_build_min_max_32_string(tmp_size, sizeof(tmp_size),
1322 				 part_ptr->min_nodes,
1323 				 part_ptr->max_nodes, true);
1324 
1325 	tmp_preempt = part_ptr->preempt_mode;
1326 	if (tmp_preempt == NO_VAL16)
1327 		tmp_preempt = slurm_get_preempt_mode();	/* use cluster param */
1328 
1329 	convert_num_unit((float)part_ptr->priority_job_factor,
1330 			 tmp_prio_job_factor, sizeof(tmp_prio_job_factor),
1331 			 UNIT_NONE, NO_VAL, working_sview_config.convert_flags);
1332 
1333 	convert_num_unit((float)part_ptr->priority_tier, tmp_prio_tier,
1334 			 sizeof(tmp_prio_tier), UNIT_NONE, NO_VAL,
1335 			 working_sview_config.convert_flags);
1336 
1337 	if (part_ptr->max_share & SHARED_FORCE) {
1338 		snprintf(tmp_over_subscribe_buf, sizeof(tmp_over_subscribe_buf),
1339 			 "force:%u", (part_ptr->max_share & ~(SHARED_FORCE)));
1340 		tmp_over_subscribe = tmp_over_subscribe_buf;
1341 	} else if (part_ptr->max_share == 0) {
1342 		tmp_over_subscribe = "exclusive";
1343 	} else if (part_ptr->max_share > 1) {
1344 		snprintf(tmp_over_subscribe_buf,
1345 			 sizeof(tmp_over_subscribe_buf), "yes:%u",
1346 			 part_ptr->max_share);
1347 		tmp_over_subscribe = tmp_over_subscribe_buf;
1348 	} else
1349 		tmp_over_subscribe = "no";
1350 
1351 	if (part_ptr->over_time_limit == INFINITE16) {
1352 		tmp_over_time_limit = "UNLIMITED";
1353 	} else if (part_ptr->over_time_limit == NO_VAL16) {
1354 		tmp_over_time_limit = "N/A";
1355 	} else {
1356 		snprintf(tmp_over_time_limit_buf,
1357 			 sizeof(tmp_over_time_limit_buf), "%u",
1358 			 part_ptr->over_time_limit);
1359 		tmp_over_time_limit = tmp_over_time_limit_buf;
1360 	}
1361 
1362 	if (part_ptr->max_time == INFINITE)
1363 		snprintf(tmp_time, sizeof(tmp_time), "infinite");
1364 	else {
1365 		secs2time_str((part_ptr->max_time * 60),
1366 			      tmp_time, sizeof(tmp_time));
1367 	}
1368 
1369 	if (part_ptr->qos_char)
1370 		tmp_qos_char = part_ptr->qos_char;
1371 	else
1372 		tmp_qos_char = "N/A";
1373 
1374 	/* Combining these records provides a slight performance improvement
1375 	 * NOTE: Some of these fields are cleared here and filled in based upon
1376 	 * the configuration of nodes within this partition. */
1377 	gtk_tree_store_set(treestore, &sview_part_info->iter_ptr,
1378 			   SORTID_ALTERNATE,  tmp_alt,
1379 			   SORTID_CLUSTER_NAME, part_ptr->cluster_name,
1380 			   SORTID_COLOR,
1381 				sview_colors[sview_part_info->color_inx],
1382 			   SORTID_COLOR_INX,  sview_part_info->color_inx,
1383 			   SORTID_CPUS,       tmp_cpu_cnt,
1384 			   SORTID_DEFAULT,    tmp_default,
1385 			   SORTID_FEATURES,   "",
1386 			   SORTID_FEATURES_ACT, "",
1387 			   SORTID_GRACE_TIME, tmp_grace,
1388 			   SORTID_QOS_CHAR,   tmp_qos_char,
1389 			   SORTID_ALLOW_ACCOUNTS, tmp_accounts,
1390 			   SORTID_ALLOW_GROUPS, tmp_groups,
1391 			   SORTID_ALLOW_QOS,  tmp_qos,
1392 			   SORTID_DENY_ACCOUNTS, tmp_deny_accounts,
1393 			   SORTID_DENY_QOS,   tmp_deny_qos,
1394 			   SORTID_EXCLUSIVE_USER, tmp_exc_user,
1395 			   SORTID_HIDDEN,     tmp_hidden,
1396 			   SORTID_JOB_DEFAULTS, job_def_str,
1397 			   SORTID_JOB_SIZE,   tmp_size,
1398 			   SORTID_MAX_CPUS_PER_NODE, tmp_max_cpus_per_node,
1399 			   SORTID_MEM,        "",
1400 			   SORTID_NAME,       part_ptr->name,
1401 			   SORTID_NODE_INX,   part_ptr->node_inx,
1402 			   SORTID_NODE_STATE, "",
1403 			   SORTID_NODE_STATE_NUM, -1,
1404 			   SORTID_NODES,      tmp_node_cnt,
1405 			   SORTID_NODES_MAX,  tmp_max_nodes,
1406 			   SORTID_NODES_MIN,  tmp_min_nodes,
1407 			   SORTID_NODELIST,   part_ptr->nodes,
1408 			   SORTID_ONLY_LINE,  0,
1409 			   SORTID_OVER_SUBSCRIBE, tmp_over_subscribe,
1410 			   SORTID_OVER_TIME_LIMIT, tmp_over_time_limit,
1411 			   SORTID_PART_STATE, tmp_state,
1412 			   SORTID_PREEMPT_MODE,
1413 				preempt_mode_string(tmp_preempt),
1414 			   SORTID_PRIORITY_JOB_FACTOR, tmp_prio_job_factor,
1415 			   SORTID_PRIORITY_TIER, tmp_prio_tier,
1416 			   SORTID_REASON,     "",
1417 			   SORTID_ROOT,       tmp_root,
1418 			   SORTID_TIMELIMIT,  tmp_time,
1419 			   SORTID_TMP_DISK,   "",
1420 			   SORTID_UPDATED,    1,
1421 			   -1);
1422 	xfree(job_def_str);
1423 
1424 	if (gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore),
1425 					 &sub_iter,
1426 					 &sview_part_info->iter_ptr))
1427 		_subdivide_part(sview_part_info,
1428 				GTK_TREE_MODEL(treestore), &sub_iter,
1429 				&sview_part_info->iter_ptr);
1430 	else
1431 		_subdivide_part(sview_part_info,
1432 				GTK_TREE_MODEL(treestore), NULL,
1433 				&sview_part_info->iter_ptr);
1434 
1435 	return;
1436 }
1437 
_update_part_sub_record(sview_part_sub_t * sview_part_sub,GtkTreeStore * treestore,GtkTreeIter * iter)1438 static void _update_part_sub_record(sview_part_sub_t *sview_part_sub,
1439 				    GtkTreeStore *treestore, GtkTreeIter *iter)
1440 {
1441 	partition_info_t *part_ptr = sview_part_sub->part_ptr;
1442 	char *tmp_cpus = NULL, *tmp_nodes = NULL, *tmp_nodelist;
1443 	char *tmp_state_lower, *tmp_state_upper;
1444 	char tmp_cnt[40], tmp_disk[40], tmp_mem[40];
1445 
1446 	tmp_state_upper = node_state_string(sview_part_sub->node_state);
1447 	tmp_state_lower = str_tolower(tmp_state_upper);
1448 
1449 	if ((sview_part_sub->node_state & NODE_STATE_BASE)
1450 	    == NODE_STATE_MIXED) {
1451 		if (sview_part_sub->cpu_alloc_cnt) {
1452 			convert_num_unit((float)sview_part_sub->cpu_alloc_cnt,
1453 					 tmp_cnt,
1454 					 sizeof(tmp_cnt), UNIT_NONE, NO_VAL,
1455 					 working_sview_config.convert_flags);
1456 			xstrfmtcat(tmp_cpus, "Alloc:%s", tmp_cnt);
1457 		}
1458 		if (sview_part_sub->cpu_idle_cnt) {
1459 			convert_num_unit((float)sview_part_sub->cpu_idle_cnt,
1460 					 tmp_cnt,
1461 					 sizeof(tmp_cnt), UNIT_NONE, NO_VAL,
1462 					 working_sview_config.convert_flags);
1463 			if (tmp_cpus)
1464 				xstrcat(tmp_cpus, " ");
1465 			xstrfmtcat(tmp_cpus, "Idle:%s", tmp_cnt);
1466 		}
1467 	} else {
1468 		tmp_cpus = xmalloc(20);
1469 		convert_num_unit((float)sview_part_sub->cpu_cnt,
1470 				 tmp_cpus, 20, UNIT_NONE, NO_VAL,
1471 				 working_sview_config.convert_flags);
1472 	}
1473 
1474 	if (!tmp_nodes) {
1475 		convert_num_unit((float)sview_part_sub->node_cnt, tmp_cnt,
1476 				 sizeof(tmp_cnt), UNIT_NONE, NO_VAL,
1477 				 working_sview_config.convert_flags);
1478 		tmp_nodes = xstrdup(tmp_cnt);
1479 	}
1480 
1481 	convert_num_unit((float)sview_part_sub->disk_total, tmp_disk,
1482 			 sizeof(tmp_disk), UNIT_NONE, NO_VAL,
1483 			 working_sview_config.convert_flags);
1484 
1485 	convert_num_unit((float)sview_part_sub->mem_total, tmp_mem,
1486 			 sizeof(tmp_mem), UNIT_MEGA, NO_VAL,
1487 			 working_sview_config.convert_flags);
1488 
1489 	tmp_nodelist = hostlist_ranged_string_xmalloc(sview_part_sub->hl);
1490 
1491 	gtk_tree_store_set(treestore, iter,
1492 			   SORTID_CPUS,           tmp_cpus,
1493 			   SORTID_FEATURES,       sview_part_sub->features,
1494 			   SORTID_FEATURES_ACT,   sview_part_sub->features_act,
1495 			   SORTID_MEM,            tmp_mem,
1496 			   SORTID_NAME,           part_ptr->name,
1497 			   SORTID_NODE_STATE_NUM, sview_part_sub->node_state,
1498 			   SORTID_NODELIST,       tmp_nodelist,
1499 			   SORTID_NODES,          tmp_nodes,
1500 			   SORTID_NODE_STATE,     tmp_state_lower,
1501 			   SORTID_REASON,         sview_part_sub->reason,
1502 			   SORTID_TMP_DISK,       tmp_disk,
1503 			   SORTID_UPDATED,        1,
1504 			   -1);
1505 
1506 	xfree(tmp_cpus);
1507 	xfree(tmp_nodelist);
1508 	xfree(tmp_nodes);
1509 	xfree(tmp_state_lower);
1510 
1511 	return;
1512 }
1513 
_append_part_record(sview_part_info_t * sview_part_info,GtkTreeStore * treestore)1514 static void _append_part_record(sview_part_info_t *sview_part_info,
1515 				GtkTreeStore *treestore)
1516 {
1517 	gtk_tree_store_append(treestore, &sview_part_info->iter_ptr, NULL);
1518 	gtk_tree_store_set(treestore, &sview_part_info->iter_ptr,
1519 			   SORTID_POS, sview_part_info->pos, -1);
1520 	_update_part_record(sview_part_info, treestore);
1521 }
1522 
_append_part_sub_record(sview_part_sub_t * sview_part_sub,GtkTreeStore * treestore,GtkTreeIter * iter,int line)1523 static void _append_part_sub_record(sview_part_sub_t *sview_part_sub,
1524 				    GtkTreeStore *treestore, GtkTreeIter *iter,
1525 				    int line)
1526 {
1527 	GtkTreeIter sub_iter;
1528 
1529 	gtk_tree_store_append(treestore, &sub_iter, iter);
1530 	gtk_tree_store_set(treestore, &sub_iter, SORTID_POS, line, -1);
1531 	_update_part_sub_record(sview_part_sub, treestore, &sub_iter);
1532 }
1533 
_update_info_part(List info_list,GtkTreeView * tree_view)1534 static void _update_info_part(List info_list,
1535 			      GtkTreeView *tree_view)
1536 {
1537 	GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
1538 	char *name = NULL;
1539 	ListIterator itr = NULL;
1540 	sview_part_info_t *sview_part_info = NULL;
1541 
1542 	set_for_update(model, SORTID_UPDATED);
1543 
1544 	itr = list_iterator_create(info_list);
1545 	while ((sview_part_info = list_next(itr))) {
1546 		/* This means the tree_store changed (added new column
1547 		   or something). */
1548 		if (last_model != model)
1549 			sview_part_info->iter_set = false;
1550 
1551 		if (sview_part_info->iter_set) {
1552 			gtk_tree_model_get(model, &sview_part_info->iter_ptr,
1553 					   SORTID_NAME, &name, -1);
1554 			if (xstrcmp(name, sview_part_info->part_name))
1555 				/* Bad pointer */
1556 				sview_part_info->iter_set = false;
1557 			g_free(name);
1558 		}
1559 		if (sview_part_info->iter_set)
1560 			_update_part_record(sview_part_info,
1561 					    GTK_TREE_STORE(model));
1562 		else {
1563 			_append_part_record(sview_part_info,
1564 					    GTK_TREE_STORE(model));
1565 			sview_part_info->iter_set = true;
1566 		}
1567 	}
1568 	list_iterator_destroy(itr);
1569 	/* remove all old partitions */
1570 	remove_old(model, SORTID_UPDATED);
1571 	last_model = model;
1572 	return;
1573 }
1574 
_part_info_free(sview_part_info_t * sview_part_info)1575 static void _part_info_free(sview_part_info_t *sview_part_info)
1576 {
1577 	if (sview_part_info) {
1578 		xfree(sview_part_info->cluster_name);
1579 		xfree(sview_part_info->part_name);
1580 		memset(&sview_part_info->sub_part_total, 0,
1581 		       sizeof(sview_part_sub_t));
1582 		FREE_NULL_LIST(sview_part_info->sub_list);
1583 	}
1584 }
1585 
_part_info_list_del(void * object)1586 static void _part_info_list_del(void *object)
1587 {
1588 	sview_part_info_t *sview_part_info = (sview_part_info_t *)object;
1589 
1590 	if (sview_part_info) {
1591 		_part_info_free(sview_part_info);
1592 		xfree(sview_part_info);
1593 	}
1594 }
1595 
_destroy_part_sub(void * object)1596 static void _destroy_part_sub(void *object)
1597 {
1598 	sview_part_sub_t *sview_part_sub = (sview_part_sub_t *)object;
1599 
1600 	if (sview_part_sub) {
1601 		xfree(sview_part_sub->features);
1602 		xfree(sview_part_sub->features_act);
1603 		xfree(sview_part_sub->reason);
1604 		if (sview_part_sub->hl)
1605 			hostlist_destroy(sview_part_sub->hl);
1606 		FREE_NULL_LIST(sview_part_sub->node_ptr_list);
1607 		xfree(sview_part_sub);
1608 	}
1609 }
1610 
_update_sview_part_sub(sview_part_sub_t * sview_part_sub,node_info_t * node_ptr)1611 static void _update_sview_part_sub(sview_part_sub_t *sview_part_sub,
1612 				   node_info_t *node_ptr)
1613 {
1614 	int idle_cpus = node_ptr->cpus;
1615 	uint16_t alloc_cpus = 0;
1616 
1617 	xassert(sview_part_sub);
1618 	xassert(sview_part_sub->node_ptr_list);
1619 	xassert(sview_part_sub->hl);
1620 
1621 	if (sview_part_sub->node_cnt == 0) {	/* first node added */
1622 		sview_part_sub->node_state   = node_ptr->node_state;
1623 		sview_part_sub->features     = xstrdup(node_ptr->features);
1624 		sview_part_sub->features_act = xstrdup(node_ptr->features_act);
1625 		sview_part_sub->reason       = xstrdup(node_ptr->reason);
1626 	} else if (hostlist_find(sview_part_sub->hl, node_ptr->name) != -1) {
1627 		/* we already have this node in this record,
1628 		 * just return, don't duplicate */
1629 		g_print("already been here\n");
1630 		return;
1631 	}
1632 
1633 	if ((sview_part_sub->node_state & NODE_STATE_BASE)
1634 	    == NODE_STATE_MIXED) {
1635 		slurm_get_select_nodeinfo(node_ptr->select_nodeinfo,
1636 					  SELECT_NODEDATA_SUBCNT,
1637 					  NODE_STATE_ALLOCATED,
1638 					  &alloc_cpus);
1639 		idle_cpus -= alloc_cpus;
1640 	} else if (sview_part_sub->node_state == NODE_STATE_ALLOCATED) {
1641 		alloc_cpus = idle_cpus;
1642 		idle_cpus = 0;
1643 	}
1644 
1645 	sview_part_sub->cpu_cnt += alloc_cpus + idle_cpus;
1646 	sview_part_sub->cpu_alloc_cnt += alloc_cpus;
1647 	sview_part_sub->cpu_idle_cnt += idle_cpus;
1648 	sview_part_sub->disk_total += node_ptr->tmp_disk;
1649 	sview_part_sub->mem_total  += node_ptr->real_memory;
1650 	sview_part_sub->node_cnt++;
1651 
1652 	list_append(sview_part_sub->node_ptr_list, node_ptr);
1653 	hostlist_push_host(sview_part_sub->hl, node_ptr->name);
1654 }
1655 
1656 /*
1657  * _create_sview_part_sub - create an sview_part_sub record for
1658  *                          the given partition
1659  * sview_part_sub OUT     - ptr to an inited sview_part_sub_t
1660  */
_create_sview_part_sub(partition_info_t * part_ptr,node_info_t * node_ptr)1661 static sview_part_sub_t *_create_sview_part_sub(partition_info_t *part_ptr,
1662 						node_info_t *node_ptr)
1663 {
1664 	sview_part_sub_t *sview_part_sub_ptr =
1665 		xmalloc(sizeof(sview_part_sub_t));
1666 
1667 	if (!part_ptr) {
1668 		g_print("got no part_ptr!\n");
1669 		xfree(sview_part_sub_ptr);
1670 		return NULL;
1671 	}
1672 	if (!node_ptr) {
1673 		g_print("got no node_ptr!\n");
1674 		xfree(sview_part_sub_ptr);
1675 		return NULL;
1676 	}
1677 	sview_part_sub_ptr->part_ptr = part_ptr;
1678 	sview_part_sub_ptr->hl = hostlist_create(NULL);
1679 	sview_part_sub_ptr->node_ptr_list = list_create(NULL);
1680 	_update_sview_part_sub(sview_part_sub_ptr, node_ptr);
1681 
1682 	return sview_part_sub_ptr;
1683 }
1684 
_insert_sview_part_sub(sview_part_info_t * sview_part_info,partition_info_t * part_ptr,node_info_t * node_ptr)1685 static int _insert_sview_part_sub(sview_part_info_t *sview_part_info,
1686 				  partition_info_t *part_ptr,
1687 				  node_info_t *node_ptr)
1688 {
1689 	sview_part_sub_t *sview_part_sub = NULL;
1690 	ListIterator itr = list_iterator_create(sview_part_info->sub_list);
1691 
1692 	while ((sview_part_sub = list_next(itr))) {
1693 		if (sview_part_sub->node_state
1694 		    == node_ptr->node_state) {
1695 			_update_sview_part_sub(sview_part_sub,
1696 					       node_ptr);
1697 			break;
1698 		}
1699 	}
1700 	list_iterator_destroy(itr);
1701 
1702 	if (!sview_part_sub) {
1703 		if ((sview_part_sub = _create_sview_part_sub(
1704 			     part_ptr, node_ptr)))
1705 			list_push(sview_part_info->sub_list,
1706 				  sview_part_sub);
1707 	}
1708 	return SLURM_SUCCESS;
1709 }
1710 
_sview_part_sort_aval_dec(void * a,void * b)1711 static int _sview_part_sort_aval_dec(void *a, void *b)
1712 {
1713 	sview_part_info_t *rec_a = *(sview_part_info_t **)a;
1714 	sview_part_info_t *rec_b = *(sview_part_info_t **)b;
1715 	int size_a;
1716 	int size_b;
1717 
1718 	size_a = rec_a->part_ptr->total_nodes;
1719 	size_b = rec_b->part_ptr->total_nodes;
1720 
1721 	if (size_a < size_b)
1722 		return -1;
1723 	else if (size_a > size_b)
1724 		return 1;
1725 
1726 	if (rec_a->part_ptr->nodes && rec_b->part_ptr->nodes) {
1727 		size_a = xstrcmp(rec_a->part_ptr->nodes,
1728 				 rec_b->part_ptr->nodes);
1729 		if (size_a < 0)
1730 			return -1;
1731 		else if (size_a > 0)
1732 			return 1;
1733 	}
1734 	return 0;
1735 }
1736 
_sview_sub_part_sort(void * a,void * b)1737 static int _sview_sub_part_sort(void *a, void *b)
1738 {
1739 	sview_part_sub_t *rec_a = *(sview_part_sub_t **)a;
1740 	sview_part_sub_t *rec_b = *(sview_part_sub_t **)b;
1741 	int size_a;
1742 	int size_b;
1743 
1744 	size_a = rec_a->node_state & NODE_STATE_BASE;
1745 	size_b = rec_b->node_state & NODE_STATE_BASE;
1746 
1747 	if (size_a < size_b)
1748 		return -1;
1749 	else if (size_a > size_b)
1750 		return 1;
1751 	return 0;
1752 }
1753 
_create_part_info_list(partition_info_msg_t * part_info_ptr,node_info_msg_t * node_info_ptr)1754 static List _create_part_info_list(partition_info_msg_t *part_info_ptr,
1755 				   node_info_msg_t *node_info_ptr)
1756 {
1757 	sview_part_info_t *sview_part_info = NULL;
1758 	partition_info_t *part_ptr = NULL;
1759 	static node_info_msg_t *last_node_info_ptr = NULL;
1760 	static partition_info_msg_t *last_part_info_ptr = NULL;
1761 	List last_list = NULL;
1762 	ListIterator last_list_itr = NULL;
1763 	node_info_t *node_ptr = NULL;
1764 	static List info_list = NULL;
1765 	int i, j2;
1766 	sview_part_sub_t *sview_part_sub = NULL;
1767 	ListIterator itr;
1768 
1769 	if (info_list && (node_info_ptr == last_node_info_ptr)
1770 	    && (part_info_ptr == last_part_info_ptr))
1771 		return info_list;
1772 
1773 	last_node_info_ptr = node_info_ptr;
1774 	last_part_info_ptr = part_info_ptr;
1775 
1776 	if (info_list)
1777 		last_list = info_list;
1778 
1779 	info_list = list_create(_part_info_list_del);
1780 
1781 	if (last_list)
1782 		last_list_itr = list_iterator_create(last_list);
1783 	for (i = 0; i < part_info_ptr->record_count; i++) {
1784 		int c_offset = 0;
1785 		part_ptr = &(part_info_ptr->partition_array[i]);
1786 
1787 		/* don't include configured excludes */
1788 		if (!working_sview_config.show_hidden &&
1789 		    part_ptr->flags & PART_FLAG_HIDDEN)
1790 			continue;
1791 
1792 		sview_part_info = NULL;
1793 
1794 		if (last_list_itr) {
1795 			while ((sview_part_info =
1796 				list_next(last_list_itr))) {
1797 				if (sview_part_info->cluster_name &&
1798 				    xstrcmp(sview_part_info->cluster_name,
1799 					    part_ptr->cluster_name))
1800 					continue;
1801 				if (!xstrcmp(sview_part_info->part_name,
1802 					     part_ptr->name)) {
1803 					list_remove(last_list_itr);
1804 					_part_info_free(sview_part_info);
1805 					break;
1806 				}
1807 			}
1808 			list_iterator_reset(last_list_itr);
1809 		}
1810 
1811 		if (!sview_part_info)
1812 			sview_part_info = xmalloc(sizeof(sview_part_info_t));
1813 		sview_part_info->part_name = xstrdup(part_ptr->name);
1814 		sview_part_info->cluster_name = xstrdup(part_ptr->cluster_name);
1815 		sview_part_info->part_ptr = part_ptr;
1816 		sview_part_info->sub_list = list_create(_destroy_part_sub);
1817 		sview_part_info->pos = i;
1818 		list_append(info_list, sview_part_info);
1819 		sview_part_info->color_inx = i % sview_colors_cnt;
1820 
1821 		if (cluster_flags & CLUSTER_FLAG_FED)
1822 			c_offset =
1823 				get_cluster_node_offset(part_ptr->cluster_name,
1824 							node_info_ptr);
1825 
1826 		j2 = 0;
1827 		while (part_ptr->node_inx[j2] >= 0) {
1828 			int i2 = 0;
1829 			for ((i2 = part_ptr->node_inx[j2]);
1830 			     (i2 <= part_ptr->node_inx[j2+1]);
1831 			     i2++) {
1832 				node_info_t *node_array;
1833 				node_array = node_info_ptr->node_array;
1834 				node_ptr   = &(node_array[i2 + c_offset]);
1835 
1836 				_insert_sview_part_sub(sview_part_info,
1837 						       part_ptr,
1838 						       node_ptr);
1839 			}
1840 			j2 += 2;
1841 		}
1842 		list_sort(sview_part_info->sub_list,
1843 			  (ListCmpF)_sview_sub_part_sort);
1844 
1845 		/* Need to do this after the fact so we deal with
1846 		   complete sub parts.
1847 		*/
1848 
1849 		itr = list_iterator_create(sview_part_info->sub_list);
1850 		while ((sview_part_sub = list_next(itr))) {
1851 			sview_part_info->sub_part_total.node_cnt +=
1852 				sview_part_sub->node_cnt;
1853 			sview_part_info->sub_part_total.cpu_cnt +=
1854 				sview_part_sub->cpu_cnt;
1855 
1856 			if (((sview_part_sub->node_state
1857 				     & NODE_STATE_BASE) == NODE_STATE_MIXED) ||
1858 				   (sview_part_sub->node_state
1859 				    == NODE_STATE_ALLOCATED))
1860 				sview_part_info->sub_part_total.node_alloc_cnt
1861 					+= sview_part_sub->node_cnt;
1862 			else if (sview_part_sub->node_state
1863 				   != NODE_STATE_IDLE)
1864 				sview_part_info->sub_part_total.node_error_cnt
1865 					+= sview_part_sub->node_cnt;
1866 			else
1867 				sview_part_info->sub_part_total.node_idle_cnt
1868 					+= sview_part_sub->node_cnt;
1869 
1870 			sview_part_info->sub_part_total.cpu_alloc_cnt +=
1871 				sview_part_sub->cpu_alloc_cnt;
1872 			sview_part_info->sub_part_total.cpu_idle_cnt +=
1873 				sview_part_sub->cpu_idle_cnt;
1874 			sview_part_info->sub_part_total.disk_total +=
1875 				sview_part_sub->disk_total;
1876 			sview_part_info->sub_part_total.mem_total +=
1877 				sview_part_sub->mem_total;
1878 			if (!sview_part_info->sub_part_total.features) {
1879 				/* store features and reasons
1880 				   in the others group */
1881 				sview_part_info->sub_part_total.features
1882 					= sview_part_sub->features;
1883 				sview_part_info->sub_part_total.features_act
1884 					= sview_part_sub->features_act;
1885 				sview_part_info->sub_part_total.reason
1886 					= sview_part_sub->reason;
1887 			}
1888 			hostlist_sort(sview_part_sub->hl);
1889 		}
1890 		list_iterator_destroy(itr);
1891 	}
1892 	list_sort(info_list, (ListCmpF)_sview_part_sort_aval_dec);
1893 
1894 	if (last_list) {
1895 		list_iterator_destroy(last_list_itr);
1896 		FREE_NULL_LIST(last_list);
1897 	}
1898 
1899 	return info_list;
1900 }
1901 
_display_info_part(List info_list,popup_info_t * popup_win)1902 static void _display_info_part(List info_list,	popup_info_t *popup_win)
1903 {
1904 	specific_info_t *spec_info = popup_win->spec_info;
1905 	char *name = (char *)spec_info->search_info->gchar_data;
1906 	char *cluster_name = (char *)spec_info->search_info->cluster_name;
1907 	int found = 0;
1908 	partition_info_t *part_ptr = NULL;
1909 	GtkTreeView *treeview = NULL;
1910 	ListIterator itr = NULL;
1911 	sview_part_info_t *sview_part_info = NULL;
1912 	int update = 0;
1913 	int j = 0;
1914 
1915 	if (!spec_info->search_info->gchar_data) {
1916 		//info = xstrdup("No pointer given!");
1917 		goto finished;
1918 	}
1919 
1920 need_refresh:
1921 	if (!spec_info->display_widget) {
1922 		treeview = create_treeview_2cols_attach_to_table(
1923 			popup_win->table);
1924 		spec_info->display_widget =
1925 			g_object_ref(GTK_WIDGET(treeview));
1926 	} else {
1927 		treeview = GTK_TREE_VIEW(spec_info->display_widget);
1928 		update = 1;
1929 	}
1930 
1931 	itr = list_iterator_create(info_list);
1932 	while ((sview_part_info = list_next(itr))) {
1933 		part_ptr = sview_part_info->part_ptr;
1934 
1935 		if (cluster_name &&
1936 		    xstrcmp(part_ptr->cluster_name, cluster_name))
1937 			continue;
1938 
1939 		if (!xstrcmp(part_ptr->name, name)) {
1940 			j = 0;
1941 			while (part_ptr->node_inx[j] >= 0) {
1942 				change_grid_color(
1943 					popup_win->grid_button_list,
1944 					part_ptr->node_inx[j],
1945 					part_ptr->node_inx[j+1],
1946 					sview_part_info->color_inx,
1947 					true, 0);
1948 				j += 2;
1949 			}
1950 			_layout_part_record(treeview, sview_part_info, update);
1951 			found = 1;
1952 			break;
1953 		}
1954 	}
1955 	list_iterator_destroy(itr);
1956 	post_setup_popup_grid_list(popup_win);
1957 
1958 	if (!found) {
1959 		if (!popup_win->not_found) {
1960 			char *temp = "PARTITION DOESN'T EXSIST\n";
1961 			GtkTreeIter iter;
1962 			GtkTreeModel *model = NULL;
1963 
1964 			/* only time this will be run so no update */
1965 			model = gtk_tree_view_get_model(treeview);
1966 			add_display_treestore_line(0,
1967 						   GTK_TREE_STORE(model),
1968 						   &iter,
1969 						   temp, "");
1970 		}
1971 		popup_win->not_found = true;
1972 	} else {
1973 		if (popup_win->not_found) {
1974 			popup_win->not_found = false;
1975 			gtk_widget_destroy(spec_info->display_widget);
1976 
1977 			goto need_refresh;
1978 		}
1979 	}
1980 	gtk_widget_show(spec_info->display_widget);
1981 
1982 finished:
1983 
1984 	return;
1985 }
1986 
_process_each_partition(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer userdata)1987 static void _process_each_partition(GtkTreeModel  *model,
1988 				    GtkTreePath   *path,
1989 				    GtkTreeIter   *iter,
1990 				    gpointer       userdata)
1991 {
1992 	char *type = userdata;
1993 	if (_DEBUG)
1994 		g_print("process_each_partition: global_multi_error = %d\n",
1995 			global_multi_error);
1996 
1997 	if (!global_multi_error) {
1998 		admin_part(model, iter, type);
1999 	}
2000 }
2001 /*process_each_partition ^^^*/
2002 
create_part_entry(update_part_msg_t * part_msg,GtkTreeModel * model,GtkTreeIter * iter)2003 extern GtkWidget *create_part_entry(update_part_msg_t *part_msg,
2004 				    GtkTreeModel *model, GtkTreeIter *iter)
2005 {
2006 	GtkScrolledWindow *window = create_scrolled_window();
2007 	GtkBin *bin = NULL;
2008 	GtkViewport *view = NULL;
2009 	GtkTable *table = NULL;
2010 	int i = 0, row = 0;
2011 	display_data_t *display_data = create_data_part;
2012 
2013 	gtk_scrolled_window_set_policy(window,
2014 				       GTK_POLICY_NEVER,
2015 				       GTK_POLICY_AUTOMATIC);
2016 	bin = GTK_BIN(&window->container);
2017 	view = GTK_VIEWPORT(bin->child);
2018 	bin = GTK_BIN(&view->bin);
2019 	table = GTK_TABLE(bin->child);
2020 	gtk_table_resize(table, SORTID_CNT, 2);
2021 
2022 	gtk_table_set_homogeneous(table, false);
2023 
2024 	for(i = 0; i < SORTID_CNT; i++) {
2025 		while (display_data++) {
2026 			if (display_data->id == -1)
2027 				break;
2028 			if (!display_data->name)
2029 				continue;
2030 			if (display_data->id != i)
2031 				continue;
2032 			display_admin_edit(
2033 				table, part_msg, &row, model, iter,
2034 				display_data,
2035 				G_CALLBACK(_admin_edit_combo_box_part),
2036 				G_CALLBACK(_admin_focus_out_part),
2037 				_set_active_combo_part);
2038 			break;
2039 		}
2040 		display_data = create_data_part;
2041 	}
2042 	gtk_table_resize(table, row, 2);
2043 
2044 	return GTK_WIDGET(window);
2045 }
2046 
check_part_includes_node(int node_dx)2047 extern bool check_part_includes_node(int node_dx)
2048 {
2049 	partition_info_t *part_ptr = NULL;
2050 	bool rc = false;
2051 	int i;
2052 	static partition_info_msg_t *part_info_ptr = NULL;
2053 
2054 	if (working_sview_config.show_hidden)
2055 		return true;
2056 
2057 	if (!g_part_info_ptr) {
2058 		i = get_new_info_part(&part_info_ptr, true);
2059 		if (!g_part_info_ptr || (i && (i != SLURM_NO_CHANGE_IN_DATA))) {
2060 			if (_DEBUG)
2061 				g_print("%s : error %d ", __func__, i);
2062 			return false;
2063 		}
2064 	}
2065 
2066 	for (i = 0; i < g_part_info_ptr->record_count; i++) {
2067 		/* don't include allow group or hidden excludes */
2068 		part_ptr = &(g_part_info_ptr->partition_array[i]);
2069 		if (part_ptr->flags & PART_FLAG_HIDDEN)
2070 			continue;
2071 		if (part_ptr->node_inx[0] >= 0) {
2072 			if (_DEBUG) {
2073 				g_print("node_dx = %d ", node_dx);
2074 				g_print("part_node_inx[0] = %d ",
2075 					part_ptr->node_inx[0]);
2076 				g_print("part_node_inx[1] = %d \n",
2077 					part_ptr->node_inx[1]);
2078 			}
2079 			if (node_dx >= part_ptr->node_inx[0] &&
2080 			    node_dx <= part_ptr->node_inx[1]) {
2081 				rc = true;
2082 				if (_DEBUG)
2083 					g_print("hit!!\n");
2084 			}
2085 		}
2086 		if (rc)
2087 			break;
2088 	}
2089 	return rc;
2090 }
2091 
2092 
refresh_part(GtkAction * action,gpointer user_data)2093 extern void refresh_part(GtkAction *action, gpointer user_data)
2094 {
2095 	popup_info_t *popup_win = (popup_info_t *)user_data;
2096 	xassert(popup_win);
2097 	xassert(popup_win->spec_info);
2098 	xassert(popup_win->spec_info->title);
2099 	popup_win->force_refresh = 1;
2100 	specific_info_part(popup_win);
2101 }
2102 
2103 
get_new_info_part(partition_info_msg_t ** part_ptr,int force)2104 extern int get_new_info_part(partition_info_msg_t **part_ptr, int force)
2105 {
2106 	static partition_info_msg_t *new_part_ptr = NULL;
2107 	uint16_t show_flags = 0;
2108 	int error_code = SLURM_NO_CHANGE_IN_DATA;
2109 	time_t now = time(NULL);
2110 	static time_t last;
2111 	static bool changed = 0;
2112 	static uint16_t last_flags = 0;
2113 
2114 	if (g_part_info_ptr && !force
2115 	    && ((now - last) < working_sview_config.refresh_delay)) {
2116 		if (*part_ptr != g_part_info_ptr)
2117 			error_code = SLURM_SUCCESS;
2118 		*part_ptr = g_part_info_ptr;
2119 		if (changed)
2120 			error_code = SLURM_SUCCESS;
2121 		goto end_it;
2122 	}
2123 	last = now;
2124 
2125 	if (cluster_flags & CLUSTER_FLAG_FED)
2126 		show_flags |= SHOW_FEDERATION;
2127 	if (working_sview_config.show_hidden)
2128 		/*ignore 'AllowGroups, Hidden settings*/
2129 		show_flags |= SHOW_ALL;
2130 
2131 	if (g_part_info_ptr) {
2132 		if (show_flags != last_flags)
2133 			g_part_info_ptr->last_update = 0;
2134 		error_code = slurm_load_partitions(g_part_info_ptr->last_update,
2135 						   &new_part_ptr, show_flags);
2136 		if (error_code == SLURM_SUCCESS) {
2137 			slurm_free_partition_info_msg(g_part_info_ptr);
2138 			changed = 1;
2139 		} else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) {
2140 			error_code = SLURM_NO_CHANGE_IN_DATA;
2141 			new_part_ptr = g_part_info_ptr;
2142 			changed = 0;
2143 		}
2144 	} else {
2145 		new_part_ptr = NULL;
2146 		error_code = slurm_load_partitions((time_t) NULL, &new_part_ptr,
2147 						   show_flags);
2148 		changed = 1;
2149 	}
2150 
2151 	last_flags = show_flags;
2152 	g_part_info_ptr = new_part_ptr;
2153 
2154 	if (g_part_info_ptr && (*part_ptr != g_part_info_ptr))
2155 		error_code = SLURM_SUCCESS;
2156 
2157 	*part_ptr = new_part_ptr;
2158 end_it:
2159 
2160 	return error_code;
2161 }
2162 
_create_model_part2(int type)2163 static GtkListStore *_create_model_part2(int type)
2164 {
2165 	GtkListStore *model = NULL;
2166 	GtkTreeIter iter;
2167 
2168 	last_model = NULL;	/* Reformat display */
2169 	switch (type) {
2170 	case SORTID_DEFAULT:
2171 	case SORTID_EXCLUSIVE_USER:
2172 	case SORTID_HIDDEN:
2173 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2174 		gtk_list_store_append(model, &iter);
2175 		gtk_list_store_set(model, &iter,
2176 				   0, "no (default)", 1, SORTID_DEFAULT, -1);
2177 		gtk_list_store_append(model, &iter);
2178 		gtk_list_store_set(model, &iter,
2179 				   0, "yes", 1, SORTID_DEFAULT, -1);
2180 		break;
2181 	case SORTID_ROOT:
2182 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2183 		gtk_list_store_append(model, &iter);
2184 		gtk_list_store_set(model, &iter,
2185 				   0, "yes (default)", 1, SORTID_DEFAULT, -1);
2186 		gtk_list_store_append(model, &iter);
2187 		gtk_list_store_set(model, &iter,
2188 				   0, "no", 1, SORTID_DEFAULT, -1);
2189 		break;
2190 	case SORTID_OVER_SUBSCRIBE:
2191 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2192 		gtk_list_store_append(model, &iter);
2193 		gtk_list_store_set(model, &iter, 0, "no (default)",
2194 				   1, SORTID_OVER_SUBSCRIBE, -1);
2195 		gtk_list_store_append(model, &iter);
2196 		gtk_list_store_set(model, &iter,  0, "yes",
2197 				  1, SORTID_OVER_SUBSCRIBE, -1);
2198 		gtk_list_store_append(model, &iter);
2199 		gtk_list_store_set(model, &iter, 0, "force",
2200 				   1, SORTID_OVER_SUBSCRIBE, -1);
2201 		gtk_list_store_append(model, &iter);
2202 		gtk_list_store_set(model, &iter, 0, "exclusive",
2203 				   1, SORTID_OVER_SUBSCRIBE, -1);
2204 		break;
2205 	case SORTID_PART_STATE:
2206 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2207 		gtk_list_store_append(model, &iter);
2208 		gtk_list_store_set(model, &iter,
2209 				   0, "up (default)", 1, SORTID_PART_STATE, -1);
2210 		gtk_list_store_append(model, &iter);
2211 		gtk_list_store_set(model, &iter,
2212 				   0, "down", 1, SORTID_PART_STATE, -1);
2213 		gtk_list_store_append(model, &iter);
2214 		gtk_list_store_set(model, &iter,
2215 				   0, "inactive", 1, SORTID_PART_STATE, -1);
2216 		gtk_list_store_append(model, &iter);
2217 		gtk_list_store_set(model, &iter,
2218 				   0, "drain", 1, SORTID_PART_STATE, -1);
2219 		break;
2220 	case SORTID_PREEMPT_MODE:
2221 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2222 		gtk_list_store_append(model, &iter);
2223 		gtk_list_store_set(model, &iter, 0,
2224 				preempt_mode_string(slurm_get_preempt_mode()),
2225 				1, SORTID_PREEMPT_MODE, -1);
2226 		gtk_list_store_append(model, &iter);
2227 		gtk_list_store_set(model, &iter,
2228 				   0, "cancel", 1, SORTID_PREEMPT_MODE, -1);
2229 		gtk_list_store_append(model, &iter);
2230 		gtk_list_store_set(model, &iter,
2231 				   0, "off", 1, SORTID_PREEMPT_MODE, -1);
2232 		gtk_list_store_append(model, &iter);
2233 		gtk_list_store_set(model, &iter,
2234 				   0, "requeue", 1, SORTID_PREEMPT_MODE, -1);
2235 		gtk_list_store_append(model, &iter);
2236 		gtk_list_store_set(model, &iter,
2237 				   0, "suspend", 1, SORTID_PREEMPT_MODE, -1);
2238 		break;
2239 	}
2240 
2241 	return model;
2242 }
2243 
create_model_part(int type)2244 extern GtkListStore *create_model_part(int type)
2245 {
2246 	GtkListStore *model = NULL;
2247 	GtkTreeIter iter;
2248 	char *upper = NULL, *lower = NULL;
2249 	int i = 0;
2250 
2251 	last_model = NULL;	/* Reformat display */
2252 	switch (type) {
2253 	case SORTID_DEFAULT:
2254 	case SORTID_EXCLUSIVE_USER:
2255 	case SORTID_HIDDEN:
2256 	case SORTID_ROOT:
2257 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2258 		gtk_list_store_append(model, &iter);
2259 		gtk_list_store_set(model, &iter,
2260 				   0, "yes", 1, type, -1);
2261 		gtk_list_store_append(model, &iter);
2262 		gtk_list_store_set(model, &iter,
2263 				   0, "no", 1, type, -1);
2264 		break;
2265 	case SORTID_PREEMPT_MODE:
2266 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2267 		gtk_list_store_append(model, &iter);
2268 		gtk_list_store_set(model, &iter,
2269 				   0, "cancel", 1, SORTID_PREEMPT_MODE, -1);
2270 		gtk_list_store_append(model, &iter);
2271 		gtk_list_store_set(model, &iter,
2272 				   0, "off", 1, SORTID_PREEMPT_MODE, -1);
2273 		gtk_list_store_append(model, &iter);
2274 		gtk_list_store_set(model, &iter,
2275 				   0, "requeue", 1, SORTID_PREEMPT_MODE, -1);
2276 		gtk_list_store_append(model, &iter);
2277 		gtk_list_store_set(model, &iter,
2278 				   0, "suspend", 1, SORTID_PREEMPT_MODE, -1);
2279 		break;
2280 	case SORTID_GRACE_TIME:
2281 	case SORTID_JOB_DEFAULTS:
2282 	case SORTID_PRIORITY_JOB_FACTOR:
2283 	case SORTID_PRIORITY_TIER:
2284 	case SORTID_TIMELIMIT:
2285 	case SORTID_NODES_MIN:
2286 	case SORTID_NODES_MAX:
2287 	case SORTID_MAX_CPUS_PER_NODE:
2288 	case SORTID_OVER_TIME_LIMIT:
2289 		break;
2290 	case SORTID_OVER_SUBSCRIBE:
2291 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2292 		gtk_list_store_append(model, &iter);
2293 		gtk_list_store_set(model, &iter, 0, "force",
2294 				   1, SORTID_OVER_SUBSCRIBE, -1);
2295 		gtk_list_store_append(model, &iter);
2296 		gtk_list_store_set(model, &iter, 0, "no",
2297 				   1, SORTID_OVER_SUBSCRIBE, -1);
2298 		gtk_list_store_append(model, &iter);
2299 		gtk_list_store_set(model, &iter, 0, "yes",
2300 				   1, SORTID_OVER_SUBSCRIBE, -1);
2301 		gtk_list_store_append(model, &iter);
2302 		gtk_list_store_set(model, &iter, 0, "exclusive",
2303 				   1, SORTID_OVER_SUBSCRIBE, -1);
2304 		break;
2305 	case SORTID_ALLOW_ACCOUNTS:
2306 		break;
2307 	case SORTID_ALLOW_GROUPS:
2308 		break;
2309 	case SORTID_ALLOW_QOS:
2310 		break;
2311 	case SORTID_DENY_ACCOUNTS:
2312 		break;
2313 	case SORTID_DENY_QOS:
2314 		break;
2315 	case SORTID_NODELIST:
2316 		break;
2317 	case SORTID_PART_STATE:
2318 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2319 		gtk_list_store_append(model, &iter);
2320 		gtk_list_store_set(model, &iter,
2321 				   0, "up", 1, SORTID_PART_STATE, -1);
2322 		gtk_list_store_append(model, &iter);
2323 		gtk_list_store_set(model, &iter,
2324 				   0, "down", 1, SORTID_PART_STATE, -1);
2325 		gtk_list_store_append(model, &iter);
2326 		gtk_list_store_set(model, &iter,
2327 				   0, "inactive", 1, SORTID_PART_STATE, -1);
2328 		gtk_list_store_append(model, &iter);
2329 		gtk_list_store_set(model, &iter,
2330 				   0, "drain", 1, SORTID_PART_STATE, -1);
2331 		break;
2332 	case SORTID_NODE_STATE:
2333 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
2334 		gtk_list_store_append(model, &iter);
2335 		gtk_list_store_set(model, &iter,
2336 				   0, "drain", 1, SORTID_NODE_STATE, -1);
2337 		gtk_list_store_append(model, &iter);
2338 		gtk_list_store_set(model, &iter,
2339 				   0, "resume", 1, SORTID_NODE_STATE, -1);
2340 		for (i = 0; i < NODE_STATE_END; i++) {
2341 			upper = node_state_string(i);
2342 			if (!xstrcmp(upper, "UNKNOWN"))
2343 				continue;
2344 
2345 			gtk_list_store_append(model, &iter);
2346 			lower = str_tolower(upper);
2347 			gtk_list_store_set(model, &iter,
2348 					   0, lower, 1, SORTID_NODE_STATE, -1);
2349 			xfree(lower);
2350 		}
2351 
2352 		break;
2353 	}
2354 
2355 	return model;
2356 }
2357 
admin_edit_part(GtkCellRendererText * cell,const char * path_string,const char * new_text,gpointer data)2358 extern void admin_edit_part(GtkCellRendererText *cell,
2359 			    const char *path_string,
2360 			    const char *new_text,
2361 			    gpointer data)
2362 {
2363 	GtkTreeStore *treestore = NULL;
2364 	GtkTreePath *path = NULL;
2365 	GtkTreeIter iter;
2366 	update_part_msg_t *part_msg = NULL;
2367 
2368 	char *temp = NULL;
2369 	char *old_text = NULL;
2370 	const char *type = NULL;
2371 	int column;
2372 
2373 	if (!new_text || !xstrcmp(new_text, ""))
2374 		goto no_input;
2375 
2376 	if (cluster_flags & CLUSTER_FLAG_FED) {
2377 		display_fed_disabled_popup(type);
2378 		goto no_input;
2379 	}
2380 
2381 	part_msg = xmalloc(sizeof(update_part_msg_t));
2382 
2383 	treestore = GTK_TREE_STORE(data);
2384 	path = gtk_tree_path_new_from_string(path_string);
2385 	gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), &iter, path);
2386 
2387 	column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column"));
2388 	if (column != SORTID_NODE_STATE) {
2389 		slurm_init_part_desc_msg(part_msg);
2390 		gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter,
2391 				   SORTID_NAME, &temp,
2392 				   column, &old_text,
2393 				   -1);
2394 		part_msg->name = xstrdup(temp);
2395 		g_free(temp);
2396 	}
2397 
2398 	type = _set_part_msg(part_msg, new_text, column);
2399 	if (global_edit_error)
2400 		goto print_error;
2401 	if (got_edit_signal) {
2402 		temp = got_edit_signal;
2403 		got_edit_signal = NULL;
2404 		admin_part(GTK_TREE_MODEL(treestore), &iter, temp);
2405 		xfree(temp);
2406 		goto no_input;
2407 	}
2408 
2409 	if (got_features_edit_signal) {
2410 		admin_part(GTK_TREE_MODEL(treestore), &iter, (char *)type);
2411 		goto no_input;
2412 	}
2413 
2414 	if ((column != SORTID_NODE_STATE) && (column != SORTID_FEATURES)) {
2415 		if (old_text && !xstrcmp(old_text, new_text)) {
2416 			temp = g_strdup_printf("No change in value.");
2417 		} else if (slurm_update_partition(part_msg)
2418 			   == SLURM_SUCCESS) {
2419 			gtk_tree_store_set(treestore, &iter, column,
2420 					   new_text, -1);
2421 			temp = g_strdup_printf("Partition %s %s changed to %s",
2422 					       part_msg->name,
2423 					       type,
2424 					       new_text);
2425 		} else {
2426 		print_error:
2427 			temp = g_strdup_printf("Partition %s %s can't be "
2428 					       "set to %s",
2429 					       part_msg->name,
2430 					       type,
2431 					       new_text);
2432 		}
2433 		display_edit_note(temp);
2434 		g_free(temp);
2435 	}
2436 no_input:
2437 	slurm_free_update_part_msg(part_msg);
2438 	gtk_tree_path_free(path);
2439 	g_free(old_text);
2440 	g_mutex_unlock(sview_mutex);
2441 }
2442 
get_info_part(GtkTable * table,display_data_t * display_data)2443 extern void get_info_part(GtkTable *table, display_data_t *display_data)
2444 {
2445 	int part_error_code = SLURM_SUCCESS;
2446 	int node_error_code = SLURM_SUCCESS;
2447 	static int view = -1;
2448 	static partition_info_msg_t *part_info_ptr = NULL;
2449 	static node_info_msg_t *node_info_ptr = NULL;
2450 	char error_char[100];
2451 	GtkWidget *label = NULL;
2452 	GtkTreeView *tree_view = NULL;
2453 	static GtkWidget *display_widget = NULL;
2454 	List info_list = NULL;
2455 	int j, k;
2456 	sview_part_info_t *sview_part_info = NULL;
2457 	partition_info_t *part_ptr = NULL;
2458 	ListIterator itr = NULL;
2459 	GtkTreePath *path = NULL;
2460 	static bool set_opts = false;
2461 
2462 	if (!set_opts)
2463 		set_page_opts(PART_PAGE, display_data_part,
2464 			      SORTID_CNT, _initial_page_opts);
2465 	set_opts = true;
2466 
2467 	/* reset */
2468 	if (!table && !display_data) {
2469 		if (display_widget)
2470 			gtk_widget_destroy(display_widget);
2471 		display_widget = NULL;
2472 		part_info_ptr = NULL;
2473 		node_info_ptr = NULL;
2474 		goto reset_curs;
2475 	}
2476 
2477 	if (display_data)
2478 		local_display_data = display_data;
2479 	if (!table) {
2480 		display_data_part->set_menu = local_display_data->set_menu;
2481 		goto reset_curs;
2482 	}
2483 	if (display_widget && toggled) {
2484 		gtk_widget_destroy(display_widget);
2485 		display_widget = NULL;
2486 		goto display_it;
2487 	}
2488 
2489 	if ((part_error_code = get_new_info_part(&part_info_ptr, force_refresh))
2490 	    == SLURM_NO_CHANGE_IN_DATA) {
2491 		// just goto the new info node
2492 	} else 	if (part_error_code != SLURM_SUCCESS) {
2493 		if (view == ERROR_VIEW)
2494 			goto end_it;
2495 		if (display_widget)
2496 			gtk_widget_destroy(display_widget);
2497 		view = ERROR_VIEW;
2498 		snprintf(error_char, 100, "slurm_load_partitions: %s",
2499 			 slurm_strerror(slurm_get_errno()));
2500 		label = gtk_label_new(error_char);
2501 		display_widget = g_object_ref(GTK_WIDGET(label));
2502 		gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
2503 		gtk_widget_show(label);
2504 		goto end_it;
2505 	}
2506 
2507 	if ((node_error_code = get_new_info_node(&node_info_ptr, force_refresh))
2508 	    == SLURM_NO_CHANGE_IN_DATA) {
2509 		if ((!display_widget || view == ERROR_VIEW)
2510 		    || (part_error_code != SLURM_NO_CHANGE_IN_DATA))
2511 			goto display_it;
2512 	} else if (node_error_code != SLURM_SUCCESS) {
2513 		if (view == ERROR_VIEW)
2514 			goto end_it;
2515 		if (display_widget)
2516 			gtk_widget_destroy(display_widget);
2517 		view = ERROR_VIEW;
2518 		snprintf(error_char, 100, "slurm_load_node: %s",
2519 			 slurm_strerror(slurm_get_errno()));
2520 		label = gtk_label_new(error_char);
2521 		display_widget = g_object_ref(GTK_WIDGET(label));
2522 		gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
2523 		gtk_widget_show(label);
2524 		goto end_it;
2525 	}
2526 
2527 display_it:
2528 
2529 	info_list = _create_part_info_list(part_info_ptr, node_info_ptr);
2530 	if (!info_list)
2531 		goto reset_curs;
2532 
2533 	/* set up the grid */
2534 	if (display_widget && GTK_IS_TREE_VIEW(display_widget)
2535 	    && gtk_tree_selection_count_selected_rows(
2536 		    gtk_tree_view_get_selection(
2537 			    GTK_TREE_VIEW(display_widget)))) {
2538 		GtkTreeViewColumn *focus_column = NULL;
2539 		/* highlight the correct nodes from the last selection */
2540 		gtk_tree_view_get_cursor(GTK_TREE_VIEW(display_widget),
2541 					 &path, &focus_column);
2542 	}
2543 	if (!path) {
2544 		int array_size = node_info_ptr->record_count;
2545 		int  *color_inx = xmalloc(sizeof(int) * array_size);
2546 		bool *color_set_flag = xmalloc(sizeof(bool) * array_size);
2547 		itr = list_iterator_create(info_list);
2548 		while ((sview_part_info = list_next(itr))) {
2549 			part_ptr = sview_part_info->part_ptr;
2550 			j = 0;
2551 			while (part_ptr->node_inx[j] >= 0) {
2552 				for (k = part_ptr->node_inx[j];
2553 				     k <= part_ptr->node_inx[j+1]; k++) {
2554 					color_set_flag[k] = true;
2555 					color_inx[k] = sview_part_info->
2556 						       color_inx;
2557 				}
2558 				j += 2;
2559 			}
2560 		}
2561 		list_iterator_destroy(itr);
2562 		change_grid_color_array(grid_button_list, array_size,
2563 					color_inx, color_set_flag, true, 0);
2564 		change_grid_color(grid_button_list, -1, -1,
2565 				  MAKE_WHITE, true, 0);
2566 		xfree(color_inx);
2567 		xfree(color_set_flag);
2568 	} else {
2569 		highlight_grid(GTK_TREE_VIEW(display_widget),
2570 			       SORTID_NODE_INX, SORTID_COLOR_INX,
2571 			       grid_button_list);
2572 		gtk_tree_path_free(path);
2573 	}
2574 
2575 	if (view == ERROR_VIEW && display_widget) {
2576 		gtk_widget_destroy(display_widget);
2577 		display_widget = NULL;
2578 	}
2579 	if (!display_widget) {
2580 		int def_sort_col = SORTID_NAME;
2581 		tree_view = create_treeview(local_display_data,
2582 					    &grid_button_list);
2583 		/*set multiple capability here*/
2584 		gtk_tree_selection_set_mode(
2585 			gtk_tree_view_get_selection(tree_view),
2586 			GTK_SELECTION_MULTIPLE);
2587 		display_widget = g_object_ref(GTK_WIDGET(tree_view));
2588 		gtk_table_attach_defaults(table,
2589 					  GTK_WIDGET(tree_view),
2590 					  0, 1, 0, 1);
2591 		/* since this function sets the model of the tree_view
2592 		   to the treestore we don't really care about
2593 		   the return value */
2594 		if (cluster_flags & CLUSTER_FLAG_FED)
2595 			def_sort_col = SORTID_CLUSTER_NAME;
2596 		create_treestore(tree_view, display_data_part, SORTID_CNT,
2597 				 def_sort_col, SORTID_COLOR);
2598 	}
2599 
2600 	view = INFO_VIEW;
2601 	_update_info_part(info_list, GTK_TREE_VIEW(display_widget));
2602 end_it:
2603 	toggled = false;
2604 	force_refresh = false;
2605 reset_curs:
2606 	if (main_window && main_window->window)
2607 		gdk_window_set_cursor(main_window->window, NULL);
2608 	return;
2609 }
2610 
specific_info_part(popup_info_t * popup_win)2611 extern void specific_info_part(popup_info_t *popup_win)
2612 {
2613 	int part_error_code = SLURM_SUCCESS;
2614 	int node_error_code = SLURM_SUCCESS;
2615 	static partition_info_msg_t *part_info_ptr = NULL;
2616 	static node_info_msg_t *node_info_ptr = NULL;
2617 	specific_info_t *spec_info = popup_win->spec_info;
2618 	char error_char[100];
2619 	GtkWidget *label = NULL;
2620 	GtkTreeView *tree_view = NULL;
2621 	List info_list = NULL;
2622 	List send_info_list = NULL;
2623 	int j=0, i=-1;
2624 	sview_part_info_t *sview_part_info_ptr = NULL;
2625 	partition_info_t *part_ptr = NULL;
2626 	ListIterator itr = NULL;
2627 	hostset_t hostset = NULL;
2628 
2629 	if (!spec_info->display_widget)
2630 		setup_popup_info(popup_win, display_data_part, SORTID_CNT);
2631 
2632 	if (spec_info->display_widget && popup_win->toggled) {
2633 		gtk_widget_destroy(spec_info->display_widget);
2634 		spec_info->display_widget = NULL;
2635 		goto display_it;
2636 	}
2637 
2638 	if ((part_error_code = get_new_info_part(&part_info_ptr,
2639 						 popup_win->force_refresh))
2640 	    == SLURM_NO_CHANGE_IN_DATA)  {
2641 
2642 	} else if (part_error_code != SLURM_SUCCESS) {
2643 		if (spec_info->view == ERROR_VIEW)
2644 			goto end_it;
2645 		if (spec_info->display_widget) {
2646 			gtk_widget_destroy(spec_info->display_widget);
2647 			spec_info->display_widget = NULL;
2648 		}
2649 		spec_info->view = ERROR_VIEW;
2650 		snprintf(error_char, 100, "slurm_load_partitions: %s",
2651 			 slurm_strerror(slurm_get_errno()));
2652 		label = gtk_label_new(error_char);
2653 		spec_info->display_widget = g_object_ref(GTK_WIDGET(label));
2654 		gtk_table_attach_defaults(popup_win->table, label, 0, 1, 0, 1);
2655 		gtk_widget_show(label);
2656 		goto end_it;
2657 	}
2658 
2659 	if ((node_error_code = get_new_info_node(&node_info_ptr,
2660 						 popup_win->force_refresh))
2661 	    == SLURM_NO_CHANGE_IN_DATA) {
2662 		if ((!spec_info->display_widget
2663 		     || spec_info->view == ERROR_VIEW)
2664 		    || (part_error_code != SLURM_NO_CHANGE_IN_DATA))
2665 			goto display_it;
2666 	} else if (node_error_code != SLURM_SUCCESS) {
2667 		if (spec_info->view == ERROR_VIEW)
2668 			goto end_it;
2669 		if (spec_info->display_widget)
2670 			gtk_widget_destroy(spec_info->display_widget);
2671 		spec_info->view = ERROR_VIEW;
2672 		snprintf(error_char, 100, "slurm_load_node: %s",
2673 			 slurm_strerror(slurm_get_errno()));
2674 		label = gtk_label_new(error_char);
2675 		spec_info->display_widget = g_object_ref(GTK_WIDGET(label));
2676 		gtk_table_attach_defaults(popup_win->table, label, 0, 1, 0, 1);
2677 		gtk_widget_show(label);
2678 		goto end_it;
2679 	}
2680 
2681 display_it:
2682 
2683 	info_list = _create_part_info_list(part_info_ptr, node_info_ptr);
2684 
2685 	if (!info_list)
2686 		return;
2687 
2688 	if (spec_info->view == ERROR_VIEW && spec_info->display_widget) {
2689 		gtk_widget_destroy(spec_info->display_widget);
2690 		spec_info->display_widget = NULL;
2691 	}
2692 
2693 	if (spec_info->type != INFO_PAGE && !spec_info->display_widget) {
2694 		tree_view = create_treeview(local_display_data,
2695 					    &popup_win->grid_button_list);
2696 		/*set multiple capability here*/
2697 		gtk_tree_selection_set_mode(
2698 			gtk_tree_view_get_selection(tree_view),
2699 			GTK_SELECTION_MULTIPLE);
2700 
2701 		spec_info->display_widget =
2702 			g_object_ref(GTK_WIDGET(tree_view));
2703 		gtk_table_attach_defaults(popup_win->table,
2704 					  GTK_WIDGET(tree_view),
2705 					  0, 1, 0, 1);
2706 
2707 		/* since this function sets the model of the tree_view
2708 		   to the treestore we don't really care about
2709 		   the return value */
2710 		create_treestore(tree_view, popup_win->display_data,
2711 				 SORTID_CNT, SORTID_NAME, SORTID_COLOR);
2712 	}
2713 
2714 	setup_popup_grid_list(popup_win);
2715 
2716 	spec_info->view = INFO_VIEW;
2717 	if (spec_info->type == INFO_PAGE) {
2718 		_display_info_part(info_list, popup_win);
2719 		goto end_it;
2720 	}
2721 
2722 	/* just linking to another list, don't free the inside, just
2723 	   the list */
2724 	send_info_list = list_create(NULL);
2725 
2726 	itr = list_iterator_create(info_list);
2727 	i = -1;
2728 	while ((sview_part_info_ptr = list_next(itr))) {
2729 		i++;
2730 		part_ptr = sview_part_info_ptr->part_ptr;
2731 		switch (spec_info->type) {
2732 		case RESV_PAGE:
2733 		case NODE_PAGE:
2734 			if (!part_ptr->nodes)
2735 				continue;
2736 
2737 			if (!(hostset = hostset_create(
2738 				      spec_info->search_info->gchar_data)))
2739 				continue;
2740 			if (!hostset_intersects(hostset, part_ptr->nodes)) {
2741 				hostset_destroy(hostset);
2742 				continue;
2743 			}
2744 			hostset_destroy(hostset);
2745 			break;
2746 		case PART_PAGE:
2747 			switch(spec_info->search_info->search_type) {
2748 			case SEARCH_PARTITION_NAME:
2749 				if (!spec_info->search_info->gchar_data)
2750 					continue;
2751 
2752 				if (xstrcmp(part_ptr->name,
2753 					    spec_info->search_info->gchar_data))
2754 					continue;
2755 
2756 				if (spec_info->search_info->cluster_name &&
2757 				    xstrcmp(
2758 					part_ptr->cluster_name,
2759 					spec_info->search_info->cluster_name))
2760 					continue;
2761 				break;
2762 			case SEARCH_PARTITION_STATE:
2763 				if (spec_info->search_info->int_data == NO_VAL)
2764 					continue;
2765 				if (part_ptr->state_up !=
2766 				    spec_info->search_info->int_data)
2767 					continue;
2768 				break;
2769 			default:
2770 				continue;
2771 				break;
2772 			}
2773 			break;
2774 		case JOB_PAGE:
2775 			if (!spec_info->search_info->gchar_data)
2776 				continue;
2777 
2778 			if (xstrcmp(part_ptr->name,
2779 				    spec_info->search_info->gchar_data))
2780 				continue;
2781 
2782 			if (spec_info->search_info->cluster_name &&
2783 			    xstrcmp(part_ptr->cluster_name,
2784 				    spec_info->search_info->cluster_name))
2785 				continue;
2786 			break;
2787 		default:
2788 			g_print("Unknown type %d\n", spec_info->type);
2789 			list_iterator_destroy(itr);
2790 			goto end_it;
2791 		}
2792 		list_push(send_info_list, sview_part_info_ptr);
2793 		j=0;
2794 		while (part_ptr->node_inx[j] >= 0) {
2795 			change_grid_color(
2796 				popup_win->grid_button_list,
2797 				part_ptr->node_inx[j],
2798 				part_ptr->node_inx[j+1],
2799 				sview_part_info_ptr->color_inx, true, 0);
2800 			j += 2;
2801 		}
2802 	}
2803 	list_iterator_destroy(itr);
2804 	post_setup_popup_grid_list(popup_win);
2805 
2806 	_update_info_part(send_info_list,
2807 			  GTK_TREE_VIEW(spec_info->display_widget));
2808 	FREE_NULL_LIST(send_info_list);
2809 end_it:
2810 	popup_win->toggled = 0;
2811 	popup_win->force_refresh = 0;
2812 
2813 	return;
2814 }
2815 
set_menus_part(void * arg,void * arg2,GtkTreePath * path,int type)2816 extern void set_menus_part(void *arg, void *arg2, GtkTreePath *path, int type)
2817 {
2818 	GtkTreeView *tree_view = (GtkTreeView *)arg;
2819 	popup_info_t *popup_win = (popup_info_t *)arg;
2820 	GtkMenu *menu = (GtkMenu *)arg2;
2821 	List button_list = (List)arg2;
2822 
2823 	switch(type) {
2824 	case TAB_CLICKED:
2825 		make_fields_menu(NULL, menu, display_data_part, SORTID_CNT);
2826 		break;
2827 	case ROW_CLICKED:
2828 		make_options_menu(tree_view, path, menu, options_data_part);
2829 		break;
2830 	case ROW_LEFT_CLICKED:
2831 		highlight_grid(tree_view, SORTID_NODE_INX,
2832 			       SORTID_COLOR_INX, button_list);
2833 		break;
2834 	case FULL_CLICKED:
2835 	{
2836 		GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
2837 		GtkTreeIter iter;
2838 		if (!gtk_tree_model_get_iter(model, &iter, path)) {
2839 			g_error("error getting iter from model\n");
2840 			break;
2841 		}
2842 
2843 		popup_all_part(model, &iter, INFO_PAGE);
2844 
2845 		break;
2846 	}
2847 	case POPUP_CLICKED:
2848 		make_fields_menu(popup_win, menu,
2849 				 popup_win->display_data, SORTID_CNT);
2850 		break;
2851 	default:
2852 		g_error("UNKNOWN type %d given to set_fields\n", type);
2853 	}
2854 }
2855 
popup_all_part(GtkTreeModel * model,GtkTreeIter * iter,int id)2856 extern void popup_all_part(GtkTreeModel *model, GtkTreeIter *iter, int id)
2857 {
2858 	char *name = NULL;
2859 	char *cluster_name = NULL;
2860 	char *state = NULL;
2861 	char title[100] = {0};
2862 	int only_line = 0;
2863 	ListIterator itr = NULL;
2864 	popup_info_t *popup_win = NULL;
2865 	GError *error = NULL;
2866 	GtkTreeIter par_iter;
2867 
2868 	gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
2869 	gtk_tree_model_get(model, iter, SORTID_CLUSTER_NAME, &cluster_name, -1);
2870 
2871 	switch(id) {
2872 	case JOB_PAGE:
2873 		snprintf(title, 100, "Job(s) in partition %s", name);
2874 		break;
2875 	case RESV_PAGE:
2876 		snprintf(title, 100, "Reservation(s) in partition %s", name);
2877 		break;
2878 	case NODE_PAGE:
2879 		gtk_tree_model_get(model, iter, SORTID_ONLY_LINE,
2880 				   &only_line, -1);
2881 		if (!only_line)
2882 			gtk_tree_model_get(model, iter,
2883 					   SORTID_NODE_STATE, &state, -1);
2884 		if (!state || !strlen(state))
2885 			snprintf(title, 100, "Node(s) in partition %s ",
2886 				 name);
2887 		else
2888 			snprintf(title, 100,
2889 				 "Node(s) in partition %s that are in "
2890 				 "'%s' state",
2891 				 name, state);
2892 		break;
2893 	case SUBMIT_PAGE:
2894 		snprintf(title, 100, "Submit job in partition %s", name);
2895 		break;
2896 	case INFO_PAGE:
2897 		snprintf(title, 100, "Full info for partition %s", name);
2898 		break;
2899 	default:
2900 		g_print("part got %d\n", id);
2901 	}
2902 
2903 	if (cluster_name && federation_name &&
2904 	    (cluster_flags & CLUSTER_FLAG_FED)) {
2905 		char *tmp_cname = xstrdup_printf(" (%s:%s)",
2906 						 federation_name, cluster_name);
2907 		strncat(title, tmp_cname, sizeof(title) - strlen(title) - 1);
2908 		xfree(tmp_cname);
2909 	}
2910 
2911 	itr = list_iterator_create(popup_list);
2912 	while ((popup_win = list_next(itr))) {
2913 		if (popup_win->spec_info)
2914 			if (!xstrcmp(popup_win->spec_info->title, title)) {
2915 				break;
2916 			}
2917 	}
2918 	list_iterator_destroy(itr);
2919 
2920 	if (!popup_win) {
2921 		if (id == INFO_PAGE)
2922 			popup_win = create_popup_info(id, PART_PAGE, title);
2923 		else
2924 			popup_win = create_popup_info(PART_PAGE, id, title);
2925 	} else {
2926 		g_free(name);
2927 		g_free(cluster_name);
2928 		g_free(state);
2929 		gtk_window_present(GTK_WINDOW(popup_win->popup));
2930 		return;
2931 	}
2932 
2933 	/* Pass the model and the structs from the iter so we can always get
2934 	   the current node_inx.
2935 	*/
2936 	popup_win->model = model;
2937 	popup_win->iter = *iter;
2938 	popup_win->node_inx_id = SORTID_NODE_INX;
2939 
2940 	if (cluster_flags & CLUSTER_FLAG_FED) {
2941 		popup_win->spec_info->search_info->cluster_name = cluster_name;
2942 		cluster_name = NULL;
2943 	}
2944 	g_free(cluster_name);
2945 
2946 	switch (id) {
2947 	case JOB_PAGE:
2948 	case INFO_PAGE:
2949 		popup_win->spec_info->search_info->gchar_data = name;
2950 		//specific_info_job(popup_win);
2951 		break;
2952 	case RESV_PAGE:
2953 	case NODE_PAGE:
2954 		g_free(name);
2955 		/* we want to include the parent's nodes here not just
2956 		   the subset */
2957 		if (gtk_tree_model_iter_parent(model, &par_iter, iter))
2958 			gtk_tree_model_get(model, &par_iter,
2959 					   SORTID_NODELIST, &name, -1);
2960 		else
2961 			gtk_tree_model_get(model, iter,
2962 					   SORTID_NODELIST, &name, -1);
2963 		popup_win->spec_info->search_info->gchar_data = name;
2964 		if (state && strlen(state)) {
2965 			popup_win->spec_info->search_info->search_type =
2966 				SEARCH_NODE_STATE;
2967 			gtk_tree_model_get(
2968 				model, iter, SORTID_NODE_STATE_NUM,
2969 				&popup_win->spec_info->search_info->int_data,
2970 				-1);
2971 		} else {
2972 			popup_win->spec_info->search_info->search_type =
2973 				SEARCH_NODE_NAME;
2974 		}
2975 		g_free(state);
2976 
2977 		//specific_info_node(popup_win);
2978 		break;
2979 	case SUBMIT_PAGE:
2980 		break;
2981 	default:
2982 		g_print("part got unknown type %d\n", id);
2983 	}
2984 	if (!sview_thread_new((gpointer)popup_thr, popup_win, false, &error)) {
2985 		g_printerr ("Failed to create part popup thread: %s\n",
2986 			    error->message);
2987 		return;
2988 	}
2989 }
2990 
select_admin_partitions(GtkTreeModel * model,GtkTreeIter * iter,display_data_t * display_data,GtkTreeView * treeview)2991 extern void select_admin_partitions(GtkTreeModel *model,
2992 				    GtkTreeIter *iter,
2993 				    display_data_t *display_data,
2994 				    GtkTreeView *treeview)
2995 {
2996 	select_admin_common(model, iter, display_data, treeview,
2997 			    SORTID_NODELIST, _process_each_partition);
2998 } /*select_admin_partitions ^^^*/
2999 
3000 
admin_part(GtkTreeModel * model,GtkTreeIter * iter,char * type)3001 extern void admin_part(GtkTreeModel *model, GtkTreeIter *iter, char *type)
3002 {
3003 	char *nodelist = NULL;
3004 	char *partid = NULL;
3005 	update_part_msg_t *part_msg = NULL;
3006 	int edit_type = 0;
3007 	int response = 0;
3008 	char tmp_char[100];
3009 	char *temp = NULL;
3010 	GtkWidget *label = NULL;
3011 	GtkWidget *entry = NULL;
3012 	GtkWidget *popup = NULL;
3013 
3014 	if (cluster_flags & CLUSTER_FLAG_FED) {
3015 		display_fed_disabled_popup(type);
3016 		return;
3017 	}
3018 
3019 	popup = gtk_dialog_new_with_buttons(
3020 		type,
3021 		GTK_WINDOW(main_window),
3022 		GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3023 		NULL);
3024 	gtk_window_set_transient_for(GTK_WINDOW(popup), NULL);
3025 
3026 	gtk_window_set_type_hint(GTK_WINDOW(popup),
3027 				 GDK_WINDOW_TYPE_HINT_NORMAL);
3028 
3029 	gtk_tree_model_get(model, iter, SORTID_NAME, &partid, -1);
3030 	gtk_tree_model_get(model, iter, SORTID_NODELIST, &nodelist, -1);
3031 
3032 	part_msg = xmalloc(sizeof(update_part_msg_t));
3033 	slurm_init_part_desc_msg(part_msg);
3034 	part_msg->name = xstrdup(partid);
3035 
3036 	if (!xstrcasecmp("Change Partition State", type)) {
3037 		GtkCellRenderer *renderer = NULL;
3038 		GtkTreeModel *model2 = GTK_TREE_MODEL(
3039 			create_model_part(SORTID_PART_STATE));
3040 		if (!model2) {
3041 			g_print("In change part, no model set up for %d(%s)\n",
3042 				SORTID_PART_STATE, partid);
3043 			xfree(part_msg);
3044 			return;
3045 		}
3046 		entry = gtk_combo_box_new_with_model(model2);
3047 		g_object_unref(model2);
3048 
3049 		_set_active_combo_part(GTK_COMBO_BOX(entry),
3050 				       model, iter, SORTID_PART_STATE);
3051 
3052 		g_signal_connect(entry, "changed",
3053 				 G_CALLBACK(_admin_edit_combo_box_part),
3054 				 part_msg);
3055 
3056 		renderer = gtk_cell_renderer_text_new();
3057 		gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(entry),
3058 					   renderer, true);
3059 		gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(entry),
3060 					      renderer, "text", 0);
3061 
3062 		label = gtk_dialog_add_button(GTK_DIALOG(popup),
3063 					      GTK_STOCK_YES, GTK_RESPONSE_OK);
3064 		gtk_window_set_default(GTK_WINDOW(popup), label);
3065 		gtk_dialog_add_button(GTK_DIALOG(popup),
3066 				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
3067 
3068 		snprintf(tmp_char, sizeof(tmp_char),
3069 			 "Which state would you like to set partition '%s' to?",
3070 			 partid);
3071 		label = gtk_label_new(tmp_char);
3072 		edit_type = EDIT_PART_STATE;
3073 	} else if (!xstrcasecmp("Remove Partition", type)) {
3074 		label = gtk_dialog_add_button(GTK_DIALOG(popup),
3075 					      GTK_STOCK_YES, GTK_RESPONSE_OK);
3076 		gtk_window_set_default(GTK_WINDOW(popup), label);
3077 		gtk_dialog_add_button(GTK_DIALOG(popup),
3078 				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
3079 
3080 		snprintf(tmp_char, sizeof(tmp_char),
3081 			 "Are you sure you want to remove partition %s?",
3082 			 partid);
3083 		label = gtk_label_new(tmp_char);
3084 		edit_type = EDIT_REMOVE_PART;
3085 	} else if (!xstrcasecmp("Edit Partition", type)) {
3086 		label = gtk_dialog_add_button(GTK_DIALOG(popup),
3087 					      GTK_STOCK_OK, GTK_RESPONSE_OK);
3088 		gtk_window_set_default(GTK_WINDOW(popup), label);
3089 		gtk_dialog_add_button(GTK_DIALOG(popup),
3090 				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
3091 
3092 		gtk_window_set_default_size(GTK_WINDOW(popup), 200, 400);
3093 		snprintf(tmp_char, sizeof(tmp_char),
3094 			 "Editing partition %s think before you type",
3095 			 partid);
3096 		label = gtk_label_new(tmp_char);
3097 		edit_type = EDIT_EDIT;
3098 		entry = _admin_full_edit_part(part_msg, model, iter);
3099 	} else if (!xstrncasecmp("Update", type, 6)) {
3100 		char *old_features = NULL;
3101 		if (got_features_edit_signal)
3102 			old_features = got_features_edit_signal;
3103 		else
3104 			gtk_tree_model_get(model, iter, SORTID_FEATURES,
3105 					   &old_features, -1);
3106 		update_avail_features_node(GTK_DIALOG(popup),
3107 					   nodelist, old_features);
3108 		if (got_features_edit_signal) {
3109 			got_features_edit_signal = NULL;
3110 			xfree(old_features);
3111 		} else
3112 			g_free(old_features);
3113 		goto end_it;
3114 	} else {
3115 		/* something that has to deal with a node state change */
3116 		update_state_node(GTK_DIALOG(popup), nodelist, type);
3117 		goto end_it;
3118 	}
3119 
3120 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
3121 			   label, false, false, 0);
3122 	if (entry)
3123 		gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
3124 				   entry, true, true, 0);
3125 	gtk_widget_show_all(popup);
3126 	response = gtk_dialog_run (GTK_DIALOG(popup));
3127 
3128 	if (response == GTK_RESPONSE_OK) {
3129 		int rc;
3130 		if (global_edit_error)
3131 			temp = global_edit_error_msg;
3132 		else if (edit_type == EDIT_REMOVE_PART) {
3133 			delete_part_msg_t part_del_msg;
3134 			part_del_msg.name = partid;
3135 			rc = slurm_delete_partition(&part_del_msg);
3136 			if (rc == SLURM_SUCCESS) {
3137 				temp = g_strdup_printf(
3138 					"Partition %s removed successfully",
3139 					partid);
3140 			} else {
3141 				temp = g_strdup_printf(
3142 					"Problem removing partition %s: %s",
3143 					partid, slurm_strerror(rc));
3144 				global_multi_error = true;
3145 			}
3146 		} else if (!global_send_update_msg) {
3147 			temp = g_strdup_printf("No change detected.");
3148 		} else if ((rc = slurm_update_partition(part_msg))
3149 			   == SLURM_SUCCESS) {
3150 			temp = g_strdup_printf(
3151 				"Partition %s updated successfully",
3152 				partid);
3153 		} else {
3154 			temp = g_strdup_printf(
3155 				"Problem updating partition %s: %s",
3156 				partid, slurm_strerror(rc));
3157 			global_multi_error = true;
3158 		}
3159 		display_edit_note(temp);
3160 		g_free(temp);
3161 	}
3162 end_it:
3163 
3164 	g_free(partid);
3165 	g_free(nodelist);
3166 	global_entry_changed = 0;
3167 	slurm_free_update_part_msg(part_msg);
3168 	gtk_widget_destroy(popup);
3169 	if (got_edit_signal) {
3170 		type = got_edit_signal;
3171 		got_edit_signal = NULL;
3172 		admin_part(model, iter, type);
3173 		xfree(type);
3174 	}
3175 	if (got_features_edit_signal) {
3176 		type = "Update Features";
3177 		admin_part(model, iter, type);
3178 	}
3179 	return;
3180 }
3181 
cluster_change_part(void)3182 extern void cluster_change_part(void)
3183 {
3184 	display_data_t *display_data = display_data_part;
3185 	while (display_data++) {
3186 		if (display_data->id == -1)
3187 			break;
3188 		if (cluster_flags & CLUSTER_FLAG_FED) {
3189 			switch(display_data->id) {
3190 			case SORTID_CLUSTER_NAME:
3191 				display_data->show = true;
3192 				break;
3193 			}
3194 		} else {
3195 			switch (display_data->id) {
3196 			case SORTID_CLUSTER_NAME:
3197 				display_data->show = false;
3198 				break;
3199 			}
3200 		}
3201 	}
3202 
3203 	get_info_part(NULL, NULL);
3204 }
3205