Logo Search packages:      
Sourcecode: slurm-llnl version File versions  Download package

part_info.c

/*****************************************************************************\
 *  part_info.c - Functions related to partition display 
 *  mode of sview.
 *****************************************************************************
 *  Copyright (C) 2004-2006 The Regents of the University of California.
 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
 *  Written by Danny Auble <da@llnl.gov>
 *
 *  UCRL-CODE-226842.
 *   
 *  This file is part of SLURM, a resource management program.
 *  For details, see <http://www.llnl.gov/linux/slurm/>.
 *  
 *  SLURM is free software; you can redistribute it and/or modify it under
 *  the terms of the GNU General Public License as published by the Free
 *  Software Foundation; either version 2 of the License, or (at your option)
 *  any later version.
 *  
 *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 *  details.
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with SLURM; if not, write to the Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
\*****************************************************************************/

#include "src/sview/sview.h"
#include "src/common/parse_time.h"

#define _DEBUG 0

typedef struct {
      partition_info_t* part_ptr;
      uint16_t node_state;

      uint32_t node_cnt;
      uint16_t min_cpus;
      uint16_t max_cpus;
      uint32_t min_disk;
      uint32_t max_disk;
      uint32_t min_mem;
      uint32_t max_mem;
      uint32_t min_weight;
      uint32_t max_weight;

      char *features;
      char *reason;

      hostlist_t hl;
      List node_ptr_list;
} sview_part_sub_t;

/* Collection of data for printing reports. Like data is combined here */
typedef struct {
      /* part_info contains partition, avail, max_time, job_size, 
       * root, share, groups */
      partition_info_t* part_ptr;
      char *color;
      List sub_list;
} sview_part_info_t;

enum { 
      EDIT_AVAIL = 1,
      EDIT_EDIT
};

/* These need to be in alpha order (except POS and CNT) */
enum { 
      SORTID_POS = POS_LOC,
      SORTID_AVAIL, 
#ifdef HAVE_BG
      SORTID_NODELIST, 
#endif
      SORTID_CPUS, 
      SORTID_DEFAULT,
      SORTID_FEATURES, 
      SORTID_GROUPS,
      SORTID_HIDDEN,
      SORTID_JOB_SIZE,
      SORTID_MAX_NODES,
      SORTID_MEM, 
      SORTID_MIN_NODES,
      SORTID_NAME, 
#ifndef HAVE_BG
      SORTID_NODELIST, 
#endif
      SORTID_NODES, 
      SORTID_ONLY_LINE, 
      SORTID_REASON,
      SORTID_ROOT, 
      SORTID_SHARE, 
      SORTID_STATE,
      SORTID_STATE_NUM,
      SORTID_TMP_DISK, 
      SORTID_TIMELIMIT, 
      SORTID_UPDATED, 
      SORTID_WEIGHT,
      SORTID_CNT
};

