From 180026f6668f966b44cd072e3171162062278889 Mon Sep 17 00:00:00 2001
From: Danny Auble <da@llnl.gov>
Date: Wed, 1 Jul 2009 20:33:48 +0000
Subject: [PATCH] Improve sview performance on very large machines.

---
 NEWS                   |   3 +-
 src/sview/block_info.c |   5 +-
 src/sview/grid.c       | 148 +++++++++++++++++------------------------
 src/sview/job_info.c   |   5 +-
 src/sview/node_info.c  |  10 ++-
 src/sview/part_info.c  |   5 +-
 src/sview/resv_info.c  |   7 +-
 src/sview/sview.c      |   7 +-
 src/sview/sview.h      |  39 ++++++-----
 9 files changed, 114 insertions(+), 115 deletions(-)

diff --git a/NEWS b/NEWS
index cabb3df7d87..7892dcc7684 100644
--- a/NEWS
+++ b/NEWS
@@ -25,8 +25,9 @@ documents those changes that are of interest to users and admins.
  -- Modify job step cancel logic for scancel and srun (on reciept of SIGTERM 
     or three SIGINT) to immediately send SIGKILL to spawned tasks.  Previous 
     logic would send SIGCONT, SIGTERM, wait KillWait seconds, SIGKILL.
---  Create a spank_get_item() option that the SPANK cpuset plugin can use to
+ -- Create a spank_get_item() option that the SPANK cpuset plugin can use to
     discover the cpus that the select/cons_res plugin has allocated to a job.
+ -- Improve sview performance on very large machines.
 
 * Changes in SLURM 2.1.0-pre1
 =============================
diff --git a/src/sview/block_info.c b/src/sview/block_info.c
index f2ae269486f..0cfdf19ca80 100644
--- a/src/sview/block_info.c
+++ b/src/sview/block_info.c
@@ -590,7 +590,8 @@ need_refresh:
 		}
 	}
 	list_iterator_destroy(itr);
-	
+	post_setup_popup_grid_list(popup_win);
+
 	if(!found) {
 		if(!popup_win->not_found) { 
 			char *temp = "BLOCK DOESN'T EXSIST\n";
@@ -907,6 +908,7 @@ display_it:
 		i++;
 	}
 	list_iterator_destroy(itr);
+	change_grid_color(grid_button_list, -1, -1, MAKE_WHITE, true, 0);
 
 	if(view == ERROR_VIEW && display_widget) {
 		gtk_widget_destroy(display_widget);
@@ -1128,6 +1130,7 @@ display_it:
 		}
 	}
 	list_iterator_destroy(itr);
+	post_setup_popup_grid_list(popup_win);
 	 
 	_update_info_block(send_block_list, 
 			   GTK_TREE_VIEW(spec_info->display_widget));
diff --git a/src/sview/grid.c b/src/sview/grid.c
index fcc3d842884..22e7410ec4f 100644
--- a/src/sview/grid.c
+++ b/src/sview/grid.c
@@ -176,8 +176,10 @@ void _put_button_as_down(grid_button_t *grid_button, int state)
 		//gtk_widget_set_sensitive (grid_button->button, TRUE);
 		return;
 	}
+
 	gtk_widget_destroy(grid_button->button);		
