From: Yuri D'Elia <[email protected]>

sacct --name follows the same logic as scancel/squeue, limiting the output only
to jobs having one of the specified name/s.

The job names are simply sent over the wire to be handled by the backend.
Both mysql and filetxt backends were updated to handle this new condition.

This requires an incompatible protocol change in the job_cond structure.
The perl api was also updated.
---
 contribs/perlapi/libslurmdb/perl/cluster.c         |    1 +
 doc/man/man1/sacct.1                               |    5 +
 slurm/slurmdb.h                                    |    1 +
 src/common/slurmdb_defs.c                          |    2 +
 src/common/slurmdb_pack.c                          |   24 +++++
 .../filetxt/filetxt_jobacct_process.c              |   14 +++
 .../mysql/as_mysql_jobacct_process.c               |   18 +++
 src/sacct/options.c                                |  110 ++++++++++++--------
 8 files changed, 131 insertions(+), 44 deletions(-)

diff --git a/contribs/perlapi/libslurmdb/perl/cluster.c 
b/contribs/perlapi/libslurmdb/perl/cluster.c
index f94e949..9452435 100644
--- a/contribs/perlapi/libslurmdb/perl/cluster.c
+++ b/contribs/perlapi/libslurmdb/perl/cluster.c
@@ -167,6 +167,7 @@ hv_to_job_cond(HV* hv, slurmdb_job_cond_t* job_cond)
     FETCH_LIST_FIELD(hv, job_cond, associd_list);
     FETCH_LIST_FIELD(hv, job_cond, cluster_list);
     FETCH_LIST_FIELD(hv, job_cond, groupid_list);
+    FETCH_LIST_FIELD(hv, job_cond, jobname_list);
     FETCH_LIST_FIELD(hv, job_cond, partition_list);
     FETCH_LIST_FIELD(hv, job_cond, qos_list);
     FETCH_LIST_FIELD(hv, job_cond, resv_list);
diff --git a/doc/man/man1/sacct.1 b/doc/man/man1/sacct.1
index ae9ebf3..84abc96 100644
--- a/doc/man/man1/sacct.1
+++ b/doc/man/man1/sacct.1
@@ -245,6 +245,11 @@ a ranged string.
 .IP
 
 .TP
+\f3\-\-name=\fP\f2jobname_list\fP
+Display jobs that have any of these name(s).
+.IP
+
+.TP
 \f3\-o\fP\f3,\fP \f3\-\-format\fP
 Comma separated list of fields. (use "\-\-helpformat" for a list of
 available fields).
diff --git a/slurm/slurmdb.h b/slurm/slurmdb.h
index 608a830..e5b0866 100644
--- a/slurm/slurmdb.h
+++ b/slurm/slurmdb.h
@@ -253,6 +253,7 @@ typedef struct {
        uint16_t duplicates;    /* report duplicate job entries */
        int32_t exitcode;       /* exit code of job */
        List groupid_list;      /* list of char * */
+       List jobname_list;      /* list of char * */
        uint32_t nodes_max;     /* number of nodes high range */
        uint32_t nodes_min;     /* number of nodes low range */
        List partition_list;    /* list of char * */
diff --git a/src/common/slurmdb_defs.c b/src/common/slurmdb_defs.c
index 89a0d99..5aa0772 100644
--- a/src/common/slurmdb_defs.c
+++ b/src/common/slurmdb_defs.c
@@ -725,6 +725,8 @@ extern void slurmdb_destroy_job_cond(void *object)
                        list_destroy(job_cond->cluster_list);
                if(job_cond->groupid_list)
                        list_destroy(job_cond->groupid_list);
+               if(job_cond->jobname_list)
+                       list_destroy(job_cond->jobname_list);
                if(job_cond->partition_list)
                        list_destroy(job_cond->partition_list);
                if(job_cond->qos_list)
diff --git a/src/common/slurmdb_pack.c b/src/common/slurmdb_pack.c
index c9c68b4..621b59e 100644
--- a/src/common/slurmdb_pack.c
+++ b/src/common/slurmdb_pack.c
@@ -3932,6 +3932,19 @@ extern void slurmdb_pack_job_cond(void *in, uint16_t 
rpc_version, Buf buffer)
                }
                count = NO_VAL;
 