static display_data_t display_data_part[] = {
      {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE, refresh_part},
      {G_TYPE_STRING, SORTID_NAME, "Partition", TRUE,
       EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_DEFAULT, "Default", TRUE,
       EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_HIDDEN, "Hidden", FALSE,
       EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_AVAIL, "Availablity", TRUE,
       EDIT_MODEL, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", 
       TRUE, EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_NODES, "Nodes", TRUE, EDIT_NONE, refresh_part,
       create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_STATE, "State", TRUE, EDIT_MODEL, refresh_part,
       create_model_part, admin_edit_part},
#ifdef HAVE_BG
      {G_TYPE_STRING, SORTID_NODELIST, "BP List", TRUE,
       EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
#else
      {G_TYPE_STRING, SORTID_NODELIST, "NodeList", TRUE,
       EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
#endif
      {G_TYPE_STRING, SORTID_JOB_SIZE, "Job Size", FALSE,
       EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_MIN_NODES, "Min Nodes", FALSE,
       EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_MAX_NODES, "Max Nodes", FALSE,
       EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_ROOT, "Root", FALSE, EDIT_MODEL, refresh_part,
       create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_SHARE, "Share", FALSE, EDIT_MODEL, refresh_part,
       create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_GROUPS, "Groups", FALSE,
       EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_CPUS, "CPUs", FALSE, EDIT_NONE, refresh_part,
       create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_TMP_DISK, "Temp Disk", FALSE,
       EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_MEM, "Memory", FALSE, EDIT_NONE, refresh_part,
       create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_WEIGHT, "Weight", FALSE,
       EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE,
       EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_STRING, SORTID_REASON, "Reason", FALSE,
       EDIT_NONE, refresh_part, create_model_part, admin_edit_part},
      {G_TYPE_INT, SORTID_STATE_NUM, NULL, FALSE, EDIT_NONE, refresh_part,
       create_model_part, admin_edit_part},
      {G_TYPE_INT, SORTID_ONLY_LINE, NULL, FALSE, EDIT_NONE, refresh_part,
       create_model_part, admin_edit_part},
      {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, EDIT_NONE, refresh_part,
       create_model_part, admin_edit_part},

      {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
};

static display_data_t options_data_part[] = {
      {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE},
      {G_TYPE_STRING, INFO_PAGE, "Full Info", TRUE, PART_PAGE},
#ifdef HAVE_BG
      {G_TYPE_STRING, PART_PAGE, "Drain Base Partitions", TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Resume Base Partitions", TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Put Base Partitions Down",
       TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Make Base Partitions Idle",
       TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Update Base Partition Features",
       TRUE, ADMIN_PAGE},
#else
      {G_TYPE_STRING, PART_PAGE, "Drain Nodes", TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Resume Nodes", TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Put Nodes Down", TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Make Nodes Idle", TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Update Node Features", TRUE, ADMIN_PAGE},
#endif
      {G_TYPE_STRING, PART_PAGE, "Change Availablity Up/Down",
       TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, PART_PAGE, "Edit Part", TRUE, ADMIN_PAGE},
      {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, PART_PAGE},
#ifdef HAVE_BG
      {G_TYPE_STRING, BLOCK_PAGE, "Blocks", TRUE, PART_PAGE},
      {G_TYPE_STRING, NODE_PAGE, "Base Partitions", TRUE, PART_PAGE},
#else
      {G_TYPE_STRING, NODE_PAGE, "Nodes", TRUE, PART_PAGE},
#endif
      {G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", FALSE, PART_PAGE},
      {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
};

#ifdef HAVE_BG
static void _update_nodes_for_bg(int node_scaling,
                         node_info_msg_t *node_msg,
                         bg_info_record_t *bg_info_record);
enum {
      SVIEW_BG_IDLE_STATE,
      SVIEW_BG_ERROR_STATE,
      SVIEW_BG_ALLOC_STATE
};
#endif

static display_data_t *local_display_data = NULL;

static char *got_edit_signal = NULL;
static char *got_features_edit_signal = NULL;

static void _update_part_sub_record(sview_part_sub_t *sview_part_sub,
                            GtkTreeStore *treestore,
                            GtkTreeIter *iter);
static void _append_part_sub_record(sview_part_sub_t *sview_part_sub,
                            GtkTreeStore *treestore, GtkTreeIter *iter,
                            int line);
static node_info_t *_find_node(char *node_name, node_info_msg_t *node_msg);

#ifdef HAVE_BG

static void _update_nodes_for_bg(int node_scaling,
                         node_info_msg_t *node_msg,
                         bg_info_record_t *bg_info_record)
{
      node_info_t *node_ptr = NULL;
      hostlist_t hl;
      char *node_name = NULL;

      /* we are using less than one node */
      if(bg_info_record->conn_type == SELECT_SMALL) 
            node_scaling = bg_info_record->node_cnt;
                     
      hl = hostlist_create(bg_info_record->nodes);
      while (1) {
            if (node_name)
                  free(node_name);
            node_name = hostlist_shift(hl);
            if (!node_name)
                  break;
            node_ptr = _find_node(node_name, node_msg);
            if (!node_ptr)
                  continue;
            /* cores is overloaded to be the cnodes in an error
             * state and used_cpus is overloaded to be the nodes in
             * use.  No block should be sent in here if it isn't
             * in use (that doesn't mean in a free state, it means
             * the user isn't slurm or the block is in an error state.  
             */
            if(bg_info_record->state == RM_PARTITION_ERROR) 
                  node_ptr->cores += node_scaling;
            else
                  node_ptr->used_cpus += node_scaling;
      }
      hostlist_destroy(hl);
      
}
#endif

static int 
_build_min_max_16_string(char *buffer, int buf_size, 
      uint16_t min, uint16_t max, bool range)
{
      char tmp_min[8];
      char tmp_max[8];
      convert_num_unit((float)min, tmp_min, sizeof(tmp_min), UNIT_NONE);
      if(max != (uint16_t) INFINITE) {
            convert_num_unit((float)max, tmp_max, sizeof(tmp_max), 
                         UNIT_NONE);
      }
      
      if (max == min)
            return snprintf(buffer, buf_size, "%s", tmp_max);
      else if (range) {
            if (max == (uint16_t) INFINITE)
                  return snprintf(buffer, buf_size, "%s-infinite", 
                              tmp_min);
            else
                  return snprintf(buffer, buf_size, "%s-%s", 
                              tmp_min, tmp_max);
      } else
            return snprintf(buffer, buf_size, "%s+", tmp_min);
}

static int 
_build_min_max_32_string(char *buffer, int buf_size, 
      uint32_t min, uint32_t max, bool range)
{
      char tmp_min[8];
      char tmp_max[8];
      convert_num_unit((float)min, tmp_min, sizeof(tmp_min), UNIT_NONE);
      convert_num_unit((float)max, tmp_max, sizeof(tmp_max), UNIT_NONE);
      
      if (max == min)
            return snprintf(buffer, buf_size, "%s", tmp_max);
      else if (range) {
            if (max == (uint32_t) INFINITE)
                  return snprintf(buffer, buf_size, "%s-infinite", 
                              tmp_min);
            else
                  return snprintf(buffer, buf_size, "%s-%s", 
                              tmp_min, tmp_max);
      } else
            return snprintf(buffer, buf_size, "%s+", tmp_min);
}

static void _set_active_combo_part(GtkComboBox *combo, 
                           GtkTreeModel *model, GtkTreeIter *iter,
                           int type)
{
      char *temp_char = NULL;
      int action = 0;
      int i = 0, unknown_found = 0;
      char *upper = NULL;

      gtk_tree_model_get(model, iter, type, &temp_char, -1);
      if(!temp_char)
            goto end_it;
      switch(type) {
      case SORTID_DEFAULT:
      case SORTID_HIDDEN:
      case SORTID_ROOT:
            if(!strcmp(temp_char, "yes"))
                  action = 0;
            else if(!strcmp(temp_char, "no"))
                  action = 1;
            else 
                  action = 0;
            
            break;
      case SORTID_SHARE:
            if(!strcmp(temp_char, "yes"))
                  action = 0;
            else if(!strcmp(temp_char, "no"))
                  action = 1;
            else if(!strcmp(temp_char, "force"))
                  action = 2;
            else 
                  action = 0;
            break;
      case SORTID_AVAIL:
            if(!strcmp(temp_char, "up"))
                  action = 0;
            else if(!strcmp(temp_char, "down"))
                  action = 1;
            else 
                  action = 0;
            break;
      case SORTID_STATE:
            if(!strcasecmp(temp_char, "drain"))
                  action = 0;
            else if(!strcasecmp(temp_char, "resume"))
                  action = 1;
            else
                  for(i = 0; i < NODE_STATE_END; i++) {
                        upper = node_state_string(i);
                        if(!strcmp(upper, "UNKNOWN")) {
                              unknown_found++;
                              continue;
                        }
                        
                        if(!strcasecmp(temp_char, upper)) {
                              action = i + 2 - unknown_found;
                              break;
                        }
                  }
                                    
            break;
      default:
            break;
      }
      g_free(temp_char);
end_it:
      gtk_combo_box_set_active(combo, action);
      
}

/* don't free this char */
static const char *_set_part_msg(update_part_msg_t *part_msg,
                         const char *new_text,
                         int column)
{
      char *type = NULL;
      int temp_int = 0;
      
      if(!part_msg)
            return NULL;
      
      switch(column) {
      case SORTID_DEFAULT:
            if (!strcasecmp(new_text, "yes")) 
                  part_msg->default_part = 1;
            else
                  part_msg->default_part = 0;
            
            type = "default";
            break;
      case SORTID_HIDDEN:
            if (!strcasecmp(new_text, "yes")) 
                  part_msg->hidden = 1;
            else
                  part_msg->hidden = 0;
            
            type = "hidden";
            break;
      case SORTID_TIMELIMIT:
            if ((strcasecmp(new_text,"infinite") == 0))
                  temp_int = INFINITE;
            else
                  temp_int = time_str2mins((char *)new_text);
            
            type = "timelimit";
            if(temp_int <= 0 && temp_int != INFINITE)
                  goto return_error;
            part_msg->max_time = (uint32_t)temp_int;
            break;
      case SORTID_MIN_NODES:
            temp_int = strtol(new_text, (char **)NULL, 10);
            type = "min_nodes";
            
            if(temp_int <= 0)
                  goto return_error;
            part_msg->min_nodes = (uint32_t)temp_int;
            break;
      case SORTID_MAX_NODES:
            if (!strcasecmp(new_text, "infinite")) {
                  temp_int = INFINITE;
            } else {
                  temp_int = strtol(new_text, (char **)NULL, 10);
            }
            
            type = "max_nodes";
            if(temp_int <= 0 && temp_int != INFINITE)
                  goto return_error;
            part_msg->max_nodes = (uint32_t)temp_int;
            break;
      case SORTID_ROOT:
            if (!strcasecmp(new_text, "yes")) {
                  part_msg->root_only = 1;
            } else {
                  part_msg->root_only = 0;
            }
            
            type = "root";
            break;
      case SORTID_SHARE:
            if (!strcasecmp(new_text, "yes")) {
                  part_msg->shared = SHARED_YES;
            } else if (!strcasecmp(new_text, "no")) {
                  part_msg->shared = SHARED_NO;
            } else {
                  part_msg->shared = SHARED_FORCE;
            }
            type = "share";
            break;
      case SORTID_GROUPS:
            type = "groups";
            part_msg->allow_groups = xstrdup(new_text);
            break;
      case SORTID_NODELIST:
            part_msg->nodes = xstrdup(new_text);
            type = "nodelist";
            break;
      case SORTID_AVAIL:
            if (!strcasecmp(new_text, "up"))
                  part_msg->state_up = 1;
            else
                  part_msg->state_up = 0;
            type = "availability";
            break;
      case SORTID_STATE:
            type = (char *)new_text;
            got_edit_signal = xstrdup(new_text);
            break;
      case SORTID_FEATURES:
            type = "Update Features";
            got_features_edit_signal = xstrdup(new_text);
            break;
      }
      
      return type;

return_error:
      errno = 1;
      return type;
      
}

static void _admin_edit_combo_box_part(GtkComboBox *combo,
                               update_part_msg_t *part_msg)
{
      GtkTreeModel *model = NULL;
      GtkTreeIter iter;
      int column = 0;
      char *name = NULL;
      
      if(!part_msg)
            return;

      if(!gtk_combo_box_get_active_iter(combo, &iter)) {
            g_print("nothing selected\n");
            return;
      }
      model = gtk_combo_box_get_model(combo);
      if(!model) {
            g_print("nothing selected\n");
            return;
      }

      gtk_tree_model_get(model, &iter, 0, &name, -1);
      gtk_tree_model_get(model, &iter, 1, &column, -1);

      _set_part_msg(part_msg, name, column);

      g_free(name);
}

static gboolean _admin_focus_out_part(GtkEntry *entry,
                              GdkEventFocus *event, 
                              update_part_msg_t *part_msg)
{
      int type = gtk_entry_get_max_length(entry);
      const char *name = gtk_entry_get_text(entry);
      type -= DEFAULT_ENTRY_LENGTH;
      _set_part_msg(part_msg, name, type);
      
      return false;
}

static GtkWidget *_admin_full_edit_part(update_part_msg_t *part_msg, 
                              GtkTreeModel *model, GtkTreeIter *iter)
{
      GtkScrolledWindow *window = create_scrolled_window();
      GtkBin *bin = NULL;
      GtkViewport *view = NULL;
      GtkTable *table = NULL;
      GtkWidget *label = NULL;
      GtkWidget *entry = NULL;
      GtkTreeModel *model2 = NULL; 
      GtkCellRenderer *renderer = NULL;
      int i = 0, row = 0;
      char *temp_char = NULL;

      gtk_scrolled_window_set_policy(window,
                               GTK_POLICY_NEVER,
                               GTK_POLICY_AUTOMATIC);
      bin = GTK_BIN(&window->container);
      view = GTK_VIEWPORT(bin->child);
      bin = GTK_BIN(&view->bin);
      table = GTK_TABLE(bin->child);
      gtk_table_resize(table, SORTID_CNT, 2);
      
      gtk_table_set_homogeneous(table, FALSE);  

      for(i = 0; i < SORTID_CNT; i++) {
            if(display_data_part[i].extra == EDIT_MODEL) {
                  /* edittable items that can only be known
                     values */
                  model2 = GTK_TREE_MODEL(
                        create_model_part(display_data_part[i].id));
                  if(!model2) {
                        g_print("no model set up for %d(%s)\n",
                              display_data_part[i].id,
                              display_data_part[i].name);
                        continue;
                  }
                  entry = gtk_combo_box_new_with_model(model2);
                  g_object_unref(model2);
                  
                  _set_active_combo_part(GTK_COMBO_BOX(entry), model,
                                    iter, display_data_part[i].id);
                  
                  g_signal_connect(entry, "changed",
                               G_CALLBACK(
                                     _admin_edit_combo_box_part),
                               part_msg);
                  
                  renderer = gtk_cell_renderer_text_new();
                  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(entry),
                                       renderer, TRUE);
                  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(entry),
                                          renderer, "text", 0);
            } else if(display_data_part[i].extra == EDIT_TEXTBOX) {
                  /* other edittable items that are unknown */
                  entry = create_entry();
                  gtk_tree_model_get(model, iter,
                                 display_data_part[i].id,
                                 &temp_char, -1);
                  gtk_entry_set_max_length(GTK_ENTRY(entry), 
                                     (DEFAULT_ENTRY_LENGTH +
                                      display_data_part[i].id));
                  
                  if(temp_char) {
                        gtk_entry_set_text(GTK_ENTRY(entry),
                                       temp_char);
                        g_free(temp_char);
                  }
                  g_signal_connect(entry, "focus-out-event",
                               G_CALLBACK(_admin_focus_out_part),
                               part_msg);
            } else /* others can't be altered by the user */
                  continue;
            label = gtk_label_new(display_data_part[i].name);
            gtk_table_attach(table, label, 0, 1, row, row+1,
                         GTK_FILL | GTK_EXPAND, GTK_SHRINK, 
                         0, 0);
            gtk_table_attach(table, entry, 1, 2, row, row+1,
                         GTK_FILL, GTK_SHRINK,
                         0, 0);
            row++;
      }
      gtk_table_resize(table, row, 2);
      
      return GTK_WIDGET(window);
}

static void _subdivide_part(sview_part_info_t *sview_part_info,
                      GtkTreeModel *model, 
                      GtkTreeIter *sub_iter,
                      GtkTreeIter *iter)
{
      GtkTreeIter first_sub_iter;
      ListIterator itr = NULL;
      uint16_t state;
      int i = 0, line = 0;
      sview_part_sub_t *sview_part_sub = NULL;
      int set = 0;

      memset(&first_sub_iter, 0, sizeof(GtkTreeIter));

      /* make sure all the steps are still here */
      if (sub_iter) {
            first_sub_iter = *sub_iter;
            while(1) {
                  gtk_tree_store_set(GTK_TREE_STORE(model), sub_iter, 
                                 SORTID_UPDATED, 0, -1);    
                  if(!gtk_tree_model_iter_next(model, sub_iter)) {
                        break;
                  }
            }
            memcpy(sub_iter, &first_sub_iter, sizeof(GtkTreeIter));
            set = 1;
      }
      itr = list_iterator_create(sview_part_info->sub_list);
      if(list_count(sview_part_info->sub_list) == 1) {
            gtk_tree_store_set(GTK_TREE_STORE(model), iter,
                           SORTID_ONLY_LINE, 1, -1);
            sview_part_sub = list_next(itr);
            _update_part_sub_record(sview_part_sub,
                              GTK_TREE_STORE(model), 
                              iter);
      } else {
            while((sview_part_sub = list_next(itr))) {
                  if (!sub_iter) {
                        i = NO_VAL;
                        goto adding;
                  } else {
                        memcpy(sub_iter, &first_sub_iter, 
                               sizeof(GtkTreeIter));        
                  }
                  
                  while(1) {
                        /* search for the state number and
                           check to see if it is in the list */
                        gtk_tree_model_get(model, sub_iter, 
                                       SORTID_STATE_NUM, 
                                       &state, -1);
                        if(state == sview_part_sub->node_state) {
                              /* update with new info */
                              _update_part_sub_record(
                                    sview_part_sub,
                                    GTK_TREE_STORE(model), 
                                    sub_iter);
                              goto found;
                        }                 
                        
                        /* see what line we were on to add the
                           next one to the list */
                        gtk_tree_model_get(model, sub_iter, 
                                       SORTID_POS, 
                                       &line, -1);
                        if(!gtk_tree_model_iter_next(model, 
                                               sub_iter)) {
                              line++;
                              break;
                        }
                  }
            adding:
                  _append_part_sub_record(sview_part_sub, 
                                    GTK_TREE_STORE(model), 
                                    iter, line);
                  if(i == NO_VAL)
                        line++;
            found:
                  ;
            }
      }
      list_iterator_destroy(itr);

      if(set) {
            sub_iter = &first_sub_iter;
            /* clear all steps that aren't active */
            while(1) {
                  gtk_tree_model_get(model, sub_iter, 
                                 SORTID_UPDATED, &i, -1);
                  if(!i) {
                        if(!gtk_tree_store_remove(
                                 GTK_TREE_STORE(model), 
                                 sub_iter))
                              break;
                        else
                              continue;
                  }
                  if(!gtk_tree_model_iter_next(model, sub_iter)) {
                        break;
                  }
            }
      }
      return;
}

static void _layout_part_record(GtkTreeView *treeview, 
                        sview_part_info_t *sview_part_info,
                        int update)
{
      GtkTreeIter iter;
      ListIterator itr = NULL;
      char time_buf[20];
      char tmp_cnt[8];
      char tmp_cnt1[8];
      char tmp_cnt2[8];
      partition_info_t *part_ptr = sview_part_info->part_ptr;
      sview_part_sub_t *sview_part_sub = NULL;
      sview_part_sub_t *temp_part_sub = NULL;
      sview_part_sub_t alloc_part_sub;
      sview_part_sub_t idle_part_sub;
      sview_part_sub_t other_part_sub;
      char tmp[1024];
      char *temp_char = NULL;
      int global_set = 0;

      GtkTreeStore *treestore = 
            GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
      
      memset(&alloc_part_sub, 0, sizeof(sview_part_sub_t));
      memset(&idle_part_sub, 0, sizeof(sview_part_sub_t));
      memset(&other_part_sub, 0, sizeof(sview_part_sub_t));
      
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_NAME),
                           part_ptr->name);

      if(part_ptr->default_part) 
            temp_char = "yes";
      else 
            temp_char = "no";
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_DEFAULT),
                           temp_char);
      
      if(part_ptr->hidden) 
            temp_char = "yes";
      else 
            temp_char = "no";
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_HIDDEN),
                           temp_char);
      
      if (part_ptr->state_up) 
            temp_char = "up";
      else 
            temp_char = "down";
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_AVAIL),
                           temp_char);
                  
      if (part_ptr->max_time == INFINITE)
            snprintf(time_buf, sizeof(time_buf), "infinite");
      else {
            secs2time_str((part_ptr->max_time * 60), 
                        time_buf, sizeof(time_buf));
      }

      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_TIMELIMIT),
                           time_buf);
      
      _build_min_max_32_string(time_buf, sizeof(time_buf), 
                        part_ptr->min_nodes, 
                        part_ptr->max_nodes, true);
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_JOB_SIZE),
                           time_buf);
      
      if (part_ptr->min_nodes == (uint32_t) INFINITE)
            snprintf(time_buf, sizeof(time_buf), "infinite");
      else {
            convert_num_unit((float)part_ptr->min_nodes, 
                         time_buf, sizeof(time_buf), UNIT_NONE);
      }
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_MIN_NODES), 
                           time_buf);
      if (part_ptr->max_nodes == (uint32_t) INFINITE)
            snprintf(time_buf, sizeof(time_buf), "infinite");
      else {
            convert_num_unit((float)part_ptr->max_nodes, 
                         time_buf, sizeof(time_buf), UNIT_NONE);
      }
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_MAX_NODES), 
                           time_buf);

      if(part_ptr->root_only)
            temp_char = "yes";
      else 
            temp_char = "no";
      add_display_treestore_line(update, treestore, &iter,
                           find_col_name(display_data_part,
                                     SORTID_ROOT),
                           temp_char);
            
      if(part_ptr->shared > 1)
            temp_char = "force";
      else if(part_ptr->shared)
            temp_char = "yes";
      else 
            temp_char = "no";
      add_display_treestore_line(update, treestore, &iter,
                           find_col_name(display_data_part,
                                     SORTID_SHARE),
                           temp_char);
            
      if(part_ptr->allow_groups)
            temp_char = part_ptr->allow_groups;
      else
            temp_char = "all";
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_GROUPS),
                           temp_char);
      
