From 8fa3fe25bfa9d2187ca7118e4c5d567c089e2489 Mon Sep 17 00:00:00 2001 From: Danny Auble <da@llnl.gov> Date: Wed, 14 May 2008 22:59:55 +0000 Subject: [PATCH] fix for formatted output. Only works with associations though. Add this to the other types later. --- src/sacctmgr/association_functions.c | 251 +++++++++++++++++---------- src/sacctmgr/print.c | 90 +++++++--- src/sacctmgr/print.h | 6 +- src/sacctmgr/sacctmgr.c | 36 ++-- 4 files changed, 255 insertions(+), 128 deletions(-) diff --git a/src/sacctmgr/association_functions.c b/src/sacctmgr/association_functions.c index 9f89934d430..a49b96ff007 100644 --- a/src/sacctmgr/association_functions.c +++ b/src/sacctmgr/association_functions.c @@ -40,7 +40,8 @@ #include "print.h" static int _set_cond(int *start, int argc, char *argv[], - acct_association_cond_t *association_cond) + acct_association_cond_t *association_cond, + List format_list) { int i, end = 0; int set = 0; @@ -68,7 +69,10 @@ static int _set_cond(int *start, int argc, char *argv[], addto_char_list(association_cond->cluster_list, argv[i]+end); set = 1; - } else if (strncasecmp (argv[i], "Partitions", 4) == 0) { + } else if (strncasecmp (argv[i], "Format", 1) == 0) { + if(format_list) + addto_char_list(format_list, argv[i]+end); + } else if (strncasecmp (argv[i], "Partitions", 4) == 0) { addto_char_list(association_cond->partition_list, argv[i]+end); set = 1; @@ -196,122 +200,185 @@ extern int sacctmgr_list_association(int argc, char *argv[]) acct_association_rec_t *assoc = NULL; int i=0; ListIterator itr = NULL; + ListIterator itr2 = NULL; + char *object; - print_field_t id_field; - print_field_t parent_field; - print_field_t cluster_field; - print_field_t acct_field; - print_field_t user_field; - print_field_t part_field; - print_field_t fairshare_field; - print_field_t maxjobs_field; - print_field_t maxnodes_field; - print_field_t maxwall_field; - print_field_t maxcpu_field; + print_field_t *field = NULL; + List format_list = list_create(slurm_destroy_char); List print_fields_list; /* types are of print_field_t */ + enum { + PRINT_ACCOUNT, + PRINT_CLUSTER, + PRINT_FAIRSHARE, + PRINT_ID, + PRINT_MAXC, + PRINT_MAXJ, + PRINT_MAXN, + PRINT_MAXW, + PRINT_PID, + PRINT_PNAME, + PRINT_PART, + PRINT_USER + }; + assoc_cond->id_list = list_create(slurm_destroy_char); assoc_cond->user_list = list_create(slurm_destroy_char); assoc_cond->acct_list = list_create(slurm_destroy_char); assoc_cond->cluster_list = list_create(slurm_destroy_char); - _set_cond(&i, argc, argv, assoc_cond); + _set_cond(&i, argc, argv, assoc_cond, format_list); assoc_list = acct_storage_g_get_associations(db_conn, assoc_cond); destroy_acct_association_cond(assoc_cond); - if(!assoc_list) + if(!assoc_list) { + list_destroy(format_list); return SLURM_ERROR; + } + print_fields_list = list_create(destroy_print_field); - print_fields_list = list_create(NULL); - - id_field.name = "ID"; - id_field.len = 6; - id_field.print_routine = print_uint; - list_append(print_fields_list, &id_field); - - parent_field.name = "Parent"; - parent_field.len = 6; - parent_field.print_routine = print_uint; - list_append(print_fields_list, &parent_field); - - cluster_field.name = "Cluster"; - cluster_field.len = 10; - cluster_field.print_routine = print_str; - list_append(print_fields_list, &cluster_field); - - acct_field.name = "Account"; - acct_field.len = 10; - acct_field.print_routine = print_str; - list_append(print_fields_list, &acct_field); - - user_field.name = "User"; - user_field.len = 10; - user_field.print_routine = print_str; - list_append(print_fields_list, &user_field); - - part_field.name = "Partition"; - part_field.len = 10; - part_field.print_routine = print_str; - list_append(print_fields_list, &part_field); - - fairshare_field.name = "FairShare"; - fairshare_field.len = 9; - fairshare_field.print_routine = print_uint; - list_append(print_fields_list, &fairshare_field); - - maxjobs_field.name = "MaxJobs"; - maxjobs_field.len = 7; - maxjobs_field.print_routine = print_uint; - list_append(print_fields_list, &maxjobs_field); - - maxnodes_field.name = "MaxNodes"; - maxnodes_field.len = 8; - maxnodes_field.print_routine = print_uint; - list_append(print_fields_list, &maxnodes_field); + if(!list_count(format_list)) + addto_char_list(format_list, "C,A,U,F,MaxC,MaxJ,MaxN,MaxW"); - maxwall_field.name = "MaxWall"; - maxwall_field.len = 11; - maxwall_field.print_routine = print_time; - list_append(print_fields_list, &maxwall_field); - - maxcpu_field.name = "MaxCPUSecs"; - maxcpu_field.len = 11; - maxcpu_field.print_routine = print_uint; - list_append(print_fields_list, &maxcpu_field); - + itr = list_iterator_create(format_list); + while((object = list_next(itr))) { + field = xmalloc(sizeof(print_field_t)); + if(!strncasecmp("Account", object, 1)) { + field->type = PRINT_ACCOUNT; + field->name = xstrdup("Account"); + field->len = 10; + field->print_routine = print_str; + } else if(!strncasecmp("Cluster", object, 1)) { + field->type = PRINT_CLUSTER; + field->name = xstrdup("Cluster"); + field->len = 10; + field->print_routine = print_str; + } else if(!strncasecmp("FairShare", object, 1)) { + field->type = PRINT_FAIRSHARE; + field->name = xstrdup("FairShare"); + field->len = 9; + field->print_routine = print_uint; + } else if(!strncasecmp("ID", object, 1)) { + field->type = PRINT_ID; + field->name = xstrdup("ID"); + field->len = 6; + field->print_routine = print_uint; + } else if(!strncasecmp("MaxCPUSecs", object, 4)) { + field->type = PRINT_MAXC; + field->name = xstrdup("MaxCPUSecs"); + field->len = 11; + field->print_routine = print_uint; + } else if(!strncasecmp("MaxJobs", object, 4)) { + field->type = PRINT_MAXJ; + field->name = xstrdup("MaxJobs"); + field->len = 7; + field->print_routine = print_uint; + } else if(!strncasecmp("MaxNodes", object, 4)) { + field->type = PRINT_MAXN; + field->name = xstrdup("MaxNodes"); + field->len = 8; + field->print_routine = print_uint; + } else if(!strncasecmp("MaxWall", object, 4)) { + field->type = PRINT_MAXW; + field->name = xstrdup("MaxWall"); + field->len = 11; + field->print_routine = print_time; + } else if(!strncasecmp("ParentID", object, 7)) { + field->type = PRINT_PID; + field->name = xstrdup("Par ID"); + field->len = 6; + field->print_routine = print_uint; + } else if(!strncasecmp("ParentName", object, 7)) { + field->type = PRINT_PNAME; + field->name = xstrdup("Par Name"); + field->len = 10; + field->print_routine = print_str; + } else if(!strncasecmp("Partition", object, 4)) { + field->type = PRINT_PART; + field->name = xstrdup("Partition"); + field->len = 10; + field->print_routine = print_str; + } else if(!strncasecmp("User", object, 1)) { + field->type = PRINT_USER; + field->name = xstrdup("User"); + field->len = 10; + field->print_routine = print_str; + } else { + printf("Unknown field '%s'", object); + xfree(field); + continue; + } + list_append(print_fields_list, field); + } + list_iterator_destroy(itr); itr = list_iterator_create(assoc_list); + itr2 = list_iterator_create(print_fields_list); print_header(print_fields_list); while((assoc = list_next(itr))) { - id_field.print_routine(VALUE, &id_field, assoc->id); - - parent_field.print_routine(VALUE, &parent_field, - assoc->parent_id); - - cluster_field.print_routine(VALUE, &cluster_field, - assoc->cluster); - acct_field.print_routine(VALUE, &acct_field, assoc->acct); - user_field.print_routine(VALUE, &user_field, assoc->user); - part_field.print_routine(VALUE, &part_field, assoc->partition); - fairshare_field.print_routine(VALUE, &fairshare_field, - assoc->fairshare); - maxjobs_field.print_routine(VALUE, &maxjobs_field, - assoc->max_jobs); - maxnodes_field.print_routine(VALUE, &maxnodes_field, - assoc->max_nodes_per_job); - maxwall_field.print_routine(VALUE, &maxwall_field, - assoc->max_wall_duration_per_job); - maxcpu_field.print_routine(VALUE, &maxcpu_field, - assoc->max_cpu_secs_per_job); - + while((field = list_next(itr2))) { + switch(field->type) { + case PRINT_ACCOUNT: + field->print_routine(VALUE, field, assoc->acct); + break; + case PRINT_CLUSTER: + field->print_routine(VALUE, field, + assoc->cluster); + break; + case PRINT_FAIRSHARE: + field->print_routine(VALUE, field, + assoc->fairshare); + break; + case PRINT_ID: + field->print_routine(VALUE, field, assoc->id); + break; + case PRINT_MAXC: + field->print_routine( + VALUE, field, + assoc->max_cpu_secs_per_job); + break; + case PRINT_MAXJ: + field->print_routine(VALUE, field, + assoc->max_jobs); + break; + case PRINT_MAXN: + field->print_routine(VALUE, field, + assoc->max_nodes_per_job); + break; + case PRINT_MAXW: + field->print_routine( + VALUE, field, + assoc->max_wall_duration_per_job); + break; + case PRINT_PID: + field->print_routine(VALUE, field, + assoc->parent_id); + break; + case PRINT_PNAME: + field->print_routine(VALUE, field, + assoc->parent_acct); + break; + case PRINT_PART: + field->print_routine(VALUE, field, + assoc->partition); + break; + case PRINT_USER: + field->print_routine(VALUE, field, assoc->user); + break; + default: + break; + } + } + list_iterator_reset(itr2); printf("\n"); } printf("\n"); + list_iterator_destroy(itr2); list_iterator_destroy(itr); list_destroy(assoc_list); list_destroy(print_fields_list); diff --git a/src/sacctmgr/print.c b/src/sacctmgr/print.c index 81c13cf3e5b..90d821eb59f 100644 --- a/src/sacctmgr/print.c +++ b/src/sacctmgr/print.c @@ -37,6 +37,8 @@ \*****************************************************************************/ #include "print.h" #include "src/common/parse_time.h" +int parsable_print = 0; +int have_header = 1; extern void destroy_print_field(void *object) { @@ -53,7 +55,7 @@ extern void print_header(List print_fields_list) ListIterator itr = NULL; print_field_t *object = NULL; - if(!print_fields_list) + if(!print_fields_list || !have_header) return; itr = list_iterator_create(print_fields_list); @@ -62,6 +64,8 @@ extern void print_header(List print_fields_list) } list_iterator_reset(itr); printf("\n"); + if(parsable_print) + return; while((object = list_next(itr))) { (object->print_routine)(UNDERSCORE, object, 0); } @@ -84,20 +88,34 @@ extern void print_str(type_t type, print_field_t *field, char *value) switch(type) { case HEADLINE: - printf("%-*.*s ", field->len, field->len, field->name); + if(parsable_print) + printf("%s|", field->name); + else + printf("%-*.*s ", field->len, field->len, field->name); break; case UNDERSCORE: - printf("%-*.*s ", field->len, field->len, - "---------------------------------------"); + if(!parsable_print) + printf("%-*.*s ", field->len, field->len, + "---------------------------------------"); break; case VALUE: - if(!print_this) - print_this = " "; - - printf("%-*.*s ", field->len, field->len, print_this); + if(!print_this) { + if(parsable_print) + print_this = ""; + else + print_this = " "; + } + + if(parsable_print) + printf("%s|", print_this); + else + printf("%-*.*s ", field->len, field->len, print_this); break; default: - printf("%-*s ", field->len, "n/a"); + if(parsable_print) + printf("%s|", "n/a"); + else + printf("%-*s ", field->len, "n/a"); break; } } @@ -106,21 +124,35 @@ extern void print_uint(type_t type, print_field_t *field, uint32_t value) { switch(type) { case HEADLINE: - printf("%-*.*s ", field->len, field->len, field->name); + if(parsable_print) + printf("%s|", field->name); + else + printf("%-*.*s ", field->len, field->len, field->name); break; case UNDERSCORE: - printf("%-*.*s ", field->len, field->len, - "---------------------------------------"); + if(!parsable_print) + printf("%-*.*s ", field->len, field->len, + "---------------------------------------"); break; case VALUE: /* (value == unset) || (value == cleared) */ - if((value == NO_VAL) || (value == INFINITE)) - printf("%-*s ", field->len, " "); - else - printf("%*u ", field->len, value); + if((value == NO_VAL) || (value == INFINITE)) { + if(parsable_print) + printf("|"); + else + printf("%-*s ", field->len, " "); + } else { + if(parsable_print) + printf("%u|", value); + else + printf("%*u ", field->len, value); + } break; default: - printf("%-*.*s ", field->len, field->len, "n/a"); + if(parsable_print) + printf("%s|", "n/a"); + else + printf("%-*.*s ", field->len, field->len, "n/a"); break; } } @@ -129,21 +161,31 @@ extern void print_time(type_t type, print_field_t *field, uint32_t value) { switch(type) { case HEADLINE: - printf("%-*.*s ", field->len, field->len, field->name); + if(parsable_print) + printf("%s|", field->name); + else + printf("%-*.*s ", field->len, field->len, field->name); break; case UNDERSCORE: - printf("%-*.*s ", field->len, field->len, - "---------------------------------------"); + if(!parsable_print) + printf("%-*.*s ", field->len, field->len, + "---------------------------------------"); break; case VALUE: /* (value == unset) || (value == cleared) */ - if((value == NO_VAL) || (value == INFINITE)) - printf("%-*s ", field->len, " "); - else { + if((value == NO_VAL) || (value == INFINITE)) { + if(parsable_print) + printf("|"); + else + printf("%-*s ", field->len, " "); + } else { char time_buf[32]; mins2time_str((time_t) value, time_buf, sizeof(time_buf)); - printf("%*s ", field->len, time_buf); + if(parsable_print) + printf("%s|", time_buf); + else + printf("%*s ", field->len, time_buf); } break; default: diff --git a/src/sacctmgr/print.h b/src/sacctmgr/print.h index 7e2d770c931..4fe15b98ca8 100644 --- a/src/sacctmgr/print.h +++ b/src/sacctmgr/print.h @@ -73,11 +73,15 @@ typedef enum { HEADLINE, } type_t; typedef struct { - char *name; /* name to be printed in header */ uint16_t len; /* what is the width of the print */ + char *name; /* name to be printed in header */ void (*print_routine) (); /* what is the function to print with */ + uint16_t type; /* defined in the local function */ } print_field_t; +extern int parsable_print; +extern int have_header; + extern void destroy_print_field(void *object); extern void print_header(List print_fields_list); extern void print_date(void); diff --git a/src/sacctmgr/sacctmgr.c b/src/sacctmgr/sacctmgr.c index 9dc2a72b827..8f8a5799836 100644 --- a/src/sacctmgr/sacctmgr.c +++ b/src/sacctmgr/sacctmgr.c @@ -107,6 +107,8 @@ main (int argc, char *argv[]) {"hide", 0, 0, OPT_LONG_HIDE}, {"immediate",0, 0, 'i'}, {"oneliner", 0, 0, 'o'}, + {"no_header", 0, 0, 'n'}, + {"parsable", 0, 0, 'p'}, {"quiet", 0, 0, 'q'}, {"usage", 0, 0, 'h'}, {"verbose", 0, 0, 'v'}, @@ -126,7 +128,7 @@ main (int argc, char *argv[]) if (getenv ("SACCTMGR_ALL")) all_flag= 1; - while((opt_char = getopt_long(argc, argv, "ahioqsvV", + while((opt_char = getopt_long(argc, argv, "ahionpqsvV", long_options, &option_index)) != -1) { switch (opt_char) { case (int)'?': @@ -149,6 +151,12 @@ main (int argc, char *argv[]) case (int)'o': one_liner = 1; break; + case (int)'n': + have_header = 0; + break; + case (int)'p': + parsable_print = 1; + break; case (int)'q': quiet_flag = 1; break; @@ -1361,9 +1369,12 @@ sacctmgr [<OPTION>] [<COMMAND>] \n\ list <ENTITY> [<SPECS>] display info of identified entity, default \n\ is display all. \n\ modify <ENTITY> <SPECS> modify entity \n\ + no_header no header will be added to the beginning of \n\ + output. \n\ oneliner report output one record per line. \n\ quiet print no messages other than error messages. \n\ quit terminate this command. \n\ + parsable output will be | delimited \n\ show same as list \n\ verbose enable detailed logging. \n\ version display tool version number. \n\ @@ -1372,15 +1383,7 @@ sacctmgr [<OPTION>] [<COMMAND>] \n\ <ENTITY> may be \"cluster\", \"account\", or \"user\". \n\ \n\ <SPECS> are different for each command entity pair. \n\ - list cluster - Names= \n\ - add cluster - Fairshare=, MaxCPUSecs=, \n\ - MaxJobs=, MaxNodes=, MaxWall=, and Names= \n\ - modify cluster - (set options) Fairshare=, MaxCPUSecs=, \n\ - MaxJobs=, MaxNodes=, and MaxWall= \n\ - (where options) Names= \n\ - delete cluster - Names= \n\ - \n\ - list account - Clusters=, Descriptions=, Names=, \n\ + list account - Clusters=, Descriptions=, Format=, Names=, \n\ Organizations=, Parents=, and WithAssocs \n\ add account - Clusters=, Description=, Fairshare=, \n\ MaxCPUSecs=, MaxJobs=, MaxNodes=, MaxWall=, \n\ @@ -1393,7 +1396,18 @@ sacctmgr [<OPTION>] [<COMMAND>] \n\ delete account - Clusters=, Descriptions=, Names=, \n\ Organizations=, and Parents= \n\ \n\ - list user - AdminLevel=, DefaultAccounts=, Names=, \n\ + list associations - Accounts=, Clusters=, Format=, ID=, \n\ + Partitions=, Parent=, Users= \n\ + \n\ + list cluster - Names= Format= \n\ + add cluster - Fairshare=, MaxCPUSecs=, \n\ + MaxJobs=, MaxNodes=, MaxWall=, and Names= \n\ + modify cluster - (set options) Fairshare=, MaxCPUSecs=, \n\ + MaxJobs=, MaxNodes=, and MaxWall= \n\ + (where options) Names= \n\ + delete cluster - Names= \n\ + \n\ + list user - AdminLevel=, DefaultAccounts=, Format=, Names=,\n\ QosLevel=, and WithAssocs \n\ add user - Accounts=, AdminLevel=, Clusters=, \n\ DefaultAccount=, Fairshare=, MaxCPUSecs=, \n\ -- GitLab