+               if(object->jobname_list)
+                       count = list_count(object->jobname_list);
+
+               pack32(count, buffer);
+               if(count && count != NO_VAL) {
+                       itr = list_iterator_create(object->jobname_list);
+                       while((tmp_info = list_next(itr))) {
+                               packstr(tmp_info, buffer);
+                       }
+                       list_iterator_destroy(itr);
+               }
+               count = NO_VAL;
+
                pack32(object->nodes_max, buffer);
                pack32(object->nodes_min, buffer);
                if(object->partition_list)
@@ -4287,6 +4300,17 @@ extern int slurmdb_unpack_job_cond(void **object, 
uint16_t rpc_version,
                        }
                }
 
+               safe_unpack32(&count, buffer);
+               if(count != NO_VAL) {
+                       object_ptr->jobname_list =
+                               list_create(slurm_destroy_char);
+                       for(i=0; i<count; i++) {
+                               safe_unpackstr_xmalloc(&tmp_info, &uint32_tmp,
+                                                      buffer);
+                               list_append(object_ptr->jobname_list, tmp_info);
+                       }
+               }
+
                safe_unpack32(&object_ptr->nodes_max, buffer);
                safe_unpack32(&object_ptr->nodes_min, buffer);
 
diff --git a/src/plugins/accounting_storage/filetxt/filetxt_jobacct_process.c 
b/src/plugins/accounting_storage/filetxt/filetxt_jobacct_process.c
index a8b9e2c..f1588bf 100644
--- a/src/plugins/accounting_storage/filetxt/filetxt_jobacct_process.c
+++ b/src/plugins/accounting_storage/filetxt/filetxt_jobacct_process.c
@@ -1130,6 +1130,20 @@ extern List 
filetxt_jobacct_process_get_jobs(slurmdb_job_cond_t *job_cond)
                }
        foundgid:
 