#ifdef HAVE_BG
      convert_num_unit((float)part_ptr->total_nodes, tmp_cnt, 
                   sizeof(tmp_cnt), UNIT_NONE);
#else
      sprintf(tmp_cnt, "%u", part_ptr->total_nodes);
#endif
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_NODES), 
                           tmp_cnt);
      convert_num_unit((float)part_ptr->total_cpus, tmp_cnt, sizeof(tmp_cnt),
                   UNIT_NONE);
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_CPUS), 
                           tmp_cnt);
      

      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_NODELIST), 
                           part_ptr->nodes);
      itr = list_iterator_create(sview_part_info->sub_list);
      while((sview_part_sub = list_next(itr))) {
            if(sview_part_sub->node_state == NODE_STATE_IDLE)
                  temp_part_sub = &idle_part_sub;
            else if(sview_part_sub->node_state == NODE_STATE_ALLOCATED)
                  temp_part_sub = &alloc_part_sub;
            else
                  temp_part_sub = &other_part_sub;
            temp_part_sub->node_cnt += sview_part_sub->node_cnt;
            temp_part_sub->min_cpus += sview_part_sub->min_cpus;
            temp_part_sub->max_cpus += sview_part_sub->max_cpus;
            
            temp_part_sub->min_disk += sview_part_sub->min_disk;
            temp_part_sub->max_disk += sview_part_sub->max_disk;
            
            temp_part_sub->min_mem += sview_part_sub->min_mem;
            temp_part_sub->max_mem += sview_part_sub->max_mem;
            
            temp_part_sub->min_weight += sview_part_sub->min_weight;
            temp_part_sub->max_weight += sview_part_sub->max_weight;
            if(!global_set) {
                  global_set = 1;
                  /* store features and reasons in the others
                     group */
                  other_part_sub.features = temp_part_sub->features;
                  other_part_sub.reason = temp_part_sub->reason;
            }
      }
      convert_num_unit((float)alloc_part_sub.node_cnt, 
                   tmp_cnt, sizeof(tmp_cnt), UNIT_NONE);
      convert_num_unit((float)idle_part_sub.node_cnt, 
                   tmp_cnt1, sizeof(tmp_cnt1), UNIT_NONE);
      convert_num_unit((float)other_part_sub.node_cnt, 
                   tmp_cnt2, sizeof(tmp_cnt2), UNIT_NONE);
      snprintf(tmp, sizeof(tmp), "%s/%s/%s",
             tmp_cnt, tmp_cnt1, tmp_cnt2);
      add_display_treestore_line(update, treestore, &iter,
                           "Nodes (Allocated/Idle/Other)",
                           tmp);
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_FEATURES), 
                           other_part_sub.features);
      add_display_treestore_line(update, treestore, &iter, 
                           find_col_name(display_data_part,
                                     SORTID_REASON), 
                           other_part_sub.reason);

}