-		
+	grid_button->color = NULL;
+	grid_button->color_inx = MAKE_DOWN;
 	grid_button->button = gtk_event_box_new();
 	gtk_tooltips_set_tip(grid_button->tip,
 			     grid_button->button,
@@ -315,22 +317,31 @@ extern grid_button_t *create_grid_button_from_another(
 	grid_button_t *send_grid_button = NULL;
 	GdkColor color;
 	uint16_t node_base_state;
+	char *new_col = NULL;
 
 	if(!grid_button || !name)
 		return NULL;
-	if(color_inx >= 0)
+	if(color_inx >= 0) {
 		color_inx %= sview_colors_cnt;
+		new_col = sview_colors[color_inx];
+	} else if(color_inx == MAKE_BLACK) 
+		new_col = blank_color;
+	else 
+		new_col = "#FFFFFF";
        			
 	send_grid_button = xmalloc(sizeof(grid_button_t));
 	memcpy(send_grid_button, grid_button, sizeof(grid_button_t));
 	node_base_state = send_grid_button->state & NODE_STATE_BASE;
+	send_grid_button->color_inx = color_inx;
+	
 	/* need to set the table to empty because we will want to fill
 	   this into the new table later */
 	send_grid_button->table = NULL;
 	if(color_inx == MAKE_BLACK) {
 		send_grid_button->button = gtk_button_new();
 		//gtk_widget_set_sensitive (send_grid_button->button, FALSE);
-		gdk_color_parse(blank_color, &color);
+		gdk_color_parse(new_col, &color);
+		send_grid_button->color = new_col;
 		gtk_widget_modify_bg(send_grid_button->button, 
 				     GTK_STATE_NORMAL, &color);
 	} else if((color_inx >= 0) && node_base_state == NODE_STATE_DOWN) {
@@ -372,10 +383,8 @@ extern grid_button_t *create_grid_button_from_another(
 			image);		
 	} else {
 		send_grid_button->button = gtk_button_new();
-		if(color_inx >= 0)
-			gdk_color_parse(sview_colors[color_inx], &color);
-		else
-			gdk_color_parse("white", &color);
+		send_grid_button->color = new_col;		
+		gdk_color_parse(new_col, &color);
 		gtk_widget_modify_bg(send_grid_button->button, 
 				     GTK_STATE_NORMAL, &color);
 	}
@@ -388,10 +397,6 @@ extern grid_button_t *create_grid_button_from_another(
 			     send_grid_button->button,
 			     send_grid_button->node_name,
 			     "click for node stats");
-	if(color_inx >= 0)
-		send_grid_button->color = sview_colors[color_inx];
-	else
-		send_grid_button->color = "white";
 	return send_grid_button;
 }
 
@@ -404,17 +409,20 @@ extern char *change_grid_color(List button_list, int start, int end,
 	grid_button_t *grid_button = NULL;
 	uint16_t node_base_state;
 	GdkColor color;
+	char *new_col = NULL;
 
 	if(!button_list)
 		return NULL;
 
 	if(color_inx >= 0) {
 		color_inx %= sview_colors_cnt;
-		gdk_color_parse(sview_colors[color_inx], &color);
+		new_col = sview_colors[color_inx];
 	} else if(color_inx == MAKE_BLACK) 
-		gdk_color_parse(blank_color, &color);
+		new_col = blank_color;
 	else 
-		gdk_color_parse("#FFFFFF", &color);
+		new_col = "#FFFFFF";
+	
+	gdk_color_parse(new_col, &color);
 
 	itr = list_iterator_create(button_list);
 	while((grid_button = list_next(itr))) {
@@ -424,15 +432,19 @@ extern char *change_grid_color(List button_list, int start, int end,
 			    ||  (grid_button->inx > end)) 
 				continue;
 		
-		if(!change_unused && !grid_button->used)
+		if(change_unused && grid_button->used)
 			continue;
-
+		
+		grid_button->used = true;
 		if(color_inx == MAKE_BLACK) {
-			_put_button_as_inactive(grid_button);
-			grid_button->color = blank_color;
-			gtk_widget_modify_bg(grid_button->button, 
-					     GTK_STATE_NORMAL, &color);
-
+			if(grid_button->color_inx != color_inx) {
+				_put_button_as_inactive(grid_button);
+				grid_button->color = new_col;
+				grid_button->color_inx = color_inx;
+				gtk_widget_modify_bg(grid_button->button, 
+						     GTK_STATE_NORMAL, &color);
+			}
+			
 			continue;
 		}
 		if(state_override != NODE_STATE_UNKNOWN)
@@ -444,17 +456,16 @@ extern char *change_grid_color(List button_list, int start, int end,
 		} else if ((state & NODE_STATE_DRAIN) 
 			   || (node_base_state == NODE_STATE_ERROR)) {
 			_put_button_as_down(grid_button, NODE_STATE_DRAIN);
-		} else {
+		} else if(grid_button->color_inx != color_inx) {
 			_put_button_as_up(grid_button);
-			if(color_inx == MAKE_WHITE) 
-				grid_button->color = "#FFFFFF";
-			else
-				grid_button->color = sview_colors[color_inx];
-			gtk_widget_modify_bg(grid_button->button, 
+			grid_button->color = new_col;
+			grid_button->color_inx = color_inx;
+			gtk_widget_modify_bg(grid_button->button,
 					     GTK_STATE_NORMAL, &color);
 		}
 	}
 	list_iterator_destroy(itr);
+
 	return sview_colors[color_inx];
 }
 
@@ -829,6 +840,7 @@ extern int setup_grid_table(GtkTable *table, List button_list, List node_list)
 		coord_y = (y_offset - y) + z;
 #endif
 		grid_button = xmalloc(sizeof(grid_button_t));
+		grid_button->color_inx = MAKE_INIT;
 		grid_button->inx = inx++;
 		grid_button->table = table;
 		grid_button->table_x = coord_x;
@@ -895,16 +907,15 @@ extern void sview_init_grid()
 	int error_code = SLURM_SUCCESS;
 	node_info_t *node_ptr = NULL;
 	int i = 0;
-	uint16_t node_base_state;
 	ListIterator itr = NULL;
 	grid_button_t *grid_button = NULL;
-	GdkColor color;
 	uint16_t error_cpus = 0;
 
 	if((error_code = get_new_info_node(&node_info_ptr, force_refresh))
 	   == SLURM_NO_CHANGE_IN_DATA) { 
 		/* need to clear out old data */
-		sview_reset_grid();
+		set_grid_used(grid_button_list, -1, -1, false);
+		//sview_reset_grid();
 		return;
 	} else if (error_code != SLURM_SUCCESS) {
 		return;
@@ -928,78 +939,35 @@ extern void sview_init_grid()
 		exit(0);
 	}
 	
-	gdk_color_parse("white", &color);
 	itr = list_iterator_create(grid_button_list);
 	for(i=0; i<node_info_ptr->record_count; i++) {
+		int tried_again = 0;
 		node_ptr = &node_info_ptr->node_array[i];
-		list_iterator_reset(itr);
+	try_again:
 		while((grid_button = list_next(itr))) {
 			if (grid_button->inx != i)
 				continue;
-
-			node_base_state = node_ptr->node_state 
-				& NODE_STATE_BASE;
-			if (node_base_state == NODE_STATE_DOWN) {
-				_put_button_as_down(grid_button,
-						    NODE_STATE_DOWN);
-			} else if ((node_ptr->node_state & NODE_STATE_DRAIN)
-				   || (node_base_state == NODE_STATE_ERROR)) {
-				_put_button_as_down(grid_button,
-						    NODE_STATE_DRAIN);
-			} else {
-				_put_button_as_up(grid_button);
-				grid_button->color = "white";
-				gtk_widget_modify_bg(grid_button->button, 
-						     GTK_STATE_NORMAL, &color);
-			}
+			grid_button->used = false;
 			grid_button->state = node_ptr->node_state;
 			break;
 		}
-	}
-	list_iterator_destroy(itr);
-}
-
-extern void sview_reset_grid()
-{
-	grid_button_t *grid_button = NULL;
-	uint16_t node_base_state;
-	ListIterator itr = NULL;
-	GdkColor color;
-	
-	if(!grid_button_list) {
-		g_print("you need to run get_system_stats() first\n");
-		exit(0);
-	}
-	gdk_color_parse("white", &color);
-		
-	itr = list_iterator_create(grid_button_list);
-	while((grid_button = list_next(itr))) {
-		node_base_state = grid_button->state & NODE_STATE_BASE;
-		if ((node_base_state == NODE_STATE_DOWN)
-		    || (grid_button->state & NODE_STATE_DRAIN)
-		    || (node_base_state == NODE_STATE_ERROR)) {
-			continue;
+		if(!grid_button && !tried_again) {
+			/* the order should never change but just to
+			 * make sure we don't miss it */
+			list_iterator_reset(itr);
+			tried_again = 1;
+			goto try_again;
 		}
-		_put_button_as_up(grid_button);
-		grid_button->color = "white";
-		gtk_widget_modify_bg(grid_button->button, 
-				     GTK_STATE_NORMAL, &color);
 	}
 	list_iterator_destroy(itr);
 }
 
-/* clear the grid */
+/* make grid if it doesn't exist and set the buttons to unused */
 extern void setup_popup_grid_list(popup_info_t *popup_win)
 {
 	int def_color = MAKE_BLACK;
-	GtkTreeIter iter;
-
-/* 	if(!popup_win->model)  */
-/* 		def_color = MAKE_WHITE; */
 
 	if(popup_win->grid_button_list) {
-		change_grid_color(popup_win->grid_button_list, -1, -1,
-				  def_color, true, 0);
 		set_grid_used(popup_win->grid_button_list, -1, -1, false);
 	} else {
 		popup_win->grid_button_list =
@@ -1008,6 +976,12 @@ extern void setup_popup_grid_list(popup_info_t *popup_win)
 				     popup_win->grid_button_list);
 		popup_win->full_grid = 1;
 	}
+}
+
+/* clear extra buttons to N/A and if model then set those as white */
+extern void post_setup_popup_grid_list(popup_info_t *popup_win)
+{
+	GtkTreeIter iter;
 
 	/* refresh the pointer */
 	if(popup_win->model 
@@ -1024,16 +998,14 @@ extern void setup_popup_grid_list(popup_info_t *popup_win)
 		int j=0;
 	       
 		while(popup_win->node_inx[j] >= 0) {
-			set_grid_used(popup_win->grid_button_list,
-				      popup_win->node_inx[j],
-				      popup_win->node_inx[j+1], true);
 			change_grid_color(
 				popup_win->grid_button_list,
 				popup_win->node_inx[j],
 				popup_win->node_inx[j+1], MAKE_WHITE, true, 0);
 			j += 2;
 		}
-	} else
-		set_grid_used(popup_win->grid_button_list, -1, -1, true);	
+	}
 
+	change_grid_color(grid_button_list, -1, -1,
+			  MAKE_BLACK, true, NODE_STATE_IDLE);
 }
