From a878abb96b54596e3c0e397b2b2deccb8e509c34 Mon Sep 17 00:00:00 2001 From: Danny Auble <da@llnl.gov> Date: Thu, 10 Aug 2006 18:02:24 +0000 Subject: [PATCH] svn merge -r8148:8857 https://eris.llnl.gov/svn/slurm/branches/sview --- auxdir/x_ac_gtk.m4 | 41 ++ configure.ac | 4 + slurm/slurm.h.in | 42 ++ src/Makefile.am | 3 +- src/api/job_info.c | 507 ++++++++++++--- src/api/job_step_info.c | 61 +- src/api/node_info.c | 93 ++- src/api/partition_info.c | 255 ++++++-- src/common/node_select.c | 2 +- src/common/slurm_protocol_api.c | 14 + src/common/slurm_protocol_api.h | 11 + src/sacct/print.c | 31 +- src/sacct/process.c | 16 - src/sacct/sacct.h | 1 - src/sview/Makefile.am | 33 + src/sview/admin_info.c | 128 ++++ src/sview/block_info.c | 1014 ++++++++++++++++++++++++++++++ src/sview/common.c | 696 +++++++++++++++++++++ src/sview/job_info.c | 1015 +++++++++++++++++++++++++++++++ src/sview/node_info.c | 489 +++++++++++++++ src/sview/part_info.c | 551 +++++++++++++++++ src/sview/submit_info.c | 128 ++++ src/sview/sview.c | 364 +++++++++++ src/sview/sview.h | 286 +++++++++ testsuite/expect/README | 15 +- testsuite/expect/regression.py | 2 +- 26 files changed, 5644 insertions(+), 158 deletions(-) create mode 100644 auxdir/x_ac_gtk.m4 create mode 100644 src/sview/Makefile.am create mode 100644 src/sview/admin_info.c create mode 100644 src/sview/block_info.c create mode 100644 src/sview/common.c create mode 100644 src/sview/job_info.c create mode 100644 src/sview/node_info.c create mode 100644 src/sview/part_info.c create mode 100644 src/sview/submit_info.c create mode 100644 src/sview/sview.c create mode 100644 src/sview/sview.h diff --git a/auxdir/x_ac_gtk.m4 b/auxdir/x_ac_gtk.m4 new file mode 100644 index 00000000000..917ce231049 --- /dev/null +++ b/auxdir/x_ac_gtk.m4 @@ -0,0 +1,41 @@ +##***************************************************************************** +## $Id: x_ac_gtk.m4 5401 2005-09-22 01:56:49Z morrone $ +##***************************************************************************** +# AUTHOR: +# Danny Auble <da@llnl.gov> +# +# SYNOPSIS: +# X_AC_GTK +# +# DESCRIPTION: +# Test for GTK. If found define +##***************************************************************************** + + +AC_DEFUN([X_AC_GTK], +[ + AC_PATH_PROG(HAVEPKGCONFIG, pkg-config, $PATH) + + if test ! -z "$HAVEPKGCONFIG"; then + $HAVEPKGCONFIG --exists libglade-2.0 gtk+-2.0 + if test $? -eq 0 ; then + GTK2_CFLAGS=`$HAVEPKGCONFIG --cflags libglade-2.0 gtk+-2.0 gthread-2.0` + GTK2_LIBS=`$HAVEPKGCONFIG --libs libglade-2.0 gtk+-2.0 gthread-2.0` + ac_have_gtk="yes" + if test ! -z "GLADE_STATIC" ; then + GTK2_LIBS=`echo $GTK2_LIBS | sed "s/-lglade-2.0/$GLADE_STATIC -lglade-2.0 $BDYNAMIC/g"` + fi + GUI_LIBS="$GUI_LIBS $GTK2_LIBS" + SETUP_GTK="setup.gtk2" + GTK_SUBDIR=gtk2 + XMLVER="2" + AC_SUBST(GTK2_CFLAGS) + AC_SUBST(GTK2_LIBS) + else + AC_MSG_ERROR([*** Either libglade-2.0 or gtk+-2.0 are not available.]) + fi + else + AC_MSG_ERROR([*** pkg-config not found. Cannot probe for libglade-2.0 or gtk+-2.0.]) + fi + +]) diff --git a/configure.ac b/configure.ac index 8f332692702..53919c2e0d4 100644 --- a/configure.ac +++ b/configure.ac @@ -126,6 +126,9 @@ X_AC_NCURSES AM_CONDITIONAL(HAVE_SOME_CURSES, test "x$ac_have_some_curses" = "xyes") AC_SUBST(HAVE_SOME_CURSES) +X_AC_GTK +AM_CONDITIONAL(HAVE_GTK, test "x$ac_have_gtk" = "xyes") + dnl checks for system services. dnl @@ -239,6 +242,7 @@ AC_CONFIG_FILES([Makefile src/squeue/Makefile src/sinfo/Makefile src/smap/Makefile + src/sview/Makefile src/plugins/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile diff --git a/slurm/slurm.h.in b/slurm/slurm.h.in index 0dbcee6b4d4..539fd68b9df 100644 --- a/slurm/slurm.h.in +++ b/slurm/slurm.h.in @@ -1167,6 +1167,17 @@ extern void slurm_print_job_info_msg PARAMS(( extern void slurm_print_job_info PARAMS(( FILE*, job_info_t * job_ptr, int one_liner )); +/* + * slurm_sprint_job_info - output information about a specific Slurm + * job based upon message as loaded using slurm_load_jobs + * IN job_ptr - an individual job information record pointer + * IN one_liner - print as a single line if true + * RET out - char * containing formatted output (must be freed after call) + * NULL is returned on failure. + */ +extern char *slurm_sprint_job_info PARAMS(( job_info_t * job_ptr, + int one_liner )); + /* * slurm_get_end_time - get the expected end time for a given slurm job * IN jobid - slurm job id @@ -1273,6 +1284,16 @@ extern void slurm_print_job_step_info PARAMS(( */ extern slurm_step_layout_t *slurm_job_step_layout_get PARAMS((uint32_t job_id, uint32_t step_id)); +/* + * slurm_sprint_job_step_info - output information about a specific Slurm + * job step based upon message as loaded using slurm_get_job_steps + * IN job_ptr - an individual job step information record pointer + * IN one_liner - print as a single line if true + * RET out - char * containing formatted output (must be freed after call) + * NULL is returned on failure. + */ +extern char *slurm_sprint_job_step_info PARAMS(( job_step_info_t * step_ptr, + int one_liner )); void slurm_job_step_layout_free PARAMS((slurm_step_layout_t *layout)); @@ -1321,6 +1342,17 @@ extern void slurm_print_node_info_msg PARAMS(( extern void slurm_print_node_table PARAMS(( FILE * out, node_info_t * node_ptr, int one_liner )); +/* + * slurm_sprint_node_table - output information about a specific Slurm nodes + * based upon message as loaded using slurm_load_node + * IN node_ptr - an individual node information record pointer + * IN one_liner - print as a single line if true + * RET out - char * containing formatted output (must be freed after call) + * NULL is returned on failure. + */ +extern char *slurm_sprint_node_table PARAMS(( node_info_t * node_ptr, + int one_liner )); + /* * slurm_update_node - issue RPC to a node's configuration per request, * only usable by user root @@ -1384,6 +1416,16 @@ extern void slurm_print_partition_info_msg PARAMS(( extern void slurm_print_partition_info PARAMS(( FILE *out , partition_info_t * part_ptr, int one_liner )); +/* + * slurm_sprint_partition_info - output information about a specific Slurm + * partition based upon message as loaded using slurm_load_partitions + * IN part_ptr - an individual partition information record pointer + * IN one_liner - print as a single line if true + * RET out - char * with formatted output (must be freed after call) + * NULL is returned on failure. + */ +extern char *slurm_sprint_partition_info PARAMS(( + partition_info_t * part_ptr, int one_liner )); /* * slurm_update_partition - issue RPC to update a partition's configuration * per request, only usable by user root diff --git a/src/Makefile.am b/src/Makefile.am index 30df910151b..e64a539bdae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,4 @@ SUBDIRS = common api slurmctld slurmd plugins srun sacct sbcast \ - scontrol scancel squeue sinfo smap slaunch salloc sbatch sattach + scontrol scancel squeue sinfo smap sview slaunch salloc sbatch sattach + diff --git a/src/api/job_info.c b/src/api/job_info.c index 30a577481fb..23ab02fa317 100644 --- a/src/api/job_info.c +++ b/src/api/job_info.c @@ -50,6 +50,7 @@ #include "src/common/xstring.h" #include "src/common/forward.h" +#define HUGE_BUF 4096 /* * slurm_print_job_info_msg - output information about all Slurm * jobs based upon message as loaded using slurm_load_jobs @@ -82,13 +83,34 @@ slurm_print_job_info_msg ( FILE* out, job_info_msg_t *jinfo, int one_liner ) */ extern void slurm_print_job_info ( FILE* out, job_info_t * job_ptr, int one_liner ) +{ + char *print_this = slurm_sprint_job_info(job_ptr, one_liner); + fprintf ( out, "%s", print_this); + xfree(print_this); +} + +/* + * slurm_sprint_job_info - output information about a specific Slurm + * job based upon message as loaded using slurm_load_jobs + * IN job_ptr - an individual job information record pointer + * IN one_liner - print as a single line if true + * RET out - char * containing formatted output (must be freed after call) + * NULL is returned on failure. + */ +extern char * +slurm_sprint_job_info ( job_info_t * job_ptr, int one_liner ) { int j; char time_str[32], select_buf[128]; struct group *group_info = NULL; - char tmp1[7], tmp2[7]; + char tmp1[7], tmp3[7]; + char tmp2[100]; uint16_t quarter = (uint16_t) NO_VAL; uint16_t nodecard = (uint16_t) NO_VAL; + char *out = xmalloc(HUGE_BUF); + int len = 0; + int lentmp2 = 0; + int tmplen = 0; #ifdef HAVE_BG char *nodelist = "BP_List"; @@ -103,194 +125,539 @@ slurm_print_job_info ( FILE* out, job_info_t * job_ptr, int one_liner ) #endif /****** Line 1 ******/ - fprintf ( out, "JobId=%u ", job_ptr->job_id); - fprintf ( out, "UserId=%s(%u) ", + sprintf ( tmp2, "JobId=%u ", job_ptr->job_id); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out, "%s", tmp2); + len += lentmp2; + + sprintf ( tmp2, "UserId=%s(%u) ", uid_to_string((uid_t) job_ptr->user_id), job_ptr->user_id); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + group_info = getgrgid( (gid_t) job_ptr->group_id ); if ( group_info && group_info->gr_name[ 0 ] ) - fprintf( out, "GroupId=%s(%u)", + sprintf ( tmp2, "GroupId=%s(%u)", group_info->gr_name, job_ptr->group_id ); else - fprintf( out, "GroupId=(%u)", job_ptr->group_id ); + sprintf ( tmp2, "GroupId=(%u)", job_ptr->group_id ); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 2 ******/ - fprintf ( out, "Name=%s", job_ptr->name); + sprintf ( tmp2, "Name=%s", job_ptr->name); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 3 ******/ - fprintf ( out, "Priority=%u Partition=%s BatchFlag=%u", + sprintf ( tmp2, "Priority=%u Partition=%s BatchFlag=%u", job_ptr->priority, job_ptr->partition, job_ptr->batch_flag); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 4 ******/ - fprintf ( out, "AllocNode:Sid=%s:%u TimeLimit=", + sprintf ( tmp2, "AllocNode:Sid=%s:%u TimeLimit=", job_ptr->alloc_node, job_ptr->alloc_sid); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (job_ptr->time_limit == INFINITE) - fprintf ( out, "UNLIMITED"); + sprintf ( tmp2, "UNLIMITED"); else if (job_ptr->time_limit == NO_VAL) - fprintf ( out, "Partition_Limit"); + sprintf ( tmp2, "Partition_Limit"); else - fprintf ( out, "%u", job_ptr->time_limit); + sprintf ( tmp2, "%u", job_ptr->time_limit); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + /****** Line 5 ******/ slurm_make_time_str ((time_t *)&job_ptr->start_time, time_str, sizeof(time_str)); - fprintf ( out, "JobState=%s StartTime=%s EndTime=", + sprintf ( tmp2, "JobState=%s StartTime=%s EndTime=", job_state_string(job_ptr->job_state), time_str); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if ((job_ptr->time_limit == INFINITE) && (job_ptr->end_time > time(NULL))) - fprintf ( out, "NONE"); + sprintf ( tmp2, "NONE"); else { slurm_make_time_str ((time_t *)&job_ptr->end_time, time_str, sizeof(time_str)); - fprintf ( out, "%s", time_str); + sprintf ( tmp2, "%s", time_str); } + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 6 ******/ - fprintf ( out, "%s=%s", nodelist, job_ptr->nodes); + sprintf ( tmp2, "%s=%s", nodelist, job_ptr->nodes); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if(job_ptr->nodes) { if(quarter != (uint16_t) NO_VAL) { if(nodecard != (uint16_t) NO_VAL) - fprintf( out, ".%d.%d", quarter, nodecard); + sprintf ( tmp2, ".%d.%d", quarter, nodecard); else - fprintf( out, ".%d", quarter); + sprintf ( tmp2, ".%d", quarter); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; } } - fprintf ( out, " "); - - fprintf ( out, "%sIndices=", nodelist); + + sprintf ( tmp2, " %sIndices=", nodelist); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + for (j = 0; job_ptr->node_inx; j++) { if (j > 0) - fprintf( out, ",%d", job_ptr->node_inx[j]); + sprintf ( tmp2, ",%d", job_ptr->node_inx[j]); else - fprintf( out, "%d", job_ptr->node_inx[j]); + sprintf ( tmp2, "%d", job_ptr->node_inx[j]); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (job_ptr->node_inx[j] == -1) break; } if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 7 ******/ convert_to_kilo(job_ptr->num_procs, tmp1); - convert_to_kilo(job_ptr->num_nodes, tmp2); + convert_to_kilo(job_ptr->num_nodes, tmp3); #ifdef HAVE_BG - fprintf ( out, "ReqProcs=%s MinBPs=%s ", tmp1, tmp2); + sprintf ( tmp2, "ReqProcs=%s MinBPs=%s ", tmp1, tmp3); #else - fprintf ( out, "ReqProcs=%s MinNodes=%s ", tmp1, tmp2); + sprintf ( tmp2, "ReqProcs=%s MinNodes=%s ", tmp1, tmp3); #endif + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + convert_to_kilo(job_ptr->shared, tmp1); - convert_to_kilo(job_ptr->contiguous, tmp2); - fprintf ( out, "Shared=%s Contiguous=%s ", tmp1, tmp2); - + convert_to_kilo(job_ptr->contiguous, tmp3); + sprintf ( tmp2, "Shared=%s Contiguous=%s ", tmp1, tmp3); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + convert_to_kilo(job_ptr->cpus_per_task, tmp1); - fprintf ( out, "CPUs/task=%s", tmp1); + sprintf ( tmp2, "CPUs/task=%s", tmp1); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 8 ******/ convert_to_kilo(job_ptr->min_procs, tmp1); - convert_to_kilo(job_ptr->min_memory, tmp2); - fprintf ( out, "MinProcs=%s MinMemory=%s ", tmp1, tmp2); + convert_to_kilo(job_ptr->min_memory, tmp3); + sprintf ( tmp2, "MinProcs=%s MinMemory=%s ", tmp1, tmp3); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; convert_to_kilo(job_ptr->min_tmp_disk, tmp1); - fprintf ( out, "Features=%s MinTmpDisk=%s", job_ptr->features, tmp1); + sprintf ( tmp2, "Features=%s MinTmpDisk=%s", job_ptr->features, tmp1); if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 9 ******/ - fprintf ( out, "Dependency=%u Account=%s Reason=%s Network=%s", + sprintf ( tmp2, "Dependency=%u Account=%s Reason=%s Network=%s", job_ptr->dependency, job_ptr->account, job_reason_string(job_ptr->wait_reason), job_ptr->network); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 10 ******/ - fprintf ( out, "Req%s=%s ", nodelist, job_ptr->req_nodes); - fprintf ( out, "Req%sIndices=", nodelist); + sprintf ( tmp2, "Req%s=%s ", nodelist, job_ptr->req_nodes); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + sprintf ( tmp2, "Req%sIndices=", nodelist); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + for (j = 0; job_ptr->req_node_inx; j++) { if (j > 0) - fprintf( out, ",%d", job_ptr->req_node_inx[j]); + sprintf ( tmp2, ",%d", job_ptr->req_node_inx[j]); else - fprintf( out, "%d", job_ptr->req_node_inx[j]); + sprintf ( tmp2, "%d", job_ptr->req_node_inx[j]); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (job_ptr->req_node_inx[j] == -1) break; } if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 11 ******/ - fprintf ( out, "Exc%s=%s ", nodelist, job_ptr->exc_nodes); - fprintf ( out, "Exc%sIndices=", nodelist); + sprintf ( tmp2, "Exc%s=%s ", nodelist, job_ptr->exc_nodes); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + sprintf ( tmp2, "Exc%sIndices=", nodelist); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + for (j = 0; job_ptr->exc_node_inx; j++) { if (j > 0) - fprintf( out, ",%d", job_ptr->exc_node_inx[j]); + sprintf ( tmp2, ",%d", job_ptr->exc_node_inx[j]); else - fprintf( out, "%d", job_ptr->exc_node_inx[j]); + sprintf ( tmp2, "%d", job_ptr->exc_node_inx[j]); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (job_ptr->exc_node_inx[j] == -1) break; } if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 12 ******/ slurm_make_time_str ((time_t *)&job_ptr->submit_time, time_str, sizeof(time_str)); - fprintf ( out, "SubmitTime=%s ", time_str); + sprintf ( tmp2, "SubmitTime=%s ", time_str); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (job_ptr->suspend_time) { slurm_make_time_str ((time_t *)&job_ptr->suspend_time, time_str, sizeof(time_str)); } else { strncpy(time_str, "None", sizeof(time_str)); } - fprintf ( out, "SuspendTime=%s PreSusTime=%ld", + sprintf ( tmp2, "SuspendTime=%s PreSusTime=%ld", time_str, (long int)job_ptr->pre_sus_time); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; /****** Line 13 (optional) ******/ select_g_sprint_jobinfo(job_ptr->select_jobinfo, select_buf, sizeof(select_buf), SELECT_PRINT_MIXED); if (select_buf[0] != '\0') { if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); - fprintf( out, "%s", select_buf); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + sprintf ( tmp2, "%s", select_buf); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; } - fprintf( out, "\n\n"); -} + sprintf ( tmp2, "\n\n"); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + return out; +} /* * slurm_load_jobs - issue RPC to get slurm all job configuration * information if changed since update_time diff --git a/src/api/job_step_info.c b/src/api/job_step_info.c index 021ea287669..535f4b4aed7 100644 --- a/src/api/job_step_info.c +++ b/src/api/job_step_info.c @@ -39,7 +39,9 @@ #include "src/api/job_info.h" #include "src/common/parse_time.h" #include "src/common/slurm_protocol_api.h" +#include "src/common/xmalloc.h" +#define HUGE_BUF 4096 /* * slurm_print_job_step_info_msg - output information about all Slurm * job steps based upon message as loaded using slurm_get_job_steps @@ -78,24 +80,75 @@ slurm_print_job_step_info_msg ( FILE* out, void slurm_print_job_step_info ( FILE* out, job_step_info_t * job_step_ptr, int one_liner ) +{ + char *print_this = slurm_sprint_job_step_info(job_step_ptr, one_liner); + fprintf ( out, "%s", print_this); + xfree(print_this); +} + +/* + * slurm_sprint_job_step_info - output information about a specific Slurm + * job step based upon message as loaded using slurm_get_job_steps + * IN job_ptr - an individual job step information record pointer + * IN one_liner - print as a single line if true + * RET out - char * containing formatted output (must be freed after call) + * NULL is returned on failure. + */ +char * +slurm_sprint_job_step_info ( job_step_info_t * job_step_ptr, + int one_liner ) { char time_str[32]; + int j; + char tmp2[100]; + char *out = xmalloc(HUGE_BUF); + int len = 0; + int lentmp2 = 0; + int tmplen = 0; /****** Line 1 ******/ slurm_make_time_str ((time_t *)&job_step_ptr->start_time, time_str, sizeof(time_str)); - fprintf ( out, "StepId=%u.%u UserId=%u Tasks=%u StartTime=%s", + sprintf ( tmp2, "StepId=%u.%u UserId=%u Tasks=%u StartTime=%s", job_step_ptr->job_id, job_step_ptr->step_id, job_step_ptr->user_id, job_step_ptr->num_tasks, time_str); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + /****** Line 2 ******/ - fprintf ( out, "Partition=%s Nodes=%s Name=%s Network=%s\n\n", + sprintf ( tmp2, "Partition=%s Nodes=%s Name=%s Network=%s\n\n", job_step_ptr->partition, job_step_ptr->nodes, job_step_ptr->name, job_step_ptr->network); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + return out; } /* diff --git a/src/api/node_info.c b/src/api/node_info.c index a176affcc80..b00946ede1a 100644 --- a/src/api/node_info.c +++ b/src/api/node_info.c @@ -42,7 +42,9 @@ #include "src/common/parse_time.h" #include "src/common/slurm_protocol_api.h" +#include "src/common/xmalloc.h" +#define HUGE_BUF 4096 /* * slurm_print_node_info_msg - output information about all Slurm nodes * based upon message as loaded using slurm_load_node @@ -78,9 +80,31 @@ slurm_print_node_info_msg ( FILE * out, node_info_msg_t * node_info_msg_ptr, */ void slurm_print_node_table ( FILE * out, node_info_t * node_ptr, int one_liner ) +{ + char *print_this = slurm_sprint_node_table(node_ptr, one_liner); + fprintf ( out, "%s", print_this); + xfree(print_this); +} + +/* + * slurm_sprint_node_table - output information about a specific Slurm nodes + * based upon message as loaded using slurm_load_node + * IN node_ptr - an individual node information record pointer + * IN one_liner - print as a single line if true + * RET out - char * containing formatted output (must be freed after call) + * NULL is returned on failure. + */ +char * +slurm_sprint_node_table (node_info_t * node_ptr, int one_liner ) { uint16_t my_state = node_ptr->node_state; char *comp_str = "", *drain_str = ""; + char tmp2[100]; + char *out = xmalloc(HUGE_BUF); + int len = 0; + int lentmp2 = 0; + int tmplen = 0; + int j; if (my_state & NODE_STATE_COMPLETING) { my_state &= (~NODE_STATE_COMPLETING); @@ -92,21 +116,76 @@ slurm_print_node_table ( FILE * out, node_info_t * node_ptr, int one_liner ) } /****** Line 1 ******/ - fprintf ( out, "NodeName=%s State=%s%s%s CPUs=%u ", + sprintf ( tmp2, "NodeName=%s State=%s%s%s CPUs=%u ", node_ptr->name, node_state_string(my_state), comp_str, drain_str, node_ptr->cpus); - fprintf ( out, "RealMemory=%u TmpDisk=%u", + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out, "%s", tmp2); + len += lentmp2; + + sprintf ( tmp2, "RealMemory=%u TmpDisk=%u", node_ptr->real_memory, node_ptr->tmp_disk); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + /****** Line 2 ******/ - fprintf ( out, "Weight=%u Features=%s " , + sprintf ( tmp2, "Weight=%u Features=%s " , node_ptr->weight, node_ptr->features); - fprintf ( out, "Reason=%s", node_ptr->reason); - fprintf ( out, "\n"); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + sprintf ( tmp2, "Reason=%s", node_ptr->reason); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + sprintf ( tmp2, "\n"); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + return out; } diff --git a/src/api/partition_info.c b/src/api/partition_info.c index 132644dcfd1..ca99932f06d 100644 --- a/src/api/partition_info.c +++ b/src/api/partition_info.c @@ -38,6 +38,9 @@ #include "src/api/job_info.h" #include "src/common/parse_time.h" #include "src/common/slurm_protocol_api.h" +#include "src/common/xmalloc.h" + +#define HUGE_BUF 4096 /* * slurm_print_partition_info_msg - output information about all Slurm @@ -73,89 +76,267 @@ void slurm_print_partition_info_msg ( FILE* out, */ void slurm_print_partition_info ( FILE* out, partition_info_t * part_ptr, int one_liner ) +{ + char *print_this = slurm_sprint_partition_info(part_ptr, one_liner); + fprintf ( out, "%s", print_this); + xfree(print_this); +} + + +/* + * slurm_sprint_partition_info - output information about a specific Slurm + * partition based upon message as loaded using slurm_load_partitions + * IN part_ptr - an individual partition information record pointer + * IN one_liner - print as a single line if true + * RET out - char * containing formatted output (must be freed after call) + * NULL is returned on failure. + */ +char *slurm_sprint_partition_info ( partition_info_t * part_ptr, + int one_liner ) { int j; char tmp1[7]; - + char tmp2[100]; + int len = 0; + int lentmp2 = 0; + int tmplen = 0; + char *out = xmalloc(HUGE_BUF); /****** Line 1 ******/ - fprintf ( out, "PartitionName=%s ", part_ptr->name); + sprintf ( tmp2, "PartitionName=%s ", part_ptr->name); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out, "%s", tmp2); + len += lentmp2; convert_to_kilo(part_ptr->total_nodes, tmp1); - fprintf ( out, "TotalNodes=%s ", tmp1); - + sprintf ( tmp2, "TotalNodes=%s ", tmp1); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + convert_to_kilo(part_ptr->total_cpus, tmp1); - fprintf ( out, "TotalCPUs=%s ", tmp1); + sprintf ( tmp2, "TotalCPUs=%s ", tmp1); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (part_ptr->root_only) - fprintf ( out, "RootOnly=YES"); + sprintf ( tmp2, "RootOnly=YES"); else - fprintf ( out, "RootOnly=NO"); + sprintf ( tmp2, "RootOnly=NO"); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); - + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + /****** Line 2 ******/ if (part_ptr->default_part) - fprintf ( out, "Default=YES "); + sprintf ( tmp2, "Default=YES "); else - fprintf ( out, "Default=NO "); + sprintf ( tmp2, "Default=NO "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (part_ptr->shared == SHARED_NO) - fprintf ( out, "Shared=NO "); + sprintf ( tmp2, "Shared=NO "); else if (part_ptr->shared == SHARED_YES) - fprintf ( out, "Shared=YES "); + sprintf ( tmp2, "Shared=YES "); else - fprintf ( out, "Shared=FORCE "); + sprintf ( tmp2, "Shared=FORCE "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (part_ptr->state_up) - fprintf ( out, "State=UP "); + sprintf ( tmp2, "State=UP "); else - fprintf ( out, "State=DOWN "); + sprintf ( tmp2, "State=DOWN "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (part_ptr->max_time == INFINITE) - fprintf ( out, "MaxTime=UNLIMITED "); + sprintf ( tmp2, "MaxTime=UNLIMITED "); else - fprintf ( out, "MaxTime=%u ", part_ptr->max_time); + sprintf ( tmp2, "MaxTime=%u ", part_ptr->max_time); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (part_ptr->hidden) - fprintf ( out, "Hidden=YES"); + sprintf ( tmp2, "Hidden=YES"); else - fprintf ( out, "Hidden=NO"); + sprintf ( tmp2, "Hidden=NO"); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); - + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + /****** Line 3 ******/ convert_to_kilo(part_ptr->min_nodes, tmp1); - fprintf ( out, "MinNodes=%s ", tmp1); + sprintf ( tmp2, "MinNodes=%s ", tmp1); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (part_ptr->max_nodes == INFINITE) - fprintf ( out, "MaxNodes=UNLIMITED "); + sprintf ( tmp2, "MaxNodes=UNLIMITED "); else { convert_to_kilo(part_ptr->max_nodes, tmp1); - fprintf ( out, "MaxNodes=%s ", tmp1); + sprintf ( tmp2, "MaxNodes=%s ", tmp1); } + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if ((part_ptr->allow_groups == NULL) || (part_ptr->allow_groups[0] == '\0')) - fprintf ( out, "AllowGroups=ALL"); + sprintf ( tmp2, "AllowGroups=ALL"); else - fprintf ( out, "AllowGroups=%s", part_ptr->allow_groups); + sprintf ( tmp2, "AllowGroups=%s", part_ptr->allow_groups); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + if (one_liner) - fprintf ( out, " "); + sprintf ( tmp2, " "); else - fprintf ( out, "\n "); - + sprintf ( tmp2, "\n "); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + + /****** Line 4 ******/ #ifdef HAVE_BG - fprintf ( out, "BasePartitions=%s BPIndices=", part_ptr->nodes); + sprintf ( tmp2, "BasePartitions=%s BPIndices=", part_ptr->nodes); #else - fprintf ( out, "Nodes=%s NodeIndices=", part_ptr->nodes); + sprintf ( tmp2, "Nodes=%s NodeIndices=", part_ptr->nodes); #endif + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; + for (j = 0; part_ptr->node_inx; j++) { if (j > 0) - fprintf( out, ",%d", part_ptr->node_inx[j]); + sprintf( tmp2, ",%d", part_ptr->node_inx[j]); else - fprintf( out, "%d", part_ptr->node_inx[j]); + sprintf( tmp2, "%d", part_ptr->node_inx[j]); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + len += lentmp2; if (part_ptr->node_inx[j] == -1) break; } - fprintf( out, "\n\n"); + sprintf( tmp2, "\n\n"); + lentmp2 = strlen(tmp2); + tmplen += lentmp2; + if(tmplen>HUGE_BUF) { + j = len + HUGE_BUF; + xrealloc(out, j); + } + sprintf ( out+len, "%s", tmp2); + + return out; } diff --git a/src/common/node_select.c b/src/common/node_select.c index b5a1e84e9f2..ddc25757323 100644 --- a/src/common/node_select.c +++ b/src/common/node_select.c @@ -938,7 +938,7 @@ extern char *select_g_sprint_jobinfo(select_jobinfo_t jobinfo, start_char, jobinfo->bg_block_id); break; case SELECT_PRINT_BG_ID: - return jobinfo->bg_block_id; + snprintf(buf, size, "%s", jobinfo->bg_block_id); break; default: error("select_g_sprint_jobinfo: bad mode %d", mode); diff --git a/src/common/slurm_protocol_api.c b/src/common/slurm_protocol_api.c index 00831a51c03..b5f61db365a 100644 --- a/src/common/slurm_protocol_api.c +++ b/src/common/slurm_protocol_api.c @@ -1927,6 +1927,20 @@ extern char *nodelist_nth_host(const char *nodelist, int inx) return name; } +void convert_num_unit(float num, char *buf, int orig_type) +{ + char *unit = "\0KMGP?"; + + while(num>1024) { + num /= 1024; + orig_type++; + } + + if(orig_type < UNIT_NONE || orig_type > UNIT_PETA) + orig_type = UNIT_UNKNOWN; + sprintf(buf, "%.2f%c", num, unit[orig_type]); +} + #if _DEBUG static void _print_data(char *data, int len) diff --git a/src/common/slurm_protocol_api.h b/src/common/slurm_protocol_api.h index c6cff59082b..afc3bdbfbeb 100644 --- a/src/common/slurm_protocol_api.h +++ b/src/common/slurm_protocol_api.h @@ -59,6 +59,16 @@ enum controller_id { SECONDARY_CONTROLLER = 2 }; +/* unit types */ +enum { + UNIT_NONE, + UNIT_KILO, + UNIT_MEGA, + UNIT_GIGA, + UNIT_PETA, + UNIT_UNKNOWN +}; + /**********************************************************************\ * protocol configuration functions \**********************************************************************/ @@ -623,4 +633,5 @@ extern int convert_to_kilo(int number, char *tmp); /* must free this memory with free not xfree */ extern char *nodelist_nth_host(const char *nodelist, int inx); +void convert_num_unit(float num, char *buf, int orig_type); #endif diff --git a/src/sacct/print.c b/src/sacct/print.c index 81ff18db2db..abc44333765 100644 --- a/src/sacct/print.c +++ b/src/sacct/print.c @@ -221,7 +221,7 @@ void print_idrss(type_t type, void *object) rusage = step->rusage; break; } - convert_num((float)rusage.ru_idrss, outbuf); + convert_num_unit((float)rusage.ru_idrss, outbuf, UNIT_NONE); printf("%8s", outbuf); } @@ -709,11 +709,13 @@ void print_pages(type_t type, void *object) sacct = job->sacct; nodes = job->nodes; pos = sacct.min_cpu_id.nodeid; - convert_num((float)sacct.max_pages, buf1); + convert_num_unit((float)sacct.max_pages, buf1, UNIT_NONE); + if(job->track_steps) snprintf(outbuf, FORMAT_STRING_SIZE, "%s/- - -", buf1); else { - convert_num((float)sacct.ave_pages, buf2); + convert_num_unit((float)sacct.ave_pages, + buf2, UNIT_NONE); find_hostname(pos, nodes, buf3); snprintf(outbuf, FORMAT_STRING_SIZE, "%s/%s:%u - %s", buf1, @@ -727,8 +729,8 @@ void print_pages(type_t type, void *object) sacct = step->sacct; nodes = step->nodes; pos = sacct.min_cpu_id.nodeid; - convert_num((float)sacct.max_pages, buf1); - convert_num((float)sacct.ave_pages, buf2); + convert_num_unit((float)sacct.max_pages, buf1, UNIT_NONE); + convert_num_unit((float)sacct.ave_pages, buf2, UNIT_NONE); find_hostname(pos, nodes, buf3); snprintf(outbuf, FORMAT_STRING_SIZE, "%s/%s:%u - %s", buf1, @@ -763,11 +765,13 @@ void print_rss(type_t type, void *object) sacct = job->sacct; nodes = job->nodes; pos = sacct.min_cpu_id.nodeid; - convert_num((float)sacct.max_rss, buf1); + convert_num_unit((float)sacct.max_rss, buf1, UNIT_NONE); + if(job->track_steps) snprintf(outbuf, FORMAT_STRING_SIZE, "%s/- - -", buf1); else { - convert_num((float)sacct.ave_rss, buf2); + convert_num_unit((float)sacct.ave_rss, + buf2, UNIT_NONE); find_hostname(pos, nodes, buf3); snprintf(outbuf, FORMAT_STRING_SIZE, "%s/%s:%u - %s", buf1, @@ -781,8 +785,8 @@ void print_rss(type_t type, void *object) sacct = step->sacct; nodes = step->nodes; pos = sacct.min_cpu_id.nodeid; - convert_num((float)sacct.max_rss, buf1); - convert_num((float)sacct.ave_rss, buf2); + convert_num_unit((float)sacct.max_rss, buf1, UNIT_NONE); + convert_num_unit((float)sacct.ave_rss, buf2, UNIT_NONE); find_hostname(pos, nodes, buf3); snprintf(outbuf, FORMAT_STRING_SIZE, "%s/%s:%u - %s", buf1, @@ -1026,11 +1030,12 @@ void print_vsize(type_t type, void *object) sacct = job->sacct; nodes = job->nodes; pos = sacct.min_cpu_id.nodeid; - convert_num((float)sacct.max_vsize, buf1); + convert_num_unit((float)sacct.max_vsize, buf1, UNIT_NONE); if(job->track_steps) snprintf(outbuf, FORMAT_STRING_SIZE, "%s/- - -", buf1); else { - convert_num((float)sacct.ave_vsize, buf2); + convert_num_unit((float)sacct.ave_vsize, + buf2, UNIT_NONE); find_hostname(pos, nodes, buf3); snprintf(outbuf, FORMAT_STRING_SIZE, "%s/%s:%u - %s", buf1, @@ -1044,8 +1049,8 @@ void print_vsize(type_t type, void *object) sacct = step->sacct; nodes = step->nodes; pos = sacct.min_cpu_id.nodeid; - convert_num((float)sacct.max_vsize, buf1); - convert_num((float)sacct.ave_vsize, buf2); + convert_num_unit((float)sacct.max_vsize, buf1, UNIT_NONE); + convert_num_unit((float)sacct.ave_vsize, buf2, UNIT_NONE); find_hostname(pos, nodes, buf3); snprintf(outbuf, FORMAT_STRING_SIZE, "%s/%s:%u - %s", buf1, diff --git a/src/sacct/process.c b/src/sacct/process.c index 462959ae22f..783639d0bbc 100644 --- a/src/sacct/process.c +++ b/src/sacct/process.c @@ -517,22 +517,6 @@ finished: destroy_job(temp); } -void convert_num(float num, char *buf) -{ - char *unit = "\0KMGP"; - int count = 0; - if(num == (float)NO_VAL) { - snprintf(buf, 20, "'N/A'"); - return; - } - - while(num>1024) { - num /= 1024; - count++; - } - snprintf(buf, 20, "%.2f%c", num, unit[count]); -} - void find_hostname(uint32_t pos, char *hosts, char *host) { hostlist_t hostlist = NULL; diff --git a/src/sacct/sacct.h b/src/sacct/sacct.h index 68a12bef8bc..0a141cf2341 100644 --- a/src/sacct/sacct.h +++ b/src/sacct/sacct.h @@ -274,7 +274,6 @@ void process_start(char *f[], int lc, int show_full, int len); void process_step(char *f[], int lc, int show_full, int len); void process_suspend(char *f[], int lc, int show_full, int len); void process_terminated(char *f[], int lc, int show_full, int len); -void convert_num(float num, char *buf); void find_hostname(uint32_t pos, char *hosts, char *host); void aggregate_sacct(sacct_t *dest, sacct_t *from); void destroy_acct_header(void *object); diff --git a/src/sview/Makefile.am b/src/sview/Makefile.am new file mode 100644 index 00000000000..abd5a84317c --- /dev/null +++ b/src/sview/Makefile.am @@ -0,0 +1,33 @@ +# $Id: Makefile.am 6669 2005-11-21 22:41:16Z da $ +# +# Makefile for sview + +AUTOMAKE_OPTIONS = foreign +INCLUDES = -I$(top_srcdir) $(BG_INCLUDES) + +if HAVE_GTK + +bin_PROGRAMS = sview + +sview_LDADD = \ + $(top_builddir)/src/plugins/select/bluegene/block_allocator/libbluegene_block_allocator.la + +noinst_HEADERS = sview.h +sview_SOURCES = sview.c part_info.c job_info.c \ + block_info.c node_info.c \ + submit_info.c admin_info.c common.c + +force: +$(sview_LDADD) : force + @cd `dirname $@` && $(MAKE) `basename $@` + +sview_LDFLAGS = -export-dynamic $(CMD_LDFLAGS) $(BG_LDFLAGS) $(GTK2_LIBS) +sview_CFLAGS = $(GTK2_CFLAGS) + +else + +EXTRA_sview_SOURCES = sview.h sview.c part_info.c job_info.c \ + block_info.c node_info.c \ + submit_info.c admin_info.c common.c + +endif diff --git a/src/sview/admin_info.c b/src/sview/admin_info.c new file mode 100644 index 00000000000..63804392225 --- /dev/null +++ b/src/sview/admin_info.c @@ -0,0 +1,128 @@ +/*****************************************************************************\ + * admin_info.c - Functions related to admin 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-217948. + * + * 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" + +#define _DEBUG 0 +DEF_TIMERS; + +enum { + SORTID_POS = POS_LOC, + SORTID_PARTITION, + SORTID_AVAIL, + SORTID_TIMELIMIT, + SORTID_NODES, + SORTID_NODELIST, + SORTID_PARTITION_CNT +}; + +static display_data_t display_data_admin[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1}, + {G_TYPE_STRING, SORTID_PARTITION, "PARTITION", TRUE, -1}, + {G_TYPE_STRING, SORTID_AVAIL, "AVAIL", TRUE, -1}, + {G_TYPE_STRING, SORTID_TIMELIMIT, "TIMELIMIT", TRUE, -1}, + {G_TYPE_STRING, SORTID_NODES, "NODES", TRUE, -1}, +#ifdef HAVE_BG + {G_TYPE_STRING, SORTID_NODELIST, "BP_LIST", TRUE, -1}, +#else + {G_TYPE_STRING, SORTID_NODELIST, "NODELIST", TRUE, -1}, +#endif + {G_TYPE_NONE, -1, NULL, FALSE, -1}}; + +static display_data_t options_data_admin[] = { + {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, -1}, + {G_TYPE_STRING, NODE_PAGE, "Nodes", TRUE, -1}, + {G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", TRUE, -1}, + {G_TYPE_STRING, ADMIN_PAGE, "Admin", TRUE, -1}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t *local_display_data = NULL; + + +extern void get_info_admin(GtkTable *table, display_data_t *display_data) +{ + local_display_data = display_data; +} + + +extern void set_menus_admin(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_admin); + break; + case ROW_CLICKED: + make_options_menu(tree_view, path, menu, options_data_admin); + 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 row_clicked_admin(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + /* job_info_msg_t *job_info_ptr = (job_info_msg_t *)user_data; */ +/* job_info_t *job_ptr = NULL; */ + int line = get_row_number(tree_view, path); + GtkWidget *popup = NULL; + GtkWidget *label = NULL; + char *info = NULL; + if(line == -1) { + g_error("problem getting line number"); + return; + } + +/* part_ptr = &new_part_ptr->partition_array[line]; */ + /* if(!(info = slurm_sprint_partition_info(part_ptr, 0))) { */ +/* info = xmalloc(100); */ +/* sprintf(info, "Problem getting partition info for %s", */ +/* part_ptr->name); */ +/* } */ + + popup = gtk_dialog_new(); + + label = gtk_label_new(info); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(popup)->vbox), + label, TRUE, TRUE, 0); + xfree(info); + gtk_widget_show(label); + + gtk_widget_show(popup); + +} + diff --git a/src/sview/block_info.c b/src/sview/block_info.c new file mode 100644 index 00000000000..1ba97c27d62 --- /dev/null +++ b/src/sview/block_info.c @@ -0,0 +1,1014 @@ +/*****************************************************************************\ + * 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-217948. + * + * 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/node_select.h" +#include "src/api/node_select_info.h" + +#define _DEBUG 0 +DEF_TIMERS; + +typedef struct { + char *bg_user_name; + char *bg_block_name; + char *slurm_part_name; + char *nodes; + enum connection_type bg_conn_type; + enum node_use_type bg_node_use; + rm_partition_state_t state; + int letter_num; + List nodelist; + int size; + uint16_t quarter; + uint16_t nodecard; + int node_cnt; + bool printed; + +} db2_block_info_t; + +enum { + SORTID_POS = POS_LOC, + SORTID_PARTITION, + SORTID_BLOCK, + SORTID_STATE, + SORTID_USER, + SORTID_CONN, + SORTID_USE, + SORTID_NODES, + SORTID_NODELIST, + SORTID_UPDATED, + SORTID_CNT +}; + +static display_data_t display_data_block[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1, refresh_block}, + {G_TYPE_STRING, SORTID_PARTITION, "Partition", + TRUE, -1, refresh_block}, + {G_TYPE_STRING, SORTID_BLOCK, "Bluegene Block", + TRUE, -1, refresh_block}, + {G_TYPE_STRING, SORTID_STATE, "State", TRUE, -1, refresh_block}, + {G_TYPE_STRING, SORTID_USER, "User", TRUE, -1, refresh_block}, + {G_TYPE_STRING, SORTID_CONN, "Connection Type", + TRUE, -1, refresh_block}, + {G_TYPE_STRING, SORTID_USE, "Node Use", TRUE, -1, refresh_block}, + {G_TYPE_STRING, SORTID_NODES, "Nodes", TRUE, -1, refresh_block}, + {G_TYPE_STRING, SORTID_NODELIST, "BP List", TRUE, -1, refresh_block}, + {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, -1, refresh_block}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t options_data_block[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1}, + {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, BLOCK_PAGE}, + {G_TYPE_STRING, PART_PAGE, "Partition", TRUE, BLOCK_PAGE}, + {G_TYPE_STRING, NODE_PAGE, "Base Partitions", TRUE, BLOCK_PAGE}, + {G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", TRUE, BLOCK_PAGE}, + {G_TYPE_STRING, ADMIN_PAGE, "Admin", TRUE, BLOCK_PAGE}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t *local_display_data = NULL; + +static char* _convert_conn_type(enum connection_type conn_type); +static char* _convert_node_use(enum node_use_type node_use); +static int _marknodes(db2_block_info_t *block_ptr, int count); +static char *_part_state_str(rm_partition_state_t state); +static void _block_list_del(void *object); +static void _nodelist_del(void *object); +static int _in_slurm_partition(List slurm_nodes, List bg_nodes); +static int _make_nodelist(char *nodes, List nodelist); +static void _append_block_record(db2_block_info_t *block_ptr, + GtkTreeStore *treestore, GtkTreeIter *iter, + int line); + + +static int _marknodes(db2_block_info_t *block_ptr, int count) +{ +#ifdef HAVE_BG + int j=0; + int start[BA_SYSTEM_DIMENSIONS]; + int end[BA_SYSTEM_DIMENSIONS]; + int number = 0; + + block_ptr->letter_num = count; + while (block_ptr->nodes[j] != '\0') { + if ((block_ptr->nodes[j] == '[' + || block_ptr->nodes[j] == ',') + && (block_ptr->nodes[j+8] == ']' + || block_ptr->nodes[j+8] == ',') + && (block_ptr->nodes[j+4] == 'x' + || block_ptr->nodes[j+4] == '-')) { + j++; + number = atoi(block_ptr->nodes + j); + start[X] = number / 100; + start[Y] = (number % 100) / 10; + start[Z] = (number % 10); + j += 4; + number = atoi(block_ptr->nodes + j); + end[X] = number / 100; + end[Y] = (number % 100) / 10; + end[Z] = (number % 10); + j += 3; + + /* if(block_ptr->state != RM_PARTITION_FREE) */ +/* block_ptr->size += set_grid_bg(start, */ +/* end, */ +/* count, */ +/* 1); */ +/* else */ +/* block_ptr->size += set_grid_bg(start, */ +/* end, */ +/* count, */ +/* 0); */ + if(block_ptr->nodes[j] != ',') + break; + j--; + } else if((block_ptr->nodes[j] < 58 + && block_ptr->nodes[j] > 47)) { + + number = atoi(block_ptr->nodes + j); + start[X] = number / 100; + start[Y] = (number % 100) / 10; + start[Z] = (number % 10); + j+=3; + /* block_ptr->size += set_grid_bg(start, */ +/* start, */ +/* count, */ +/* 0); */ + if(block_ptr->nodes[j] != ',') + break; + } + j++; + } +#endif + return SLURM_SUCCESS; +} + +static char *_part_state_str(rm_partition_state_t state) +{ + static char tmp[16]; + +#ifdef HAVE_BG + switch (state) { + case RM_PARTITION_BUSY: + return "BUSY"; + case RM_PARTITION_CONFIGURING: + return "CONFIG"; + case RM_PARTITION_DEALLOCATING: + return "DEALLOC"; + case RM_PARTITION_ERROR: + return "ERROR"; + case RM_PARTITION_FREE: + return "FREE"; + case RM_PARTITION_NAV: + return "NAV"; + case RM_PARTITION_READY: + return "READY"; + } +#endif + + snprintf(tmp, sizeof(tmp), "%d", state); + return tmp; +} + +static void _block_list_del(void *object) +{ + db2_block_info_t *block_ptr = (db2_block_info_t *)object; + + if (block_ptr) { + xfree(block_ptr->bg_user_name); + xfree(block_ptr->bg_block_name); + xfree(block_ptr->slurm_part_name); + xfree(block_ptr->nodes); + if(block_ptr->nodelist) + list_destroy(block_ptr->nodelist); + + xfree(block_ptr); + + } +} + +static void _nodelist_del(void *object) +{ + int *coord = (int *)object; + xfree(coord); + return; +} + +static int _in_slurm_partition(List slurm_nodes, List bg_nodes) +{ + ListIterator slurm_itr; + ListIterator bg_itr; + int *coord = NULL; + int *slurm_coord = NULL; + int found = 0; + + bg_itr = list_iterator_create(bg_nodes); + slurm_itr = list_iterator_create(slurm_nodes); + while ((coord = list_next(bg_itr)) != NULL) { + list_iterator_reset(slurm_itr); + found = 0; + while ((slurm_coord = list_next(slurm_itr)) != NULL) { + if((coord[X] == slurm_coord[X]) + && (coord[Y] == slurm_coord[Y]) + && (coord[Z] == slurm_coord[Z])) { + found=1; + break; + } + } + if(!found) { + break; + } + } + list_iterator_destroy(slurm_itr); + list_iterator_destroy(bg_itr); + + if(found) + return 1; + else + return 0; + +} + +static int _addto_nodelist(List nodelist, int *start, int *end) +{ + int *coord = NULL; + int x,y,z; + +// assert(end[X] < DIM_SIZE[X]); + assert(start[X] >= 0); + //assert(end[Y] < DIM_SIZE[Y]); + assert(start[Y] >= 0); + //assert(end[Z] < DIM_SIZE[Z]); + assert(start[Z] >= 0); + + for (x = start[X]; x <= end[X]; x++) { + for (y = start[Y]; y <= end[Y]; y++) { + for (z = start[Z]; z <= end[Z]; z++) { + coord = xmalloc(sizeof(int)*3); + coord[X] = x; + coord[Y] = y; + coord[Z] = z; + list_append(nodelist, coord); + } + } + } + return 1; +} + +static int _make_nodelist(char *nodes, List nodelist) +{ + int j = 0; + int number; + int start[BA_SYSTEM_DIMENSIONS]; + int end[BA_SYSTEM_DIMENSIONS]; + + if(!nodelist) + nodelist = list_create(_nodelist_del); + while (nodes[j] != '\0') { + if ((nodes[j] == '[' + || nodes[j] == ',') + && (nodes[j+8] == ']' + || nodes[j+8] == ',') + && (nodes[j+4] == 'x' + || nodes[j+4] == '-')) { + j++; + number = atoi(nodes + j); + start[X] = number / 100; + start[Y] = (number % 100) / 10; + start[Z] = (number % 10); + j += 4; + number = atoi(nodes + j); + end[X] = number / 100; + end[Y] = (number % 100) / 10; + end[Z] = (number % 10); + j += 3; + _addto_nodelist(nodelist, start, end); + if(nodes[j] != ',') + break; + j--; + } else if((nodes[j] < 58 + && nodes[j] > 47)) { + + number = atoi(nodes + j); + start[X] = number / 100; + start[Y] = (number % 100) / 10; + start[Z] = (number % 10); + j+=3; + _addto_nodelist(nodelist, start, start); + if(nodes[j] != ',') + break; + } + j++; + } + return 1; +} + +static char* _convert_conn_type(enum connection_type conn_type) +{ + switch (conn_type) { + case (SELECT_MESH): + return "MESH"; + case (SELECT_TORUS): + return "TORUS"; + case (SELECT_SMALL): + return "SMALL"; + case (SELECT_NAV): + return "NAV"; + } + return "?"; +} + +static char* _convert_node_use(enum node_use_type node_use) +{ + switch (node_use) { + case (SELECT_COPROCESSOR_MODE): + return "COPROCESSOR"; + case (SELECT_VIRTUAL_NODE_MODE): + return "VIRTUAL"; + case (SELECT_NAV_MODE): + return "NAV"; + } + return "?"; +} + +static void _update_block_record(db2_block_info_t *block_ptr, + GtkTreeStore *treestore, GtkTreeIter *iter) +{ + char *nodes = NULL; + char tmp_cnt[7]; + char tmp_nodes[30]; + + gtk_tree_store_set(treestore, iter, SORTID_BLOCK, + block_ptr->bg_block_name, -1); + gtk_tree_store_set(treestore, iter, SORTID_PARTITION, + block_ptr->slurm_part_name, -1); + gtk_tree_store_set(treestore, iter, SORTID_STATE, + _part_state_str(block_ptr->state), -1); + gtk_tree_store_set(treestore, iter, SORTID_USER, + block_ptr->bg_user_name, -1); + gtk_tree_store_set(treestore, iter, SORTID_CONN, + _convert_conn_type(block_ptr->bg_conn_type), -1); + gtk_tree_store_set(treestore, iter, SORTID_USE, + _convert_node_use(block_ptr->bg_node_use), -1); + + convert_to_kilo(block_ptr->node_cnt, tmp_cnt); + gtk_tree_store_set(treestore, iter, SORTID_NODES, tmp_cnt, -1); + + nodes = block_ptr->nodes; + if(block_ptr && (block_ptr->quarter != (uint16_t) NO_VAL)) { + if(block_ptr->nodecard != (uint16_t) NO_VAL) + sprintf(tmp_nodes, "%s.%d.%d", nodes, + block_ptr->quarter, + block_ptr->nodecard); + else + sprintf(tmp_nodes, "%s.%d", nodes, + block_ptr->quarter); + nodes = tmp_nodes; + } + gtk_tree_store_set(treestore, iter, SORTID_NODELIST, nodes, -1); + + gtk_tree_store_set(treestore, iter, SORTID_UPDATED, 1, -1); + + return; +} + +static void _append_block_record(db2_block_info_t *block_ptr, + GtkTreeStore *treestore, GtkTreeIter *iter, + int line) +{ + gtk_tree_store_append(treestore, iter, NULL); + gtk_tree_store_set(treestore, iter, SORTID_POS, line, -1); + _update_block_record(block_ptr, treestore, iter); +} + +static void _update_info_block(List block_list, + GtkTreeView *tree_view, + specific_info_t *spec_info) +{ + ListIterator itr; + db2_block_info_t *block_ptr = NULL; + GtkTreePath *path = gtk_tree_path_new_first(); + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeIter iter; + char *name = NULL; + char *host = NULL, *host2 = NULL; + hostlist_t hostlist = NULL; + int found = 0; + int line = 0; + + if (!block_list) { + g_print("No block_list given"); + return; + } + + if(spec_info) { + switch(spec_info->type) { + case NODE_PAGE: + hostlist = hostlist_create((char *)spec_info->data); + host = hostlist_shift(hostlist); + hostlist_destroy(hostlist); + if(host == NULL) { + g_print("nodelist was empty"); + return; + } + break; + } + } + + /* 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; + } + } + } + + + /* Report the BG Blocks */ + + itr = list_iterator_create(block_list); + while ((block_ptr = (db2_block_info_t*) list_next(itr))) { + if(block_ptr->node_cnt == 0) + block_ptr->node_cnt = block_ptr->size; + if(!block_ptr->slurm_part_name) + block_ptr->slurm_part_name = "no part"; + + /* 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_BLOCK, + &name, -1); + if(!strcmp(name, block_ptr->bg_block_name)) { + /* update with new info */ + g_free(name); + _update_block_record(block_ptr, + GTK_TREE_STORE(model), + &iter); + goto found; + } + g_free(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: + if(spec_info) { + switch(spec_info->type) { + case PART_PAGE: + if(strcmp(block_ptr->slurm_part_name, + (char *)spec_info->data)) + continue; + break; + case NODE_PAGE: + if(!block_ptr->nodes || !host) + continue; + + hostlist = hostlist_create(block_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 JOB_PAGE: + if(strcmp(block_ptr->bg_block_name, + (char *)spec_info->data)) + continue; + break; + default: + g_print("Unkown type %d\n", spec_info->type); + continue; + } + } + + + /* this is the letter for later + part.root_only = + (int) letters[block_ptr->letter_num%62]; + */ + _append_block_record(block_ptr, GTK_TREE_STORE(model), + &iter, line); + found: + ; + } + + list_iterator_destroy(itr); + if(host) + free(host); + + gtk_tree_path_free(path); + /* remove all old blocks */ + remove_old(model, SORTID_UPDATED); +} + +static List _create_block_list(partition_info_msg_t *part_info_ptr, + node_select_info_msg_t *node_select_ptr) +{ + int i, j, last_count = -1; + List block_list = list_create(_block_list_del); + ListIterator itr; + List nodelist = NULL; + partition_info_t part; + db2_block_info_t *block_ptr = NULL; + db2_block_info_t *found_block = NULL; + + if (!block_list) { + g_print("malloc error\n"); + return NULL; + } + + for (i=0; i<node_select_ptr->record_count; i++) { + block_ptr = xmalloc(sizeof(db2_block_info_t)); + + block_ptr->bg_block_name + = xstrdup(node_select_ptr-> + bg_info_array[i].bg_block_id); + block_ptr->nodes + = xstrdup(node_select_ptr->bg_info_array[i].nodes); + block_ptr->nodelist = list_create(_nodelist_del); + _make_nodelist(block_ptr->nodes,block_ptr->nodelist); + + block_ptr->bg_user_name + = xstrdup(node_select_ptr-> + bg_info_array[i].owner_name); + block_ptr->state + = node_select_ptr->bg_info_array[i].state; + block_ptr->bg_conn_type + = node_select_ptr->bg_info_array[i].conn_type; + block_ptr->bg_node_use + = node_select_ptr->bg_info_array[i].node_use; + block_ptr->quarter + = node_select_ptr->bg_info_array[i].quarter; + block_ptr->nodecard + = node_select_ptr->bg_info_array[i].nodecard; + block_ptr->node_cnt + = node_select_ptr->bg_info_array[i].node_cnt; + + itr = list_iterator_create(block_list); + while ((found_block = (db2_block_info_t*)list_next(itr)) + != NULL) { + if(!strcmp(block_ptr->nodes, found_block->nodes)) { + block_ptr->letter_num = + found_block->letter_num; + break; + } + } + list_iterator_destroy(itr); + + if(!found_block) { + last_count++; + _marknodes(block_ptr, last_count); + } + + if(block_ptr->bg_conn_type == SELECT_SMALL) + block_ptr->size = 0; + + list_append(block_list, block_ptr); + } + for (i = 0; i < part_info_ptr->record_count; i++) { + j = 0; + part = part_info_ptr->partition_array[i]; + + if (!part.nodes || (part.nodes[0] == '\0')) + continue; /* empty partition */ + nodelist = list_create(_nodelist_del); + _make_nodelist(part.nodes, nodelist); + + itr = list_iterator_create(block_list); + while ((block_ptr = (db2_block_info_t*) list_next(itr))) { + if(_in_slurm_partition(nodelist, + block_ptr->nodelist)) { + block_ptr->slurm_part_name + = xstrdup(part.name); + } + } + list_iterator_destroy(itr); + list_destroy(nodelist); + } + + return block_list; +} + +void *_popup_thr_block(void *arg) +{ + popup_thr(arg); + return NULL; +} + +extern void refresh_block(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); + specific_info_block(popup_win); +} + +extern int get_new_info_node_select(node_select_info_msg_t **node_select_ptr) +{ + static node_select_info_msg_t *bg_info_ptr = NULL; + static node_select_info_msg_t *new_bg_ptr = NULL; + int error_code = SLURM_SUCCESS; + + if (bg_info_ptr) { + error_code = slurm_load_node_select(bg_info_ptr->last_update, + &new_bg_ptr); + if (error_code == SLURM_SUCCESS) + select_g_free_node_info(&bg_info_ptr); + else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) { + error_code = SLURM_NO_CHANGE_IN_DATA; + new_bg_ptr = bg_info_ptr; + } + } else { + error_code = slurm_load_node_select((time_t) NULL, + &new_bg_ptr); + } + + bg_info_ptr = new_bg_ptr; + *node_select_ptr = new_bg_ptr; + return error_code; +} + +extern void get_info_block(GtkTable *table, display_data_t *display_data) +{ + int part_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_select_info_msg_t *node_select_ptr = NULL; + char error_char[100]; + GtkWidget *label = NULL; + GtkTreeView *tree_view = NULL; + static GtkWidget *display_widget = NULL; + static List block_list = NULL; + + if(display_data) + local_display_data = display_data; + if(!table) { + display_data_block->set_menu = local_display_data->set_menu; + return; + } + if(block_list && toggled) { + gtk_widget_destroy(display_widget); + display_widget = NULL; + goto display_it; + } + + if((part_error_code = get_new_info_part(&part_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA) { + goto get_node_select; + } + + if (part_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_partitions: %s", + slurm_strerror(slurm_get_errno())); + label = gtk_label_new(error_char); + gtk_table_attach_defaults(GTK_TABLE(table), + label, + 0, 1, 0, 1); + gtk_widget_show(label); + display_widget = gtk_widget_ref(label); + goto end_it; + } + +get_node_select: + if((block_error_code = get_new_info_node_select(&node_select_ptr)) + == SLURM_NO_CHANGE_IN_DATA) { + if((!display_widget || view == ERROR_VIEW) + || (part_error_code != SLURM_NO_CHANGE_IN_DATA)) + goto display_it; + goto end_it; + } + + 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: + if (block_list) + /* clear the old list */ + list_destroy(block_list); + + block_list = _create_block_list(part_info_ptr, node_select_ptr); + if(!block_list) + return; + + if(view == ERROR_VIEW && display_widget) { + gtk_widget_destroy(display_widget); + display_widget = NULL; + } + if(!display_widget) { + tree_view = create_treeview(local_display_data, block_list); + display_widget = gtk_widget_ref(GTK_WIDGET(tree_view)); + gtk_table_attach_defaults(table, + GTK_WIDGET(tree_view), + 0, 1, 0, 1); + gtk_widget_show(GTK_WIDGET(tree_view)); + /* 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_block, SORTID_CNT); + } + view = INFO_VIEW; + _update_info_block(block_list, GTK_TREE_VIEW(display_widget), NULL); +end_it: + toggled = FALSE; + + return; +} + +extern void specific_info_block(popup_info_t *popup_win) +{ + int part_error_code = SLURM_SUCCESS; + int block_error_code = SLURM_SUCCESS; + static partition_info_msg_t *part_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; + static List block_list = NULL; + + if(!spec_info->display_widget) { + setup_popup_info(popup_win, display_data_block, SORTID_CNT); + } + + if(block_list && 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)) + == SLURM_NO_CHANGE_IN_DATA) { + goto get_node_select; + } + + if (part_error_code != SLURM_SUCCESS) { + if(spec_info->view == ERROR_VIEW) + goto end_it; + spec_info->view = ERROR_VIEW; + if(spec_info->display_widget) + gtk_widget_destroy(spec_info->display_widget); + sprintf(error_char, "slurm_load_partitions: %s", + slurm_strerror(slurm_get_errno())); + label = gtk_label_new(error_char); + gtk_table_attach_defaults(popup_win->table, + label, + 0, 1, 0, 1); + gtk_widget_show(label); + spec_info->display_widget = gtk_widget_ref(label); + goto end_it; + } + +get_node_select: + if((block_error_code = get_new_info_node_select(&node_select_ptr)) + == SLURM_NO_CHANGE_IN_DATA) { + if((!spec_info->display_widget + || spec_info->view == ERROR_VIEW) + || (part_error_code != SLURM_NO_CHANGE_IN_DATA)) { + goto display_it; + } + goto end_it; + } + + if (block_error_code != SLURM_SUCCESS) { + if(spec_info->view == ERROR_VIEW) + goto end_it; + spec_info->view = ERROR_VIEW; + if(spec_info->display_widget) + gtk_widget_destroy(spec_info->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(popup_win->table, + label, + 0, 1, 0, 1); + gtk_widget_show(label); + spec_info->display_widget = gtk_widget_ref(label); + goto end_it; + } + +display_it: + if (block_list) + /* clear the old list */ + list_destroy(block_list); + block_list = _create_block_list(part_info_ptr, node_select_ptr); + if(!block_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->display_widget) { + tree_view = create_treeview(local_display_data, block_list); + 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); + gtk_widget_show(GTK_WIDGET(tree_view)); + /* 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); + } + spec_info->view = INFO_VIEW; + _update_info_block(block_list, + GTK_TREE_VIEW(spec_info->display_widget), + spec_info); + +end_it: + popup_win->toggled = 0; + + return; +} + +extern void set_menus_block(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_block); + break; + case ROW_CLICKED: + make_options_menu(tree_view, path, menu, options_data_block); + 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 row_clicked_block(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + List block_list = (List)user_data; + GtkWidget *popup = NULL; + GtkWidget *label = NULL; + char *info_label = "No extra info avaliable."; + if (!block_list) { + g_print("No block_list given\n"); + return; + } + + popup = gtk_dialog_new(); + + label = gtk_label_new(info_label); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(popup)->vbox), + label, TRUE, TRUE, 0); + gtk_widget_show(label); + + gtk_widget_show(popup); + +} + +extern void popup_all_block(GtkTreeModel *model, GtkTreeIter *iter, int id) +{ + char *name = NULL; + char title[100]; + ListIterator itr = NULL; + popup_info_t *popup_win = NULL; + GError *error = NULL; + int i=0; + + gtk_tree_model_get(model, iter, SORTID_BLOCK, &name, -1); + switch(id) { + case JOB_PAGE: + snprintf(title, 100, "Jobs(s) in block %s", name); + break; + case PART_PAGE: + snprintf(title, 100, "Partition(s) containing block %s", name); + break; + case NODE_PAGE: + snprintf(title, 100, "Base Partition(s) in block %s", name); + break; + case ADMIN_PAGE: + snprintf(title, 100, "Admin Page for %s", name); + break; + case SUBMIT_PAGE: + snprintf(title, 100, "Submit job on %s", name); + break; + default: + g_print("Block 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) + popup_win = create_popup_info(BLOCK_PAGE, id, title); + + switch(id) { + case JOB_PAGE: + popup_win->spec_info->data = name; + break; + case PART_PAGE: + g_free(name); + gtk_tree_model_get(model, iter, SORTID_PARTITION, &name, -1); + popup_win->spec_info->data = name; + break; + case NODE_PAGE: + g_free(name); + gtk_tree_model_get(model, iter, SORTID_NODELIST, &name, -1); + /* strip off the quarter and nodecard part */ + while(name[i]) { + if(name[i] == '.') { + name[i] = '\0'; + break; + } + i++; + } + popup_win->spec_info->data = name; + break; + default: + g_print("block got %d\n", id); + } + + + if (!g_thread_create(_popup_thr_block, popup_win, FALSE, &error)) + { + g_printerr ("Failed to create part popup thread: %s\n", + error->message); + return; + } +} diff --git a/src/sview/common.c b/src/sview/common.c new file mode 100644 index 00000000000..03b4fb84759 --- /dev/null +++ b/src/sview/common.c @@ -0,0 +1,696 @@ +/*****************************************************************************\ + * common.c - common functions used by tabs in 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-217948. + * + * 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" + +typedef struct { + GtkTreeModel *model; + GtkTreeIter iter; +} treedata_t; + + +static int _sort_iter_compare_func_char(GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer userdata) +{ + int sortcol = GPOINTER_TO_INT(userdata); + int ret = 0; + gchar *name1 = NULL, *name2 = NULL; + + gtk_tree_model_get(model, a, sortcol, &name1, -1); + gtk_tree_model_get(model, b, sortcol, &name2, -1); + + if (name1 == NULL || name2 == NULL) + { + if (name1 == NULL && name2 == NULL) + goto cleanup; /* both equal => ret = 0 */ + + ret = (name1 == NULL) ? -1 : 1; + } + else + { + ret = g_utf8_collate(name1,name2); + } +cleanup: + g_free(name1); + g_free(name2); + + return ret; +} + +static int _sort_iter_compare_func_int(GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer userdata) +{ + int sortcol = GPOINTER_TO_INT(userdata); + int ret = 0; + gint int1, int2; + + gtk_tree_model_get(model, a, sortcol, &int1, -1); + gtk_tree_model_get(model, b, sortcol, &int2, -1); + + if (int1 != int2) + ret = (int1 > int2) ? 1 : -1; + + return ret; +} + +static void _add_col_to_treeview(GtkTreeView *tree_view, + display_data_t *display_data) +{ + GtkTreeViewColumn *col; + GtkCellRenderer *renderer; + renderer = gtk_cell_renderer_text_new(); + col = gtk_tree_view_column_new(); + gtk_tree_view_column_pack_start (col, renderer, TRUE); + gtk_tree_view_column_add_attribute (col, renderer, + "text", display_data->id); + gtk_tree_view_column_set_title (col, display_data->name); + gtk_tree_view_column_set_reorderable(col, true); + gtk_tree_view_column_set_resizable(col, true); + gtk_tree_view_column_set_expand(col, true); + gtk_tree_view_append_column(tree_view, col); + gtk_tree_view_column_set_sort_column_id(col, display_data->id); + +} + +static void _toggle_state_changed(GtkCheckMenuItem *menuitem, + display_data_t *display_data) +{ + if(display_data->show) + display_data->show = FALSE; + else + display_data->show = TRUE; + toggled = TRUE; + refresh_main(NULL, NULL); +} + +static void _popup_state_changed(GtkCheckMenuItem *menuitem, + display_data_t *display_data) +{ + popup_info_t *popup_win = (popup_info_t *) display_data->user_data; + popup_win->toggled = 1; + if(display_data->show) + display_data->show = FALSE; + else + display_data->show = TRUE; + + (display_data->refresh)(NULL, display_data->user_data); +} + +static void _selected_page(GtkMenuItem *menuitem, + display_data_t *display_data) +{ + treedata_t *treedata = (treedata_t *)display_data->user_data; + + switch(display_data->extra) { + case PART_PAGE: + popup_all_part(treedata->model, &treedata->iter, + display_data->id); + break; + case JOB_PAGE: + popup_all_job(treedata->model, &treedata->iter, + display_data->id); + break; + case NODE_PAGE: + popup_all_node(treedata->model, &treedata->iter, + display_data->id); + break; + case BLOCK_PAGE: + popup_all_block(treedata->model, &treedata->iter, + display_data->id); + break; + default: + g_print("common got %d %d\n", display_data->extra, + display_data->id); + } + xfree(treedata); +} + +static void _set_up_button(GtkTreeView *tree_view, GdkEventButton *event, + const display_data_t *display_data) +{ + //local_display_data->user_data = user_data; + row_clicked(tree_view, event, display_data); +} + +extern void snprint_time(char *buf, size_t buf_size, time_t time) +{ + if (time == INFINITE) { + snprintf(buf, buf_size, "UNLIMITED"); + } else { + long days, hours, minutes, seconds; + seconds = time % 60; + minutes = (time / 60) % 60; + hours = (time / 3600) % 24; + days = time / 86400; + + if (days) + snprintf(buf, buf_size, + "%ld-%2.2ld:%2.2ld:%2.2ld", + days, hours, minutes, seconds); + else if (hours) + snprintf(buf, buf_size, + "%ld:%2.2ld:%2.2ld", + hours, minutes, seconds); + else + snprintf(buf, buf_size, + "%ld:%2.2ld", minutes,seconds); + } +} + +extern int get_row_number(GtkTreeView *tree_view, GtkTreePath *path) +{ + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeIter iter; + int line = 0; + + if(!model) { + g_error("error getting the model from the tree_view"); + return -1; + } + + if (!gtk_tree_model_get_iter(model, &iter, path)) { + g_error("error getting iter from model"); + return -1; + } + gtk_tree_model_get(model, &iter, POS_LOC, &line, -1); + return line; +} + +extern void load_header(GtkTreeView *tree_view, display_data_t *display_data) +{ + while(display_data++) { + if(display_data->id == -1) + break; + else if(!display_data->show) + continue; + _add_col_to_treeview(tree_view, display_data); + } +} + +extern void make_fields_menu(GtkMenu *menu, display_data_t *display_data) +{ + GtkWidget *menuitem = NULL; + + while(display_data++) { + if(display_data->id == -1) + break; + if(!display_data->name) + continue; + menuitem = gtk_check_menu_item_new_with_label( + display_data->name); + + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), + display_data->show); + g_signal_connect(menuitem, "toggled", + G_CALLBACK(_toggle_state_changed), + display_data); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } +} + +extern void make_options_menu(GtkTreeView *tree_view, GtkTreePath *path, + GtkMenu *menu, display_data_t *display_data) +{ + GtkWidget *menuitem = NULL; + treedata_t *treedata = xmalloc(sizeof(treedata_t)); + treedata->model = gtk_tree_view_get_model(tree_view); + if (!gtk_tree_model_get_iter(treedata->model, &treedata->iter, path)) { + g_error("error getting iter from model\n"); + return; + } + if(display_data->user_data) + xfree(display_data->user_data); + + while(display_data++) { + if(display_data->id == -1) + break; + if(!display_data->name) + continue; + + display_data->user_data = treedata; + menuitem = gtk_menu_item_new_with_label(display_data->name); + g_signal_connect(menuitem, "activate", + G_CALLBACK(_selected_page), + display_data); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } +} + +extern void make_popup_fields_menu(popup_info_t *popup_win, GtkMenu *menu) +{ + GtkWidget *menuitem = NULL; + display_data_t *display_data = popup_win->display_data; + + while(display_data++) { + if(display_data->id == -1) + break; + if(!display_data->name) + continue; + display_data->user_data = popup_win; + menuitem = + gtk_check_menu_item_new_with_label(display_data->name); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), + display_data->show); + g_signal_connect(menuitem, "toggled", + G_CALLBACK(_popup_state_changed), + display_data); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } +} + + +extern GtkScrolledWindow *create_scrolled_window() +{ + GtkScrolledWindow *scrolled_window = NULL; + GtkWidget *table = NULL; + table = gtk_table_new(1, 1, FALSE); + + gtk_container_set_border_width(GTK_CONTAINER(table), 10); + + scrolled_window = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new( + NULL, NULL)); + gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 10); + + gtk_scrolled_window_set_policy(scrolled_window, + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_scrolled_window_add_with_viewport(scrolled_window, table); + + return scrolled_window; +} +extern void create_page(GtkNotebook *notebook, display_data_t *display_data) +{ + GtkScrolledWindow *scrolled_window = create_scrolled_window(); + GtkWidget *event_box = NULL; + GtkWidget *label = NULL; + int err; + + event_box = gtk_event_box_new(); + gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box), FALSE); + g_signal_connect(G_OBJECT(event_box), "button-press-event", + G_CALLBACK(tab_pressed), + display_data); + + label = gtk_label_new(display_data->name); + gtk_container_add(GTK_CONTAINER(event_box), label); + gtk_widget_show(label); + //(display_data->set_fields)(GTK_MENU(menu)); + if((err = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), + GTK_WIDGET(scrolled_window), + event_box)) == -1) { + g_error("Couldn't add page to notebook\n"); + } + + display_data->extra = err; + +} + +extern GtkTreeView *create_treeview(display_data_t *local, gpointer user_data) +{ + GtkTreeView *tree_view = GTK_TREE_VIEW(gtk_tree_view_new()); + /* g_signal_connect(G_OBJECT(tree_view), "row-activated", */ +/* G_CALLBACK(local->row_clicked), */ +/* user_data); */ + + local->user_data = user_data; + g_signal_connect(G_OBJECT(tree_view), "button_press_event", + G_CALLBACK(_set_up_button), + local); + + + gtk_widget_show(GTK_WIDGET(tree_view)); + + return tree_view; + +} + +extern GtkTreeStore *create_treestore(GtkTreeView *tree_view, + display_data_t *display_data, + int count) +{ + GtkTreeStore *treestore = NULL; + GType types[count]; + int i=0; + + /*set up the types defined in the display_data_t */ + for(i=0; i<count; i++) + types[i] = display_data[i].type; + + treestore = gtk_tree_store_newv(count, types); + if(!treestore) + return NULL; + + for(i=1; i<count; i++) { + if(display_data[i].show) { + switch(display_data[i].type) { + case G_TYPE_INT: + gtk_tree_sortable_set_sort_func( + GTK_TREE_SORTABLE(treestore), + i, + _sort_iter_compare_func_int, + GINT_TO_POINTER(i), + NULL); + + break; + case G_TYPE_STRING: + gtk_tree_sortable_set_sort_func( + GTK_TREE_SORTABLE(treestore), + i, + _sort_iter_compare_func_char, + GINT_TO_POINTER(i), + NULL); + break; + default: + g_print("unknown type %d", + (int)display_data[i].type); + } + } + } + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(treestore), + 1, + GTK_SORT_ASCENDING); + + load_header(tree_view, display_data); + gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(treestore)); + g_object_unref(GTK_TREE_MODEL(treestore)); + + return treestore; +} + +extern void right_button_pressed(GtkTreeView *tree_view, + GtkTreePath *path, + GdkEventButton *event, + const display_data_t *display_data, + int type) +{ + if(event->button == 3) { + GtkMenu *menu = GTK_MENU(gtk_menu_new()); + + (display_data->set_menu)(tree_view, path, menu, type); + + gtk_widget_show_all(GTK_WIDGET(menu)); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, + (event != NULL) ? event->button : 0, + gdk_event_get_time((GdkEvent*)event)); + } +} + +extern void row_clicked(GtkTreeView *tree_view, GdkEventButton *event, + const display_data_t *display_data) +{ + GtkTreePath *path = NULL; + GtkTreeSelection *selection = NULL; + + if(!gtk_tree_view_get_path_at_pos(tree_view, + (gint) event->x, + (gint) event->y, + &path, NULL, NULL, NULL)) { + return; + } + selection = gtk_tree_view_get_selection(tree_view); + gtk_tree_selection_unselect_all(selection); + gtk_tree_selection_select_path(selection, path); + + /* expand/collapse row + or right mouse button + or double click? + */ + if(event->x <= 20) { + if(!gtk_tree_view_expand_row(tree_view, path, FALSE)) + gtk_tree_view_collapse_row(tree_view, path); + } else if(event->button == 3) { + right_button_pressed(tree_view, path, event, + display_data, ROW_CLICKED); + } else if(event->type==GDK_2BUTTON_PRESS || + event->type==GDK_3BUTTON_PRESS) { + (display_data->row_clicked)(tree_view, path, + NULL, display_data->user_data); + } + gtk_tree_path_free(path); +} + +extern popup_info_t *create_popup_info(int type, int dest_type, char *title) +{ + GtkScrolledWindow *window = NULL; + GtkBin *bin = NULL; + GtkViewport *view = NULL; + GtkBin *bin2 = NULL; + GtkWidget *table = NULL; + GtkWidget *popup = NULL; + popup_info_t *popup_win = xmalloc(sizeof(popup_info_t)); + + list_push(popup_list, popup_win); + + popup_win->spec_info = xmalloc(sizeof(specific_info_t)); + popup_win->popup = gtk_dialog_new(); + popup_win->toggled = 0; + popup_win->type = dest_type; + + gtk_window_set_default_size(GTK_WINDOW(popup_win->popup), + 600, 400); + gtk_window_set_title(GTK_WINDOW(popup_win->popup), title); + + popup = popup_win->popup; + + table = gtk_table_new(1, 2, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(table), 10); + + popup_win->event_box = gtk_event_box_new(); + gtk_event_box_set_above_child( + GTK_EVENT_BOX(popup_win->event_box), + FALSE); + popup_win->button = gtk_button_new_with_label("Refresh"); + gtk_table_attach_defaults(GTK_TABLE(table), + popup_win->event_box, + 0, 1, 0, 1); + gtk_table_attach(GTK_TABLE(table), + popup_win->button, + 1, 2, 0, 1, + GTK_SHRINK, GTK_EXPAND | GTK_FILL, + 0, 0); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox), + table, FALSE, FALSE, 0); + + window = create_scrolled_window(); + bin = GTK_BIN(&window->container); + view = GTK_VIEWPORT(bin->child); + bin2 = GTK_BIN(&view->bin); + popup_win->table = GTK_TABLE(bin2->child); + + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(popup)->vbox), + GTK_WIDGET(window), TRUE, TRUE, 0); + popup_win->spec_info->type = type; + popup_win->spec_info->title = xstrdup(title); + g_signal_connect(G_OBJECT(popup_win->popup), "delete_event", + G_CALLBACK(delete_popup), + popup_win->spec_info->title); + gtk_widget_show_all(popup_win->popup); + return popup_win; +} + +extern void setup_popup_info(popup_info_t *popup_win, + display_data_t *display_data, + int cnt) +{ + GtkWidget *label = NULL; + int i = 0; + specific_info_t *spec_info = popup_win->spec_info; + + popup_win->display_data = xmalloc(sizeof(display_data_t)*(cnt+2)); + for(i=0; i<cnt+1; i++) { + memcpy(&popup_win->display_data[i], + &display_data[i], + sizeof(display_data_t)); + } + + g_signal_connect(G_OBJECT(popup_win->event_box), + "button-press-event", + G_CALLBACK(redo_popup), + popup_win); + + g_signal_connect(G_OBJECT(popup_win->button), + "pressed", + G_CALLBACK(popup_win->display_data->refresh), + popup_win); + + label = gtk_label_new(spec_info->title); + gtk_container_add(GTK_CONTAINER(popup_win->event_box), label); + gtk_widget_show(label); +} + +extern void redo_popup(GtkWidget *widget, GdkEventButton *event, + popup_info_t *popup_win) +{ + if(event->button == 3) { + GtkMenu *menu = GTK_MENU(gtk_menu_new()); + + (popup_win->display_data->set_menu)(popup_win, + NULL, + menu, POPUP_CLICKED); + + gtk_widget_show_all(GTK_WIDGET(menu)); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, + (event != NULL) ? event->button : 0, + gdk_event_get_time((GdkEvent*)event)); + } +} + +extern void destroy_specific_info(void *arg) +{ + specific_info_t *spec_info = (specific_info_t *)arg; + if(spec_info) { + xfree(spec_info->title); + if(spec_info->data) { + g_free(spec_info->data); + spec_info->data = NULL; + } + if(spec_info->display_widget) { + gtk_widget_destroy(spec_info->display_widget); + spec_info->display_widget = NULL; + } + xfree(spec_info); + } +} + +extern void destroy_popup_info(void *arg) +{ + popup_info_t *popup_win = (popup_info_t *)arg; + if(popup_win) { + *popup_win->running = 0; + /* these are all childern of each other so must + be freed in this order */ + if(popup_win->table) { + gtk_widget_destroy(GTK_WIDGET(popup_win->table)); + popup_win->table = NULL; + } + if(popup_win->button) { + gtk_widget_destroy(popup_win->button); + popup_win->button = NULL; + } + if(popup_win->event_box) { + gtk_widget_destroy(popup_win->event_box); + popup_win->event_box = NULL; + } + if(popup_win->popup) { + gtk_widget_destroy(popup_win->popup); + popup_win->popup = NULL; + } + + destroy_specific_info(popup_win->spec_info); + xfree(popup_win->display_data); + xfree(popup_win); + } +} + +extern gboolean delete_popup(GtkWidget *widget, GtkWidget *event, char *title) +{ + ListIterator itr = list_iterator_create(popup_list); + popup_info_t *popup_win = NULL; + + while((popup_win = list_next(itr))) { + if(popup_win->spec_info) { + if(!strcmp(popup_win->spec_info->title, title)) { + //g_print("removing %s\n", title); + list_remove(itr); + destroy_popup_info(popup_win); + break; + } + } + } + list_iterator_destroy(itr); + + + return FALSE; +} + +extern void *popup_thr(popup_info_t *popup_win) +{ + void (*specifc_info) (popup_info_t *popup_win) = NULL; + int running = 1; + switch(popup_win->type) { + case PART_PAGE: + specifc_info = specific_info_part; + break; + case JOB_PAGE: + specifc_info = specific_info_job; + break; + case NODE_PAGE: + specifc_info = specific_info_node; + break; + case BLOCK_PAGE: + specifc_info = specific_info_block; + break; + case ADMIN_PAGE: + case SUBMIT_PAGE: + default: + g_print("thread got unknown type %d\n", popup_win->type); + return NULL; + } + /* this will switch to 0 when popup is closed. */ + popup_win->running = &running; + /* when popup is killed toggled will be set to -1 */ + while(running) { + gdk_threads_enter(); + (specifc_info)(popup_win); + gdk_flush(); + gdk_threads_leave(); + sleep(5); + } + return NULL; +} + +extern void remove_old(GtkTreeModel *model, int updated) +{ + GtkTreePath *path = gtk_tree_path_new_first(); + GtkTreeIter iter; + int i; + + /* remove all old partitions */ + if (gtk_tree_model_get_iter(model, &iter, path)) { + while(1) { + gtk_tree_model_get(model, &iter, updated, &i, -1); + if(!i) { + if(!gtk_tree_store_remove( + GTK_TREE_STORE(model), + &iter)) + break; + else + continue; + } + if(!gtk_tree_model_iter_next(model, &iter)) { + break; + } + } + } + gtk_tree_path_free(path); +} diff --git a/src/sview/job_info.c b/src/sview/job_info.c new file mode 100644 index 00000000000..15f2d88c44a --- /dev/null +++ b/src/sview/job_info.c @@ -0,0 +1,1015 @@ +/*****************************************************************************\ + * job_info.c - Functions related to job 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-217948. + * + * 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/common/uid.h" +#include "src/common/node_select.h" +#include "src/sview/sview.h" + +#define _DEBUG 0 +DEF_TIMERS; + +typedef struct { + job_info_msg_t *job_info_ptr; + job_step_info_response_msg_t *step_info_ptr; +} job_and_step_info_t; + + +enum { + SORTID_POS = POS_LOC, + SORTID_JOBID, + SORTID_PARTITION, +#ifdef HAVE_BG + SORTID_BLOCK, +#endif + SORTID_USER, + SORTID_NAME, + SORTID_STATE, + SORTID_TIME, + SORTID_NODES, + SORTID_NODELIST, + SORTID_REQ_NODELIST, + SORTID_EXC_NODELIST, + SORTID_SUBMIT, + SORTID_START, + SORTID_END, + SORTID_SUSPEND, + SORTID_PRIORITY, + SORTID_NUM_PROCS, + SORTID_SHARED, + SORTID_CPUS_PER_TASK, + SORTID_TASKS, + SORTID_ACCOUNT, + SORTID_REASON, + SORTID_UPDATED, + SORTID_CNT +}; + +static display_data_t display_data_job[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1, refresh_job}, + {G_TYPE_INT, SORTID_JOBID, "JobID", TRUE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_PARTITION, "Partition", TRUE, -1, refresh_job}, +#ifdef HAVE_BG + {G_TYPE_STRING, SORTID_BLOCK, "BG Block", TRUE, -1, refresh_job}, +#endif + {G_TYPE_STRING, SORTID_USER, "User", TRUE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_NAME, "Name", TRUE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_STATE, "State", TRUE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_TIME, "Running Time", TRUE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_NODES, "Nodes", TRUE, -1, refresh_job}, +#ifdef HAVE_BG + {G_TYPE_STRING, SORTID_NODELIST, "BP List", TRUE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_REQ_NODELIST, "Requested BP List", + FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_EXC_NODELIST, "Excluded BP List", + FALSE, -1, refresh_job}, +#else + {G_TYPE_STRING, SORTID_NODELIST, "Nodelist", TRUE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_REQ_NODELIST, "Requested NodeList", + FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_EXC_NODELIST, "Excluded NodeList", + FALSE, -1, refresh_job}, +#endif + {G_TYPE_STRING, SORTID_SUBMIT, "Submit Time", FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_START, "Start Time", FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_END, "End Time", FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_SUSPEND, "Suspend Time", + FALSE, -1, refresh_job}, + {G_TYPE_INT, SORTID_PRIORITY, "Priority", FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_NUM_PROCS, "Num Processors", + FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_TASKS, "Num Tasks", + FALSE, -1, refresh_job}, + {G_TYPE_INT, SORTID_SHARED, "Shared", FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_CPUS_PER_TASK, "Cpus per Task", + FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_ACCOUNT, "Account Charged", + FALSE, -1, refresh_job}, + {G_TYPE_STRING, SORTID_REASON, "Wait Reason", + FALSE, -1, refresh_job}, + {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, -1, refresh_job}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t options_data_job[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1}, + {G_TYPE_STRING, PART_PAGE, "Partition", TRUE, JOB_PAGE}, +#ifdef HAVE_BG + {G_TYPE_STRING, BLOCK_PAGE, "Blocks", TRUE, JOB_PAGE}, + {G_TYPE_STRING, NODE_PAGE, "Base Partitions", TRUE, JOB_PAGE}, +#else + {G_TYPE_STRING, NODE_PAGE, "Nodes", TRUE, JOB_PAGE}, +#endif + {G_TYPE_STRING, ADMIN_PAGE, "Admin", TRUE, JOB_PAGE}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t *local_display_data = NULL; + +static void _update_info_step(job_step_info_response_msg_t *step_info_ptr, + int jobid, + GtkTreeModel *model, + GtkTreeIter *step_iter, + GtkTreeIter *iter, + int changed); + + +static int _nodes_in_list(char *node_list) +{ + hostset_t host_set = hostset_create(node_list); + int count = hostset_count(host_set); + hostset_destroy(host_set); + return count; +} + +static int _get_node_cnt(job_info_t * job) +{ + int node_cnt = 0; + bool completing = job->job_state & JOB_COMPLETING; + uint16_t base_job_state = job->job_state & (~JOB_COMPLETING); + + if (base_job_state == JOB_PENDING || completing) { + node_cnt = _nodes_in_list(job->req_nodes); + node_cnt = MAX(node_cnt, job->num_nodes); + } else + node_cnt = _nodes_in_list(job->nodes); + return node_cnt; +} + +static void _update_job_record(job_info_t *job_ptr, + job_step_info_response_msg_t *step_info_ptr, + GtkTreeStore *treestore, + GtkTreeIter *iter, + int changed) +{ + char *nodes = NULL, time_buf[20]; + char tmp_cnt[7]; + char tmp_char[50]; + time_t now_time = time(NULL); + uint16_t quarter = (uint16_t) NO_VAL; + uint16_t nodecard = (uint16_t) NO_VAL; + GtkTreeIter step_iter; + int childern = 0; + uint32_t node_cnt = 0; + + if(!job_ptr->nodes || !strcasecmp(job_ptr->nodes,"waiting...")) { + sprintf(time_buf,"0:00:00"); + nodes = "waiting..."; + } else { + now_time -= job_ptr->start_time; + snprint_time(time_buf, sizeof(time_buf), now_time); + nodes = job_ptr->nodes; + } + gtk_tree_store_set(treestore, iter, + SORTID_TIME, time_buf, -1); + if(!changed) + goto update_steps; + + gtk_tree_store_set(treestore, iter, + SORTID_JOBID, job_ptr->job_id, -1); + gtk_tree_store_set(treestore, iter, + SORTID_PARTITION, job_ptr->partition, -1); +#ifdef HAVE_BG + gtk_tree_store_set(treestore, iter, + SORTID_BLOCK, + select_g_sprint_jobinfo( + job_ptr->select_jobinfo, + time_buf, + sizeof(time_buf), + SELECT_PRINT_BG_ID), -1); +#endif + gtk_tree_store_set(treestore, iter, + SORTID_USER, + uid_to_string((uid_t)job_ptr->user_id), -1); + gtk_tree_store_set(treestore, iter, + SORTID_NAME, job_ptr->name, -1); + gtk_tree_store_set(treestore, iter, + SORTID_STATE, + job_state_string(job_ptr->job_state), -1); + +#ifdef HAVE_BG + select_g_get_jobinfo(job_ptr->select_jobinfo, + SELECT_DATA_NODE_CNT, + &node_cnt); +#endif + if(!node_cnt) + node_cnt = _get_node_cnt(job_ptr); + + + + convert_to_kilo(node_cnt, tmp_cnt); + gtk_tree_store_set(treestore, iter, + SORTID_NODES, tmp_cnt, -1); + + convert_to_kilo(job_ptr->num_procs, tmp_cnt); + gtk_tree_store_set(treestore, iter, + SORTID_NUM_PROCS, tmp_cnt, -1); + + if(quarter != (uint16_t) NO_VAL) { + if(nodecard != (uint16_t) NO_VAL) + snprintf(tmp_char, 50, "%s.%d.%d", + nodes, quarter, nodecard); + else + snprintf(tmp_char, 50, "%s.%d", nodes, quarter); + gtk_tree_store_set(treestore, iter, + SORTID_NODELIST, tmp_char, -1); + } else + gtk_tree_store_set(treestore, iter, + SORTID_NODELIST, nodes, -1); +update_steps: + childern = gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore), + &step_iter, iter); + if(gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore), + &step_iter, iter)) + _update_info_step(step_info_ptr, job_ptr->job_id, + GTK_TREE_MODEL(treestore), &step_iter, iter, + changed); + else + _update_info_step(step_info_ptr, job_ptr->job_id, + GTK_TREE_MODEL(treestore), NULL, iter, + changed); + + return; +} + +static void _update_step_record(job_step_info_t *step_ptr, + GtkTreeStore *treestore, + GtkTreeIter *iter, + int changed) +{ + char *nodes = NULL, time_buf[20]; + char tmp_cnt[7]; + char tmp_char[50]; + time_t now_time = time(NULL); + uint16_t quarter = (uint16_t) NO_VAL; + uint16_t nodecard = (uint16_t) NO_VAL; + + if(!step_ptr->nodes + || !strcasecmp(step_ptr->nodes,"waiting...")) { + sprintf(time_buf,"0:00:00"); + nodes = "waiting..."; + } else { + now_time -= step_ptr->start_time; + snprint_time(time_buf, sizeof(time_buf), now_time); + nodes = step_ptr->nodes; + } + gtk_tree_store_set(treestore, iter, + SORTID_TIME, time_buf, -1); + gtk_tree_store_set(treestore, iter, SORTID_UPDATED, 1, -1); + + if(!changed) + return; + + + gtk_tree_store_set(treestore, iter, + SORTID_JOBID, step_ptr->step_id, -1); + gtk_tree_store_set(treestore, iter, + SORTID_PARTITION, step_ptr->partition, -1); +/* #ifdef HAVE_BG */ +/* gtk_tree_store_set(treestore, iter, */ +/* SORTID_BLOCK, */ +/* select_g_sprint_jobinfo( */ +/* step_ptr->select_jobinfo, */ +/* time_buf, */ +/* sizeof(time_buf), */ +/* SELECT_PRINT_BG_ID), -1); */ +/* #endif */ + gtk_tree_store_set(treestore, iter, + SORTID_USER, + uid_to_string((uid_t)step_ptr->user_id), -1); + gtk_tree_store_set(treestore, iter, + SORTID_NAME, step_ptr->name, -1); + /* gtk_tree_store_set(treestore, iter, */ +/* SORTID_STATE, */ +/* job_state_string(step_ptr->job_state), -1); */ + + convert_to_kilo(step_ptr->num_tasks, tmp_cnt); + gtk_tree_store_set(treestore, iter, + SORTID_TASKS, tmp_cnt, -1); + + if(quarter != (uint16_t) NO_VAL) { + if(nodecard != (uint16_t) NO_VAL) + snprintf(tmp_char, 50, "%s.%d.%d", + nodes, quarter, nodecard); + else + snprintf(tmp_char, 50, "%s.%d", nodes, quarter); + gtk_tree_store_set(treestore, iter, + SORTID_NODELIST, tmp_char, -1); + } else + gtk_tree_store_set(treestore, iter, + SORTID_NODELIST, nodes, -1); + + return; +} + +static void _append_job_record(job_info_t *job_ptr, + job_step_info_response_msg_t *step_info_ptr, + GtkTreeStore *treestore, GtkTreeIter *iter, + int line) +{ + gtk_tree_store_append(treestore, iter, NULL); + gtk_tree_store_set(treestore, iter, SORTID_POS, line, -1); + _update_job_record(job_ptr, step_info_ptr, treestore, iter, 1); +} + +static void _append_step_record(job_step_info_t *step_ptr, + GtkTreeStore *treestore, GtkTreeIter *iter, + int jobid) +{ + GtkTreeIter step_iter; + + gtk_tree_store_append(treestore, &step_iter, iter); + gtk_tree_store_set(treestore, &step_iter, SORTID_POS, jobid, -1); + _update_step_record(step_ptr, treestore, &step_iter, 1); +} + +static void _update_info_step(job_step_info_response_msg_t *step_info_ptr, + int jobid, + GtkTreeModel *model, + GtkTreeIter *step_iter, + GtkTreeIter *iter, + int changed) +{ + job_step_info_t step; + int stepid = 0; + int i; + GtkTreeIter *first_step_iter = NULL; + /* make sure all the steps are still here */ + if (step_iter) { + first_step_iter = gtk_tree_iter_copy(step_iter); + while(1) { + gtk_tree_store_set(GTK_TREE_STORE(model), step_iter, + SORTID_UPDATED, 0, -1); + if(!gtk_tree_model_iter_next(model, step_iter)) { + break; + } + } + step_iter = gtk_tree_iter_copy(first_step_iter); + } + for (i = 0; i < step_info_ptr->job_step_count; i++) { + step = step_info_ptr->job_steps[i]; + if(step.job_id != jobid) + continue; + /* get the iter, or find out the list is + empty goto add */ + if (!step_iter) { + goto adding; + } + while(1) { + /* search for the jobid and check to see if + it is in the list */ + gtk_tree_model_get(model, step_iter, SORTID_JOBID, + &stepid, -1); + if(stepid == (int)step.step_id) { + /* update with new info */ + _update_step_record(&step, + GTK_TREE_STORE(model), + step_iter, + changed); + goto found; + } + + if(!gtk_tree_model_iter_next(model, step_iter)) { + step_iter = NULL; + break; + } + } + adding: + _append_step_record(&step, GTK_TREE_STORE(model), + iter, jobid); + found: + ; + } + if(first_step_iter) { + if(step_iter) + gtk_tree_iter_free(step_iter); + step_iter = gtk_tree_iter_copy(first_step_iter); + /* clear all steps that aren't active */ + while(1) { + gtk_tree_model_get(model, step_iter, + SORTID_UPDATED, &i, -1); + if(!i) { + if(!gtk_tree_store_remove( + GTK_TREE_STORE(model), + step_iter)) + break; + else + continue; + } + if(!gtk_tree_model_iter_next(model, step_iter)) { + break; + } + } + gtk_tree_iter_free(first_step_iter); + } + return; +} + +static void _update_info_job(job_info_msg_t *job_info_ptr, + job_step_info_response_msg_t *step_info_ptr, + GtkTreeView *tree_view, + specific_info_t *spec_info, + int changed) +{ + GtkTreePath *path = gtk_tree_path_new_first(); + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeIter iter; + int jobid = 0; + int i; + job_info_t job; + int line = 0; + char name[30]; + char *host = NULL, *host2 = NULL; + hostlist_t hostlist = NULL; + int found = 0; + + if(spec_info) { + switch(spec_info->type) { + case NODE_PAGE: + hostlist = hostlist_create( + (char *)spec_info->data); + host = hostlist_shift(hostlist); + hostlist_destroy(hostlist); + if(host == NULL) { + g_print("nodelist was empty\n"); + return; + + } + break; + } + } + + for (i = 0; i < job_info_ptr->record_count; i++) { + job = job_info_ptr->job_array[i]; + /* 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_JOBID, + &jobid, -1); + if(jobid == job.job_id) { + /* We don't really want to display the + completed jobs so well remove it + from the list and continue to + the next job */ + if ((job.job_state != JOB_PENDING) + && (job.job_state != JOB_RUNNING) + && (job.job_state != JOB_SUSPENDED) + && (!(job.job_state & JOB_COMPLETING))) { + gtk_tree_store_remove( + GTK_TREE_STORE(model), + &iter); + goto found; /* job has completed */ + } + /* update with new info */ + _update_job_record(&job, step_info_ptr, + GTK_TREE_STORE(model), + &iter, + changed); + goto found; + } + + /* 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: + if ((job.job_state != JOB_PENDING) + && (job.job_state != JOB_RUNNING) + && (job.job_state != JOB_SUSPENDED) + && (!(job.job_state & JOB_COMPLETING))) + continue; /* job has completed */ + + if(spec_info) { + switch(spec_info->type) { + case PART_PAGE: + if(strcmp((char *)spec_info->data, + job.partition)) + continue; + break; + case BLOCK_PAGE: + select_g_sprint_jobinfo( + job.select_jobinfo, + name, + sizeof(name), + SELECT_PRINT_BG_ID); + if(strcmp((char *)spec_info->data, name)) + continue; + break; + case NODE_PAGE: + if(!job.nodes || !host) + continue; + + hostlist = hostlist_create(job.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; + default: + continue; + } + } + _append_job_record(&job, step_info_ptr, GTK_TREE_STORE(model), + &iter, line); + found: + ; + } + if(host) + free(host); + gtk_tree_path_free(path); + return; +} + +void *_popup_thr_job(void *arg) +{ + popup_thr(arg); + return NULL; +} + +extern void refresh_job(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); + specific_info_job(popup_win); +} + +extern int get_new_info_job(job_info_msg_t **info_ptr) +{ + static job_info_msg_t *job_info_ptr = NULL, *new_job_ptr = NULL; + uint16_t show_flags = 0; + int error_code = SLURM_SUCCESS; + + show_flags |= SHOW_ALL; + if (job_info_ptr) { + error_code = slurm_load_jobs(job_info_ptr->last_update, + &new_job_ptr, show_flags); + if (error_code == SLURM_SUCCESS) + slurm_free_job_info_msg(job_info_ptr); + else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) { + error_code = SLURM_NO_CHANGE_IN_DATA; + new_job_ptr = job_info_ptr; + } + } else + error_code = slurm_load_jobs((time_t) NULL, &new_job_ptr, + show_flags); + job_info_ptr = new_job_ptr; + *info_ptr = new_job_ptr; + return error_code; +} + +extern int get_new_info_job_step(job_step_info_response_msg_t **info_ptr) +{ + static job_step_info_response_msg_t *old_step_ptr = NULL; + static job_step_info_response_msg_t *new_step_ptr = NULL; + uint16_t show_flags = 0; + int error_code = SLURM_SUCCESS; + + show_flags |= SHOW_ALL; + if (old_step_ptr) { + error_code = slurm_get_job_steps(old_step_ptr->last_update, + 0, 0, &new_step_ptr, + show_flags); + if (error_code == SLURM_SUCCESS) + slurm_free_job_step_info_response_msg(old_step_ptr); + else if (slurm_get_errno () == SLURM_NO_CHANGE_IN_DATA) { + error_code = SLURM_NO_CHANGE_IN_DATA; + new_step_ptr = old_step_ptr; + } + } else + error_code = slurm_get_job_steps((time_t) NULL, 0, 0, + &new_step_ptr, show_flags); + old_step_ptr = new_step_ptr; + *info_ptr = new_step_ptr; + return error_code; +} + +extern void get_info_job(GtkTable *table, display_data_t *display_data) +{ + int job_error_code = SLURM_SUCCESS; + int step_error_code = SLURM_SUCCESS; + static int view = -1; + static job_info_msg_t *job_info_ptr = NULL; + static job_step_info_response_msg_t *step_info_ptr = NULL; + static job_and_step_info_t job_and_step_info; + char error_char[100]; + GtkWidget *label = NULL; + GtkTreeView *tree_view = NULL; + static GtkWidget *display_widget = NULL; + + if(display_data) + local_display_data = display_data; + if(!table) { + display_data_job->set_menu = local_display_data->set_menu; + return; + } + if(job_info_ptr && toggled) { + gtk_widget_destroy(display_widget); + display_widget = NULL; + goto display_it; + } + + if((job_error_code = get_new_info_job(&job_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA){ + goto get_steps; + } + + if (job_error_code != SLURM_SUCCESS) { + if(view == ERROR_VIEW) + goto end_it; + if(display_widget) + gtk_widget_destroy(display_widget); + view = ERROR_VIEW; + sprintf(error_char, "slurm_load_job: %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(GTK_WIDGET(label)); + goto end_it; + } +get_steps: + if((step_error_code = get_new_info_job_step(&step_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA){ + if((!display_widget || view == ERROR_VIEW) + || (job_error_code != SLURM_NO_CHANGE_IN_DATA)) + goto display_it; + _update_info_job(job_info_ptr, step_info_ptr, + GTK_TREE_VIEW(display_widget), + NULL, 0); + goto end_it; + } + + if (step_error_code != SLURM_SUCCESS) { + if(view == ERROR_VIEW) + goto end_it; + if(display_widget) + gtk_widget_destroy(display_widget); + view = ERROR_VIEW; + sprintf(error_char, "slurm_load_job_step: %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(GTK_WIDGET(label)); + goto end_it; + } +display_it: + if(view == ERROR_VIEW && display_widget) { + gtk_widget_destroy(display_widget); + display_widget = NULL; + } + if(!display_widget) { + job_and_step_info.job_info_ptr = job_info_ptr; + job_and_step_info.step_info_ptr = step_info_ptr; + tree_view = create_treeview(local_display_data, + &job_and_step_info); + + display_widget = gtk_widget_ref(GTK_WIDGET(tree_view)); + gtk_table_attach_defaults(GTK_TABLE(table), + GTK_WIDGET(tree_view), + 0, 1, 0, 1); + gtk_widget_show(GTK_WIDGET(tree_view)); + /* 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_job, SORTID_CNT); + } + view = INFO_VIEW; + _update_info_job(job_info_ptr, step_info_ptr, + GTK_TREE_VIEW(display_widget), NULL, 1); +end_it: + toggled = FALSE; + + return; +} + +extern void specific_info_job(popup_info_t *popup_win) +{ + int job_error_code = SLURM_SUCCESS; + int step_error_code = SLURM_SUCCESS; + static job_info_msg_t *job_info_ptr = NULL; + static job_step_info_response_msg_t *step_info_ptr = NULL; + static job_and_step_info_t job_and_step_info; + specific_info_t *spec_info = popup_win->spec_info; + char error_char[100]; + GtkWidget *label = NULL; + GtkTreeView *tree_view = NULL; + + if(!spec_info->display_widget) + setup_popup_info(popup_win, display_data_job, SORTID_CNT); + + if(job_info_ptr && popup_win->toggled) { + gtk_widget_destroy(spec_info->display_widget); + spec_info->display_widget = NULL; + goto display_it; + } + + if((job_error_code = get_new_info_job(&job_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA) { + goto get_steps; + } + + if (job_error_code != SLURM_SUCCESS) { + if(spec_info->view == ERROR_VIEW) + goto end_it; + spec_info->view = ERROR_VIEW; + if(spec_info->display_widget) + gtk_widget_destroy(spec_info->display_widget); + + sprintf(error_char, "slurm_load_job: %s", + slurm_strerror(slurm_get_errno())); + label = gtk_label_new(error_char); + gtk_table_attach_defaults(GTK_TABLE(popup_win->table), + label, + 0, 1, 0, 1); + gtk_widget_show(label); + spec_info->display_widget = gtk_widget_ref(GTK_WIDGET(label)); + goto end_it; + } +get_steps: + if((step_error_code = get_new_info_job_step(&step_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA){ + if((!spec_info->display_widget + || spec_info->view == ERROR_VIEW) + || (job_error_code != SLURM_NO_CHANGE_IN_DATA)) + goto display_it; + _update_info_job(job_info_ptr, step_info_ptr, + GTK_TREE_VIEW(spec_info->display_widget), + NULL, 0); + goto end_it; + } + + if (step_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_job_step: %s", + slurm_strerror(slurm_get_errno())); + label = gtk_label_new(error_char); + gtk_table_attach_defaults(popup_win->table, label, + 0, 1, 0, 1); + gtk_widget_show(label); + spec_info->display_widget = gtk_widget_ref(GTK_WIDGET(label)); + goto end_it; + } +display_it: + 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->display_widget) { + job_and_step_info.job_info_ptr = job_info_ptr; + job_and_step_info.step_info_ptr = step_info_ptr; + tree_view = create_treeview(local_display_data, + &job_and_step_info); + + 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); + } + spec_info->view = INFO_VIEW; + _update_info_job(job_info_ptr, step_info_ptr, + GTK_TREE_VIEW(spec_info->display_widget), spec_info, + 1); +end_it: + popup_win->toggled = 0; + return; +} + +extern void set_menus_job(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_job); + break; + case ROW_CLICKED: + make_options_menu(tree_view, path, menu, options_data_job); + 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 row_clicked_job(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + job_and_step_info_t *job_and_step_info_ptr = + (job_and_step_info_t *)user_data; + job_info_msg_t *job_info_ptr = job_and_step_info_ptr->job_info_ptr; + job_step_info_response_msg_t *step_info_ptr = + job_and_step_info_ptr->step_info_ptr; + job_info_t *job_ptr = NULL; + job_step_info_t *step_ptr = NULL; + int job_id = 0, i, pos = 0; + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkWidget *popup = NULL; + GtkWidget *label = NULL; + GtkTreeIter iter; + char *info = NULL; + bool found = false; + + if(!model) { + g_error("error getting the model from the tree_view"); + return; + } + + if (!gtk_tree_model_get_iter(model, &iter, path)) { + g_error("error getting iter from model"); + return; + } + gtk_tree_model_get(model, &iter, SORTID_JOBID, &job_id, -1); + gtk_tree_model_get(model, &iter, SORTID_POS, &pos, -1); + + for (i = 0; i < job_info_ptr->record_count; i++) { + if(job_info_ptr->job_array[i].job_id == job_id) { + job_ptr = &job_info_ptr->job_array[i]; + if(!(info = slurm_sprint_job_info(job_ptr, 0))) { + info = xmalloc(100); + sprintf(info, + "Problem getting job info for %d", + job_ptr->job_id); + } + found = true; + break; + } + } + if(!found && pos > 0) { + for (i = 0; i < step_info_ptr->job_step_count; i++) { + if((step_info_ptr->job_steps[i].job_id == pos) + && step_info_ptr->job_steps[i].step_id == job_id) { + step_ptr = &step_info_ptr->job_steps[i]; + if(!(info = slurm_sprint_job_step_info( + step_ptr, 0))) { + info = xmalloc(100); + sprintf(info, + "Problem getting job " + "info for %d.%d", + step_ptr->job_id, + step_ptr->step_id); + } + } + found = true; + break; + } + if(!found) { + info = xmalloc(100); + sprintf(info, "Job step %d.%d was not found!", + pos, job_id); + } + } else if(!found) { + info = xmalloc(100); + sprintf(info, "Job %d was not found!", job_id); + } + + popup = gtk_dialog_new(); + + label = gtk_label_new(info); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(popup)->vbox), + label, TRUE, TRUE, 0); + xfree(info); + gtk_widget_show(label); + + gtk_widget_show(popup); + +} + +extern void popup_all_job(GtkTreeModel *model, GtkTreeIter *iter, int id) +{ + char *name = NULL; + char title[100]; + ListIterator itr = NULL; + popup_info_t *popup_win = NULL; + int jobid = -1; + GError *error = NULL; + + gtk_tree_model_get(model, iter, SORTID_JOBID, &jobid, -1); + switch(id) { + case PART_PAGE: + snprintf(title, 100, "Partition with job %d", jobid); + break; + case NODE_PAGE: +#ifdef HAVE_BG + snprintf(title, 100, + "Base partition(s) running job %d", jobid); +#else + snprintf(title, 100, "Node(s) running job %d", jobid); +#endif + break; + case BLOCK_PAGE: + snprintf(title, 100, "Block with job %d", jobid); + break; + case ADMIN_PAGE: + snprintf(title, 100, "Admin Page for job %d", jobid); + break; + case SUBMIT_PAGE: + snprintf(title, 100, "Submit job on job %d", jobid); + break; + default: + g_print("jobs got id %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) + popup_win = create_popup_info(JOB_PAGE, id, title); + + popup_win->type = id; + + switch(id) { + case NODE_PAGE: + gtk_tree_model_get(model, iter, SORTID_NODELIST, &name, -1); + popup_win->spec_info->data = name; + break; + case PART_PAGE: + gtk_tree_model_get(model, iter, SORTID_PARTITION, &name, -1); + popup_win->spec_info->data = name; + break; + case BLOCK_PAGE: + gtk_tree_model_get(model, iter, SORTID_BLOCK, &name, -1); + popup_win->spec_info->data = name; + break; + case ADMIN_PAGE: + gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1); + break; + case SUBMIT_PAGE: + gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1); + break; + default: + g_print("jobs got %d\n", id); + } + if (!g_thread_create(_popup_thr_job, popup_win, FALSE, &error)) + { + g_printerr ("Failed to create part popup thread: %s\n", + error->message); + return; + } +} diff --git a/src/sview/node_info.c b/src/sview/node_info.c new file mode 100644 index 00000000000..2d10a295b6b --- /dev/null +++ b/src/sview/node_info.c @@ -0,0 +1,489 @@ +/*****************************************************************************\ + * node_info.c - Functions related to node 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-217948. + * + * 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" + +#define _DEBUG 0 +DEF_TIMERS; + +enum { + SORTID_POS = POS_LOC, + SORTID_NAME, + SORTID_STATE, + SORTID_CPUS, + SORTID_MEMORY, + SORTID_DISK, + SORTID_WEIGHT, + SORTID_FEATURES, + SORTID_REASON, + SORTID_UPDATED, + SORTID_CNT +}; + +static display_data_t display_data_node[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1, refresh_node}, + {G_TYPE_STRING, SORTID_NAME, "Name", TRUE, -1, refresh_node}, + {G_TYPE_STRING, SORTID_STATE, "State", TRUE, -1, refresh_node}, + {G_TYPE_INT, SORTID_CPUS, "CPU Count", TRUE, -1, refresh_node}, + {G_TYPE_STRING, SORTID_MEMORY, "Real Memory", TRUE, -1, refresh_node}, + {G_TYPE_STRING, SORTID_DISK, "Tmp Disk", TRUE, -1, refresh_node}, + {G_TYPE_INT, SORTID_WEIGHT,"Weight", FALSE, -1, refresh_node}, + {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE, -1, refresh_node}, + {G_TYPE_STRING, SORTID_REASON, "Reason", FALSE, -1, refresh_node}, + {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, -1, refresh_node}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t options_data_node[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1}, + {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, NODE_PAGE}, +#ifdef HAVE_BG + {G_TYPE_STRING, BLOCK_PAGE, "Blocks", TRUE, NODE_PAGE}, +#endif + {G_TYPE_STRING, PART_PAGE, "Partition", TRUE, NODE_PAGE}, + {G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", TRUE, NODE_PAGE}, + {G_TYPE_STRING, ADMIN_PAGE, "Admin", TRUE, NODE_PAGE}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t *local_display_data = NULL; + +static void _update_node_record(node_info_t *node_ptr, + GtkTreeStore *treestore, GtkTreeIter *iter) +{ + char tmp_cnt[7]; + + gtk_tree_store_set(treestore, iter, SORTID_NAME, node_ptr->name, -1); + gtk_tree_store_set(treestore, iter, SORTID_STATE, + node_state_string(node_ptr->node_state), -1); + gtk_tree_store_set(treestore, iter, SORTID_CPUS, node_ptr->cpus, -1); + + convert_num_unit((float)node_ptr->real_memory, tmp_cnt, UNIT_MEGA); + gtk_tree_store_set(treestore, iter, SORTID_MEMORY, tmp_cnt, -1); + convert_num_unit((float)node_ptr->tmp_disk, tmp_cnt, UNIT_MEGA); + gtk_tree_store_set(treestore, iter, SORTID_DISK, tmp_cnt, -1); + gtk_tree_store_set(treestore, iter, SORTID_WEIGHT, + node_ptr->weight, -1); + gtk_tree_store_set(treestore, iter, SORTID_FEATURES, + node_ptr->features, -1); + gtk_tree_store_set(treestore, iter, SORTID_REASON, + node_ptr->reason, -1); + gtk_tree_store_set(treestore, iter, SORTID_UPDATED, 1, -1); + + return; +} + +static void _append_node_record(node_info_t *node_ptr, + GtkTreeStore *treestore, GtkTreeIter *iter, + int line) +{ + gtk_tree_store_append(treestore, iter, NULL); + gtk_tree_store_set(treestore, iter, SORTID_POS, line, -1); + _update_node_record(node_ptr, treestore, iter); +} + +static void _update_info_node(node_info_msg_t *node_info_ptr, + GtkTreeView *tree_view, + specific_info_t *spec_info) +{ + GtkTreePath *path = gtk_tree_path_new_first(); + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeIter iter; + node_info_t node; + int i, line = 0; + char *name; + hostlist_t hostlist = NULL; + hostlist_iterator_t itr = NULL; + + if(spec_info) { + hostlist = hostlist_create((char *)spec_info->data); + itr = hostlist_iterator_create(hostlist); + } + + /* 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; + } + } + } + for (i = 0; i < node_info_ptr->record_count; i++) { + node = node_info_ptr->node_array[i]; + /* 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 node name and check to see if + it is in the list */ + gtk_tree_model_get(model, &iter, SORTID_NAME, + &name, -1); + if(!strcmp(name, node.name)) { + /* update with new info */ + g_free(name); + _update_node_record(&node, + GTK_TREE_STORE(model), + &iter); + goto found; + } + g_free(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: + if(spec_info) { + int found = 0; + char *host = NULL; + while((host = hostlist_next(itr))) { + if(!strcmp(host, node.name)) { + free(host); + found = 1; + break; + } + free(host); + } + hostlist_iterator_reset(itr); + if(!found) + continue; + } + + _append_node_record(&node, GTK_TREE_STORE(model), &iter, i); + found: + ; + } + gtk_tree_path_free(path); + /* remove all old nodes */ + remove_old(model, SORTID_UPDATED); + if(spec_info) { + hostlist_iterator_destroy(itr); + hostlist_destroy(hostlist); + } + + +} + +void *_popup_thr_node(void *arg) +{ + popup_thr(arg); + return NULL; +} + +extern void refresh_node(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); + specific_info_node(popup_win); +} + +extern int get_new_info_node(node_info_msg_t **info_ptr) +{ + static node_info_msg_t *node_info_ptr = NULL, *new_node_ptr = NULL; + uint16_t show_flags = 0; + int error_code = SLURM_SUCCESS; + + show_flags |= SHOW_ALL; + if (node_info_ptr) { + error_code = slurm_load_node(node_info_ptr->last_update, + &new_node_ptr, show_flags); + if (error_code == SLURM_SUCCESS) + slurm_free_node_info_msg(node_info_ptr); + else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) { + error_code = SLURM_NO_CHANGE_IN_DATA; + new_node_ptr = node_info_ptr; + } + } else + error_code = slurm_load_node((time_t) NULL, &new_node_ptr, + show_flags); + node_info_ptr = new_node_ptr; + *info_ptr = new_node_ptr; + return error_code; +} + +extern void get_info_node(GtkTable *table, display_data_t *display_data) +{ + int error_code = SLURM_SUCCESS; + static int view = -1; + static node_info_msg_t *node_info_ptr = NULL; + char error_char[100]; + GtkWidget *label = NULL; + GtkTreeView *tree_view = NULL; + static GtkWidget *display_widget = NULL; + + if(display_data) + local_display_data = display_data; + if(!table) { + display_data_node->set_menu = local_display_data->set_menu; + return; + } + if(node_info_ptr && toggled) { + gtk_widget_destroy(display_widget); + display_widget = NULL; + goto display_it; + } + + if((error_code = get_new_info_node(&node_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA) { + if(!display_widget || view == ERROR_VIEW) + goto display_it; + goto end_it; + } + + if (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: %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: + if(view == ERROR_VIEW && display_widget) { + gtk_widget_destroy(display_widget); + display_widget = NULL; + } + if(!display_widget) { + tree_view = create_treeview(local_display_data, node_info_ptr); + + display_widget = gtk_widget_ref(GTK_WIDGET(tree_view)); + gtk_table_attach_defaults(GTK_TABLE(table), + GTK_WIDGET(tree_view), + 0, 1, 0, 1); + gtk_widget_show(GTK_WIDGET(tree_view)); + /* 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_node, SORTID_CNT); + } + view = INFO_VIEW; + _update_info_node(node_info_ptr, GTK_TREE_VIEW(display_widget), NULL); +end_it: + toggled = FALSE; + return; + +} + +extern void specific_info_node(popup_info_t *popup_win) +{ + int error_code = SLURM_SUCCESS; + static node_info_msg_t *node_info_ptr = NULL; + specific_info_t *spec_info = popup_win->spec_info; + char error_char[100]; + GtkWidget *label = NULL; + GtkTreeView *tree_view = NULL; + + if(!spec_info->display_widget) + setup_popup_info(popup_win, display_data_node, SORTID_CNT); + + if(node_info_ptr && popup_win->toggled) { + gtk_widget_destroy(spec_info->display_widget); + spec_info->display_widget = NULL; + goto display_it; + } + + if((error_code = get_new_info_node(&node_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA) { + if(!spec_info->display_widget || spec_info->view == ERROR_VIEW) + goto display_it; + goto end_it; + } + + if (error_code != SLURM_SUCCESS) { + if(spec_info->view == ERROR_VIEW) + goto end_it; + spec_info->view = ERROR_VIEW; + if(spec_info->display_widget) + gtk_widget_destroy(spec_info->display_widget); + sprintf(error_char, "slurm_load_node: %s", + slurm_strerror(slurm_get_errno())); + label = gtk_label_new(error_char); + gtk_table_attach_defaults(popup_win->table, + label, + 0, 1, 0, 1); + gtk_widget_show(label); + spec_info->display_widget = gtk_widget_ref(GTK_WIDGET(label)); + return; + } +display_it: + + 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->display_widget) { + tree_view = create_treeview(local_display_data, node_info_ptr); + + 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); + } + spec_info->view = INFO_VIEW; + _update_info_node(node_info_ptr, + GTK_TREE_VIEW(spec_info->display_widget), spec_info); +end_it: + popup_win->toggled = 0; + + return; + +} + +extern void set_menus_node(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_node); + break; + case ROW_CLICKED: + make_options_menu(tree_view, path, menu, options_data_node); + 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 row_clicked_node(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + node_info_msg_t *node_info_ptr = (node_info_msg_t *)user_data; + node_info_t *node_ptr = NULL; + int line = get_row_number(tree_view, path); + GtkWidget *popup = NULL; + GtkWidget *label = NULL; + char *info = NULL; + if(line == -1) { + g_error("problem getting line number"); + return; + } + + node_ptr = &node_info_ptr->node_array[line]; + if(!(info = slurm_sprint_node_table(node_ptr, 0))) { + info = xmalloc(100); + sprintf(info, "Problem getting node info for %s", + node_ptr->name); + } + + popup = gtk_dialog_new(); + + label = gtk_label_new(info); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(popup)->vbox), + label, TRUE, TRUE, 0); + xfree(info); + gtk_widget_show(label); + + gtk_widget_show(popup); +} + +extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id) +{ + char *name = NULL; + char title[100]; + ListIterator itr = NULL; + popup_info_t *popup_win = NULL; + GError *error = NULL; + +#ifdef HAVE_BG + char *node = "base partition"; +#else + char *node = "node"; +#endif + gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1); + switch(id) { + case JOB_PAGE: + snprintf(title, 100, "Jobs(s) with %s %s", node, name); + break; + case PART_PAGE: + snprintf(title, 100, "Partition(s) with %s %s", node, name); + break; + case BLOCK_PAGE: + snprintf(title, 100, "Blocks(s) with %s %s", node, name); + break; + case ADMIN_PAGE: + snprintf(title, 100, "Admin Page for %s %s", node, name); + break; + case SUBMIT_PAGE: + snprintf(title, 100, "Submit job on %s %s", node, name); + break; + default: + g_print("%s got %d\n", node, 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) + popup_win = create_popup_info(NODE_PAGE, id, title); + popup_win->spec_info->data = name; + + if (!g_thread_create(_popup_thr_node, popup_win, FALSE, &error)) + { + g_printerr ("Failed to create part popup thread: %s\n", + error->message); + return; + } +} diff --git a/src/sview/part_info.c b/src/sview/part_info.c new file mode 100644 index 00000000000..c18721184f0 --- /dev/null +++ b/src/sview/part_info.c @@ -0,0 +1,551 @@ +/*****************************************************************************\ + * 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-217948. + * + * 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" + +#define _DEBUG 0 +DEF_TIMERS; + +enum { + SORTID_POS = POS_LOC, + SORTID_NAME, + SORTID_AVAIL, + SORTID_TIMELIMIT, + SORTID_NODES, + SORTID_NODELIST, + SORTID_UPDATED, + SORTID_CNT +}; + +static display_data_t display_data_part[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1, refresh_part}, + {G_TYPE_STRING, SORTID_NAME, "Partition", TRUE, -1, refresh_part}, + {G_TYPE_STRING, SORTID_AVAIL, "Availablity", TRUE, -1, refresh_part}, + {G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", + TRUE, -1, refresh_part}, + {G_TYPE_STRING, SORTID_NODES, "Nodes", TRUE, -1, refresh_part}, +#ifdef HAVE_BG + {G_TYPE_STRING, SORTID_NODELIST, "BP List", TRUE, -1, refresh_part}, +#else + {G_TYPE_STRING, SORTID_NODELIST, "NodeList", TRUE, -1, refresh_part}, +#endif + {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, -1, refresh_part}, + + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t options_data_part[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1}, + {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", TRUE, PART_PAGE}, + {G_TYPE_STRING, ADMIN_PAGE, "Admin", TRUE, PART_PAGE}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t *local_display_data = NULL; + + +static void _update_part_record(partition_info_t *part_ptr, + GtkTreeStore *treestore, GtkTreeIter *iter) +{ + char time_buf[20]; + char tmp_cnt[7]; + + gtk_tree_store_set(treestore, iter, SORTID_NAME, part_ptr->name, -1); + + if (part_ptr->state_up) + gtk_tree_store_set(treestore, iter, SORTID_AVAIL, "up", -1); + else + gtk_tree_store_set(treestore, iter, SORTID_AVAIL, "down", -1); + + if (part_ptr->max_time == INFINITE) + snprintf(time_buf, sizeof(time_buf), "infinite"); + else { + snprint_time(time_buf, sizeof(time_buf), + (part_ptr->max_time * 60)); + } + + gtk_tree_store_set(treestore, iter, SORTID_TIMELIMIT, time_buf, -1); + + convert_to_kilo(part_ptr->total_nodes, tmp_cnt); + 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_UPDATED, 1, -1); + + return; +} +static void _append_part_record(partition_info_t *part_ptr, + 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(part_ptr, treestore, iter); +} + +static void _update_info_part(partition_info_msg_t *part_info_ptr, + GtkTreeView *tree_view, + specific_info_t *spec_info) +{ + GtkTreePath *path = gtk_tree_path_new_first(); + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + GtkTreeIter iter; + int i; + partition_info_t part; + int line = 0; + char *host = NULL, *host2 = NULL, *part_name = NULL; + hostlist_t hostlist = NULL; + int found = 0; + + if(spec_info) { + switch(spec_info->type) { + case NODE_PAGE: + hostlist = hostlist_create((char *)spec_info->data); + host = hostlist_shift(hostlist); + hostlist_destroy(hostlist); + if(host == NULL) { + g_print("nodelist was empty"); + return; + } + break; + } + } + + /* 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; + } + } + } + + for (i = 0; i < part_info_ptr->record_count; i++) { + part = part_info_ptr->partition_array[i]; + if (!part.nodes || (part.nodes[0] == '\0')) + continue; /* empty partition */ + /* 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.name)) { + /* update with new info */ + g_free(part_name); + _update_part_record(&part, + 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: + if(spec_info) { + switch(spec_info->type) { + case NODE_PAGE: + if(!part.nodes || !host) + continue; + + hostlist = hostlist_create(part.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 BLOCK_PAGE: + case JOB_PAGE: + if(strcmp(part.name, (char *)spec_info->data)) + continue; + break; + default: + g_print("Unkown type %d\n", spec_info->type); + continue; + } + } + _append_part_record(&part, GTK_TREE_STORE(model), + &iter, line); + found: + ; + } + if(host) + free(host); + + gtk_tree_path_free(path); + /* remove all old partitions */ + remove_old(model, SORTID_UPDATED); +} + +void *_popup_thr_part(void *arg) +{ + popup_thr(arg); + return NULL; +} + +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); + specific_info_part(popup_win); +} + +extern int get_new_info_part(partition_info_msg_t **part_ptr) +{ + static partition_info_msg_t *part_info_ptr = NULL; + static partition_info_msg_t *new_part_ptr = NULL; + int error_code = SLURM_SUCCESS; + + 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); + else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) { + error_code = SLURM_NO_CHANGE_IN_DATA; + new_part_ptr = part_info_ptr; + } + } else { + error_code = slurm_load_partitions((time_t) NULL, + &new_part_ptr, SHOW_ALL); + } + + part_info_ptr = new_part_ptr; + *part_ptr = new_part_ptr; + return error_code; +} + +extern void get_info_part(GtkTable *table, display_data_t *display_data) +{ + int error_code = SLURM_SUCCESS; + static int view = -1; + static partition_info_msg_t *part_info_ptr = NULL; + char error_char[100]; + GtkWidget *label = NULL; + GtkTreeView *tree_view = NULL; + static GtkWidget *display_widget = NULL; + + if(display_data) + local_display_data = display_data; + if(!table) { + display_data_part->set_menu = local_display_data->set_menu; + return; + } + if(part_info_ptr && toggled) { + gtk_widget_destroy(display_widget); + display_widget = NULL; + goto display_it; + } + + if((error_code = get_new_info_part(&part_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA) { + if(!display_widget || view == ERROR_VIEW) + goto display_it; + goto end_it; + } + + if (error_code != SLURM_SUCCESS) { + if(view == ERROR_VIEW) + goto end_it; + if(display_widget) + gtk_widget_destroy(display_widget); + view = ERROR_VIEW; + sprintf(error_char, "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; + } +display_it: + if(view == ERROR_VIEW && display_widget) { + gtk_widget_destroy(display_widget); + display_widget = NULL; + } + if(!display_widget) { + tree_view = create_treeview(local_display_data, part_info_ptr); + + display_widget = gtk_widget_ref(GTK_WIDGET(tree_view)); + gtk_table_attach_defaults(table, + GTK_WIDGET(tree_view), + 0, 1, 0, 1); + gtk_widget_show(GTK_WIDGET(tree_view)); + /* 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(part_info_ptr, GTK_TREE_VIEW(display_widget), NULL); +end_it: + toggled = FALSE; + + return; +} + +extern void specific_info_part(popup_info_t *popup_win) +{ + int error_code = SLURM_SUCCESS; + static partition_info_msg_t *part_info_ptr = NULL; + specific_info_t *spec_info = popup_win->spec_info; + char error_char[100]; + GtkWidget *label = NULL; + GtkTreeView *tree_view = NULL; + + if(!spec_info->display_widget) + setup_popup_info(popup_win, display_data_part, SORTID_CNT); + + if(part_info_ptr && popup_win->toggled) { + gtk_widget_destroy(spec_info->display_widget); + spec_info->display_widget = NULL; + goto display_it; + } + + if((error_code = get_new_info_part(&part_info_ptr)) + == SLURM_NO_CHANGE_IN_DATA) { + if(!spec_info->display_widget || spec_info->view == ERROR_VIEW) + goto display_it; + _update_info_part(part_info_ptr, + GTK_TREE_VIEW(spec_info->display_widget), + spec_info); + return; + } + + if (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; + sprintf(error_char, "slurm_load_partitions: %s", + slurm_strerror(slurm_get_errno())); + label = gtk_label_new(error_char); + gtk_table_attach_defaults(popup_win->table, + label, + 0, 1, 0, 1); + gtk_widget_show(label); + spec_info->display_widget = gtk_widget_ref(GTK_WIDGET(label)); + goto end_it; + } +display_it: + + 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->display_widget) { + tree_view = create_treeview(local_display_data, part_info_ptr); + + 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); + } + spec_info->view = INFO_VIEW; + _update_info_part(part_info_ptr, + GTK_TREE_VIEW(spec_info->display_widget), spec_info); +end_it: + popup_win->toggled = 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); + 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 row_clicked_part(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + partition_info_msg_t *part_info_ptr = + (partition_info_msg_t *)user_data; + partition_info_t *part_ptr = NULL; + int line = get_row_number(tree_view, path); + GtkWidget *popup = NULL; + GtkWidget *label = NULL; + char *info = NULL; + if(line == -1) { + g_error("problem getting line number"); + return; + } + + part_ptr = &part_info_ptr->partition_array[line]; + if(!(info = slurm_sprint_partition_info(part_ptr, 0))) { + info = xmalloc(100); + sprintf(info, "Problem getting partition info for %s", + part_ptr->name); + } + + popup = gtk_dialog_new(); + + label = gtk_label_new(info); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(popup)->vbox), + label, TRUE, TRUE, 0); + xfree(info); + gtk_widget_show(label); + + gtk_widget_show(popup); + +} + +extern void popup_all_part(GtkTreeModel *model, GtkTreeIter *iter, int id) +{ + char *name = NULL; + char title[100]; + 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: +#ifdef HAVE_BG + snprintf(title, 100, + "Base partition(s) in partition %s", name); +#else + snprintf(title, 100, "Node(s) in partition %s", name); +#endif + break; + case BLOCK_PAGE: + snprintf(title, 100, "Block(s) in partition %s", name); + break; + case ADMIN_PAGE: + snprintf(title, 100, "Admin page for partition %s", name); + break; + case SUBMIT_PAGE: + snprintf(title, 100, "Submit job in 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) + popup_win = create_popup_info(PART_PAGE, id, title); + + switch(id) { + case JOB_PAGE: + popup_win->spec_info->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->data = name; + //specific_info_node(popup_win); + break; + case BLOCK_PAGE: + popup_win->spec_info->data = name; + break; + case ADMIN_PAGE: + gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1); + break; + case SUBMIT_PAGE: + gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1); + break; + default: + g_print("part got %d\n", id); + } + if (!g_thread_create(_popup_thr_part, popup_win, FALSE, &error)) + { + g_printerr ("Failed to create part popup thread: %s\n", + error->message); + return; + } +} diff --git a/src/sview/submit_info.c b/src/sview/submit_info.c new file mode 100644 index 00000000000..04c07aeb800 --- /dev/null +++ b/src/sview/submit_info.c @@ -0,0 +1,128 @@ +/*****************************************************************************\ + * submit_info.c - Functions related to submit 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-217948. + * + * 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" + +#define _DEBUG 0 +DEF_TIMERS; + +enum { + SORTID_POS = POS_LOC, + SORTID_PARTITION, + SORTID_AVAIL, + SORTID_TIMELIMIT, + SORTID_NODES, + SORTID_NODELIST, + SORTID_CNT +}; + +static display_data_t display_data_submit[] = { + {G_TYPE_INT, SORTID_POS, NULL, FALSE, -1}, + {G_TYPE_STRING, SORTID_PARTITION, "PARTITION", TRUE, -1}, + {G_TYPE_STRING, SORTID_AVAIL, "AVAIL", TRUE, -1}, + {G_TYPE_STRING, SORTID_TIMELIMIT, "TIMELIMIT", TRUE, -1}, + {G_TYPE_STRING, SORTID_NODES, "NODES", TRUE, -1}, +#ifdef HAVE_BG + {G_TYPE_STRING, SORTID_NODELIST, "BP_LIST", TRUE, -1}, +#else + {G_TYPE_STRING, SORTID_NODELIST, "NODELIST", TRUE, -1}, +#endif + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t options_data_submit[] = { + {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, -1}, + {G_TYPE_STRING, NODE_PAGE, "Nodes", TRUE, -1}, + {G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", TRUE, -1}, + {G_TYPE_STRING, ADMIN_PAGE, "Admin", TRUE, -1}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +static display_data_t *local_display_data = NULL; + +extern void get_info_submit(GtkTable *table, display_data_t *display_data) +{ + local_display_data = display_data; +} + + +extern void set_menus_submit(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_submit); + break; + case ROW_CLICKED: + make_options_menu(tree_view, path, menu, options_data_submit); + 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 row_clicked_submit(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + /* job_info_msg_t *job_info_ptr = (job_info_msg_t *)user_data; */ +/* job_info_t *job_ptr = NULL; */ + int line = get_row_number(tree_view, path); + GtkWidget *popup = NULL; + GtkWidget *label = NULL; + char *info = NULL; + if(line == -1) { + g_error("problem getting line number"); + return; + } + +/* part_ptr = &new_part_ptr->partition_array[line]; */ + /* if(!(info = slurm_sprint_partition_info(part_ptr, 0))) { */ +/* info = xmalloc(100); */ +/* sprintf(info, "Problem getting partition info for %s", */ +/* part_ptr->name); */ +/* } */ + + popup = gtk_dialog_new(); + + label = gtk_label_new(info); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(popup)->vbox), + label, TRUE, TRUE, 0); + xfree(info); + gtk_widget_show(label); + + gtk_widget_show(popup); + +} + diff --git a/src/sview/sview.c b/src/sview/sview.c new file mode 100644 index 00000000000..81be8681741 --- /dev/null +++ b/src/sview/sview.c @@ -0,0 +1,364 @@ +/****************************************************************************\ + * sview.c - main for sview + ***************************************************************************** + * Copyright (C) 2004 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Danny Auble <da@llnl.gov> + * UCRL-CODE-217948. + * + * 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 "sview.h" + +#define MAX_RETRIES 3 /* g_thread_create retries */ + +typedef struct { + GtkTable *table; + int page_num; +} page_thr_t; + +/* globals */ +sview_parameters_t params; +int adding = 1; +int fini = 0; +bool toggled = FALSE; +List popup_list; +int page_running[PAGE_CNT]; + +GtkWidget *main_notebook = NULL; +display_data_t main_display_data[] = { + {G_TYPE_NONE, PART_PAGE, "Partitions", TRUE, -1, + refresh_main, get_info_part, specific_info_part, + set_menus_part, row_clicked_part, NULL}, + {G_TYPE_NONE, JOB_PAGE, "Jobs", TRUE, -1, + refresh_main, get_info_job, specific_info_job, + set_menus_job, row_clicked_job, NULL}, +#ifdef HAVE_BG + {G_TYPE_NONE, BLOCK_PAGE, "BG Blocks", TRUE, -1, + refresh_main, get_info_block, specific_info_block, + set_menus_block, row_clicked_block, NULL}, + {G_TYPE_NONE, NODE_PAGE, "Base Partitions", TRUE, -1, + refresh_main, get_info_node, specific_info_node, + set_menus_node, row_clicked_node, NULL}, +#else + {G_TYPE_NONE, BLOCK_PAGE, "BG Blocks", FALSE, -1, + refresh_main, get_info_block, specific_info_block, + set_menus_block, row_clicked_block, NULL}, + {G_TYPE_NONE, NODE_PAGE, "Nodes", TRUE, -1, + refresh_main, get_info_node, specific_info_node, + set_menus_node, row_clicked_node, NULL}, +#endif + {G_TYPE_NONE, SUBMIT_PAGE, "Submit Job", TRUE, -1, + refresh_main, NULL, NULL, + NULL, NULL, NULL}, + {G_TYPE_NONE, ADMIN_PAGE, "Admin", TRUE, -1, + refresh_main, NULL, NULL, + NULL, NULL, NULL}, + {G_TYPE_NONE, -1, NULL, FALSE, -1} +}; + +void *_page_thr(void *arg) +{ + page_thr_t *page = (page_thr_t *)arg; + int num = page->page_num; + GtkTable *table = page->table; + display_data_t *display_data = &main_display_data[num]; + xfree(page); + + while(page_running[num]) { + gdk_threads_enter(); + (display_data->get_info)(table, display_data); + gdk_flush(); + gdk_threads_leave(); + sleep(5); + } + + return NULL; +} + +static void _page_switched(GtkNotebook *notebook, + GtkNotebookPage *page, + guint page_num, + gpointer user_data) +{ + GtkScrolledWindow *window = GTK_SCROLLED_WINDOW( + gtk_notebook_get_nth_page(notebook, page_num)); + if(!window) + return; + GtkBin *bin = GTK_BIN(&window->container); + GtkViewport *view = GTK_VIEWPORT(bin->child); + GtkBin *bin2 = GTK_BIN(&view->bin); + GtkTable *table = GTK_TABLE(bin2->child); + int i; + static int running=-1; + + /* make sure we aren't adding the page, and really asking for info */ + if(adding) + return; + if(running != -1) { + page_running[running] = 0; + } + + for(i=0; i<PAGE_CNT; i++) { + if(main_display_data[i].id == -1) + break; + else if(!main_display_data[i].show) + continue; + if(main_display_data[i].extra == page_num) + break; + } + + if(main_display_data[i].extra != page_num) { + g_print("page %d not found\n", page_num); + return; + } + if(main_display_data[i].get_info) { + page_thr_t *page = xmalloc(sizeof(page_thr_t)); + GError *error = NULL; + running = i; + page_running[i] = 1; + + page->page_num = i; + page->table = table; + if (!g_thread_create(_page_thr, page, FALSE, &error)) + { + g_printerr ("Failed to create YES thread: %s\n", + error->message); + return; + } + } +} + +static void _tab_pos(GtkRadioAction *action, + GtkRadioAction *extra, + GtkNotebook *notebook) +{ + gtk_notebook_set_tab_pos(notebook, + gtk_radio_action_get_current_value(action)); +} + +static void _next_page(GtkAction *action, + GtkNotebook *notebook) +{ + int page = gtk_notebook_get_current_page(notebook); + int cnt = gtk_notebook_get_n_pages(notebook); + + cnt--; + + if(page < cnt) + gtk_notebook_next_page(notebook); + else + gtk_notebook_set_current_page(notebook, 0); +} + +static void _prev_page(GtkAction *action, + GtkNotebook *notebook) +{ + int page = gtk_notebook_get_current_page(notebook); + int cnt = gtk_notebook_get_n_pages(notebook); + + cnt--; + + if(page != 0) + gtk_notebook_prev_page(notebook); + else + gtk_notebook_set_current_page(notebook, cnt); + //gtk_notebook_prev_page(notebook); +} + +static void _init_pages() +{ + int i; + for(i=0; i<PAGE_CNT; i++) { + if(!main_display_data[i].get_info) + continue; + (main_display_data[i].get_info)(NULL, &main_display_data[i]); + } +} + +/* Our menu*/ +static const char *ui_description = +"<ui>" +" <menubar name='MainMenu'>" +" <menu action='Options'>" +" <menuitem action='Refresh'/>" +" <separator/>" +" <menu action='Tab Pos'>" +" <menuitem action='Top'/>" +" <menuitem action='Bottom'/>" +" <menuitem action='Left'/>" +" <menuitem action='Right'/>" +" </menu>" +" <separator/>" +" <menuitem action='NextPage'/>" +" <menuitem action='PrevPage'/>" +" </menu>" +" <menu action='Help'>" +" <menuitem action='About'/>" +" </menu>" +" </menubar>" +"</ui>"; + +static GtkActionEntry entries[] = { + {"Options", NULL, "_Options"}, + {"Tab Pos", NULL, "_Tab Pos"}, + {"NextPage", NULL, "_NextPage", + "<control>N", "Moves to next page", G_CALLBACK(_next_page)}, + {"PrevPage", NULL, "_PrevPage", + "<control>P", "Moves to previous page", G_CALLBACK(_prev_page)}, + {"Refresh", NULL, "Refresh", + "F5", "Refreshes page", G_CALLBACK(refresh_main)}, + {"Help", NULL, "_Help"}, + {"About", NULL, "_About"} +}; + +static GtkRadioActionEntry radio_entries[] = { + {"Top", NULL, "_Top", + "<control>T", "Move tabs to top", 2}, + {"Bottom", NULL, "_Bottom", + "<control>B", "Move tabs to the bottom", 3}, + {"Left", NULL, "_Left", + "<control>L", "Move tabs to the Left", 4}, + {"Right", NULL, "_Right", + "<control>R", "Move tabs to the Right", 1} +}; + +/* Returns a menubar widget made from the above menu */ +static GtkWidget *_get_menubar_menu(GtkWidget *window, GtkWidget *notebook) +{ + GtkActionGroup *action_group = NULL; + GtkUIManager *ui_manager = NULL; + GtkAccelGroup *accel_group = NULL; + GError *error = NULL; + + /* Make an accelerator group (shortcut keys) */ + action_group = gtk_action_group_new ("MenuActions"); + gtk_action_group_add_actions(action_group, entries, + G_N_ELEMENTS(entries), notebook); + gtk_action_group_add_radio_actions(action_group, radio_entries, + G_N_ELEMENTS(radio_entries), + 0, G_CALLBACK(_tab_pos), notebook); + ui_manager = gtk_ui_manager_new (); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + + accel_group = gtk_ui_manager_get_accel_group (ui_manager); + gtk_window_add_accel_group(GTK_WINDOW(window), accel_group); + + if (!gtk_ui_manager_add_ui_from_string (ui_manager, ui_description, + -1, &error)) + { + g_error("building menus failed: %s", error->message); + g_error_free (error); + exit (0); + } + + /* Finally, return the actual menu bar created by the item factory. */ + return gtk_ui_manager_get_widget (ui_manager, "/MainMenu"); +} + +static gboolean _delete(GtkWidget *widget, + GtkWidget *event, + gpointer data) +{ + gtk_main_quit (); + list_destroy(popup_list); + fini = 1; + return FALSE; +} + +int main(int argc, char *argv[]) +{ + GtkWidget *window; + GtkWidget *menubar; + int i=0; + + _init_pages(); + g_thread_init(NULL); + gdk_threads_init(); + gdk_threads_enter(); + /* Initialize GTK */ + gtk_init (&argc, &argv); + /* fill in all static info for pages */ + /* Make a window */ + window = gtk_dialog_new(); + g_signal_connect(G_OBJECT(window), "delete_event", + G_CALLBACK(_delete), NULL); + gtk_window_set_title(GTK_WINDOW(window), "Sview"); + gtk_window_set_default_size(GTK_WINDOW(window), 600, 400); + gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(window)->vbox), + 1); + /* Create the main notebook, place the position of the tabs */ + main_notebook = gtk_notebook_new(); + g_signal_connect(G_OBJECT(main_notebook), "switch_page", + G_CALLBACK(_page_switched), + NULL); + + /* Create a menu */ + menubar = _get_menubar_menu(window, main_notebook); + + gtk_notebook_popup_enable(GTK_NOTEBOOK(main_notebook)); + gtk_notebook_set_scrollable(GTK_NOTEBOOK(main_notebook), TRUE); + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(main_notebook), GTK_POS_TOP); + + /* Pack it all together */ + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), + menubar, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->vbox), + main_notebook, TRUE, TRUE, 0); + + for(i=0; i<PAGE_CNT; i++) { + if(main_display_data[i].id == -1) + break; + else if(!main_display_data[i].show) + continue; + create_page(GTK_NOTEBOOK(main_notebook), + &main_display_data[i]); + } + /* tell signal we are done adding */ + adding = 0; + popup_list = list_create(destroy_popup_info); + gtk_widget_show_all (window); + + /* Finished! */ + gtk_main (); + gdk_threads_leave(); + + return 0; +} + +extern void refresh_main(GtkAction *action, gpointer user_data) +{ + int page = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_notebook)); + if(page == -1) + g_error("no pages in notebook for refresh\n"); + _page_switched(GTK_NOTEBOOK(main_notebook), NULL, page, NULL); +} + +extern void tab_pressed(GtkWidget *widget, GdkEventButton *event, + const display_data_t *display_data) +{ + /* single click with the right mouse button? */ + gtk_notebook_set_current_page(GTK_NOTEBOOK(main_notebook), + display_data->extra); + if(event->button == 3) { + right_button_pressed(NULL, NULL, event, + display_data, TAB_CLICKED); + } +} + diff --git a/src/sview/sview.h b/src/sview/sview.h new file mode 100644 index 00000000000..1318606e76f --- /dev/null +++ b/src/sview/sview.h @@ -0,0 +1,286 @@ +/****************************************************************************\ + * sview.h - definitions used for sview data functions + ***************************************************************************** + * Copyright (C) 2004 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Danny Auble <da@llnl.gov> + * UCRL-CODE-217948. + * + * 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. +\****************************************************************************/ + +#ifndef _SVIEW_H +#define _SVIEW_H + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else /* !HAVE_INTTYPES_H */ +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif /* HAVE_INTTYPES_H */ + +#if HAVE_GETOPT_H +# include <getopt.h> +#else +# include "src/common/getopt.h" +#endif + +#include <stdlib.h> +#include <pwd.h> +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <gtk/gtk.h> + +#include "src/common/bitstring.h" +#include "src/common/hostlist.h" +#include "src/common/list.h" +#include "src/common/macros.h" +#include "src/plugins/select/bluegene/block_allocator/block_allocator.h" +#include "src/common/slurm_protocol_api.h" + +#include "src/plugins/select/bluegene/wrap_rm_api.h" + +/* getopt_long options, integers but not characters */ +#define OPT_LONG_HELP 0x100 +#define OPT_LONG_USAGE 0x101 +#define OPT_LONG_HIDE 0x102 + +#define POS_LOC 0 + +enum { PART_PAGE, + JOB_PAGE, + NODE_PAGE, + BLOCK_PAGE, + SUBMIT_PAGE, + ADMIN_PAGE, + PAGE_CNT +}; +enum { TAB_CLICKED, + ROW_CLICKED, + POPUP_CLICKED +}; + +enum { ERROR_VIEW, + INFO_VIEW +}; + +/* Input parameters */ +typedef struct { + bool all_flag; + bool no_header; + + char *format; + char *sort; + char *states; + + int iterate; + int verbose; + int display; + + bool long_output; + bool commandline; + bool parse; + + char *nodes; + char *partition; + + int node_field_size; + +} sview_parameters_t; + +typedef struct display_data display_data_t; +typedef struct specific_info specific_info_t; +typedef struct popup_info popup_info_t; + +struct display_data { + GType type; + int id; + char *name; + bool show; + int extra; + void (*refresh) (GtkAction *action, gpointer user_data); + void (*get_info) (GtkTable *table, display_data_t *display_data); + void (*specific) (popup_info_t *popup_win); + void (*set_menu) (void *arg, GtkTreePath *path, + GtkMenu *menu, int type); + void (*row_clicked) (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data); + gpointer user_data; +}; + +struct specific_info { + int type; /* calling window type */ + int view; + void *data; + char *title; + GtkWidget *display_widget; +}; + +struct popup_info { + int type; /* window type */ + int toggled; + int *running; + GtkWidget *popup; + GtkWidget *event_box; + GtkWidget *button; + GtkTable *table; + specific_info_t *spec_info; + display_data_t *display_data; +}; + +extern sview_parameters_t params; +extern int text_line_cnt; + +extern void parse_command_line(int argc, char *argv[]); + +extern ba_system_t *ba_system_ptr; +extern int quiet_flag; +extern bool toggled; +extern List popup_list; + + +extern void init_grid(node_info_msg_t *node_info_ptr); +extern int set_grid(int start, int end, int count); +extern int set_grid_bg(int *start, int *end, int count, int set); +extern void print_grid(int dir); + +extern void parse_command_line(int argc, char *argv[]); +extern void print_date(); +extern void clear_window(WINDOW *win); + +//sview.c +extern void refresh_main(GtkAction *action, gpointer user_data); +extern void tab_pressed(GtkWidget *widget, GdkEventButton *event, + const display_data_t *display_data); + +// part_info.c +extern void refresh_part(GtkAction *action, gpointer user_data); +extern int get_new_info_part(partition_info_msg_t **part_ptr); +extern void get_info_part(GtkTable *table, display_data_t *display_data); +extern void specific_info_part(popup_info_t *popup_win); +extern void set_menus_part(void *arg, GtkTreePath *path, + GtkMenu *menu, int type); +extern void row_clicked_part(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data); +extern void popup_all_part(GtkTreeModel *model, GtkTreeIter *iter, int id); + +// block_info.c +extern void refresh_block(GtkAction *action, gpointer user_data); +extern int get_new_info_node_select(node_select_info_msg_t **node_select_ptr); +extern void get_info_block(GtkTable *table, display_data_t *display_data); +extern void specific_info_block(popup_info_t *popup_win); +extern void set_menus_block(void *arg, GtkTreePath *path, + GtkMenu *menu, int type); +extern void row_clicked_block(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data); +extern void popup_all_block(GtkTreeModel *model, GtkTreeIter *iter, int id); + +// job_info.c +extern void refresh_job(GtkAction *action, gpointer user_data); +extern int get_new_info_job(job_info_msg_t **info_ptr); +extern int get_new_info_job_step(job_step_info_response_msg_t **info_ptr); +extern void get_info_job(GtkTable *table, display_data_t *display_data); +extern void specific_info_job(popup_info_t *popup_win); +extern void set_menus_job(void *arg, GtkTreePath *path, + GtkMenu *menu, int type); +extern void row_clicked_job(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data); +extern void popup_all_job(GtkTreeModel *model, GtkTreeIter *iter, int id); + +// admin_info.c +extern void get_info_admin(GtkTable *table, display_data_t *display_data); +extern void set_menus_admin(void *arg, GtkTreePath *path, + GtkMenu *menu, int type); +extern void row_clicked_admin(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data); + +// node_info.c +extern void refresh_node(GtkAction *action, gpointer user_data); +extern int get_new_info_node(node_info_msg_t **info_ptr); +extern void get_info_node(GtkTable *table, display_data_t *display_data); +extern void specific_info_node(popup_info_t *popup_win); +extern void set_menus_node(void *arg, GtkTreePath *path, + GtkMenu *menu, int type); +extern void row_clicked_node(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data); +extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id); + +// submit_info.c +extern void get_info_submit(GtkTable *table, display_data_t *display_data); +extern void set_menus_submit(void *arg, GtkTreePath *path, + GtkMenu *menu, int type); +extern void row_clicked_submit(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data); + +// common.c +extern void snprint_time(char *buf, size_t buf_size, time_t time); +extern int get_row_number(GtkTreeView *tree_view, GtkTreePath *path); +extern void load_header(GtkTreeView *tree_view, display_data_t *display_data); +extern void make_fields_menu(GtkMenu *menu, display_data_t *display_data); +extern void make_popup_fields_menu(popup_info_t *popup_win, GtkMenu *men); +extern void make_options_menu(GtkTreeView *tree_view, GtkTreePath *path, + GtkMenu *menu, display_data_t *display_data); +extern GtkScrolledWindow *create_scrolled_window(); +extern void create_page(GtkNotebook *notebook, display_data_t *display_data); +extern GtkTreeView *create_treeview(display_data_t *local, gpointer user_data); +extern GtkTreeStore *create_treestore(GtkTreeView *tree_view, + display_data_t *display_data, int count); +extern void right_button_pressed(GtkTreeView *tree_view, GtkTreePath *path, + GdkEventButton *event, + const display_data_t *display_data, + int type); +extern void row_clicked(GtkTreeView *tree_view, GdkEventButton *event, + const display_data_t *display_data); +extern popup_info_t *create_popup_info(int type, int dest_type, char *title); +extern void setup_popup_info(popup_info_t *popup_win, + display_data_t *display_data, + int cnt); +extern void redo_popup(GtkWidget *widget, GdkEventButton *event, + popup_info_t *popup_win); +extern void destroy_specific_info(void *arg); +extern void destroy_popup_info(void *arg); +extern gboolean delete_popup(GtkWidget *widget, GtkWidget *event, char *title); +extern void *popup_thr(popup_info_t *popup_win); +extern void remove_old(GtkTreeModel *model, int updated); + +#endif diff --git a/testsuite/expect/README b/testsuite/expect/README index 2c9009db232..2267c2b618c 100644 --- a/testsuite/expect/README +++ b/testsuite/expect/README @@ -23,14 +23,15 @@ ############################################################################ This directory contains a battery of SLURM regression tests. The tests make use -of the "expect" scripting language. You must copy "globals.example" to a new -file "globals" and modify that file to identify locations of files to be used -in testing, especially the variable "slurm_dir". These tests expect single -node jobs submitted to the default partition to respond within a one minutes. -If that is not the case, modify the value of "max_job_delay" in the "globals" -file to an appropriate value or the tests will report failures due to timeouts. +of the "expect" scripting language. You can create "globals.local" and +identify locations of files to be used in testing, especially the +variable "slurm_dir". These tests expect single node jobs submitted to the +default partition to respond within a one minutes. +If that is not the case, modify the value of "max_job_delay" in the +"globals.local" file to an appropriate value or the tests will report +failures due to timeouts. If there are file propagation delays (e.g. due to NFS), the value of -"max_file_delay" in the "globals" file may need modification. +"max_file_delay" in the "globals.local" file may need modification. Each test can be executed independently. Upon successful completion, the test will print "SUCCESS" and terminate with an exit code of zero. Upon failure, diff --git a/testsuite/expect/regression.py b/testsuite/expect/regression.py index 57dbcaadca9..8ed3f882d09 100755 --- a/testsuite/expect/regression.py +++ b/testsuite/expect/regression.py @@ -62,7 +62,7 @@ def main(argv=None): # Sanity check if not os.path.isfile('globals'): - print >>sys.stderr, 'ERROR: copy "globals.example" to "globals" and modify as needed' + print >>sys.stderr, 'ERROR: "globals" not here as needed' return -1 # Read the current working directory and build a sorted list -- GitLab