static void _update_part_record(sview_part_info_t *sview_part_info,
                        GtkTreeStore *treestore, 
                        GtkTreeIter *iter)
{
      char time_buf[20];
      char tmp_cnt[8];
      char *temp_char = NULL;
      partition_info_t *part_ptr = sview_part_info->part_ptr;
      GtkTreeIter sub_iter;
      int childern = 0;
      
      gtk_tree_store_set(treestore, iter, SORTID_NAME, part_ptr->name, -1);

      if(part_ptr->default_part)
            temp_char = "yes";
      else
            temp_char = "no";
      gtk_tree_store_set(treestore, iter, SORTID_DEFAULT, temp_char, -1);
      
      if(part_ptr->hidden)
            temp_char = "yes";
      else
            temp_char = "no";
      gtk_tree_store_set(treestore, iter, SORTID_HIDDEN, temp_char, -1);
      
      if (part_ptr->state_up) 
            temp_char = "up";
      else
            temp_char = "down";
      gtk_tree_store_set(treestore, iter, SORTID_AVAIL, temp_char, -1);
            
      if (part_ptr->max_time == INFINITE)
            snprintf(time_buf, sizeof(time_buf), "infinite");
      else {
            secs2time_str((part_ptr->max_time * 60), 
                        time_buf, sizeof(time_buf));
      }
      
      gtk_tree_store_set(treestore, iter, SORTID_TIMELIMIT, time_buf, -1);
      
      _build_min_max_32_string(time_buf, sizeof(time_buf), 
                        part_ptr->min_nodes, 
                        part_ptr->max_nodes, true);
      gtk_tree_store_set(treestore, iter, SORTID_JOB_SIZE, time_buf, -1);
      
      if (part_ptr->min_nodes == (uint32_t) INFINITE)
            snprintf(time_buf, sizeof(time_buf), "infinite");
      else {
            convert_num_unit((float)part_ptr->min_nodes, 
                         time_buf, sizeof(time_buf), UNIT_NONE);
      }
      gtk_tree_store_set(treestore, iter, SORTID_MIN_NODES, 
                     time_buf, -1);
      if (part_ptr->max_nodes == (uint32_t) INFINITE)
            snprintf(time_buf, sizeof(time_buf), "infinite");
      else {
            convert_num_unit((float)part_ptr->max_nodes, 
                         time_buf, sizeof(time_buf), UNIT_NONE);
      }
      gtk_tree_store_set(treestore, iter, SORTID_MAX_NODES, 
                     time_buf, -1);

      if(part_ptr->root_only)
            temp_char = "yes";
      else
            temp_char = "no";
      gtk_tree_store_set(treestore, iter, SORTID_ROOT, temp_char, -1);
      
      if(part_ptr->shared > 1)
            temp_char = "force";
      else if(part_ptr->shared)
            temp_char = "yes";
      else 
            temp_char = "no";
      gtk_tree_store_set(treestore, iter, SORTID_SHARE, temp_char, -1);
      
      if(part_ptr->allow_groups)
            temp_char = part_ptr->allow_groups;
      else
            temp_char = "all";
      gtk_tree_store_set(treestore, iter, SORTID_GROUPS, temp_char, -1);
      
#ifdef HAVE_BG
      convert_num_unit((float)part_ptr->total_nodes, tmp_cnt, 
                   sizeof(tmp_cnt), UNIT_NONE);
#else
      sprintf(tmp_cnt, "%u", part_ptr->total_nodes);
#endif
      gtk_tree_store_set(treestore, iter, SORTID_NODES, tmp_cnt, -1);

      gtk_tree_store_set(treestore, iter, SORTID_NODELIST, 
                     part_ptr->nodes, -1);
      
      gtk_tree_store_set(treestore, iter, SORTID_ONLY_LINE, 0, -1);
      /* clear out info for the main listing */
      gtk_tree_store_set(treestore, iter, SORTID_STATE, "", -1);
      gtk_tree_store_set(treestore, iter, SORTID_STATE_NUM, -1, -1);
      gtk_tree_store_set(treestore, iter, SORTID_CPUS, "", -1);
      gtk_tree_store_set(treestore, iter, SORTID_TMP_DISK, "", -1);
      gtk_tree_store_set(treestore, iter, SORTID_MEM, "", -1);
      gtk_tree_store_set(treestore, iter, SORTID_WEIGHT, "", -1);
      gtk_tree_store_set(treestore, iter, SORTID_UPDATED, 1, -1); 
      gtk_tree_store_set(treestore, iter, SORTID_FEATURES, "", -1);     
      gtk_tree_store_set(treestore, iter, SORTID_REASON, "", -1); 
      
      childern = gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore),
                                    &sub_iter, iter);
      if(gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore),
                              &sub_iter, iter))
            _subdivide_part(sview_part_info, 
                        GTK_TREE_MODEL(treestore), &sub_iter, iter);
      else
            _subdivide_part(sview_part_info, 
                        GTK_TREE_MODEL(treestore), NULL, iter);

      return;
}

static void _update_part_sub_record(sview_part_sub_t *sview_part_sub,
                            GtkTreeStore *treestore, GtkTreeIter *iter)
{
      char time_buf[20];
      char tmp_cnt[8];
      partition_info_t *part_ptr = sview_part_sub->part_ptr;
      char *upper = NULL, *lower = NULL;             
      char tmp[MAXHOSTRANGELEN];

      gtk_tree_store_set(treestore, iter, SORTID_NAME, part_ptr->name, -1);
      
      upper = node_state_string(sview_part_sub->node_state);
      lower = str_tolower(upper);
      gtk_tree_store_set(treestore, iter, SORTID_STATE, 
                     lower, -1);
      xfree(lower);
      
      gtk_tree_store_set(treestore, iter, SORTID_STATE_NUM,
                     sview_part_sub->node_state, -1);
      
      _build_min_max_16_string(time_buf, sizeof(time_buf), 
                        sview_part_sub->min_cpus, 
                        sview_part_sub->max_cpus, false);
      gtk_tree_store_set(treestore, iter, SORTID_CPUS, time_buf, -1);
      
      _build_min_max_32_string(time_buf, sizeof(time_buf), 
                        sview_part_sub->min_disk, 
                        sview_part_sub->max_disk, false);
      gtk_tree_store_set(treestore, iter, SORTID_TMP_DISK, time_buf, -1);

      _build_min_max_32_string(time_buf, sizeof(time_buf), 
                        sview_part_sub->min_mem, 
                        sview_part_sub->max_mem, false);
      gtk_tree_store_set(treestore, iter, SORTID_MEM, time_buf, -1);

      _build_min_max_32_string(time_buf, sizeof(time_buf), 
                        sview_part_sub->min_weight, 
                        sview_part_sub->max_weight, false);
      gtk_tree_store_set(treestore, iter, SORTID_WEIGHT, time_buf, -1);

      convert_num_unit((float)sview_part_sub->node_cnt, tmp_cnt, 
                   sizeof(tmp_cnt), UNIT_NONE);
      gtk_tree_store_set(treestore, iter, SORTID_NODES, tmp_cnt, -1);
      
      hostlist_ranged_string(sview_part_sub->hl, sizeof(tmp), tmp);
      gtk_tree_store_set(treestore, iter, SORTID_NODELIST, 
                     tmp, -1);
      gtk_tree_store_set(treestore, iter, SORTID_UPDATED, 1, -1); 
      
      gtk_tree_store_set(treestore, iter, SORTID_FEATURES,
                     sview_part_sub->features, -1);
      gtk_tree_store_set(treestore, iter, SORTID_REASON,
                     sview_part_sub->reason, -1);
            
      return;
}

static void _append_part_record(sview_part_info_t *sview_part_info,
                        GtkTreeStore *treestore, GtkTreeIter *iter,
                        int line)
{
      gtk_tree_store_append(treestore, iter, NULL);
      gtk_tree_store_set(treestore, iter, SORTID_POS, line, -1);
      _update_part_record(sview_part_info, treestore, iter);
}

static void _append_part_sub_record(sview_part_sub_t *sview_part_sub,
                            GtkTreeStore *treestore, GtkTreeIter *iter,
                            int line)
{
      GtkTreeIter sub_iter;
      
      gtk_tree_store_append(treestore, &sub_iter, iter);
      gtk_tree_store_set(treestore, &sub_iter, SORTID_POS, line, -1);
      _update_part_sub_record(sview_part_sub, treestore, &sub_iter);
}

static void _update_info_part(List info_list, 
                        GtkTreeView *tree_view)
{
      GtkTreePath *path = gtk_tree_path_new_first();
      GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
      GtkTreeIter iter;
      partition_info_t *part_ptr = NULL;
      int line = 0;
      char *host = NULL, *part_name = NULL;
      ListIterator itr = NULL;
      sview_part_info_t *sview_part_info = NULL;

      /* get the iter, or find out the list is empty goto add */
      if (gtk_tree_model_get_iter(model, &iter, path)) {
            /* make sure all the partitions are still here */
            while(1) {
                  gtk_tree_store_set(GTK_TREE_STORE(model), &iter, 
                                 SORTID_UPDATED, 0, -1);    
                  if(!gtk_tree_model_iter_next(model, &iter)) {
                        break;
                  }
            }
      }

      itr = list_iterator_create(info_list);
      while ((sview_part_info = (sview_part_info_t*) list_next(itr))) {
            part_ptr = sview_part_info->part_ptr;
            /* get the iter, or find out the list is empty goto add */
            if (!gtk_tree_model_get_iter(model, &iter, path)) {
                  goto adding;
            } 
            while(1) {
                  /* search for the jobid and check to see if 
                     it is in the list */
                  gtk_tree_model_get(model, &iter, SORTID_NAME, 
                                 &part_name, -1);
                  if(!strcmp(part_name, part_ptr->name)) {
                        /* update with new info */
                        g_free(part_name);
                        _update_part_record(sview_part_info, 
                                        GTK_TREE_STORE(model), 
                                        &iter);
                        goto found;
                  }
                  g_free(part_name);
                        
                  /* see what line we were on to add the next one 
                     to the list */
                  gtk_tree_model_get(model, &iter, SORTID_POS, 
                                 &line, -1);
                  if(!gtk_tree_model_iter_next(model, &iter)) {
                        line++;
                        break;
                  }
            }
      adding:
            _append_part_record(sview_part_info, GTK_TREE_STORE(model), 
                            &iter, line);
      found:
            ;
      }
      list_iterator_destroy(itr);
      if(host)
            free(host);

      gtk_tree_path_free(path);
      /* remove all old partitions */
      remove_old(model, SORTID_UPDATED);
      return;
}

static void _part_info_list_del(void *object)
{
      sview_part_info_t *sview_part_info = (sview_part_info_t *)object;

      if (sview_part_info) {
            if(sview_part_info->sub_list)
                  list_destroy(sview_part_info->sub_list);
            xfree(sview_part_info);
      }
}

static void _destroy_part_sub(void *object)
{
      sview_part_sub_t *sview_part_sub = (sview_part_sub_t *)object;

      if (sview_part_sub) {
            xfree(sview_part_sub->features);
            xfree(sview_part_sub->reason);
            if(sview_part_sub->hl)
                  hostlist_destroy(sview_part_sub->hl);
            if(sview_part_sub->node_ptr_list)
                  list_destroy(sview_part_sub->node_ptr_list);
            xfree(sview_part_sub);
      }
}

/* like strcmp, but works with NULL pointers */
static int _strcmp(char *data1, char *data2) 
{
      static char null_str[] = "(null)";

      if (data1 == NULL)
            data1 = null_str;
      if (data2 == NULL)
            data2 = null_str;
      return strcmp(data1, data2);
}

/* 
 * _find_node - find a node by name
 * node_name IN     - name of node to locate
 * node_msg IN      - node information message from API
 */