diff --git a/src/sview/job_info.c b/src/sview/job_info.c
index 46d839ee57a..3f28ed08406 100644
--- a/src/sview/job_info.c
+++ b/src/sview/job_info.c
@@ -2362,7 +2362,8 @@ need_refresh:
 		}
 		list_iterator_destroy(itr);
 	}
-	
+	post_setup_popup_grid_list(popup_win);
+
 	if(!found) {
 		if(!popup_win->not_found) { 
 			char *temp = "JOB ALREADY FINISHED OR NOT FOUND\n";
@@ -2774,6 +2775,7 @@ display_it:
 		i++;
 	}
 	list_iterator_destroy(itr);
+	change_grid_color(grid_button_list, -1, -1, MAKE_WHITE, true, 0);
 
 	if(view == ERROR_VIEW && display_widget) {
 		gtk_widget_destroy(display_widget);
@@ -3017,6 +3019,7 @@ display_it:
 		}
 	}
 	list_iterator_destroy(itr);
+	post_setup_popup_grid_list(popup_win);
 
 	_update_info_job(send_info_list,
 			 GTK_TREE_VIEW(spec_info->display_widget));
diff --git a/src/sview/node_info.c b/src/sview/node_info.c
index dbb916e871d..295163555de 100644
--- a/src/sview/node_info.c
+++ b/src/sview/node_info.c
@@ -580,9 +580,12 @@ extern int get_new_info_node(node_info_msg_t **info_ptr, int force)
 
 	if(*info_ptr != node_info_ptr) 
 		error_code = SLURM_SUCCESS;
