From cdf9dbd37eb17155a7f4e6c77fcdb44fa1ca7ea9 Mon Sep 17 00:00:00 2001 From: Danny Auble <da@llnl.gov> Date: Thu, 2 Dec 2010 00:38:27 +0000 Subject: [PATCH] added new report for sreport job SizesByAccountAndWckey --- contribs/perlapi/libslurmdb/perl/cluster.c | 5 +- doc/man/man1/sreport.1 | 16 +- slurm/slurmdb.h | 7 + src/db_api/job_report_functions.c | 315 ++++++++++++++------- src/sreport/common.c | 4 +- src/sreport/job_reports.c | 237 +++++++++++++++- src/sreport/job_reports.h | 1 + src/sreport/sreport.c | 22 +- 8 files changed, 488 insertions(+), 119 deletions(-) diff --git a/contribs/perlapi/libslurmdb/perl/cluster.c b/contribs/perlapi/libslurmdb/perl/cluster.c index 7757957cf31..f94e9492032 100644 --- a/contribs/perlapi/libslurmdb/perl/cluster.c +++ b/contribs/perlapi/libslurmdb/perl/cluster.c @@ -218,7 +218,8 @@ hv_to_user_cond(HV* hv, slurmdb_user_cond_t* user_cond) int report_job_grouping_to_hv(slurmdb_report_job_grouping_t* rec, HV* hv) { - /* List jobs should be null*/ + /* FIX ME: include the job list here (is is not NULL, as + * previously thought) */ STORE_FIELD(hv, rec, min_size, uint32_t); STORE_FIELD(hv, rec, max_size, uint32_t); STORE_FIELD(hv, rec, count, uint32_t); @@ -236,6 +237,7 @@ report_acct_grouping_to_hv(slurmdb_report_acct_grouping_t* rec, HV* hv) ListIterator itr = NULL; STORE_FIELD(hv, rec, acct, charp); + STORE_FIELD(hv, rec, count, uint32_t); STORE_FIELD(hv, rec, cpu_secs, uint64_t); STORE_FIELD(hv, rec, lft, uint32_t); STORE_FIELD(hv, rec, rgt, uint32_t); @@ -266,6 +268,7 @@ report_cluster_grouping_to_hv(slurmdb_report_cluster_grouping_t* rec, HV* hv) ListIterator itr = NULL; STORE_FIELD(hv, rec, cluster, charp); + STORE_FIELD(hv, rec, count, uint32_t); STORE_FIELD(hv, rec, cpu_secs, uint64_t); if (rec->acct_list) { diff --git a/doc/man/man1/sreport.1 b/doc/man/man1/sreport.1 index c326f23959f..aa0ba34b6c1 100644 --- a/doc/man/man1/sreport.1 +++ b/doc/man/man1/sreport.1 @@ -140,7 +140,7 @@ Valid report types are: UserUtilizationByWckey, Utilization, WCKeyUtilizationByUser .B job -\- SizesByAccount, SizesByWckey +\- SizesByAccount, SizesByAccountAndWcKey, SizesByWckey .B reservation \- Utilization @@ -188,6 +188,12 @@ accounts with the 'account=' option sreport will use those accounts as the root account and you will receive the sub accounts for the accounts listed. .TP +.B job SizesByAccountAndWckey +This report is very similar to SizesByAccount with the difference being +each account is pair with wckeys so the identifier is account:wckey +instead of just account so there will most likely be multiple accounts +listed depending on the number of wckeys used. +.TP .B job SizesByWckey This report will dispay the amount of time for each wckey for job ranges specified by the 'grouping=' option. @@ -277,15 +283,15 @@ List of wckeys to include in report. Default is all. .TP .B Accounts=<OPT> -List of accounts to use for the report Default is all. The SizesByAccount +List of accounts to use for the report Default is all. The SizesByAccount(*) report only displays 1 hierarchical level. If accounts are specified the next layer of accounts under those specified will be displayed, -not the accounts specified. In the SizesByAccount reports the default +not the accounts specified. In the SizesByAccount(*) reports the default for accounts is root. This explanation does not apply when ran with the FlatView option. .TP .B FlatView -When used with the SizesbyAccount will not group accounts in a +When used with the SizesbyAccount(*) will not group accounts in a hierarchical level, but print each account where jobs ran on a separate line without any hierarchy. .TP @@ -371,7 +377,7 @@ Allocated, Cluster, CPUCount, Down, Idle, Overcommited, PlannedDown, Reported, R .TP \fBFORMAT OPTIONS FOR JOB REPORTS\fP .in 10 -SizesByAccount: +SizesByAccount, SizesByAccountAndWckey: .in 14 Account, Cluster diff --git a/slurm/slurmdb.h b/slurm/slurmdb.h index 9c8c9893e21..61a2c17833f 100644 --- a/slurm/slurmdb.h +++ b/slurm/slurmdb.h @@ -851,6 +851,7 @@ typedef struct { typedef struct { char *acct; /*account name */ + uint32_t count; /* total count of jobs taken up by this acct */ uint64_t cpu_secs; /* how many cpus secs taken up by this * acct */ List groups; /* containing slurmdb_report_job_grouping_t's*/ @@ -860,6 +861,7 @@ typedef struct { typedef struct { char *cluster; /*cluster name */ + uint32_t count; /* total count of jobs taken up by this cluster */ uint64_t cpu_secs; /* how many cpus secs taken up by this * cluster */ List acct_list; /* containing slurmdb_report_acct_grouping_t's */ @@ -1041,6 +1043,11 @@ extern List slurmdb_report_job_sizes_grouped_by_top_account(void *db_conn, extern List slurmdb_report_job_sizes_grouped_by_wckey(void *db_conn, slurmdb_job_cond_t *job_cond, List grouping_list); +extern List slurmdb_report_job_sizes_grouped_by_top_account_then_wckey( + void *db_conn, slurmdb_job_cond_t *job_cond, + List grouping_list, bool flat_view); + + /* report on users with top usage * IN: slurmdb_user_cond_t *user_cond * IN: group_accounts - Whether or not to group all accounts together diff --git a/src/db_api/job_report_functions.c b/src/db_api/job_report_functions.c index 647c5c0345c..8d702571cab 100644 --- a/src/db_api/job_report_functions.c +++ b/src/db_api/job_report_functions.c @@ -62,20 +62,99 @@ static int _sort_group_asc(char *group_a, char *group_b) return 0; } -static List _process_grouped_report(void *db_conn, - slurmdb_job_cond_t *job_cond, List grouping_list, - bool flat_view, bool wckey_type) +static void _check_create_grouping( + List cluster_list, ListIterator group_itr, + char *cluster, char *name, void *object, + bool individual, bool wckey_type) +{ + ListIterator itr; + slurmdb_wckey_rec_t *wckey = (slurmdb_wckey_rec_t *)object; + slurmdb_association_rec_t *assoc = (slurmdb_association_rec_t *)object; + slurmdb_report_cluster_grouping_t *cluster_group = NULL; + slurmdb_report_acct_grouping_t *acct_group = NULL; + slurmdb_report_job_grouping_t *job_group = NULL; + + itr = list_iterator_create(cluster_list); + while((cluster_group = list_next(itr))) { + if(!strcmp(cluster, cluster_group->cluster)) + break; + } + list_iterator_destroy(itr); + + if(!cluster_group) { + cluster_group = xmalloc( + sizeof(slurmdb_report_cluster_grouping_t)); + cluster_group->cluster = xstrdup(cluster); + cluster_group->acct_list = list_create( + slurmdb_destroy_report_acct_grouping); + list_append(cluster_list, cluster_group); + } + + itr = list_iterator_create(cluster_group->acct_list); + while((acct_group = list_next(itr))) { + if(!strcmp(name, acct_group->acct)) + break; + } + list_iterator_destroy(itr); + + if(!acct_group) { + uint32_t last_size = 0; + char *group = NULL; + acct_group = xmalloc(sizeof(slurmdb_report_acct_grouping_t)); + + acct_group->acct = xstrdup(name); + if (wckey_type == 1 || wckey_type == 3) + acct_group->lft = wckey->id; + else { + acct_group->lft = assoc->lft; + acct_group->rgt = assoc->rgt; + } + acct_group->groups = list_create( + slurmdb_destroy_report_job_grouping); + list_append(cluster_group->acct_list, acct_group); + while ((group = list_next(group_itr))) { + job_group = xmalloc( + sizeof(slurmdb_report_job_grouping_t)); + job_group->jobs = list_create(NULL); + if(!individual) + job_group->min_size = last_size; + last_size = atoi(group); + if(!individual) + job_group->max_size = last_size-1; + else + job_group->min_size = + job_group->max_size = last_size; + list_append(acct_group->groups, job_group); + } + if(last_size && !individual) { + job_group = xmalloc( + sizeof(slurmdb_report_job_grouping_t)); + job_group->jobs = list_create(NULL); + job_group->min_size = last_size; + if(individual) + job_group->max_size = + job_group->min_size; + else + job_group->max_size = INFINITE; + list_append(acct_group->groups, job_group); + } + list_iterator_reset(group_itr); + } +} + +static List _process_grouped_report( + void *db_conn, slurmdb_job_cond_t *job_cond, List grouping_list, + bool flat_view, bool wckey_type, bool both) { int exit_code = 0; - void *object = NULL; + void *object = NULL, *object2 = NULL; - ListIterator itr = NULL; + ListIterator itr = NULL, itr2 = NULL; ListIterator cluster_itr = NULL; ListIterator local_itr = NULL; ListIterator acct_itr = NULL; ListIterator group_itr = NULL; - slurmdb_job_rec_t *job = NULL; slurmdb_report_cluster_grouping_t *cluster_group = NULL; slurmdb_report_acct_grouping_t *acct_group = NULL; @@ -83,7 +162,7 @@ static List _process_grouped_report(void *db_conn, List job_list = NULL; List cluster_list = NULL; - List object_list = NULL; + List object_list = NULL, object2_list = NULL; List tmp_acct_list = NULL; bool destroy_job_cond = 0; @@ -152,15 +231,7 @@ static List _process_grouped_report(void *db_conn, if(flat_view) goto no_objects; - if(wckey_type) { - slurmdb_wckey_cond_t wckey_cond; - memset(&wckey_cond, 0, sizeof(slurmdb_wckey_cond_t)); - wckey_cond.name_list = job_cond->wckey_list; - wckey_cond.cluster_list = job_cond->cluster_list; - - object_list = acct_storage_g_get_wckeys(db_conn, my_uid, - &wckey_cond); - } else { + if (!wckey_type || both) { slurmdb_association_cond_t assoc_cond; memset(&assoc_cond, 0, sizeof(slurmdb_association_cond_t)); assoc_cond.id_list = job_cond->associd_list; @@ -178,98 +249,83 @@ static List _process_grouped_report(void *db_conn, &assoc_cond); } + if (wckey_type || both) { + slurmdb_wckey_cond_t wckey_cond; + memset(&wckey_cond, 0, sizeof(slurmdb_wckey_cond_t)); + wckey_cond.name_list = job_cond->wckey_list; + wckey_cond.cluster_list = job_cond->cluster_list; + + object2_list = acct_storage_g_get_wckeys(db_conn, my_uid, + &wckey_cond); + if (!object_list) { + object_list = object2_list; + object2_list = NULL; + } + } + if(!object_list) { debug2(" No join list given.\n"); goto no_objects; } itr = list_iterator_create(object_list); + if (object2_list) + itr2 = list_iterator_create(object2_list); while((object = list_next(itr))) { - char *cluster = NULL, *name = NULL; + char *cluster = NULL; slurmdb_wckey_rec_t *wckey = (slurmdb_wckey_rec_t *)object; slurmdb_association_rec_t *assoc = (slurmdb_association_rec_t *)object; - - if(wckey_type) { - cluster = wckey->cluster; - name = wckey->name; - } else { - cluster = assoc->cluster; - name = assoc->acct; - } - - while((cluster_group = list_next(cluster_itr))) { - if(!strcmp(cluster, cluster_group->cluster)) - break; - } - if(!cluster_group) { - cluster_group = xmalloc( - sizeof(slurmdb_report_cluster_grouping_t)); - cluster_group->cluster = xstrdup(cluster); - cluster_group->acct_list = list_create( - slurmdb_destroy_report_acct_grouping); - list_append(cluster_list, cluster_group); - } - - acct_itr = list_iterator_create(cluster_group->acct_list); - while((acct_group = list_next(acct_itr))) { - if(!strcmp(name, acct_group->acct)) - break; + if (!itr2) { + char *name = NULL; + if(wckey_type) { + cluster = wckey->cluster; + name = wckey->name; + } else { + cluster = assoc->cluster; + name = assoc->acct; + } + _check_create_grouping(cluster_list, group_itr, + cluster, name, object, + individual, wckey_type); + continue; } - list_iterator_destroy(acct_itr); - if(!acct_group) { - uint32_t last_size = 0; - char *group = NULL; - acct_group = xmalloc( - sizeof(slurmdb_report_acct_grouping_t)); - acct_group->acct = xstrdup(name); - if(wckey_type) - acct_group->lft = wckey->id; - else { - acct_group->lft = assoc->lft; - acct_group->rgt = assoc->rgt; - } - acct_group->groups = list_create( - slurmdb_destroy_report_job_grouping); - list_append(cluster_group->acct_list, acct_group); - while((group = list_next(group_itr))) { - job_group = xmalloc( - sizeof(slurmdb_report_job_grouping_t)); - job_group->jobs = list_create(NULL); - if(!individual) - job_group->min_size = last_size; - last_size = atoi(group); - if(!individual) - job_group->max_size = last_size-1; - else - job_group->min_size = - job_group->max_size = last_size; - list_append(acct_group->groups, job_group); + while((object2 = list_next(itr2))) { + slurmdb_wckey_rec_t *wckey2 = + (slurmdb_wckey_rec_t *)object2; + slurmdb_association_rec_t *assoc2 = + (slurmdb_association_rec_t *)object2; + char name[200]; + if (!wckey_type) { + if (strcmp(assoc->cluster, wckey2->cluster)) + continue; + cluster = assoc->cluster; + snprintf(name, sizeof(name), "%s:%s", + assoc->acct, wckey2->name); + } else { + if (strcmp(wckey->cluster, assoc2->cluster)) + continue; + cluster = wckey->cluster; + snprintf(name, sizeof(name), "%s:%s", + wckey2->name, assoc->acct); } - if(last_size && !individual) { - job_group = xmalloc( - sizeof(slurmdb_report_job_grouping_t)); - job_group->jobs = list_create(NULL); - job_group->min_size = last_size; - if(individual) - job_group->max_size = - job_group->min_size; - else - job_group->max_size = INFINITE; - list_append(acct_group->groups, job_group); - } - list_iterator_reset(group_itr); + _check_create_grouping(cluster_list, group_itr, + cluster, name, object, + individual, wckey_type); } - list_iterator_reset(cluster_itr); + list_iterator_reset(itr2); } list_iterator_destroy(itr); + if (itr2) + list_iterator_destroy(itr2); + no_objects: itr = list_iterator_create(job_list); while((job = list_next(itr))) { char *local_cluster = "UNKNOWN"; - char *local_account = "UNKNOWN"; + char tmp_acct[200]; if(!job->elapsed) { /* here we don't care about jobs that didn't @@ -278,8 +334,28 @@ no_objects: } if(job->cluster) local_cluster = job->cluster; - if(job->account) - local_account = job->account; + + if (!wckey_type) { + if (both && job->wckey) { + snprintf(tmp_acct, sizeof(tmp_acct), + "%s:%s", + job->account, + job->wckey); + } else { + snprintf(tmp_acct, sizeof(tmp_acct), + "%s", job->account); + } + } else { + if (both && job->account) { + snprintf(tmp_acct, sizeof(tmp_acct), + "%s:%s", + job->wckey, + job->account); + } else { + snprintf(tmp_acct, sizeof(tmp_acct), + "%s", job->wckey); + } + } list_iterator_reset(cluster_itr); while((cluster_group = list_next(cluster_itr))) { @@ -302,8 +378,8 @@ no_objects: acct_itr = list_iterator_create(cluster_group->acct_list); while((acct_group = list_next(acct_itr))) { - if(wckey_type) { - if(!strcmp(job->wckey, acct_group->acct)) + if (wckey_type) { + if(!strcmp(tmp_acct, acct_group->acct)) break; continue; } @@ -314,10 +390,21 @@ no_objects: /* keep separate since we don't want * to so a strcmp if we don't have to */ - if(job->lft > acct_group->lft - && job->lft < acct_group->rgt) - break; - } else if(!strcmp(acct_group->acct, local_account)) + if (job->lft > acct_group->lft + && job->lft < acct_group->rgt) { + char *mywckey; + if (!both) + break; + mywckey = strstr(acct_group->acct, ":"); + mywckey++; + if (!job->wckey && !mywckey) + break; + else if (!mywckey || !job->wckey) + continue; + else if (!strcmp(mywckey, job->wckey)) + break; + } + } else if (!strcmp(acct_group->acct, tmp_acct)) break; } list_iterator_destroy(acct_itr); @@ -333,7 +420,7 @@ no_objects: acct_group = xmalloc( sizeof(slurmdb_report_acct_grouping_t)); - acct_group->acct = xstrdup(local_account); + acct_group->acct = xstrdup(tmp_acct); acct_group->groups = list_create( slurmdb_destroy_report_job_grouping); list_append(cluster_group->acct_list, acct_group); @@ -375,6 +462,8 @@ no_objects: continue; list_append(job_group->jobs, job); job_group->count++; + acct_group->count++; + cluster_group->count++; total_secs = (uint64_t)job->elapsed * (uint64_t)job->alloc_cpus; job_group->cpu_secs += total_secs; @@ -385,12 +474,31 @@ no_objects: } list_iterator_destroy(itr); list_iterator_destroy(group_itr); + list_iterator_reset(cluster_itr); + while ((cluster_group = list_next(cluster_itr))) { + ListIterator acct_itr; + if (!cluster_group->count) { + list_delete_item(cluster_itr); + continue; + } + acct_itr = list_iterator_create(cluster_group->acct_list); + while ((acct_group = list_next(acct_itr))) { + if (!acct_group->count) { + list_delete_item(acct_itr); + continue; + } + } + list_iterator_destroy(acct_itr); + } list_iterator_destroy(cluster_itr); end_it: if(object_list) list_destroy(object_list); + if(object2_list) + list_destroy(object2_list); + if(destroy_job_cond) slurmdb_destroy_job_cond(job_cond); @@ -407,16 +515,25 @@ end_it: return cluster_list; } - extern List slurmdb_report_job_sizes_grouped_by_top_account(void *db_conn, slurmdb_job_cond_t *job_cond, List grouping_list, bool flat_view) { return _process_grouped_report(db_conn, job_cond, grouping_list, - flat_view, 0); + flat_view, 0, 0); } extern List slurmdb_report_job_sizes_grouped_by_wckey(void *db_conn, slurmdb_job_cond_t *job_cond, List grouping_list) { - return _process_grouped_report(db_conn, job_cond, grouping_list, 0, 1); + return _process_grouped_report(db_conn, job_cond, grouping_list, + 0, 1, 0); } + +extern List slurmdb_report_job_sizes_grouped_by_top_account_then_wckey( + void *db_conn, slurmdb_job_cond_t *job_cond, + List grouping_list, bool flat_view) +{ + return _process_grouped_report( + db_conn, job_cond, grouping_list, flat_view, 0, 1); +} + diff --git a/src/sreport/common.c b/src/sreport/common.c index f61eee6e86a..88f9ac2dfc3 100644 --- a/src/sreport/common.c +++ b/src/sreport/common.c @@ -40,8 +40,8 @@ #include "sreport.h" -extern void slurmdb_report_print_time(print_field_t *field, - uint64_t value, uint64_t total_time, int last) +extern void slurmdb_report_print_time(print_field_t *field, uint64_t value, + uint64_t total_time, int last) { int abs_len = abs(field->len); diff --git a/src/sreport/job_reports.c b/src/sreport/job_reports.c index a448db5c1c0..45c00483f90 100644 --- a/src/sreport/job_reports.c +++ b/src/sreport/job_reports.c @@ -578,6 +578,8 @@ extern int job_sizes_grouped_by_top_acct(int argc, char *argv[]) int i=0; + uint64_t count1, count2; + ListIterator itr = NULL; ListIterator itr2 = NULL; ListIterator cluster_itr = NULL; @@ -724,9 +726,15 @@ extern int job_sizes_grouped_by_top_acct(int argc, char *argv[]) temp_format = time_format; time_format = SLURMDB_REPORT_TIME_PERCENT; + if (!print_job_count) { + count1 = acct_group->cpu_secs; + count2 = cluster_group->cpu_secs; + } else { + count1 = acct_group->count; + count2 = cluster_group->count; + } total_field.print_routine(&total_field, - acct_group->cpu_secs, - cluster_group->cpu_secs, 1); + count1, count2, 1); time_format = temp_format; printf("\n"); } @@ -737,6 +745,7 @@ extern int job_sizes_grouped_by_top_acct(int argc, char *argv[]) // time_format = temp_time_format; end_it: + xfree(total_field.name); if(print_job_count) print_job_count = 0; @@ -779,6 +788,8 @@ extern int job_sizes_grouped_by_wckey(int argc, char *argv[]) slurmdb_job_cond_t *job_cond = xmalloc(sizeof(slurmdb_job_cond_t)); int i=0; + uint64_t count1, count2; + ListIterator itr = NULL; ListIterator itr2 = NULL; ListIterator cluster_itr = NULL; @@ -925,9 +936,15 @@ extern int job_sizes_grouped_by_wckey(int argc, char *argv[]) temp_format = time_format; time_format = SLURMDB_REPORT_TIME_PERCENT; + if (!print_job_count) { + count1 = acct_group->cpu_secs; + count2 = cluster_group->cpu_secs; + } else { + count1 = acct_group->count; + count2 = cluster_group->count; + } total_field.print_routine(&total_field, - acct_group->cpu_secs, - cluster_group->cpu_secs, 1); + count1, count2, 1); time_format = temp_format; printf("\n"); } @@ -938,6 +955,7 @@ extern int job_sizes_grouped_by_wckey(int argc, char *argv[]) // time_format = temp_time_format; end_it: + xfree(total_field.name); if(print_job_count) print_job_count = 0; @@ -974,3 +992,214 @@ end_it: return rc; } +extern int job_sizes_grouped_by_top_acct_and_wckey(int argc, char *argv[]) +{ + int rc = SLURM_SUCCESS; + slurmdb_job_cond_t *job_cond = xmalloc(sizeof(slurmdb_job_cond_t)); + + int i=0; + + uint64_t count1, count2; + + ListIterator itr = NULL; + ListIterator itr2 = NULL; + ListIterator cluster_itr = NULL; + ListIterator local_itr = NULL; + ListIterator acct_itr = NULL; + + slurmdb_report_cluster_grouping_t *cluster_group = NULL; + slurmdb_report_acct_grouping_t *acct_group = NULL; + slurmdb_report_job_grouping_t *job_group = NULL; + + print_field_t *field = NULL; + print_field_t total_field; + uint32_t total_time = 0; + slurmdb_report_time_format_t temp_format; + + List slurmdb_report_cluster_grouping_list = NULL; + List assoc_list = NULL; + + List format_list = list_create(slurm_destroy_char); + List grouping_list = list_create(slurm_destroy_char); + + List header_list = NULL; + +// slurmdb_report_time_format_t temp_time_format = time_format; + + print_fields_list = list_create(destroy_print_field); + + _set_cond(&i, argc, argv, job_cond, format_list, grouping_list); + + if(!list_count(format_list)) + slurm_addto_char_list(format_list, "Cl,a%-20"); + + if(!individual_grouping && !list_count(grouping_list)) + slurm_addto_char_list(grouping_list, "50,250,500,1000"); + + _setup_print_fields_list(format_list); + list_destroy(format_list); + + if(!(slurmdb_report_cluster_grouping_list = + slurmdb_report_job_sizes_grouped_by_top_account_then_wckey( + db_conn, job_cond, grouping_list, flat_view))) { + exit_code = 1; + goto end_it; + } + + _setup_grouping_print_fields_list(grouping_list); + + if(print_fields_have_header) { + char start_char[20]; + char end_char[20]; + time_t my_start = job_cond->usage_start; + time_t my_end = job_cond->usage_end-1; + + slurm_make_time_str(&my_start, start_char, sizeof(start_char)); + slurm_make_time_str(&my_end, end_char, sizeof(end_char)); + printf("----------------------------------------" + "----------------------------------------\n"); + printf("Job Sizes %s - %s (%d secs)\n", + start_char, end_char, + (int)(job_cond->usage_end - job_cond->usage_start)); + if(print_job_count) + printf("Units are in number of jobs ran\n"); + else + printf("Time reported in %s\n", time_format_string); + printf("----------------------------------------" + "----------------------------------------\n"); + } + total_time = job_cond->usage_end - job_cond->usage_start; + + header_list = list_create(NULL); + list_append_list(header_list, print_fields_list); + list_append_list(header_list, grouping_print_fields_list); + + memset(&total_field, 0, sizeof(print_field_t)); + total_field.type = PRINT_JOB_SIZE; + total_field.name = xstrdup("% of cluster"); + total_field.len = 12; + total_field.print_routine = slurmdb_report_print_time; + list_append(header_list, &total_field); + + print_fields_header(header_list); + list_destroy(header_list); + +// time_format = SLURMDB_REPORT_TIME_PERCENT; + + itr = list_iterator_create(print_fields_list); + itr2 = list_iterator_create(grouping_print_fields_list); + list_sort(slurmdb_report_cluster_grouping_list, + (ListCmpF)_sort_cluster_grouping_dec); + cluster_itr = + list_iterator_create(slurmdb_report_cluster_grouping_list); + while((cluster_group = list_next(cluster_itr))) { + list_sort(cluster_group->acct_list, + (ListCmpF)_sort_acct_grouping_dec); + acct_itr = list_iterator_create(cluster_group->acct_list); + while((acct_group = list_next(acct_itr))) { + + while((field = list_next(itr))) { + switch(field->type) { + case PRINT_JOB_CLUSTER: + field->print_routine( + field, + cluster_group->cluster, 0); + break; + case PRINT_JOB_ACCOUNT: + field->print_routine(field, + acct_group->acct, + 0); + break; + default: + field->print_routine(field, + NULL, + 0); + break; + } + } + list_iterator_reset(itr); + local_itr = list_iterator_create(acct_group->groups); + while((job_group = list_next(local_itr))) { + field = list_next(itr2); + switch(field->type) { + case PRINT_JOB_SIZE: + field->print_routine( + field, + job_group->cpu_secs, + acct_group->cpu_secs, + 0); + break; + case PRINT_JOB_COUNT: + field->print_routine( + field, + job_group->count, + 0); + break; + default: + field->print_routine(field, + NULL, + 0); + break; + } + } + list_iterator_reset(itr2); + list_iterator_destroy(local_itr); + + temp_format = time_format; + time_format = SLURMDB_REPORT_TIME_PERCENT; + if (!print_job_count) { + count1 = acct_group->cpu_secs; + count2 = cluster_group->cpu_secs; + } else { + count1 = acct_group->count; + count2 = cluster_group->count; + } + total_field.print_routine(&total_field, + count1, count2, 1); + time_format = temp_format; + printf("\n"); + } + list_iterator_destroy(acct_itr); + } + list_iterator_destroy(itr); + +// time_format = temp_time_format; + +end_it: + xfree(total_field.name); + if(print_job_count) + print_job_count = 0; + + if(individual_grouping) + individual_grouping = 0; + + slurmdb_destroy_job_cond(job_cond); + + if(grouping_list) { + list_destroy(grouping_list); + grouping_list = NULL; + } + + if(assoc_list) { + list_destroy(assoc_list); + assoc_list = NULL; + } + + if(slurmdb_report_cluster_grouping_list) { + list_destroy(slurmdb_report_cluster_grouping_list); + slurmdb_report_cluster_grouping_list = NULL; + } + + if(print_fields_list) { + list_destroy(print_fields_list); + print_fields_list = NULL; + } + + if(grouping_print_fields_list) { + list_destroy(grouping_print_fields_list); + grouping_print_fields_list = NULL; + } + + return rc; +} + diff --git a/src/sreport/job_reports.h b/src/sreport/job_reports.h index 672d1b6bd6b..c82936a03aa 100644 --- a/src/sreport/job_reports.h +++ b/src/sreport/job_reports.h @@ -45,5 +45,6 @@ extern int job_sizes_grouped_by_top_acct(int argc, char *argv[]); extern int job_sizes_grouped_by_wckey(int argc, char *argv[]); +extern int job_sizes_grouped_by_top_acct_and_wckey(int argc, char *argv[]); #endif diff --git a/src/sreport/sreport.c b/src/sreport/sreport.c index 463c206e3c5..db623e3738c 100644 --- a/src/sreport/sreport.c +++ b/src/sreport/sreport.c @@ -246,11 +246,17 @@ static void _job_rep (int argc, char *argv[]) "SizesByWcKey", MAX(command_len, 8))) { error_code = job_sizes_grouped_by_wckey( (argc - 1), &argv[1]); + } else if (!strncasecmp (argv[0], + "SizesByAccountAndWcKey", + MAX(command_len, 15))) { + error_code = job_sizes_grouped_by_top_acct_and_wckey( + (argc - 1), &argv[1]); } else { exit_code = 1; fprintf(stderr, "Not valid report %s\n", argv[0]); fprintf(stderr, "Valid job reports are, "); - fprintf(stderr, "\"SizesByAccount, and SizesByWckey\"\n"); + fprintf(stderr, "\"SizesByAccount, SizesByAccountAndWcKey, "); + fprintf(stderr, "and SizesByWckey\"\n"); } if (error_code) { @@ -692,7 +698,7 @@ sreport [<OPTION>] [<COMMAND>] \n\ <REPORT> is different for each report type. \n\ cluster - AccountUtilizationByUser, UserUtilizationByAccount, \n\ UserUtilizationByWckey, Utilization, WCKeyUtilizationByUser \n\ - job - SizesByAccount, SizesByWckey \n\ + job - SizesByAccount, SizesByAccountAndWckey, SizesByWckey \n\ reservation \n\ - Utilization \n\ user - TopUsage \n\ @@ -725,16 +731,16 @@ sreport [<OPTION>] [<COMMAND>] \n\ to include in report. Default is all. \n\ \n\ job - Accounts=<OPT> - List of accounts to use for the report \n\ - Default is all. The SizesbyAccount \n\ + Default is all. The SizesbyAccount(*) \n\ report only displays 1 hierarchical level.\n\ If accounts are specified the next layer \n\ of accounts under those specified will be\n\ displayed, not the accounts specified. \n\ - In the SizesByAccount reports the default\n\ - for accounts is root. This explanation \n\ - does not apply when ran with the FlatView\n\ - option. \n\ - - FlatView - When used with the SizesbyAccount \n\ + In the SizesByAccount(*) reports the \n\ + default for accounts is root. This \n\ + explanation does not apply when ran with \n\ + the FlatView option. \n\ + - FlatView - When used with the SizesbyAccount(*) \n\ will not group accounts in a \n\ hierarchical level, but print each \n\ account where jobs ran on a separate \n\ -- GitLab