static node_info_t *_find_node(char *node_name, node_info_msg_t *node_msg)
{
      int i;
      if (node_name == NULL)
            return NULL;

      for (i=0; i<node_msg->record_count; i++) {
            if (_strcmp(node_name, node_msg->node_array[i].name))
                  continue;
            return &(node_msg->node_array[i]);
      }

      /* not found */
      return NULL;
}

static void _update_sview_part_sub(sview_part_sub_t *sview_part_sub, 
                           node_info_t *node_ptr, 
                           int node_scaling)
{
      list_append(sview_part_sub->node_ptr_list, node_ptr);

#ifdef HAVE_BG
      node_scaling = node_ptr->threads;
      if(!node_scaling)
            return;
#else
      if(!node_scaling)
            node_scaling = 1;
#endif      
      if (sview_part_sub->node_cnt == 0) {      /* first node added */
            sview_part_sub->node_state = node_ptr->node_state;
            sview_part_sub->features   = xstrdup(node_ptr->features);
            sview_part_sub->reason     = xstrdup(node_ptr->reason);
            sview_part_sub->min_cpus   = node_ptr->cpus;
            sview_part_sub->max_cpus   = node_ptr->cpus;
            sview_part_sub->min_disk   = node_ptr->tmp_disk;
            sview_part_sub->max_disk   = node_ptr->tmp_disk;
            sview_part_sub->min_mem    = node_ptr->real_memory;
            sview_part_sub->max_mem    = node_ptr->real_memory;
            sview_part_sub->min_weight = node_ptr->weight;
            sview_part_sub->max_weight = node_ptr->weight;
      } else if (hostlist_find(sview_part_sub->hl, 
                         node_ptr->name) != -1) {
            /* we already have this node in this record,
             * just return, don't duplicate */
            return;
      } else {
            if (sview_part_sub->min_cpus > node_ptr->cpus)
                  sview_part_sub->min_cpus = node_ptr->cpus;
            if (sview_part_sub->max_cpus < node_ptr->cpus)
                  sview_part_sub->max_cpus = node_ptr->cpus;

            if (sview_part_sub->min_disk > node_ptr->tmp_disk)
                  sview_part_sub->min_disk = node_ptr->tmp_disk;
            if (sview_part_sub->max_disk < node_ptr->tmp_disk)
                  sview_part_sub->max_disk = node_ptr->tmp_disk;

            if (sview_part_sub->min_mem > node_ptr->real_memory)
                  sview_part_sub->min_mem = node_ptr->real_memory;
            if (sview_part_sub->max_mem < node_ptr->real_memory)
                  sview_part_sub->max_mem = node_ptr->real_memory;

            if (sview_part_sub->min_weight> node_ptr->weight)
                  sview_part_sub->min_weight = node_ptr->weight;
            if (sview_part_sub->max_weight < node_ptr->weight)
                  sview_part_sub->max_weight = node_ptr->weight;
      }

      sview_part_sub->node_cnt += node_scaling;
      hostlist_push(sview_part_sub->hl, node_ptr->name);
}

/* 
 * _create_sview_part_sub - create an sview_part_sub record for 
 *                          the given partition
 * sview_part_sub OUT     - ptr to an inited sview_part_sub_t
 */
static sview_part_sub_t *_create_sview_part_sub(partition_info_t *part_ptr,
                                    node_info_t *node_ptr, 
                                    int node_scaling)
{
      sview_part_sub_t *sview_part_sub_ptr = 
            xmalloc(sizeof(sview_part_sub_t));
      
#ifdef HAVE_BG
      node_scaling = node_ptr->threads;
      if(!node_scaling)
            return NULL;
#else
      if(!node_scaling)
            node_scaling = 1;
#endif

      if (!part_ptr) {
            g_print("got no part_ptr!\n");
            xfree(sview_part_sub_ptr);
            return NULL;
      }
      if (!node_ptr) {
            g_print("got no node_ptr!\n");
            xfree(sview_part_sub_ptr);
            return NULL;
      }
      sview_part_sub_ptr->part_ptr = part_ptr;
      sview_part_sub_ptr->node_state = node_ptr->node_state;
      sview_part_sub_ptr->node_cnt = node_scaling;
      
      sview_part_sub_ptr->min_cpus = node_ptr->cpus;
      sview_part_sub_ptr->max_cpus = node_ptr->cpus;

      sview_part_sub_ptr->min_disk = node_ptr->tmp_disk;
      sview_part_sub_ptr->max_disk = node_ptr->tmp_disk;

      sview_part_sub_ptr->min_mem = node_ptr->real_memory;
      sview_part_sub_ptr->max_mem = node_ptr->real_memory;

      sview_part_sub_ptr->min_weight = node_ptr->weight;
      sview_part_sub_ptr->max_weight = node_ptr->weight;

      sview_part_sub_ptr->features = xstrdup(node_ptr->features);
      sview_part_sub_ptr->reason   = xstrdup(node_ptr->reason);

      sview_part_sub_ptr->hl = hostlist_create(node_ptr->name);
      
      sview_part_sub_ptr->node_ptr_list = list_create(NULL);

      list_push(sview_part_sub_ptr->node_ptr_list, node_ptr);

      return sview_part_sub_ptr;
}

/* 
 * _create_sview_part_info - create an sview_part_info record for 
 *                           the given partition
 * part_ptr IN             - pointer to partition record to add
 * sview_part_info OUT     - ptr to an inited sview_part_info_t
 */
static sview_part_info_t *_create_sview_part_info(partition_info_t* part_ptr)
{
      sview_part_info_t *sview_part_info = 
            xmalloc(sizeof(sview_part_info_t));
            
      
      sview_part_info->part_ptr = part_ptr;
      sview_part_info->sub_list = list_create(_destroy_part_sub);
      return sview_part_info;
}

static List _create_part_info_list(partition_info_msg_t *part_info_ptr,
                           node_info_msg_t *node_info_ptr,
                           node_select_info_msg_t *node_select_ptr,
                           int changed)
{
      sview_part_info_t *sview_part_info = NULL;
      sview_part_sub_t *sview_part_sub = NULL;
      partition_info_t *part_ptr = NULL;
      node_info_t *node_ptr = NULL;
      static List info_list = NULL;
      char *node_name = NULL;
      int i, found = 0;
      ListIterator itr = NULL;
      hostlist_t hl;
#ifdef HAVE_BG
      bg_info_record_t *bg_info_record = NULL;
      int node_scaling = part_info_ptr->partition_array[0].node_scaling;
      char *slurm_user = NULL;
#endif
      if(!changed && info_list) {
            return info_list;
      }
      
      if(info_list) {
            list_destroy(info_list);
      }
      info_list = list_create(_part_info_list_del);
      if (!info_list) {
            g_print("malloc error\n");
            return NULL;
      }

#ifdef HAVE_BG
      slurm_user = xstrdup(slurmctld_conf.slurm_user_name);

      for (i=0; i<node_info_ptr->record_count; i++) {
            node_ptr = &(node_info_ptr->node_array[i]);
            /* in each node_ptr we overload the threads var
             * with the number of cnodes in the used_cpus var
             * will be used to tell how many cnodes are
             * allocated and the cores will represent the cnodes
             * in an error state. So we can get an idle count by
             * subtracting those 2 numbers from the total possible
             * cnodes (which are the idle cnodes).
             */
            node_ptr->threads = node_scaling;
            node_ptr->cores = 0;
            node_ptr->used_cpus = 0;
      }

      for (i=0; i<node_select_ptr->record_count; i++) {
            bg_info_record = &(node_select_ptr->bg_info_array[i]);
            
            /* this block is idle we won't mark it */
            if (bg_info_record->state != RM_PARTITION_ERROR
                && !strcmp(slurm_user, bg_info_record->owner_name))
                  continue;
            _update_nodes_for_bg(node_scaling, node_info_ptr,
                             bg_info_record);
      }
      xfree(slurm_user);

#endif


      for (i=0; i<part_info_ptr->record_count; i++) {
            part_ptr = &(part_info_ptr->partition_array[i]);
            if (!part_ptr->nodes || (part_ptr->nodes[0] == '\0'))
                  continue;   /* empty partition */
            
            sview_part_info = _create_sview_part_info(part_ptr);
            hl = hostlist_create(part_ptr->nodes);
            while((node_name = hostlist_shift(hl))) {
                  node_ptr = _find_node(node_name, node_info_ptr);
                  free(node_name);
#ifdef HAVE_BG
                  for(i=0; i<3; i++) {
                        int norm = 0;
                        switch(i) {
                        case SVIEW_BG_IDLE_STATE:
                              /* get the idle node count if
                               * we don't have any error or
                               * allocated nodes then we set
                               * the norm flag and add it
                               * as it's current state 
                               */
                              node_ptr->threads -=
                                    (node_ptr->cores
                                     + node_ptr->used_cpus);
                              if(node_ptr->threads == node_scaling)
                                    norm = 1;
                              else
                                    node_ptr->node_state =
                                          NODE_STATE_IDLE;
                              
                              break;
                        case SVIEW_BG_ERROR_STATE:
                              /* get the error node count */
                              if(!node_ptr->cores) 
                                    continue;
                              node_ptr->node_state |= 
                                    NODE_STATE_DRAIN;
                              node_ptr->threads = node_ptr->cores;
                              break;
                        case SVIEW_BG_ALLOC_STATE:
                              /* get the allocated node count */
                              if(!node_ptr->used_cpus) 
                                    continue;
                              node_ptr->node_state =
                                    NODE_STATE_ALLOCATED;
                              
                              node_ptr->threads =
                                    node_ptr->used_cpus;
                              break;
                        default:
                              error("unknown state");
                              break;
                        }
#endif
                  itr = list_iterator_create(sview_part_info->sub_list);
                  while((sview_part_sub = list_next(itr))) {
                        if(sview_part_sub->node_state
                           == node_ptr->node_state) {
                              _update_sview_part_sub(
                                    sview_part_sub, 
                                    node_ptr,
                                    part_ptr->node_scaling);
                              found = 1;
                              break;
                        }
                  }
                  list_iterator_destroy(itr);

                  if(!found) {
                        sview_part_sub = 
                              _create_sview_part_sub(
                                    part_ptr,
                                    node_ptr,
                                    part_ptr->node_scaling);
                        if(sview_part_sub)
                              list_push(sview_part_info->sub_list, 
                                      sview_part_sub);
                  }

                  found = 0;
#ifdef HAVE_BG
                  /* if we used the current state of
                   * the node then we just continue.
                   */
                  if(norm) 
                        break;
                  }
#endif
            }
            hostlist_destroy(hl);
            list_append(info_list, sview_part_info);
      }
      return info_list;
}