+               if (job_cond->jobname_list
+                   && list_count(job_cond->jobname_list)) {
+                       itr = list_iterator_create(job_cond->jobname_list);
+                       while((object = list_next(itr))) {
+                               if (!strcasecmp(f[F_JOBNAME], object)) {
+                                       list_iterator_destroy(itr);
+                                       goto foundjobname;
+                               }
+                       }
+                       list_iterator_destroy(itr);
+                       continue;       /* no match */
+               }
+       foundjobname:
+
                if (job_cond->step_list
                    && list_count(job_cond->step_list)) {
                        itr = list_iterator_create(job_cond->step_list);
diff --git a/src/plugins/accounting_storage/mysql/as_mysql_jobacct_process.c 
b/src/plugins/accounting_storage/mysql/as_mysql_jobacct_process.c
index f279b81..21efe7e 100644
--- a/src/plugins/accounting_storage/mysql/as_mysql_jobacct_process.c
+++ b/src/plugins/accounting_storage/mysql/as_mysql_jobacct_process.c
@@ -1125,6 +1125,24 @@ extern int setup_job_cond_limits(mysql_conn_t 
*mysql_conn,
                xstrcat(*extra, ")");
        }
 
+       if (job_cond->jobname_list && list_count(job_cond->jobname_list)) {
+               set = 0;
+               if (*extra)
+                       xstrcat(*extra, " && (");
+               else
+                       xstrcat(*extra, " where (");
+
+               itr = list_iterator_create(job_cond->jobname_list);
+               while ((object = list_next(itr))) {
+                       if (set)
+                               xstrcat(*extra, " || ");
+                       xstrfmtcat(*extra, "t1.job_name='%s'", object);
+                       set = 1;
+               }
+               list_iterator_destroy(itr);
+               xstrcat(*extra, ")");
+       }
+
        if (job_cond->partition_list && list_count(job_cond->partition_list)) {
                set = 0;
                if (*extra)
diff --git a/src/sacct/options.c b/src/sacct/options.c
index 316f67d..6e14d43 100644
--- a/src/sacct/options.c
+++ b/src/sacct/options.c
@@ -44,6 +44,9 @@
 #include "sacct.h"
 #include <time.h>
 
+/* getopt_long options, integers but not characters */
+#define OPT_LONG_NAME  0x100
+
 void _help_fields_msg(void);
 void _help_msg(void);
 void _usage(void);
@@ -462,6 +465,8 @@ sacct [<OPTION>]                                            
                \n\
      -N, --nodelist:                                                        \n\
                    Display jobs that ran on any of these nodes,             \n\
                    can be one or more using a ranged string.                \n\
+         --name:                                                            \n\
+                   Display jobs that have any of these name(s).             \n\
      -o, --format:                                                          \n\
                   Comma separated list of fields. (use \"--helpformat\"    \n\
                    for a list of available fields).                         \n\
@@ -604,50 +609,51 @@ void parse_command_line(int argc, char **argv)
        bool set;
 
        static struct option long_options[] = {
-               {"allusers", 0,0, 'a'},
-               {"accounts", 1, 0, 'A'},
-               {"allocations", 0, &params.opt_allocs,  1},
-               {"brief", 0, 0, 'b'},
-               {"completion", 0, &params.opt_completion, 'c'},
-               {"dump", 0, 0, 'd'},
-               {"duplicates", 0, &params.opt_dup, 1},
-               {"helpformat", 0, 0, 'e'},
-               {"help-fields", 0, 0, 'e'},
-               {"endtime", 1, 0, 'E'},
-               {"file", 1, 0, 'f'},
-               {"gid", 1, 0, 'g'},
-               {"group", 1, 0, 'g'},
-               {"help", 0, 0, 'h'},
-               {"helpformat", 0, &params.opt_help, 2},
-               {"nnodes", 1, 0, 'i'},
-               {"ncpus", 1, 0, 'I'},
-               {"jobs", 1, 0, 'j'},
-               {"timelimit-min", 1, 0, 'k'},
-               {"timelimit-max", 1, 0, 'K'},
-               {"long", 0, 0, 'l'},
-               {"allclusters", 0,0, 'L'},
-               {"cluster", 1, 0, 'M'},
-               {"clusters", 1, 0, 'M'},
-               {"nodelist", 1, 0, 'N'},
-               {"noheader", 0, 0, 'n'},
-               {"fields", 1, 0, 'o'},
-               {"format", 1, 0, 'o'},
-               {"formatted_dump", 0, 0, 'O'},
-               {"parsable", 0, 0, 'p'},
-               {"parsable2", 0, 0, 'P'},
-               {"qos", 1, 0, 'q'},
-               {"partition", 1, 0, 'r'},
-               {"state", 1, 0, 's'},
-               {"starttime", 1, 0, 'S'},
-               {"truncate", 0, 0, 'T'},
-               {"uid", 1, 0, 'u'},
-               {"usage", 0, &params.opt_help, 3},
-               {"user", 1, 0, 'u'},
-               {"verbose", 0, 0, 'v'},
-               {"version", 0, 0, 'V'},
-               {"wckeys", 1, 0, 'W'},
-               {"associations", 1, 0, 'x'},
-               {0, 0, 0, 0}};
+                {"allusers",       no_argument,       0,                      
'a'},
+                {"accounts",       required_argument, 0,                      
'A'},
+                {"allocations",    no_argument,       &params.opt_allocs,     
1},
+                {"brief",          no_argument,       0,                      
'b'},
+                {"completion",     no_argument,       &params.opt_completion, 
'c'},
+                {"dump",           no_argument,       0,                      
'd'},
+                {"duplicates",     no_argument,       &params.opt_dup,        
1},
+                {"helpformat",     no_argument,       0,                      
'e'},
+                {"help-fields",    no_argument,       0,                      
'e'},
+                {"endtime",        required_argument, 0,                      
'E'},
+                {"file",           required_argument, 0,                      
'f'},
+                {"gid",            required_argument, 0,                      
'g'},
+                {"group",          required_argument, 0,                      
'g'},
+                {"help",           no_argument,       0,                      
'h'},
+                {"helpformat",     no_argument,       &params.opt_help,       
2},
+                {"name",           required_argument, 0,                      
OPT_LONG_NAME},
+                {"nnodes",         required_argument, 0,                      
'i'},
+                {"ncpus",          required_argument, 0,                      
'I'},
+                {"jobs",           required_argument, 0,                      
'j'},
+                {"timelimit-min",  required_argument, 0,                      
'k'},
+                {"timelimit-max",  required_argument, 0,                      
'K'},
+                {"long",           no_argument,       0,                      
'l'},
+                {"allclusters",    no_argument,       0,                      
'L'},
+                {"cluster",        required_argument, 0,                      
'M'},
+                {"clusters",       required_argument, 0,                      
'M'},
+                {"nodelist",       required_argument, 0,                      
'N'},
+                {"noheader",       no_argument,       0,                      
'n'},
+                {"fields",         required_argument, 0,                      
'o'},
+                {"format",         required_argument, 0,                      
'o'},
+                {"formatted_dump", no_argument,       0,                      
'O'},
+                {"parsable",       no_argument,       0,                      
'p'},
+                {"parsable2",      no_argument,       0,                      
'P'},
+                {"qos",            required_argument, 0,                      
'q'},
+                {"partition",      required_argument, 0,                      
'r'},
+                {"state",          required_argument, 0,                      
's'},
+                {"starttime",      required_argument, 0,                      
'S'},
+                {"truncate",       no_argument,       0,                      
'T'},
+                {"uid",            required_argument, 0,                      
'u'},
+                {"usage",          no_argument,       &params.opt_help,       
3},
+                {"user",           required_argument, 0,                      
'u'},
+                {"verbose",        no_argument,       0,                      
'v'},
+                {"version",        no_argument,       0,                      
'V'},
+                {"wckeys",         required_argument, 0,                      
'W'},
+                {"associations",   required_argument, 0,                      
'x'},
+                {0,                0,                0,                      
0}};
 
        params.opt_uid = getuid();
        params.opt_gid = getgid();
@@ -791,6 +797,12 @@ void parse_command_line(int argc, char **argv)
                        }
                        job_cond->used_nodes = xstrdup(optarg);
                        break;
+               case OPT_LONG_NAME:
+                       if(!job_cond->jobname_list)
+                               job_cond->jobname_list =
+                                       list_create(slurm_destroy_char);
+                       slurm_addto_char_list(job_cond->jobname_list, optarg);
+                       break;
                case 'o':
                        xstrfmtcat(params.opt_field_list, "%s,", optarg);
                        break;
@@ -1109,6 +1121,16 @@ void parse_command_line(int argc, char **argv)
                debug2("Timelimit requested\t: %s", time_str);
        }
 
+       /* specific jobnames requested? */
+       if (job_cond->jobname_list && list_count(job_cond->jobname_list)) {
+               debug2("Jobnames requested:");
+               itr = list_iterator_create(job_cond->jobname_list);
+               while((start = list_next(itr))) {
+                       debug2("\t: %s", start);
+               }
+               list_iterator_destroy(itr);
+       }
+
        /* select the output fields */
        if(brief_output) {
                if(params.opt_completion)
-- 
1.7.7.3

Reply via email to