-	
-	g_node_scaling = new_node_ptr->node_scaling;
-	cpus_per_node = new_node_ptr->node_array[0].cpus / g_node_scaling;
+
+	if(new_node_ptr) {
+		g_node_scaling = new_node_ptr->node_scaling;
+		cpus_per_node = 
+			new_node_ptr->node_array[0].cpus / g_node_scaling;
+	}
 
 	*info_ptr = new_node_ptr;
 	return error_code;
@@ -1133,6 +1136,7 @@ display_it:
 				  i, i, 0, true, 0);
 	}
 	list_iterator_destroy(itr);
+	post_setup_popup_grid_list(popup_win);
 
 	if(search_info->gchar_data) {
 		hostlist_iterator_destroy(host_itr);
diff --git a/src/sview/part_info.c b/src/sview/part_info.c
index df9edf4b7a9..4535593d01a 100644
--- a/src/sview/part_info.c
+++ b/src/sview/part_info.c
@@ -1576,7 +1576,8 @@ need_refresh:
 		}
 	}
 	list_iterator_destroy(itr);
-	
+	post_setup_popup_grid_list(popup_win);
+
 	if(!found) {
 		if(!popup_win->not_found) { 
 			char *temp = "PARTITION DOESN'T EXSIST\n";
@@ -1978,6 +1979,7 @@ display_it:
 		i++;
 	}
 	list_iterator_destroy(itr);
+	change_grid_color(grid_button_list, -1, -1, MAKE_WHITE, true, 0);
 		
 	if(view == ERROR_VIEW && display_widget) {
 		gtk_widget_destroy(display_widget);
@@ -2183,6 +2185,7 @@ display_it:
 		}
 	}
 	list_iterator_destroy(itr);