void _display_info_part(List info_list,   popup_info_t *popup_win)
{
      specific_info_t *spec_info = popup_win->spec_info;
      char *name = (char *)spec_info->search_info->gchar_data;
      int found = 0;
      partition_info_t *part_ptr = NULL;
      GtkTreeView *treeview = NULL;
      ListIterator itr = NULL;
      sview_part_info_t *sview_part_info = NULL;
      int update = 0;
      int i = -1, j = 0;
      int first_time = 0;

      if(!spec_info->search_info->gchar_data) {
            //info = xstrdup("No pointer given!");
            goto finished;
      }
      if(!list_count(popup_win->grid_button_list)) 
            first_time = 1;

need_refresh:
      if(!spec_info->display_widget) {
            treeview = create_treeview_2cols_attach_to_table(
                  popup_win->table);
            spec_info->display_widget = 
                  gtk_widget_ref(GTK_WIDGET(treeview));
      } else {
            treeview = GTK_TREE_VIEW(spec_info->display_widget);
            update = 1;
      }
      
      itr = list_iterator_create(info_list);
      while ((sview_part_info = (sview_part_info_t*) list_next(itr))) {
            part_ptr = sview_part_info->part_ptr;
            i++;
            if(!strcmp(part_ptr->name, name)) {
                  j=0;
                  while(part_ptr->node_inx[j] >= 0) {
                        if(!first_time)
                              change_grid_color(
                                    popup_win->grid_button_list,
                                    part_ptr->node_inx[j],
                                    part_ptr->node_inx[j+1], i);
                        else
                              get_button_list_from_main(
                                    &popup_win->grid_button_list,
                                    part_ptr->node_inx[j],
                                    part_ptr->node_inx[j+1],
                                    i);
                        j += 2;
                  }
                  _layout_part_record(treeview, sview_part_info, update);
                  found = 1;
                  break;
            }
      }
      list_iterator_destroy(itr);
      
      if(!found) {
            if(!popup_win->not_found) { 
                  char *temp = "PARTITION DOESN'T EXSIST\n";
                  GtkTreeIter iter;
                  GtkTreeModel *model = NULL;
      
                  /* only time this will be run so no update */
                  model = gtk_tree_view_get_model(treeview);
                  add_display_treestore_line(0, 
                                       GTK_TREE_STORE(model), 
                                       &iter,
                                       temp, "");
            }
            popup_win->not_found = true;
      } else {
            if(popup_win->not_found) { 
                  popup_win->not_found = false;
                  gtk_widget_destroy(spec_info->display_widget);
                  
                  goto need_refresh;
            }
            put_buttons_in_table(popup_win->grid_table,
                             popup_win->grid_button_list);

      }
      gtk_widget_show(spec_info->display_widget);
            
finished:
            
      return;
}

extern void refresh_part(GtkAction *action, gpointer user_data)
{
      popup_info_t *popup_win = (popup_info_t *)user_data;
      xassert(popup_win != NULL);
      xassert(popup_win->spec_info != NULL);
      xassert(popup_win->spec_info->title != NULL);
      popup_win->force_refresh = 1;
      specific_info_part(popup_win);
}

extern int get_new_info_part(partition_info_msg_t **part_ptr, int force)
{
      static partition_info_msg_t *part_info_ptr = NULL;
      static partition_info_msg_t *new_part_ptr = NULL;
      int error_code = SLURM_NO_CHANGE_IN_DATA;
      time_t now = time(NULL);
      static time_t last;
      static bool changed = 0;
            
      if(!force && ((now - last) < global_sleep_time)) {
            *part_ptr = part_info_ptr;
            if(changed) 
                  return SLURM_SUCCESS;
            return error_code;
      }
      last = now;
      if (part_info_ptr) {
            error_code = slurm_load_partitions(part_info_ptr->last_update, 
                                       &new_part_ptr, SHOW_ALL);
            if (error_code == SLURM_SUCCESS) {
                  slurm_free_partition_info_msg(part_info_ptr);
                  changed = 1;
            } else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) {
                  error_code = SLURM_NO_CHANGE_IN_DATA;
                  new_part_ptr = part_info_ptr;
                        changed = 0;
            }
      } else {
            error_code = slurm_load_partitions((time_t) NULL, 
                                       &new_part_ptr, SHOW_ALL);
            changed = 1;
      }
      
      part_info_ptr = new_part_ptr;
      *part_ptr = new_part_ptr;
      return error_code;
}

extern GtkListStore *create_model_part(int type)
{
      GtkListStore *model = NULL;
      GtkTreeIter iter;
      char *upper = NULL, *lower = NULL;             
      int i=0;
      switch(type) {
      case SORTID_DEFAULT:
            model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "yes",
                           1, SORTID_DEFAULT,
                           -1);     
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "no",
                           1, SORTID_DEFAULT,
                           -1);     

            break;
      case SORTID_HIDDEN:
            model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "yes",
                           1, SORTID_HIDDEN,
                           -1);     
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "no",
                           1, SORTID_HIDDEN,
                           -1);     

            break;
      case SORTID_TIMELIMIT:
      case SORTID_MIN_NODES:
      case SORTID_MAX_NODES:
            break;
      case SORTID_ROOT:
            model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "yes",
                           1, SORTID_ROOT,
                           -1);     
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "no",
                           1, SORTID_ROOT,
                           -1);     
            break;
      case SORTID_SHARE:
            model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "yes",
                           1, SORTID_SHARE,
                           -1);     
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "no",
                           1, SORTID_SHARE,
                           -1);     
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "force",
                           1, SORTID_SHARE,
                           -1);     
            break;
      case SORTID_GROUPS:
            break;
      case SORTID_NODELIST:
            break;
      case SORTID_AVAIL:
            model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "up",
                           1, SORTID_AVAIL,
                           -1);     
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "down",
                           1, SORTID_AVAIL,
                           -1);     
            break;
      case SORTID_STATE:
            model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "drain",
                           1, SORTID_STATE,
                           -1);     
            gtk_list_store_append(model, &iter);
            gtk_list_store_set(model, &iter,
                           0, "resume",
                           1, SORTID_STATE,
                           -1);     
            for(i = 0; i < NODE_STATE_END; i++) {
                  upper = node_state_string(i);
                  if(!strcmp(upper, "UNKNOWN"))
                        continue;
                  
                  gtk_list_store_append(model, &iter);
                  lower = str_tolower(upper);
                  gtk_list_store_set(model, &iter,
                                 0, lower,
                                 1, SORTID_STATE,
                                 -1);
                  xfree(lower);
            }
                                    
            break;

      }
      return model;
}

extern void admin_edit_part(GtkCellRendererText *cell,
                      const char *path_string,
                      const char *new_text,
                      gpointer data)
{
      GtkTreeStore *treestore = GTK_TREE_STORE(data);
      GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
      GtkTreeIter iter;
      update_part_msg_t *part_msg = xmalloc(sizeof(update_part_msg_t));
      
      char *temp = NULL;
      char *old_text = NULL;
      const char *type = NULL;
      int column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), 
                                           "column"));
      
      if(!new_text || !strcmp(new_text, ""))
            goto no_input;
      
      gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), &iter, path);

      if(column != SORTID_STATE) {
            slurm_init_part_desc_msg(part_msg);
            gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter, 
                           SORTID_NAME, &temp, 
                           column, &old_text,
                           -1);
            part_msg->name = xstrdup(temp);
            g_free(temp);
      }
      
      type = _set_part_msg(part_msg, new_text, column);
      if(errno)
            goto print_error;
      if(got_edit_signal) {
            temp = got_edit_signal;
            got_edit_signal = NULL;
            admin_part(GTK_TREE_MODEL(treestore), &iter, temp);
            xfree(temp);
            goto no_input;
      }

      if(got_features_edit_signal) {
            admin_part(GTK_TREE_MODEL(treestore), &iter, (char *)type);
            goto no_input;
      }
      
      if(column != SORTID_STATE && column != SORTID_FEATURES ) {
            if(old_text && !strcmp(old_text, new_text)) {
                  temp = g_strdup_printf("No change in value.");
                  display_edit_note(temp);
                  g_free(temp);     
            } else if(slurm_update_partition(part_msg) == SLURM_SUCCESS) {
                  gtk_tree_store_set(treestore, &iter, column,
                                 new_text, -1);
                  temp = g_strdup_printf("Partition %s %s changed to %s",
                                     part_msg->name,
                                     type,
                                     new_text);
                  display_edit_note(temp);
                  g_free(temp);
            } else {
            print_error:
                  temp = g_strdup_printf("Partition %s %s can't be "
                                     "set to %s",
                                     part_msg->name,
                                     type,
                                     new_text);
                  display_edit_note(temp);
                  g_free(temp);
            }
      }
no_input:
      slurm_free_update_part_msg(part_msg);
      gtk_tree_path_free (path);
      g_free(old_text);
      g_static_mutex_unlock(&sview_mutex);
}

