1 /****************************************************************************\
2 * grid.c - put display grid info here
3 *****************************************************************************
4 * Copyright (C) 2004-2007 The Regents of the University of California.
5 * Copyright (C) 2008-2010 Lawrence Livermore National Security.
6 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
7 * Written by Danny Auble <da@llnl.gov>, et. al.
8 * CODE-OCEC-09-009. All rights reserved.
9 *
10 * This file is part of Slurm, a resource management program.
11 * For details, see <https://slurm.schedmd.com/>.
12 * Please also read the included file: DISCLAIMER.
13 *
14 * Slurm is free software; you can redistribute it and/or modify it under
15 * the terms of the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at your option)
17 * any later version.
18 *
19 * In addition, as a special exception, the copyright holders give permission
20 * to link the code of portions of this program with the OpenSSL library under
21 * certain conditions as described in each individual source file, and
22 * distribute linked combinations including the two. You must obey the GNU
23 * General Public License in all respects for all of the code used other than
24 * OpenSSL. If you modify file(s) with this exception, you may extend this
25 * exception to your version of the file(s), but you are not obligated to do
26 * so. If you do not wish to do so, delete this exception statement from your
27 * version. If you delete this exception statement from all source files in
28 * the program, then also delete it here.
29 *
30 * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
31 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
32 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
33 * details.
34 *
35 * You should have received a copy of the GNU General Public License along
36 * with Slurm; if not, write to the Free Software Foundation, Inc.,
37 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38 \*****************************************************************************/
39
40 #include "config.h"
41
42 #include "sview.h"
43
44 #define RESET_GRID -2
45 #define TOPO_DEBUG 0
46
47 List grid_button_list = NULL;
48 List blinking_button_list = NULL;
49 List multi_button_list = NULL;
50
51 char *sview_colors[] = {"#0000FF", "#00FF00", "#00FFFF", "#FFFF00",
52 "#FF0000", "#4D4DC6", "#F09A09", "#BDFA19",
53 "#715627", "#6A8CA2", "#4C7127", "#25B9B9",
54 "#A020F0", "#8293ED", "#FFA500", "#FFC0CB",
55 "#8B6914", "#18A24E", "#F827FC", "#B8A40C"};
56 char *blank_color = "#919191";
57 char *white_color = "#FFFFFF";
58 char *topo1_color = "honeydew"; //"seashell";DarkTurquoise
59 char *topo2_color = "gray94";//honeydew";
60
61 int sview_colors_cnt = 20;
62
63 typedef struct {
64 int node_inx_id;
65 int color_inx_id;
66 List button_list;
67 } grid_foreach_t;
68
69 typedef struct {
70 List button_list;
71 int *coord_x;
72 int *coord_y;
73 int default_y_offset;
74 grid_button_t *grid_button;
75 int *inx;
76 GtkTable *table;
77 int table_y;
78 bool force_row_break;
79 } button_processor_t;
80
_mouseover_node(GtkWidget * widget,GdkEventButton * event,grid_button_t * grid_button)81 static gboolean _mouseover_node(GtkWidget *widget, GdkEventButton *event,
82 grid_button_t *grid_button)
83 {
84 gboolean rc = true;
85
86 grid_button->last_state = gtk_widget_get_state(widget);
87 #ifdef GTK2_USE_TOOLTIP
88 gtk_widget_set_tooltip_text(grid_button->button,
89 grid_button->node_name);
90 #else
91 if (!grid_button->tip)
92 grid_button->tip = gtk_tooltips_new();
93 gtk_tooltips_set_tip(grid_button->tip,
94 grid_button->button,
95 grid_button->node_name,
96 "click for node stats");
97 #endif
98 //g_print("on at %s\n", grid_button->node_name);
99 gtk_widget_set_state(grid_button->button, GTK_STATE_PRELIGHT);
100
101 return rc;
102 }
103
_mouseoff_node(GtkWidget * widget,GdkEventButton * event,grid_button_t * grid_button)104 static gboolean _mouseoff_node(GtkWidget *widget, GdkEventButton *event,
105 grid_button_t *grid_button)
106 {
107 gboolean rc = false;
108
109 if (grid_button->last_state == GTK_STATE_ACTIVE) {
110 gtk_widget_set_state(grid_button->button, GTK_STATE_ACTIVE);
111 rc = true;
112 //g_print("off of %s\n", grid_button->node_name);
113 }
114 return rc;
115 }
116
_open_node(GtkWidget * widget,GdkEventButton * event,grid_button_t * grid_button)117 static gboolean _open_node(GtkWidget *widget, GdkEventButton *event,
118 grid_button_t *grid_button)
119 {
120 if (event->button == 1) {
121 popup_all_node_name(grid_button->node_name, INFO_PAGE, NULL);
122 } else if (event->button == 3) {
123 /* right click */
124 admin_menu_node_name(grid_button->node_name, event);
125 }
126
127 return false;
128 }
129
130 /* static void _state_changed(GtkWidget *button, GtkStateType state, */
131 /* grid_button_t *grid_button) */
132 /* { */
133 /* g_print("state of %s is now %d\n", grid_button->node_name, state); */
134 /* } */
135
_add_button_signals(grid_button_t * grid_button)136 static void _add_button_signals(grid_button_t *grid_button)
137 {
138 /* g_signal_connect(G_OBJECT(grid_button->button), */
139 /* "state-changed", */
140 /* G_CALLBACK(_state_changed), */
141 /* grid_button); */
142 g_signal_connect(G_OBJECT(grid_button->button),
143 "button-press-event",
144 G_CALLBACK(_open_node),
145 grid_button);
146 g_signal_connect(G_OBJECT(grid_button->button),
147 "enter-notify-event",
148 G_CALLBACK(_mouseover_node),
149 grid_button);
150 g_signal_connect(G_OBJECT(grid_button->button),
151 "leave-notify-event",
152 G_CALLBACK(_mouseoff_node),
153 grid_button);
154 }
155
156 /*
157 * Comparator used for sorting buttons
158 *
159 * returns: -1: button_a->inx > button_b->inx
160 * 0: rec_a == rec_b
161 * 1: rec_a < rec_b
162 *
163 */
_sort_button_inx(void * b1,void * b2)164 static int _sort_button_inx(void *b1, void *b2)
165 {
166 grid_button_t *button_a = *(grid_button_t **)b1;
167 grid_button_t *button_b = *(grid_button_t **)b2;
168 int inx_a;
169 int inx_b;
170
171 inx_a = button_a->inx;
172 inx_b = button_b->inx;
173
174 if (inx_a < inx_b)
175 return -1;
176 else if (inx_a > inx_b)
177 return 1;
178 return 0;
179 }
180
_put_button_as_down(grid_button_t * grid_button,int state)181 void _put_button_as_down(grid_button_t *grid_button, int state)
182 {
183 GtkWidget *image = NULL;
184 /* GdkColor color; */
185
186 if (GTK_IS_EVENT_BOX(grid_button->button)) {
187 //gtk_widget_set_sensitive (grid_button->button, true);
188 return;
189 }
190
191 gtk_widget_destroy(grid_button->button);
192 grid_button->color = NULL;
193 grid_button->color_inx = MAKE_DOWN;
194 grid_button->button = gtk_event_box_new();
195 gtk_widget_set_size_request(grid_button->button,
196 working_sview_config.button_size,
197 working_sview_config.button_size);
198 gtk_event_box_set_above_child(GTK_EVENT_BOX(grid_button->button),
199 false);
200 _add_button_signals(grid_button);
201
202 /* if (grid_button->frame) */
203 /* gtk_container_add(GTK_CONTAINER(grid_button->frame), */
204 /* grid_button->button); */
205 if (grid_button->table)
206 gtk_table_attach(grid_button->table, grid_button->button,
207 grid_button->table_x,
208 (grid_button->table_x+1),
209 grid_button->table_y,
210 (grid_button->table_y+1),
211 GTK_SHRINK, GTK_SHRINK,
212 1, 1);
213
214 //gdk_color_parse("black", &color);
215 //sview_widget_modify_bg(grid_button->button, GTK_STATE_NORMAL, color);
216 //gdk_color_parse(white_color, &color);
217 //sview_widget_modify_bg(grid_button->button, GTK_STATE_ACTIVE, color);
218 if (state == NODE_STATE_DRAIN)
219 image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_ERROR,
220 GTK_ICON_SIZE_SMALL_TOOLBAR);
221 else
222 image = gtk_image_new_from_stock(GTK_STOCK_CANCEL,
223 GTK_ICON_SIZE_SMALL_TOOLBAR);
224 gtk_container_add(GTK_CONTAINER(grid_button->button), image);
225 gtk_widget_show_all(grid_button->button);
226 return;
227 }
228
229
_put_button_as_up(grid_button_t * grid_button)230 void _put_button_as_up(grid_button_t *grid_button)
231 {
232 if (GTK_IS_BUTTON(grid_button->button)) {
233 return;
234 }
235 gtk_widget_destroy(grid_button->button);
236 grid_button->button = gtk_button_new();
237 gtk_widget_set_size_request(grid_button->button,
238 working_sview_config.button_size,
239 working_sview_config.button_size);
240 _add_button_signals(grid_button);
241
242 /* if (grid_button->frame) */
243 /* gtk_container_add(GTK_CONTAINER(grid_button->frame), */
244 /* grid_button->button); */
245 if (grid_button->table)
246 gtk_table_attach(grid_button->table, grid_button->button,
247 grid_button->table_x,
248 (grid_button->table_x+1),
249 grid_button->table_y,
250 (grid_button->table_y+1),
251 GTK_SHRINK, GTK_SHRINK,
252 1, 1);
253 gtk_widget_show_all(grid_button->button);
254 return;
255 }
256
_put_button_as_inactive(grid_button_t * grid_button)257 void _put_button_as_inactive(grid_button_t *grid_button)
258 {
259 if (GTK_IS_BUTTON(grid_button->button)) {
260 //gtk_widget_set_sensitive (grid_button->button, false);
261 return;
262 }
263 gtk_widget_destroy(grid_button->button);
264 grid_button->button = gtk_button_new();
265 gtk_widget_set_size_request(grid_button->button,
266 working_sview_config.button_size,
267 working_sview_config.button_size);
268 //gtk_widget_set_sensitive (grid_button->button, false);
269
270 _add_button_signals(grid_button);
271
272 /* if (grid_button->frame) */
273 /* gtk_container_add(GTK_CONTAINER(grid_button->frame), */
274 /* grid_button->button); */
275 if (grid_button->table)
276 gtk_table_attach(grid_button->table, grid_button->button,
277 grid_button->table_x,
278 (grid_button->table_x+1),
279 grid_button->table_y,
280 (grid_button->table_y+1),
281 GTK_SHRINK, GTK_SHRINK,
282 1, 1);
283 gtk_widget_show_all(grid_button->button);
284 return;
285 }
286
_change_button_color(grid_button_t * grid_button,int color_inx,char * new_col,GdkColor color,bool only_change_unused,enum node_states state_override)287 static bool _change_button_color(grid_button_t *grid_button,
288 int color_inx, char *new_col, GdkColor color,
289 bool only_change_unused,
290 enum node_states state_override)
291 {
292 enum node_states state;
293 uint16_t node_base_state;
294 bool changed = 0;
295
296 xassert(grid_button);
297 if (only_change_unused && grid_button->used)
298 return 0;
299
300 grid_button->used = true;
301 if (color_inx == MAKE_BLACK) {
302 if (grid_button->color_inx != color_inx) {
303 _put_button_as_inactive(grid_button);
304 grid_button->color = new_col;
305 grid_button->color_inx = color_inx;
306 sview_widget_modify_bg(grid_button->button,
307 GTK_STATE_NORMAL, color);
308 /* sview_widget_modify_bg(grid_button->button, */
309 /* GTK_STATE_ACTIVE, */
310 /* color); */
311 changed = 1;
312 }
313
314 return changed;
315 }
316
317 if (state_override != NODE_STATE_UNKNOWN)
318 state = state_override;
319 else
320 state = grid_button->state;
321
322 node_base_state = state & NODE_STATE_BASE;
323
324 if (node_base_state == NODE_STATE_DOWN) {
325 _put_button_as_down(grid_button, NODE_STATE_DOWN);
326 } else if (state & NODE_STATE_DRAIN) {
327 _put_button_as_down(grid_button, NODE_STATE_DRAIN);
328 } else if (grid_button->node_name &&
329 !xstrcmp(grid_button->node_name, "EMPTY")) {
330 grid_button->color_inx = MAKE_BLACK;
331 // _put_button_as_up(grid_button);
332 } else if (grid_button->color_inx != color_inx) {
333 _put_button_as_up(grid_button);
334 grid_button->color = new_col;
335 grid_button->color_inx = color_inx;
336 sview_widget_modify_bg(grid_button->button,
337 GTK_STATE_NORMAL, color);
338 /* sview_widget_modify_bg(grid_button->button, */
339 /* GTK_STATE_ACTIVE, color); */
340 changed = 1;
341 }
342
343 return changed;
344 }
345
346
_each_highlightd(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer userdata)347 static void _each_highlightd(GtkTreeModel *model,
348 GtkTreePath *path,
349 GtkTreeIter *iter,
350 gpointer userdata)
351 {
352 ListIterator itr = NULL;
353 grid_button_t *grid_button = NULL;
354 int *node_inx = NULL;
355 int color_inx;
356
357 int j=0;
358 GdkColor color;
359
360 grid_foreach_t *grid_foreach = userdata;
361
362 gtk_tree_model_get(model, iter, grid_foreach->node_inx_id,
363 &node_inx, -1);
364 gtk_tree_model_get(model, iter, grid_foreach->color_inx_id,
365 &color_inx, -1);
366
367 if (!node_inx)
368 return;
369
370 if (color_inx > sview_colors_cnt) {
371 g_print("hey the color_inx from %d was set to %d > %d\n",
372 grid_foreach->color_inx_id, color_inx,
373 sview_colors_cnt);
374 color_inx %= sview_colors_cnt;
375 }
376 gdk_color_parse(sview_colors[color_inx], &color);
377
378 itr = list_iterator_create(grid_foreach->button_list);
379 while ((grid_button = list_next(itr))) {
380 /*For multiple selections, need to retain all selected.
381 *(previously this assumed only one selected).
382 */
383
384 if ((node_inx[j] < 0)
385 || (grid_button->inx < node_inx[j])
386 || (grid_button->inx > node_inx[j+1]))
387 continue;
388
389 (void)_change_button_color(grid_button, color_inx,
390 sview_colors[color_inx],
391 color, 0, 0);
392
393 if (gtk_widget_get_state(grid_button->button) != GTK_STATE_NORMAL)
394 gtk_widget_set_state(grid_button->button,
395 GTK_STATE_NORMAL);
396
397 if (grid_button->inx == node_inx[j+1])
398 j+=2;
399
400 }
401
402 list_iterator_destroy(itr);
403 return;
404 }
405
_each_highlight_selected(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer userdata)406 static void _each_highlight_selected(GtkTreeModel *model,
407 GtkTreePath *path,
408 GtkTreeIter *iter,
409 gpointer userdata)
410 {
411
412 grid_button_t *grid_button = NULL;
413 int node_inx = 0;
414 bool speedup_break = true;
415 grid_foreach_t *grid_foreach = userdata;
416 ListIterator itr = NULL;
417
418 xassert(grid_foreach);
419 if (working_sview_config.grid_topological)
420 speedup_break = false;
421
422 gtk_tree_model_get(model, iter, grid_foreach->node_inx_id,
423 &node_inx, -1);
424
425 if (node_inx < 0 || !grid_foreach->button_list)
426 return;
427 itr = list_iterator_create(grid_foreach->button_list);
428 while ((grid_button = list_next(itr))) {
429 /* For multiple selections, need to retain all selected.
430 * (previously this assumed only one selected). */
431 if (grid_button->inx != node_inx)
432 continue;
433 else if (gtk_widget_get_state(grid_button->button)
434 != GTK_STATE_NORMAL) {
435 gtk_widget_set_state(grid_button->button,
436 GTK_STATE_NORMAL);
437 change_grid_color(grid_button_list, grid_button->inx,
438 grid_button->inx,
439 grid_button->inx, true, 0);
440 }
441 if (speedup_break)
442 break;
443 speedup_break = true; //allow for secondary grid button
444 }
445 list_iterator_destroy(itr);
446 return;
447
448 }
449
450 /*
451 * This is used to add an entry to the grid for a node which is not configured
452 * in the system (e.g. there is a gap in the 3-D torus for a service or login
453 * node.
454 */
_build_empty_node(int coord_x,int coord_y,button_processor_t * button_processor)455 static void _build_empty_node(int coord_x, int coord_y,
456 button_processor_t *button_processor)
457 {
458 grid_button_t *grid_button;
459
460 (*button_processor->coord_x) = coord_x;
461 (*button_processor->coord_y) = coord_y;
462 grid_button = xmalloc(sizeof(grid_button_t));
463 grid_button->color_inx = MAKE_BLACK;
464 grid_button->inx = (*button_processor->inx);
465 grid_button->state = NODE_STATE_FUTURE;
466 grid_button->table = button_processor->table;
467 grid_button->table_x = (*button_processor->coord_x);
468 grid_button->table_y = (*button_processor->coord_y);
469 grid_button->button = gtk_button_new();
470 grid_button->node_name = xstrdup("EMPTY"); /* Needed by popups */
471
472 gtk_widget_set_state(grid_button->button, GTK_STATE_ACTIVE);
473 list_append(button_processor->button_list, grid_button);
474
475 gtk_table_attach(button_processor->table, grid_button->button,
476 (*button_processor->coord_x),
477 ((*button_processor->coord_x) + 1),
478 (*button_processor->coord_y),
479 ((*button_processor->coord_y) + 1),
480 GTK_SHRINK, GTK_SHRINK, 1, 1);
481 }
482
_calc_coord_3d(int x,int y,int z,int default_y_offset,int * coord_x,int * coord_y,int * dim_size)483 static void _calc_coord_3d(int x, int y, int z, int default_y_offset,
484 int *coord_x, int *coord_y, int *dim_size)
485 {
486 int y_offset;
487
488 *coord_x = (x + (dim_size[2] - 1)) - z;
489 y_offset = default_y_offset - (dim_size[2] * y);
490 *coord_y = (y_offset - y) + z;
491 }
492
_get_cluster_dims(void)493 static int *_get_cluster_dims(void)
494 {
495 int *my_dim_size = slurmdb_setup_cluster_dim_size();
496
497 if ((cluster_flags & CLUSTER_FLAG_CRAY_A) && my_dim_size) {
498 static int cray_dim_size[3] = {-1, -1, -1};
499 /* For now, assume four nodes per coordinate all in
500 * the same cage. Need to refine. */
501 cray_dim_size[0] = my_dim_size[0];
502 cray_dim_size[1] = my_dim_size[1];
503 cray_dim_size[2] = my_dim_size[2];
504 return cray_dim_size;
505 }
506
507 return my_dim_size;
508 }
509
510 /* Add a button for a given node. If node_ptr == NULL then fill in any gaps
511 * in the grid just for a clean look. Always call with node_ptr == NULL for
512 * the last call in the sequence. */
_add_button_to_list(node_info_t * node_ptr,button_processor_t * button_processor)513 static int _add_button_to_list(node_info_t *node_ptr,
514 button_processor_t *button_processor)
515 {
516 static bool *node_exists = NULL;
517 static int node_exists_cnt = 1;
518 grid_button_t *grid_button = button_processor->grid_button;
519 int *dim_size = NULL, i, coord_x = 0, coord_y = 0;
520 int len = 0, len_a = 0;
521
522 if (cluster_dims > 1) {
523 dim_size = _get_cluster_dims();
524 if (dim_size == NULL) {
525 g_error("Could not read dim_size\n");
526 return SLURM_ERROR;
527 }
528 if ((dim_size[0] < 1) || (cluster_dims < 1)) {
529 g_error("Invalid dim_size %d or cluster_dims %d\n",
530 dim_size[0], cluster_dims);
531 return SLURM_ERROR;
532 }
533
534 /* Translate a 3D or 4D space into a 2D space to the extent
535 * possible. */
536 if (node_exists == NULL) {
537 node_exists_cnt = 1;
538 for (i = 0; i < cluster_dims; i++)
539 node_exists_cnt *= dim_size[i];
540 node_exists = xmalloc(sizeof(bool) * node_exists_cnt);
541 }
542 if (node_ptr) {
543 len = strlen(node_ptr->name);
544 if (len < cluster_dims) {
545 g_error("bad node name %s\n", node_ptr->name);
546 return SLURM_ERROR;
547 }
548 if (cluster_flags & CLUSTER_FLAG_CRAY_A) {
549 len_a = strlen(node_ptr->node_addr);
550 if (len_a < cluster_dims) {
551 g_error("bad node addr %s\n",
552 node_ptr->node_addr);
553 return SLURM_ERROR;
554 }
555 }
556 }
557 }
558
559 if (cluster_dims == 3) {
560 int x, y, z;
561 if (node_ptr) {
562 if (cluster_flags & CLUSTER_FLAG_CRAY_A) {
563 x = select_char2coord(
564 node_ptr->node_addr[len_a-3]);
565 y = select_char2coord(
566 node_ptr->node_addr[len_a-2]);
567 z = select_char2coord(
568 node_ptr->node_addr[len_a-1]);
569 } else {
570 x = select_char2coord(node_ptr->name[len-3]);
571 y = select_char2coord(node_ptr->name[len-2]);
572 z = select_char2coord(node_ptr->name[len-1]);
573 }
574 i = (x * dim_size[1] + y) * dim_size[2] + z;
575 node_exists[i] = true;
576 _calc_coord_3d(x, y, z,
577 button_processor->default_y_offset,
578 &coord_x, &coord_y, dim_size);
579 } else {
580 for (x = 0; x < dim_size[0]; x++) {
581 for (y = 0; y < dim_size[1]; y++) {
582 for (z = 0; z < dim_size[2]; z++) {
583 i = (x * dim_size[1] + y) *
584 dim_size[2] + z;
585 if (node_exists[i])
586 continue;
587 _calc_coord_3d(x, y, z,
588 button_processor->
589 default_y_offset,
590 &coord_x, &coord_y,
591 dim_size);
592 _build_empty_node(
593 coord_x, coord_y,
594 button_processor);
595 }
596 }
597 }
598 xfree(node_exists);
599 return SLURM_SUCCESS;
600 }
601 }
602 if (node_ptr == NULL)
603 return SLURM_SUCCESS;
604
605 if (cluster_dims > 1) {
606 (*button_processor->coord_x) = coord_x;
607 (*button_processor->coord_y) = coord_y;
608 #if 0
609 g_print("%s %d:%d\n", node_ptr->name, coord_x, coord_y);
610 #endif
611 }
612
613 if (!grid_button) {
614 grid_button = xmalloc(sizeof(grid_button_t));
615 grid_button->color_inx = MAKE_INIT;
616 grid_button->inx = (*button_processor->inx);
617 grid_button->table = button_processor->table;
618 grid_button->table_x = (*button_processor->coord_x);
619 grid_button->table_y = (*button_processor->coord_y);
620 grid_button->button = gtk_button_new();
621 grid_button->node_name = xstrdup(node_ptr->name);
622
623 gtk_widget_set_size_request(grid_button->button,
624 working_sview_config.button_size,
625 working_sview_config.button_size);
626 _add_button_signals(grid_button);
627 list_append(button_processor->button_list, grid_button);
628
629 gtk_table_attach(button_processor->table, grid_button->button,
630 (*button_processor->coord_x),
631 ((*button_processor->coord_x)+1),
632 (*button_processor->coord_y),
633 ((*button_processor->coord_y)+1),
634 GTK_SHRINK, GTK_SHRINK,
635 1, 1);
636 } else {
637 grid_button->table_x = (*button_processor->coord_x);
638 grid_button->table_y = (*button_processor->coord_y);
639 gtk_container_child_set(
640 GTK_CONTAINER(button_processor->table),
641 grid_button->button,
642 "left-attach", (*button_processor->coord_x),
643 "right-attach", ((*button_processor->coord_x)+1),
644 "top-attach", (*button_processor->coord_y),
645 "bottom-attach", ((*button_processor->coord_y)+1),
646 NULL);
647 }
648 /* gtk_container_add(GTK_CONTAINER(grid_button->frame), */
649 /* grid_button->button); */
650 /* gtk_frame_set_shadow_type(GTK_FRAME(grid_button->frame), */
651 /* GTK_SHADOW_ETCHED_OUT); */
652 if (cluster_dims < 3) {
653 /* On linear systems we just up the x_coord until we hit the
654 * side of the table and then increment the coord_y. We add
655 * space between each tenth row. */
656 (*button_processor->coord_x)++;
657
658 if (button_processor->force_row_break) {
659 (*button_processor->coord_x) = 0;
660 (*button_processor->coord_y)++;
661 gtk_table_set_row_spacing(
662 button_processor->table,
663 (*button_processor->coord_y)-1,
664 working_sview_config.gap_size);
665 return SLURM_SUCCESS;
666 }
667
668 if ((*button_processor->coord_x)
669 == working_sview_config.grid_x_width) {
670 (*button_processor->coord_x) = 0;
671 (*button_processor->coord_y)++;
672 if (!((*button_processor->coord_y)
673 % working_sview_config.grid_vert))
674 gtk_table_set_row_spacing(
675 button_processor->table,
676 (*button_processor->coord_y)-1,
677 working_sview_config.gap_size);
678 }
679
680 if ((*button_processor->coord_y) == button_processor->table_y)
681 return SLURM_SUCCESS;
682
683 if ((*button_processor->coord_x) &&
684 !((*button_processor->coord_x)
685 % working_sview_config.grid_hori))
686 gtk_table_set_col_spacing(
687 button_processor->table,
688 (*button_processor->coord_x)-1,
689 working_sview_config.gap_size);
690 }
691 return SLURM_SUCCESS;
692 }
693
_grid_table_by_switch(button_processor_t * button_processor,List node_list)694 static int _grid_table_by_switch(button_processor_t *button_processor,
695 List node_list)
696 {
697 int rc = SLURM_SUCCESS;
698 int inx = 0, ii = 0;
699 switch_record_bitmaps_t *sw_nodes_bitmaps_ptr = g_switch_nodes_maps;
700 #if TOPO_DEBUG
701 /* engage if want original display below switched */
702 ListIterator itr = list_iterator_create(node_list);
703 sview_node_info_t *sview_node_info_ptr = NULL;
704 #endif
705 button_processor->inx = &inx;
706 for (ii=0; ii<g_topo_info_msg_ptr->record_count;
707 ii++, sw_nodes_bitmaps_ptr++) {
708 int j = 0, first, last;
709 if (g_topo_info_msg_ptr->topo_array[ii].level)
710 continue;
711 first = bit_ffs(sw_nodes_bitmaps_ptr->node_bitmap);
712 if (first == -1)
713 continue;
714 last = bit_fls(sw_nodes_bitmaps_ptr->node_bitmap);
715 button_processor->inx = &j;
716 button_processor->force_row_break = false;
717 for (j = first; j <= last; j++) {
718 if (TOPO_DEBUG)
719 g_print("allocated node = %s button# %d\n",
720 g_node_info_ptr->node_array[j].name,
721 j);
722 if (!bit_test(sw_nodes_bitmaps_ptr->node_bitmap, j))
723 continue;
724 /* if (!working_sview_config.show_hidden) { */
725 /* if (!check_part_includes_node(j)) */
726 /* continue; */
727 /* } */
728 if (j == last)
729 button_processor->force_row_break = true;
730 if ((rc = _add_button_to_list(
731 &g_node_info_ptr->node_array[j],
732 button_processor)) != SLURM_SUCCESS)
733 break;
734 button_processor->force_row_break = false;
735 }
736 rc = _add_button_to_list(NULL, button_processor);
737 }
738
739 #if TOPO_DEBUG
740 /* engage this if want original display below
741 * switched grid */
742 button_processor->inx = &inx;
743 while ((sview_node_info_ptr = list_next(itr))) {
744 if ((rc = _add_button_to_list(
745 sview_node_info_ptr->node_ptr,
746 button_processor)) != SLURM_SUCCESS)
747 break;
748 inx++;
749 }
750 list_iterator_destroy(itr);
751 #endif
752
753 /* This is needed to get the correct width of the grid window.
754 * If it is not given then we get a really narrow window. */
755 gtk_table_set_row_spacing(button_processor->table,
756 (*button_processor->coord_y)?
757 ((*button_processor->coord_y)-1):0, 1);
758
759 return rc;
760
761 }
762
_grid_table_by_list(button_processor_t * button_processor,List node_list)763 static int _grid_table_by_list(button_processor_t *button_processor,
764 List node_list)
765 {
766 sview_node_info_t *sview_node_info_ptr = NULL;
767 int inx = 0, rc = SLURM_SUCCESS;
768 ListIterator itr = list_iterator_create(node_list);
769 button_processor->inx = &inx;
770
771 while ((sview_node_info_ptr = list_next(itr))) {
772 /* if (!working_sview_config.show_hidden) { */
773 /* if (!check_part_includes_node(inx)) { */
774 /* inx++; */
775 /* continue; */
776 /* } */
777 /* } */
778 if ((rc = _add_button_to_list(
779 sview_node_info_ptr->node_ptr,
780 button_processor)) != SLURM_SUCCESS)
781 break;
782 inx++;
783 }
784 list_iterator_destroy(itr);
785 rc = _add_button_to_list(NULL, button_processor);
786
787 /* This is needed to get the correct width of the grid window.
788 * If it is not given then we get a really narrow window. */
789 gtk_table_set_row_spacing(button_processor->table,
790 (*button_processor->coord_y)?
791 ((*button_processor->coord_y)-1):0, 1);
792
793
794 return rc;
795 }
796
_init_button_processor(button_processor_t * button_processor,int node_count)797 static int _init_button_processor(button_processor_t *button_processor,
798 int node_count)
799 {
800 int *dim_size = NULL;
801
802 if (node_count == 0) {
803 g_print("_init_button_processor: no nodes selected\n");
804 return SLURM_ERROR;
805 }
806
807 memset(button_processor, 0, sizeof(button_processor_t));
808
809 if (cluster_dims > 1) {
810 dim_size = _get_cluster_dims();
811 if (dim_size == NULL) {
812 g_error("could not read dim_size\n");
813 return SLURM_ERROR;
814 }
815 }
816
817 if (cluster_dims == 3) {
818 button_processor->default_y_offset = (dim_size[2] * dim_size[1])
819 + (dim_size[1] - dim_size[2]);
820 working_sview_config.grid_x_width = dim_size[0] + dim_size[2];
821 button_processor->table_y = (dim_size[2] * dim_size[1])
822 + dim_size[1];
823 } else {
824 if (!working_sview_config.grid_x_width) {
825 if (node_count < 50) {
826 working_sview_config.grid_x_width = 1;
827 } else if (node_count < 500) {
828 working_sview_config.grid_x_width = 10;
829 } else {
830 working_sview_config.grid_x_width = 20;
831 }
832 }
833 button_processor->table_y =
834 (node_count / working_sview_config.grid_x_width) + 1;
835 }
836
837 button_processor->force_row_break = false;
838
839 return SLURM_SUCCESS;
840 }
841 /* static void _destroy_grid_foreach(void *arg) */
842 /* { */
843 /* grid_foreach_t *grid_foreach = (grid_foreach_t *)arg; */
844
845 /* if (grid_foreach) { */
846 /* xfree(grid_foreach); */
847 /* } */
848 /* } */
849
destroy_grid_button(void * arg)850 extern void destroy_grid_button(void *arg)
851 {
852 grid_button_t *grid_button = (grid_button_t *)arg;
853 if (grid_button) {
854 if (grid_button->button) {
855 gtk_widget_destroy(grid_button->button);
856 grid_button->button = NULL;
857 }
858 xfree(grid_button->node_name);
859 xfree(grid_button);
860 }
861 }
862
863 /* we don't set the call back for the button here because sometimes we
864 * need to get a different call back based on what we are doing with
865 * the button, an example of this would be in
866 * add_extra_bluegene_buttons were the small block buttons do
867 * something different than they do regularly
868 * TODO - this may be simplified now that bluegene is gone.
869 */
870
create_grid_button_from_another(grid_button_t * grid_button,char * name,int color_inx)871 extern grid_button_t *create_grid_button_from_another(
872 grid_button_t *grid_button, char *name, int color_inx)
873 {
874 grid_button_t *send_grid_button = NULL;
875 GdkColor color;
876 uint16_t node_base_state;
877 char *new_col = NULL;
878
879 if (!grid_button || !name)
880 return NULL;
881 if (color_inx >= 0) {
882 color_inx %= sview_colors_cnt;
883 new_col = sview_colors[color_inx];
884 } else if (color_inx == MAKE_BLACK)
885 new_col = blank_color;
886 else
887 new_col = white_color;
888
889 send_grid_button = xmalloc(sizeof(grid_button_t));
890 memcpy(send_grid_button, grid_button, sizeof(grid_button_t));
891 node_base_state = send_grid_button->state & NODE_STATE_BASE;
892 send_grid_button->color_inx = color_inx;
893
894 /* need to set the table to empty because we will want to fill
895 this into the new table later */
896 send_grid_button->table = NULL;
897 if (color_inx == MAKE_BLACK) {
898 send_grid_button->button = gtk_button_new();
899 //gtk_widget_set_sensitive (send_grid_button->button, false);
900 gdk_color_parse(new_col, &color);
901 send_grid_button->color = new_col;
902 sview_widget_modify_bg(send_grid_button->button,
903 GTK_STATE_NORMAL, color);
904 /* sview_widget_modify_bg(send_grid_button->button, */
905 /* GTK_STATE_ACTIVE, color); */
906 } else if ((color_inx >= 0) && node_base_state == NODE_STATE_DOWN) {
907 GtkWidget *image = gtk_image_new_from_stock(
908 GTK_STOCK_CANCEL,
909 GTK_ICON_SIZE_SMALL_TOOLBAR);
910 send_grid_button->button = gtk_event_box_new();
911 gtk_event_box_set_above_child(
912 GTK_EVENT_BOX(send_grid_button->button),
913 false);
914 gdk_color_parse("black", &color);
915 sview_widget_modify_bg(send_grid_button->button,
916 GTK_STATE_NORMAL, color);
917 //gdk_color_parse("white", &color);
918 /* sview_widget_modify_bg(send_grid_button->button, */
919 /* GTK_STATE_ACTIVE, color); */
920 gtk_container_add(
921 GTK_CONTAINER(send_grid_button->button),
922 image);
923 } else if ((color_inx >= 0)
924 && (send_grid_button->state & NODE_STATE_DRAIN)) {
925 GtkWidget *image = gtk_image_new_from_stock(
926 GTK_STOCK_DIALOG_ERROR,
927 GTK_ICON_SIZE_SMALL_TOOLBAR);
928
929 send_grid_button->button = gtk_event_box_new();
930 gtk_event_box_set_above_child(
931 GTK_EVENT_BOX(send_grid_button->button),
932 false);
933 gdk_color_parse("black", &color);
934 /* sview_widget_modify_bg(send_grid_button->button, */
935 /* GTK_STATE_NORMAL, color); */
936 //gdk_color_parse("white", &color);
937 /* sview_widget_modify_bg(send_grid_button->button, */
938 /* GTK_STATE_ACTIVE, color); */
939 gtk_container_add(
940 GTK_CONTAINER(send_grid_button->button),
941 image);
942 } else {
943 send_grid_button->button = gtk_button_new();
944 send_grid_button->color = new_col;
945 gdk_color_parse(new_col, &color);
946 sview_widget_modify_bg(send_grid_button->button,
947 GTK_STATE_NORMAL, color);
948 /* sview_widget_modify_bg(send_grid_button->button, */
949 /* GTK_STATE_ACTIVE, color); */
950 }
951 gtk_widget_set_size_request(send_grid_button->button,
952 working_sview_config.button_size,
953 working_sview_config.button_size);
954
955 send_grid_button->node_name = xstrdup(name);
956
957 return send_grid_button;
958 }
959
960 /* start == -1 for all */
change_grid_color(List button_list,int start,int end,int color_inx,bool only_change_unused,enum node_states state_override)961 extern void change_grid_color(List button_list, int start, int end,
962 int color_inx, bool only_change_unused,
963 enum node_states state_override)
964 {
965 ListIterator itr = NULL;
966 grid_button_t *grid_button = NULL;
967 GdkColor color;
968 char *new_col = NULL;
969
970 if (!button_list)
971 return;
972
973 if (color_inx >= 0) {
974 color_inx %= sview_colors_cnt;
975 new_col = sview_colors[color_inx];
976 } else if (color_inx == MAKE_BLACK) {
977 new_col = blank_color;
978 } else if (color_inx == MAKE_TOPO_1) {
979 new_col = topo1_color;
980 } else if (color_inx == MAKE_TOPO_2) {
981 new_col = topo2_color;
982 } else
983 new_col = white_color;
984
985 gdk_color_parse(new_col, &color);
986
987 itr = list_iterator_create(button_list);
988 while ((grid_button = list_next(itr))) {
989 if ((start != -1) &&
990 ((grid_button->inx < start) || (grid_button->inx > end)))
991 continue;
992 _change_button_color(grid_button, color_inx, new_col,
993 color, only_change_unused, state_override);
994 }
995 list_iterator_destroy(itr);
996 }
997
998 /* This variation of change_grid_color() is faster when changing many
999 * button colors at the same time since we can issue a single call to
1000 * _change_button_color() and eliminate a nested loop. */
change_grid_color_array(List button_list,int array_len,int * color_inx,bool * color_set_flag,bool only_change_unused,enum node_states state_override)1001 extern void change_grid_color_array(List button_list, int array_len,
1002 int *color_inx, bool *color_set_flag,
1003 bool only_change_unused,
1004 enum node_states state_override)
1005 {
1006 ListIterator itr = NULL;
1007 grid_button_t *grid_button = NULL;
1008 GdkColor color;
1009 char *new_col = NULL;
1010
1011 if (!button_list)
1012 return;
1013
1014 itr = list_iterator_create(button_list);
1015 while ((grid_button = list_next(itr))) {
1016 if ((grid_button->inx < 0) || (grid_button->inx >= array_len))
1017 continue;
1018 if (!color_set_flag[grid_button->inx])
1019 continue;
1020
1021 if (color_inx[grid_button->inx] >= 0) {
1022 color_inx[grid_button->inx] %= sview_colors_cnt;
1023 new_col = sview_colors[color_inx[grid_button->inx]];
1024 } else if (color_inx[grid_button->inx] == MAKE_BLACK) {
1025 new_col = blank_color;
1026 } else if (color_inx[grid_button->inx] == MAKE_TOPO_1) {
1027 new_col = topo1_color;
1028 } else if (color_inx[grid_button->inx] == MAKE_TOPO_2) {
1029 new_col = topo2_color;
1030 } else
1031 new_col = white_color;
1032 gdk_color_parse(new_col, &color);
1033
1034 _change_button_color(grid_button, color_inx[grid_button->inx],
1035 new_col, color, only_change_unused,
1036 state_override);
1037 }
1038 list_iterator_destroy(itr);
1039 return;
1040 }
1041
highlight_grid(GtkTreeView * tree_view,int node_inx_id,int color_inx_id,List button_list)1042 extern void highlight_grid(GtkTreeView *tree_view,
1043 int node_inx_id, int color_inx_id, List button_list)
1044 {
1045 ListIterator itr = NULL;
1046 grid_button_t *grid_button = NULL;
1047 grid_foreach_t grid_foreach;
1048
1049 if (!button_list || !tree_view)
1050 return;
1051
1052 /*first clear all grid buttons*/
1053 itr = list_iterator_create(button_list);
1054 while ((grid_button = list_next(itr))) {
1055 /* clear everyone */
1056 if ((gtk_widget_get_state(grid_button->button)
1057 != GTK_STATE_ACTIVE)) {
1058 gtk_widget_set_state(grid_button->button,
1059 GTK_STATE_ACTIVE);
1060 }
1061 }
1062 list_iterator_destroy(itr);
1063
1064 /* for each currently selected row,go back & ensure the
1065 * corresponding grid button is highlighted */
1066 memset(&grid_foreach, 0, sizeof(grid_foreach_t));
1067 grid_foreach.node_inx_id = node_inx_id;
1068 grid_foreach.color_inx_id = color_inx_id;
1069 grid_foreach.button_list = button_list;
1070 if (grid_foreach.color_inx_id != (int)NO_VAL)
1071 gtk_tree_selection_selected_foreach(
1072 gtk_tree_view_get_selection(tree_view),
1073 _each_highlightd, &grid_foreach);
1074 else
1075 gtk_tree_selection_selected_foreach(
1076 gtk_tree_view_get_selection(tree_view),
1077 _each_highlight_selected, &grid_foreach);
1078
1079 return;
1080 }
1081
1082 /* start == -1 for all */
highlight_grid_range(int start,int end,List button_list)1083 extern void highlight_grid_range(int start, int end, List button_list)
1084 {
1085 ListIterator itr = NULL;
1086 grid_button_t *grid_button = NULL;
1087
1088 if (!button_list)
1089 return;
1090
1091 itr = list_iterator_create(button_list);
1092 while ((grid_button = list_next(itr))) {
1093 if (start != -1)
1094 if ((grid_button->inx < start)
1095 || (grid_button->inx > end)) {
1096 /* clear everyone else */
1097 if ((gtk_widget_get_state(grid_button->button)
1098 != GTK_STATE_ACTIVE))
1099 gtk_widget_set_state(
1100 grid_button->button,
1101 GTK_STATE_ACTIVE);
1102 continue;
1103 }
1104 /* highlight this one, if it is already hightlighted,
1105 * put it back to normal */
1106 //g_print("highlighting %d\n", grid_button->inx);
1107 if ((gtk_widget_get_state(grid_button->button)
1108 != GTK_STATE_NORMAL))
1109 gtk_widget_set_state(grid_button->button,
1110 GTK_STATE_NORMAL);
1111 }
1112 list_iterator_destroy(itr);
1113
1114 return;
1115 }
1116
set_grid_used(List button_list,int start,int end,bool used,bool reset_highlight)1117 extern void set_grid_used(List button_list, int start, int end,
1118 bool used, bool reset_highlight)
1119 {
1120 ListIterator itr = NULL;
1121 grid_button_t *grid_button = NULL;
1122
1123 if (!button_list)
1124 return;
1125
1126 itr = list_iterator_create(button_list);
1127 while ((grid_button = list_next(itr))) {
1128 if (start != -1)
1129 if ((grid_button->inx < start)
1130 || (grid_button->inx > end))
1131 continue;
1132 grid_button->used = used;
1133 if (reset_highlight)
1134 gtk_widget_set_state(grid_button->button,
1135 GTK_STATE_NORMAL);
1136
1137 }
1138 list_iterator_destroy(itr);
1139
1140 return;
1141 }
1142
get_button_list_from_main(List * button_list,int start,int end,int color_inx)1143 extern void get_button_list_from_main(List *button_list, int start, int end,
1144 int color_inx)
1145 {
1146 ListIterator itr = NULL;
1147 ListIterator button_itr = NULL;
1148 grid_button_t *grid_button = NULL;
1149 grid_button_t *send_grid_button = NULL;
1150
1151 if (!*button_list)
1152 *button_list = list_create(destroy_grid_button);
1153
1154 color_inx %= sview_colors_cnt;
1155 itr = list_iterator_create(grid_button_list);
1156 while ((grid_button = list_next(itr))) {
1157 if ((grid_button->inx < start)
1158 || (grid_button->inx > end))
1159 continue;
1160 button_itr = list_iterator_create(*button_list);
1161 while ((send_grid_button = list_next(button_itr))) {
1162 if (send_grid_button->inx == grid_button->inx)
1163 break;
1164 }
1165 list_iterator_destroy(button_itr);
1166 if (send_grid_button)
1167 continue;
1168
1169 send_grid_button = create_grid_button_from_another(
1170 grid_button, grid_button->node_name, color_inx);
1171 if (send_grid_button) {
1172 send_grid_button->button_list = *button_list;
1173 _add_button_signals(send_grid_button);
1174 list_append(*button_list, send_grid_button);
1175 }
1176 }
1177 list_iterator_destroy(itr);
1178 return;
1179 }
1180
copy_main_button_list(int initial_color)1181 extern List copy_main_button_list(int initial_color)
1182 {
1183 ListIterator itr = NULL;
1184 grid_button_t *grid_button = NULL;
1185 grid_button_t *send_grid_button = NULL;
1186 List button_list = list_create(destroy_grid_button);
1187
1188 itr = list_iterator_create(grid_button_list);
1189 while ((grid_button = list_next(itr))) {
1190 send_grid_button = create_grid_button_from_another(
1191 grid_button, grid_button->node_name, initial_color);
1192 if (send_grid_button) {
1193 send_grid_button->button_list = button_list;
1194 _add_button_signals(send_grid_button);
1195 send_grid_button->used = false;
1196 list_append(button_list, send_grid_button);
1197 }
1198 }
1199 list_iterator_destroy(itr);
1200 return button_list;
1201 }
1202
put_buttons_in_table(GtkTable * table,List button_list)1203 extern void put_buttons_in_table(GtkTable *table, List button_list)
1204 {
1205 int coord_x=0, coord_y=0;
1206 button_processor_t button_processor;
1207 grid_button_t *grid_button = NULL;
1208 ListIterator itr = NULL;
1209 list_sort(button_list, (ListCmpF) _sort_button_inx);
1210
1211 if (!button_list) {
1212 g_print("put_buttons_in_table: no node_list given\n");
1213 return;
1214 }
1215
1216 if (_init_button_processor(&button_processor, list_count(button_list))
1217 != SLURM_SUCCESS)
1218 return;
1219
1220 button_processor.table = table;
1221 button_processor.button_list = button_list;
1222 button_processor.coord_x = &coord_x;
1223 button_processor.coord_y = &coord_y;
1224
1225 gtk_table_resize(table, button_processor.table_y,
1226 working_sview_config.grid_x_width);
1227
1228 itr = list_iterator_create(button_list);
1229 while ((grid_button = list_next(itr))) {
1230 if (cluster_dims == 3) {
1231 grid_button->table = table;
1232 gtk_table_attach(table, grid_button->button,
1233 grid_button->table_x,
1234 (grid_button->table_x+1),
1235 grid_button->table_y,
1236 (grid_button->table_y+1),
1237 GTK_SHRINK, GTK_SHRINK,
1238 1, 1);
1239 if (!grid_button->table_x) {
1240 gtk_table_set_row_spacing(table,
1241 grid_button->table_y,
1242 working_sview_config.gap_size);
1243 }
1244 } else {
1245 grid_button->table = table;
1246 grid_button->table_x = coord_x;
1247 grid_button->table_y = coord_y;
1248 gtk_table_attach(table, grid_button->button,
1249 coord_x, (coord_x+1),
1250 coord_y, (coord_y+1),
1251 GTK_SHRINK, GTK_SHRINK,
1252 1, 1);
1253 coord_x++;
1254 if (coord_x == working_sview_config.grid_x_width) {
1255 coord_x = 0;
1256 coord_y++;
1257 if (!(coord_y % working_sview_config.grid_vert))
1258 gtk_table_set_row_spacing(
1259 table, coord_y-1,
1260 working_sview_config.gap_size);
1261 }
1262
1263 if (coord_y == button_processor.table_y)
1264 break;
1265
1266 if (coord_x
1267 && !(coord_x % working_sview_config.grid_hori))
1268 gtk_table_set_col_spacing(table, coord_x-1, 5);
1269 }
1270 }
1271 list_iterator_destroy(itr);
1272
1273 if (cluster_dims == 0) {
1274 /* This is needed to get the correct width of the grid window.
1275 * If it is not given then we get a really narrow window. */
1276 gtk_table_set_row_spacing(table, coord_y?(coord_y-1):0, 1);
1277 }
1278 gtk_widget_show_all(GTK_WIDGET(table));
1279 }
1280
update_grid_table(GtkTable * table,List button_list,List node_list)1281 extern int update_grid_table(GtkTable *table, List button_list, List node_list)
1282 {
1283 int rc = SLURM_SUCCESS;
1284 int coord_x=0, coord_y=0, inx=0;
1285 ListIterator itr = NULL, itr2 = NULL;
1286 sview_node_info_t *sview_node_info_ptr = NULL;
1287 button_processor_t button_processor;
1288
1289 if (!node_list) {
1290 g_print("update_grid_table: no node_list given\n");
1291 return SLURM_ERROR;
1292 }
1293
1294 if (_init_button_processor(&button_processor, list_count(node_list))
1295 != SLURM_SUCCESS)
1296 return SLURM_ERROR;
1297
1298 button_processor.table = table;
1299 button_processor.button_list = button_list;
1300 button_processor.coord_x = &coord_x;
1301 button_processor.coord_y = &coord_y;
1302 button_processor.inx = &inx;
1303
1304 gtk_table_resize(table, button_processor.table_y,
1305 working_sview_config.grid_x_width);
1306 gtk_table_set_row_spacings(table, 0);
1307 gtk_table_set_col_spacings(table, 0);
1308 itr = list_iterator_create(node_list);
1309 itr2 = list_iterator_create(button_list);
1310
1311 while ((sview_node_info_ptr = list_next(itr))) {
1312 int found = 0;
1313 /* if (!working_sview_config.show_hidden */
1314 /* && !check_part_includes_node(inx)) { */
1315 /* inx++; */
1316 /* continue; */
1317 /* } */
1318
1319 // again:
1320 while ((button_processor.grid_button = list_next(itr2))) {
1321 if (button_processor.grid_button->inx != inx) {
1322 continue;
1323 }
1324 found = 1;
1325
1326 if ((rc = _add_button_to_list(
1327 sview_node_info_ptr->node_ptr,
1328 &button_processor)) != SLURM_SUCCESS)
1329 goto end_it;
1330 break;
1331 }
1332 if (!found) {
1333 //list_iterator_reset(itr2);
1334 //goto again;
1335 return RESET_GRID;
1336 }
1337 inx++;
1338 }
1339 rc = _add_button_to_list(NULL, &button_processor);
1340
1341 /* This is needed to get the correct width of the grid window.
1342 * If it is not given then we get a really narrow window. */
1343 gtk_table_set_row_spacing(table, coord_y?(coord_y-1):0, 1);
1344
1345 end_it:
1346 list_iterator_destroy(itr);
1347 list_iterator_destroy(itr2);
1348 return rc;
1349 }
1350
get_system_stats(GtkTable * table)1351 extern int get_system_stats(GtkTable *table)
1352 {
1353 int rc = SLURM_SUCCESS;
1354 node_info_msg_t *node_info_ptr = NULL;
1355 List node_list = NULL;
1356
1357 if ((rc = get_new_info_node(&node_info_ptr, force_refresh))
1358 == SLURM_NO_CHANGE_IN_DATA) {
1359 } else if (rc != SLURM_SUCCESS)
1360 return SLURM_ERROR;
1361
1362 node_list = create_node_info_list(node_info_ptr, false);
1363 if (grid_button_list) {
1364 rc = update_grid_table(main_grid_table, grid_button_list,
1365 node_list);
1366 if (rc == RESET_GRID) {
1367 FREE_NULL_LIST(grid_button_list);
1368 grid_button_list = list_create(destroy_grid_button);
1369 setup_grid_table(main_grid_table, grid_button_list,
1370 node_list);
1371 }
1372 } else {
1373 grid_button_list = list_create(destroy_grid_button);
1374 setup_grid_table(main_grid_table, grid_button_list, node_list);
1375 }
1376
1377 gtk_widget_show_all(GTK_WIDGET(main_grid_table));
1378
1379 return SLURM_SUCCESS;
1380 }
1381
setup_grid_table(GtkTable * table,List button_list,List node_list)1382 extern int setup_grid_table(GtkTable *table, List button_list, List node_list)
1383 {
1384 int rc = SLURM_SUCCESS;
1385 button_processor_t button_processor;
1386 int coord_x=0, coord_y=0;
1387
1388 if (!node_list) {
1389 g_print("setup_grid_table: no node_list given\n");
1390 return SLURM_ERROR;
1391 }
1392
1393 if (_init_button_processor(&button_processor, list_count(node_list))
1394 != SLURM_SUCCESS)
1395 return SLURM_ERROR;
1396
1397 button_processor.table = table;
1398 button_processor.button_list = button_list;
1399 button_processor.coord_x = &coord_x;
1400 button_processor.coord_y = &coord_y;
1401
1402 gtk_table_resize(table, button_processor.table_y,
1403 working_sview_config.grid_x_width);
1404
1405 if (default_sview_config.grid_topological && g_topo_info_msg_ptr)
1406 rc = _grid_table_by_switch(&button_processor, node_list);
1407 else
1408 rc = _grid_table_by_list(&button_processor, node_list);
1409
1410 list_sort(button_list, (ListCmpF) _sort_button_inx);
1411
1412 return rc;
1413 }
1414
sview_init_grid(bool reset_highlight)1415 extern void sview_init_grid(bool reset_highlight)
1416 {
1417 static node_info_msg_t *node_info_ptr = NULL;
1418 int rc = SLURM_SUCCESS;
1419 node_info_t *node_ptr = NULL;
1420 int i = 0;
1421 ListIterator itr = NULL;
1422 grid_button_t *grid_button = NULL;
1423
1424 rc = get_new_info_node(&node_info_ptr, force_refresh);
1425 if (rc == SLURM_NO_CHANGE_IN_DATA) {
1426 /* need to clear out old data */
1427 set_grid_used(grid_button_list, -1, -1, false, reset_highlight);
1428 return;
1429 } else if (rc != SLURM_SUCCESS) {
1430 return;
1431 }
1432
1433 if (!grid_button_list) {
1434 g_print("you need to run get_system_stats() first\n");
1435 exit(0);
1436 }
1437
1438 itr = list_iterator_create(grid_button_list);
1439 for (i = 0; i < node_info_ptr->record_count; i++) {
1440 int tried_again = 0;
1441 node_ptr = &node_info_ptr->node_array[i];
1442 try_again:
1443 while ((grid_button = list_next(itr))) {
1444 if (grid_button->inx != i)
1445 continue;
1446 grid_button->state = node_ptr->node_state;
1447 gtk_widget_set_state(grid_button->button,
1448 GTK_STATE_NORMAL);
1449 grid_button->used = false;
1450 break;
1451 }
1452 if (!grid_button && !tried_again) {
1453 /* the order should never change but just to
1454 * make sure we don't miss it */
1455 list_iterator_reset(itr);
1456 tried_again = 1;
1457 goto try_again;
1458 }
1459 }
1460 list_iterator_destroy(itr);
1461 }
1462
1463 /* make grid if it doesn't exist and set the buttons to unused */
setup_popup_grid_list(popup_info_t * popup_win)1464 extern void setup_popup_grid_list(popup_info_t *popup_win)
1465 {
1466 int def_color = MAKE_BLACK;
1467
1468 if (popup_win->grid_button_list) {
1469 set_grid_used(popup_win->grid_button_list,
1470 -1, -1, false, false);
1471 } else {
1472 popup_win->grid_button_list =
1473 copy_main_button_list(def_color);
1474 put_buttons_in_table(popup_win->grid_table,
1475 popup_win->grid_button_list);
1476 popup_win->full_grid = 1;
1477 }
1478 }
1479
1480 /* clear extra buttons to N/A and if model then set those as white */
post_setup_popup_grid_list(popup_info_t * popup_win)1481 extern void post_setup_popup_grid_list(popup_info_t *popup_win)
1482 {
1483 /* refresh the pointer */
1484 if (popup_win->model
1485 && gtk_tree_store_iter_is_valid(GTK_TREE_STORE(popup_win->model),
1486 &popup_win->iter)) {
1487 gtk_tree_model_get(popup_win->model, &popup_win->iter,
1488 popup_win->node_inx_id,
1489 &popup_win->node_inx, -1);
1490 } else {
1491 popup_win->node_inx = NULL;
1492 }
1493
1494 if (popup_win->node_inx) {
1495 int j=0;
1496 while (popup_win->node_inx[j] >= 0) {
1497 change_grid_color(
1498 popup_win->grid_button_list,
1499 popup_win->node_inx[j],
1500 popup_win->node_inx[j+1], MAKE_WHITE, true, 0);
1501 j += 2;
1502 }
1503 }
1504
1505 change_grid_color(popup_win->grid_button_list, -1, -1,
1506 MAKE_BLACK, true, NODE_STATE_IDLE);
1507 }
1508