+	post_setup_popup_grid_list(popup_win);
 	 
 	_update_info_part(send_info_list, 
 			  GTK_TREE_VIEW(spec_info->display_widget));
diff --git a/src/sview/resv_info.c b/src/sview/resv_info.c
index f79989b0bcc..3b7e20085d2 100644
--- a/src/sview/resv_info.c
+++ b/src/sview/resv_info.c
@@ -756,7 +756,8 @@ need_refresh:
 		}
 	}
 	list_iterator_destroy(itr);
-	
+	post_setup_popup_grid_list(popup_win);
+
 	if(!found) {
 		if(!popup_win->not_found) { 
 			char *temp = "RESERVATION DOESN'T EXSIST\n";
@@ -1009,7 +1010,8 @@ display_it:
 		i++;
 	}
 	list_iterator_destroy(itr);
-		
+	change_grid_color(grid_button_list, -1, -1, MAKE_WHITE, true, 0);
+	
 	if(view == ERROR_VIEW && display_widget) {
 		gtk_widget_destroy(display_widget);
 		display_widget = NULL;
@@ -1176,6 +1178,7 @@ display_it:
 		}
 	}
 	list_iterator_destroy(itr);
+	post_setup_popup_grid_list(popup_win);
 
 	_update_info_resv(send_resv_list, 
 			  GTK_TREE_VIEW(spec_info->display_widget));
diff --git a/src/sview/sview.c b/src/sview/sview.c
index 97b592480eb..8be92f9b78b 100644
--- a/src/sview/sview.c
+++ b/src/sview/sview.c
@@ -119,7 +119,7 @@ void *_page_thr(void *arg)
 	GtkTable *table = page->table;
 	display_data_t *display_data = &main_display_data[num];
 	static int thread_count = 0;