extern void get_info_part(GtkTable *table, display_data_t *display_data)
{
      int part_error_code = SLURM_SUCCESS;
      int node_error_code = SLURM_SUCCESS;
      int block_error_code = SLURM_SUCCESS;
      static int view = -1;
      static partition_info_msg_t *part_info_ptr = NULL;
      static node_info_msg_t *node_info_ptr = NULL;
      static node_select_info_msg_t *node_select_ptr = NULL;
      char error_char[100];
      GtkWidget *label = NULL;
      GtkTreeView *tree_view = NULL;
      static GtkWidget *display_widget = NULL;
      List info_list = NULL;
      int changed = 1;
      int j=0, i=0;
      sview_part_info_t *sview_part_info = NULL;
      partition_info_t *part_ptr = NULL;
      ListIterator itr = NULL;
      
      if(display_data)
            local_display_data = display_data;
      if(!table) {
            display_data_part->set_menu = local_display_data->set_menu;
            return;
      }
      if(display_widget && toggled) {
            gtk_widget_destroy(display_widget);
            display_widget = NULL;
            goto display_it;
      }
      
      if((part_error_code = get_new_info_part(&part_info_ptr, force_refresh))
         == SLURM_NO_CHANGE_IN_DATA) { 
            // just goto the new info node 
      } else      if (part_error_code != SLURM_SUCCESS) {
            if(view == ERROR_VIEW)
                  goto end_it;
            if(display_widget)
                  gtk_widget_destroy(display_widget);
            view = ERROR_VIEW;
            snprintf(error_char, 100, "slurm_load_partitions: %s",
                  slurm_strerror(slurm_get_errno()));
            label = gtk_label_new(error_char);
            display_widget = gtk_widget_ref(GTK_WIDGET(label));
            gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
            gtk_widget_show(label);
            goto end_it;
      }

      if((node_error_code = get_new_info_node(&node_info_ptr, force_refresh))
         == SLURM_NO_CHANGE_IN_DATA) { 
            // just goto the new info node select
      } else if (node_error_code != SLURM_SUCCESS) {
            if(view == ERROR_VIEW)
                  goto end_it;
            if(display_widget)
                  gtk_widget_destroy(display_widget);
            view = ERROR_VIEW;
            snprintf(error_char, 100, "slurm_load_node: %s",
                  slurm_strerror(slurm_get_errno()));
            label = gtk_label_new(error_char);
            display_widget = gtk_widget_ref(GTK_WIDGET(label));
            gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
            gtk_widget_show(label);
            goto end_it;
      }

      if((block_error_code = get_new_info_node_select(&node_select_ptr, 
                                          force_refresh))
         == SLURM_NO_CHANGE_IN_DATA) { 
            if((!display_widget || view == ERROR_VIEW) 
               || (part_error_code != SLURM_NO_CHANGE_IN_DATA)
               || (node_error_code != SLURM_NO_CHANGE_IN_DATA)) {
                  goto display_it;
            }
            changed = 0;
      } else if (block_error_code != SLURM_SUCCESS) {
            if(view == ERROR_VIEW)
                  goto end_it;
            view = ERROR_VIEW;
            if(display_widget)
                  gtk_widget_destroy(display_widget);
            sprintf(error_char, "slurm_load_node_select: %s",
                  slurm_strerror(slurm_get_errno()));
            label = gtk_label_new(error_char);
            gtk_table_attach_defaults(table, 
                                label,
                                0, 1, 0, 1); 
            gtk_widget_show(label); 
            display_widget = gtk_widget_ref(label);
            goto end_it;
      }

display_it:

      info_list = _create_part_info_list(part_info_ptr,
                                 node_info_ptr,
                                 node_select_ptr,
                                 changed);
      if(!info_list)
            return;
      /* set up the grid */
      itr = list_iterator_create(info_list);
      while ((sview_part_info = list_next(itr))) {
            part_ptr = sview_part_info->part_ptr;
            j=0;
            while(part_ptr->node_inx[j] >= 0) {
                  sview_part_info->color = 
                        change_grid_color(grid_button_list,
                                      part_ptr->node_inx[j],
                                      part_ptr->node_inx[j+1],
                                      i);
                  j += 2;
            }
            i++;
      }
      list_iterator_destroy(itr);
            
      if(view == ERROR_VIEW && display_widget) {
            gtk_widget_destroy(display_widget);
            display_widget = NULL;
      }
      if(!display_widget) {
            tree_view = create_treeview(local_display_data);

            display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
            gtk_table_attach_defaults(table,
                                GTK_WIDGET(tree_view),
                                0, 1, 0, 1);
            /* since this function sets the model of the tree_view 
               to the treestore we don't really care about 
               the return value */
            create_treestore(tree_view, display_data_part, SORTID_CNT);
      }
      view = INFO_VIEW;
      _update_info_part(info_list, GTK_TREE_VIEW(display_widget));
end_it:
      toggled = FALSE;
      force_refresh = FALSE;
      
      return;
}

extern void specific_info_part(popup_info_t *popup_win)
{
      int part_error_code = SLURM_SUCCESS;
      int node_error_code = SLURM_SUCCESS;
      int block_error_code = SLURM_SUCCESS;
      static partition_info_msg_t *part_info_ptr = NULL;
      static node_info_msg_t *node_info_ptr = NULL;
      static node_select_info_msg_t *node_select_ptr = NULL;
      specific_info_t *spec_info = popup_win->spec_info;
      char error_char[100];
      GtkWidget *label = NULL;
      GtkTreeView *tree_view = NULL;
      List info_list = NULL;
      List send_info_list = NULL;
      int changed = 1;
      int j=0, i=-1;
      sview_part_info_t *sview_part_info_ptr = NULL;
      partition_info_t *part_ptr = NULL;
      ListIterator itr = NULL;
      char *host = NULL, *host2 = NULL;
      hostlist_t hostlist = NULL;
      int found = 0;
      
      if(!spec_info->display_widget)
            setup_popup_info(popup_win, display_data_part, SORTID_CNT);
      
      if(spec_info->display_widget && popup_win->toggled) {
            gtk_widget_destroy(spec_info->display_widget);
            spec_info->display_widget = NULL;
            goto display_it;
      }

      if((part_error_code = get_new_info_part(&part_info_ptr, 
                                    popup_win->force_refresh))
         == SLURM_NO_CHANGE_IN_DATA)  {
            
      } else if (part_error_code != SLURM_SUCCESS) {
            if(spec_info->view == ERROR_VIEW)
                  goto end_it;
            if(spec_info->display_widget) {
                  gtk_widget_destroy(spec_info->display_widget);
                  spec_info->display_widget = NULL;
            }
            spec_info->view = ERROR_VIEW;
            snprintf(error_char, 100, "slurm_load_partitions: %s",
                   slurm_strerror(slurm_get_errno()));
            label = gtk_label_new(error_char);
            spec_info->display_widget = gtk_widget_ref(GTK_WIDGET(label));
            gtk_table_attach_defaults(popup_win->table, label, 0, 1, 0, 1);
            gtk_widget_show(label);             
            goto end_it;
      }

      if((node_error_code = get_new_info_node(&node_info_ptr, 
                                    popup_win->force_refresh))
         == SLURM_NO_CHANGE_IN_DATA) { 
                              
      } else if (node_error_code != SLURM_SUCCESS) {
            if(spec_info->view == ERROR_VIEW)
                  goto end_it;
            if(spec_info->display_widget)
                  gtk_widget_destroy(spec_info->display_widget);
            spec_info->view = ERROR_VIEW;
            snprintf(error_char, 100, "slurm_load_node: %s",
                  slurm_strerror(slurm_get_errno()));
            label = gtk_label_new(error_char);
            spec_info->display_widget = gtk_widget_ref(GTK_WIDGET(label));
            gtk_table_attach_defaults(popup_win->table, label, 0, 1, 0, 1);
            gtk_widget_show(label);
            goto end_it;
      }

      if((block_error_code = get_new_info_node_select(&node_select_ptr, 
                                          force_refresh))
         == SLURM_NO_CHANGE_IN_DATA) { 
            if((!spec_info->display_widget
                || spec_info->view == ERROR_VIEW) 
               || (part_error_code != SLURM_NO_CHANGE_IN_DATA)
               || (node_error_code != SLURM_NO_CHANGE_IN_DATA))
                  goto display_it;
            changed = 0;
      } else if (block_error_code != SLURM_SUCCESS) {
            if(spec_info->view == ERROR_VIEW)
                  goto end_it;
            if(spec_info->display_widget)
                  gtk_widget_destroy(spec_info->display_widget);
            spec_info->view = ERROR_VIEW;
            sprintf(error_char, "slurm_load_node_select: %s",
                  slurm_strerror(slurm_get_errno()));
            label = gtk_label_new(error_char);
            spec_info->display_widget = gtk_widget_ref(label);
            gtk_table_attach_defaults(popup_win->table, label, 0, 1, 0, 1);
            gtk_widget_show(label); 
            goto end_it;
      }

display_it: 
      
      info_list = _create_part_info_list(part_info_ptr,
                                 node_info_ptr,
                                 node_select_ptr,
                                 changed);
      if(!info_list)
            return;           
      
      if(spec_info->view == ERROR_VIEW && spec_info->display_widget) {
            gtk_widget_destroy(spec_info->display_widget);
            spec_info->display_widget = NULL;
      }
      
      if(spec_info->type != INFO_PAGE && !spec_info->display_widget) {
            tree_view = create_treeview(local_display_data);
            
            spec_info->display_widget = 
                  gtk_widget_ref(GTK_WIDGET(tree_view));
            gtk_table_attach_defaults(popup_win->table,
                                GTK_WIDGET(tree_view),
                                0, 1, 0, 1);
            
            /* since this function sets the model of the tree_view 
               to the treestore we don't really care about 
               the return value */
            create_treestore(tree_view, popup_win->display_data, 
                         SORTID_CNT);
      }
      
      if(popup_win->grid_button_list) {
            list_destroy(popup_win->grid_button_list);
      }            
      
#ifdef HAVE_BG
      popup_win->grid_button_list = copy_main_button_list();
#else
      popup_win->grid_button_list = list_create(destroy_grid_button);
#endif      

      spec_info->view = INFO_VIEW;
      if(spec_info->type == INFO_PAGE) {
            _display_info_part(info_list, popup_win);
            goto end_it;
      } 
      
      /* just linking to another list, don't free the inside, just
         the list */
      send_info_list = list_create(NULL); 
      
      itr = list_iterator_create(info_list);
      while ((sview_part_info_ptr = list_next(itr))) {
            i++;
            part_ptr = sview_part_info_ptr->part_ptr; 
            switch(spec_info->type) {
            case NODE_PAGE:
                  if(!part_ptr->nodes)
                        continue;

                  hostlist = hostlist_create(
                        spec_info->search_info->gchar_data);
                  host = hostlist_shift(hostlist);
                  hostlist_destroy(hostlist);
                  if(!host) 
                        continue;
                  
                  hostlist = hostlist_create(part_ptr->nodes);
                  found = 0;
                  while((host2 = hostlist_shift(hostlist))) { 
                        if(!strcmp(host, host2)) {
                              free(host2);
                              found = 1;
                              break; 
                        }
                        free(host2);
                  }
                  hostlist_destroy(hostlist);
                  if(!found)
                        continue;
                  break;
            case PART_PAGE:
            case BLOCK_PAGE:
            case JOB_PAGE:
                  if(strcmp(part_ptr->name, 
                          spec_info->search_info->gchar_data)) 
                        continue;
                  break;
            default:
                  g_print("Unkown type %d\n", spec_info->type);
                  list_iterator_destroy(itr);
                  goto end_it;
            }
            list_push(send_info_list, sview_part_info_ptr);
            j=0;
            while(part_ptr->node_inx[j] >= 0) {
#ifdef HAVE_BG
                  change_grid_color(
                        popup_win->grid_button_list,
                        part_ptr->node_inx[j],
                        part_ptr->node_inx[j+1], i);
#else
                  get_button_list_from_main(
                        &popup_win->grid_button_list,
                        part_ptr->node_inx[j],
                        part_ptr->node_inx[j+1], i);
#endif
                  j += 2;
            }
      }
      list_iterator_destroy(itr);
      put_buttons_in_table(popup_win->grid_table,
                       popup_win->grid_button_list);
       
      _update_info_part(send_info_list, 
                    GTK_TREE_VIEW(spec_info->display_widget));
      list_destroy(send_info_list);
end_it:
      popup_win->toggled = 0;
      popup_win->force_refresh = 0;
            
      return;
}

extern void set_menus_part(void *arg, GtkTreePath *path, 
                     GtkMenu *menu, int type)
{
      GtkTreeView *tree_view = (GtkTreeView *)arg;
      popup_info_t *popup_win = (popup_info_t *)arg;

      switch(type) {
      case TAB_CLICKED:
            make_fields_menu(menu, display_data_part, SORTID_CNT);
            break;
      case ROW_CLICKED:
            make_options_menu(tree_view, path, menu, options_data_part);
            break;
      case POPUP_CLICKED:
            make_popup_fields_menu(popup_win, menu);
            break;
      default:
            g_error("UNKNOWN type %d given to set_fields\n", type);
      }
}

extern void popup_all_part(GtkTreeModel *model, GtkTreeIter *iter, int id)
{
      char *name = NULL;
      char *state = NULL;
      char title[100];
      int only_line = 0;
      ListIterator itr = NULL;
      popup_info_t *popup_win = NULL;
      GError *error = NULL;
                        
      gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
      
      switch(id) {
      case JOB_PAGE:
            snprintf(title, 100, "Job(s) in partition %s", name);
            break;
      case NODE_PAGE:
            gtk_tree_model_get(model, iter, SORTID_ONLY_LINE,
                           &only_line, -1);
            if(!only_line)
                  gtk_tree_model_get(model, iter,
                                 SORTID_STATE, &state, -1);
#ifdef HAVE_BG
            if(!state || !strlen(state))
                  snprintf(title, 100, 
                         "Base partition(s) in partition %s",
                         name);
            else
                  snprintf(title, 100, 
                         "Base partition(s) in partition %s "
                         "that are in '%s' state",
                         name, state);
#else
            if(!state || !strlen(state))
                  snprintf(title, 100, "Node(s) in partition %s ",
                         name);
            else
                  snprintf(title, 100, 
                         "Node(s) in partition %s that are in "
                         "'%s' state",
                         name, state);
#endif
            break;
      case BLOCK_PAGE: 
            snprintf(title, 100, "Block(s) in partition %s", name);
            break;
      case SUBMIT_PAGE: 
            snprintf(title, 100, "Submit job in partition %s", name);
            break;
      case INFO_PAGE: 
            snprintf(title, 100, "Full info for partition %s", name);
            break;
      default:
            g_print("part got %d\n", id);
      }
      
      itr = list_iterator_create(popup_list);
      while((popup_win = list_next(itr))) {
            if(popup_win->spec_info)
                  if(!strcmp(popup_win->spec_info->title, title)) {
                        break;
                  } 
      }
      list_iterator_destroy(itr);

      if(!popup_win) {
            if(id == INFO_PAGE)
                  popup_win = create_popup_info(id, PART_PAGE, title);
            else
                  popup_win = create_popup_info(PART_PAGE, id, title);
      } else {
            g_free(name);
            g_free(state);
            gtk_window_present(GTK_WINDOW(popup_win->popup));
            return;
      }

      switch(id) {
      case JOB_PAGE:
      case BLOCK_PAGE: 
      case INFO_PAGE:
            popup_win->spec_info->search_info->gchar_data = name;
            //specific_info_job(popup_win);
            break;
      case NODE_PAGE:
            g_free(name);
            gtk_tree_model_get(model, iter, SORTID_NODELIST, &name, -1);
            popup_win->spec_info->search_info->gchar_data = name;
            if(state && strlen(state)) {
                  popup_win->spec_info->search_info->search_type =
                        SEARCH_NODE_STATE;
                  gtk_tree_model_get(
                        model, iter, SORTID_STATE_NUM,
                        &popup_win->spec_info->search_info->int_data,
                        -1);
            } else {
                  popup_win->spec_info->search_info->search_type = 
                        SEARCH_NODE_NAME;
            }
            g_free(state);
            
            //specific_info_node(popup_win);
            break;
      case SUBMIT_PAGE: 
            break;
      default:
            g_print("part got unknown type %d\n", id);
      }
      if (!g_thread_create((gpointer)popup_thr, popup_win, FALSE, &error))
      {
            g_printerr ("Failed to create part popup thread: %s\n", 
                      error->message);
            return;
      }           
}

extern void admin_part(GtkTreeModel *model, GtkTreeIter *iter, char *type)
{
      update_part_msg_t *part_msg = xmalloc(sizeof(update_part_msg_t));
      char *partid = NULL;
      char *nodelist = NULL;
      char *state = NULL;
      char tmp_char[100];
      char *temp = NULL;
      int edit_type = 0;
      int response = 0; 
      GtkWidget *label = NULL;
      GtkWidget *entry = NULL;
      GtkWidget *popup = gtk_dialog_new_with_buttons(
            type,
            GTK_WINDOW(main_window),
            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
            NULL);
      gtk_window_set_transient_for(GTK_WINDOW(popup), NULL);

      gtk_tree_model_get(model, iter, SORTID_NAME, &partid, -1);
      gtk_tree_model_get(model, iter, SORTID_NODELIST, &nodelist, -1);
      gtk_tree_model_get(model, iter, SORTID_AVAIL, &state, -1);
      slurm_init_part_desc_msg(part_msg);
      
      part_msg->name = xstrdup(partid);
            
      if(!strcasecmp("Change Availablity Up/Down", type)) {
            label = gtk_dialog_add_button(GTK_DIALOG(popup),
                                    GTK_STOCK_YES, GTK_RESPONSE_OK);
            gtk_window_set_default(GTK_WINDOW(popup), label);
            gtk_dialog_add_button(GTK_DIALOG(popup),
                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
            
            if(!strcasecmp("down", type)) 
                  temp = "up";
            else
                  temp = "down";
            snprintf(tmp_char, sizeof(tmp_char), 
                   "Are you sure you want to set partition %s %s?",
                   partid, temp);
            label = gtk_label_new(tmp_char);
            edit_type = EDIT_AVAIL;
      } else if(!strcasecmp("Edit Part", type)) {
            label = gtk_dialog_add_button(GTK_DIALOG(popup),
                                    GTK_STOCK_OK, GTK_RESPONSE_OK);
            gtk_window_set_default(GTK_WINDOW(popup), label);
            gtk_dialog_add_button(GTK_DIALOG(popup),
                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);

            gtk_window_set_default_size(GTK_WINDOW(popup), 200, 400);
            snprintf(tmp_char, sizeof(tmp_char), 
                   "Editing partition %s think before you type",
                   partid);
            label = gtk_label_new(tmp_char);
            edit_type = EDIT_EDIT;
            entry = _admin_full_edit_part(part_msg, model, iter);
      } else if(!strncasecmp("Update", type, 6)) {
            char *old_features = NULL;
            if(got_features_edit_signal) 
                  old_features = got_features_edit_signal;
            else 
                  gtk_tree_model_get(model, iter, SORTID_FEATURES,
                                 &old_features, -1);
            update_features_node(GTK_DIALOG(popup),
                             nodelist, old_features);
            if(got_features_edit_signal) {
                  got_features_edit_signal = NULL;
                  xfree(old_features);
            } else 
                  g_free(old_features);
            goto end_it;
      } else {
            /* something that has to deal with a node state change */
            update_state_node(GTK_DIALOG(popup), nodelist, type);
            goto end_it;
      }

      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox), 
                     label, FALSE, FALSE, 0);
      if(entry)
            gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox), 
                           entry, TRUE, TRUE, 0);
      gtk_widget_show_all(popup);
      response = gtk_dialog_run (GTK_DIALOG(popup));

      if (response == GTK_RESPONSE_OK) {
            if(slurm_update_partition(part_msg) == SLURM_SUCCESS) {
                  temp = g_strdup_printf(
                        "Partition %s updated successfully",
                        partid);
            } else {
                  temp = g_strdup_printf(
                        "Problem updating partition %s.",
                        partid);
            }
            display_edit_note(temp);
            g_free(temp);
      }
end_it:
            
      g_free(state);
      g_free(partid);
      g_free(nodelist);
      slurm_free_update_part_msg(part_msg);
      gtk_widget_destroy(popup);
      if(got_edit_signal) {
            type = got_edit_signal;
            got_edit_signal = NULL;
            admin_part(model, iter, type);
            xfree(type);
      }                 
      if(got_features_edit_signal) {
            type = "Update Features";           
            admin_part(model, iter, type);            
      } 
      return;
}


Generated by  Doxygen 1.6.0   Back to index