-
+	DEF_TIMERS;
 	xfree(page);
 	
 	if(!grid_init) {
@@ -143,6 +143,7 @@ void *_page_thr(void *arg)
 	gdk_flush();
 	gdk_threads_leave();
 	while(page_running[num]) {		
+		START_TIMER;
 		g_static_mutex_lock(&sview_mutex);
 		gdk_threads_enter();
 		sview_init_grid();
@@ -150,7 +151,8 @@ void *_page_thr(void *arg)
 		gdk_flush();
 		gdk_threads_leave();
 		g_static_mutex_unlock(&sview_mutex);
-				
+		END_TIMER;
+//		g_print("got for initeration: %s\n", TIME_STR);
 		sleep(global_sleep_time);
 		
 		gdk_threads_enter();
@@ -352,6 +354,7 @@ static gboolean _delete(GtkWidget *widget,
 	gtk_main_quit ();
 	list_destroy(popup_list);
 	fini = 1;
+
 	return FALSE;
 }
 
diff --git a/src/sview/sview.h b/src/sview/sview.h
index 90e1ce78761..b19e14eea3e 100644
--- a/src/sview/sview.h
+++ b/src/sview/sview.h
@@ -87,6 +87,8 @@
 #define POS_LOC 0
 #define DEFAULT_ENTRY_LENGTH 500
 
+#define MAKE_INIT -4
+#define MAKE_DOWN -3
 #define MAKE_BLACK -2
 #define MAKE_WHITE -1
 
@@ -202,36 +204,37 @@ struct specific_info {
 };
 
 struct popup_info {
-	int type; /* window type */
-	int toggled;
+	display_data_t *display_data;
+	GtkWidget *event_box;
 	int force_refresh;
-	int *running;
-	int *node_inx;
-	int show_grid;
 	int full_grid;
-	bool not_found;
-	GtkWidget *popup;
-	GtkWidget *event_box;
-	GtkTable *table;
-	GtkTable *grid_table;
 	List grid_button_list;
-	specific_info_t *spec_info;
-	display_data_t *display_data;
-	GtkTreeModel *model;
+	GtkTable *grid_table;
 	GtkTreeIter iter;
+	GtkTreeModel *model;
+	int *node_inx;
 	int node_inx_id;
+	bool not_found;
+	GtkWidget *popup;
+	int *running;
+	int show_grid;
+	specific_info_t *spec_info;
+	GtkTable *table;
+	int toggled;
+	int type; /* window type */
 };
 
 typedef struct {
 	GtkWidget *button;
-	GtkTooltips *tip;
-	GtkTable *table;
-	char *node_name;
 	char *color;
+	int color_inx;
 	int inx;
+	char *node_name;
 	int state;
+	GtkTable *table;
 	int table_x;
 	int table_y;
+	GtkTooltips *tip;
 	bool used;
 } grid_button_t;
 
@@ -245,6 +248,7 @@ extern int text_line_cnt;
 
 extern void parse_command_line(int argc, char *argv[]);
 
+extern int fini;
 extern ba_system_t *ba_system_ptr;
 extern int quiet_flag;
 extern bool toggled;
@@ -301,7 +305,9 @@ extern int get_system_stats(GtkTable *table);
 extern int setup_grid_table(GtkTable *table, List button_list, List node_list);
 extern void sview_init_grid();
 extern void sview_reset_grid();
+extern void sview_clear_unused_grid(List button_list, int color_inx);
 extern void setup_popup_grid_list(popup_info_t *popup_win);
+extern void post_setup_popup_grid_list(popup_info_t *popup_win);
 
 // part_info.c
 extern void refresh_part(GtkAction *action, gpointer user_data);
@@ -439,4 +445,5 @@ extern void add_display_treestore_line(int update,
 				       GtkTreeStore *treestore,
 				       GtkTreeIter *iter,
 				       const char *name, char *value);
+
 #endif
-- 
GitLab