diff --git a/NEWS b/NEWS index 68403bec3b6589a083792abd25c0d3a4929b6244..16acf25cfaec82115e35ce4b9867de6902c452ce 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,7 @@ documents those changes that are of interest to users and admins. * Changes in SLURM 2.1.0-pre5 ============================= - + -- Add squeue option "--start" to report expected start time of pending jobs. * Changes in SLURM 2.1.0-pre4 ============================= diff --git a/doc/man/man1/squeue.1 b/doc/man/man1/squeue.1 index 194086e60378a177e38304d18a8d977c6a232087..e21d714491b5f0e848ac999cfdb53b89a54ebf41 100644 --- a/doc/man/man1/squeue.1 +++ b/doc/man/man1/squeue.1 @@ -1,4 +1,4 @@ -.TH SQUEUE "1" "July 2009" "squeue 2.1" "Slurm components" +.TH SQUEUE "1" "September 2009" "squeue 2.1" "Slurm components" .SH "NAME" squeue \- view information about jobs located in the SLURM scheduling queue. @@ -234,7 +234,7 @@ Node use (VIRTUAL or COPROCESSOR), etc. .TP \fB%S\fR -Start time of the job or job step. +Actual or expected start time of the job or job step. .TP \fB%t\fR Job state, compact form: @@ -298,6 +298,16 @@ decreasing priority). The default value of sort for job steps is "P,i" (increasing partition name then within a given partition by increasing step id). +.TP +\fB\-\-start\fR +Report the expected start time of pending jobs in order of increasing +start time. This is equivalent to the following options: +\fB\-\-format="%.7i %.9P %.8j %.8u %.2t %.19S %.6D %R"\fR, +\fB\-\-sort=S\fR and \fB\-\-states=PENDING\fR. +Any of these options may be explicitly changed as desired by +combining the \fB\-\-start\fR option with other option values +(e.g. to use a different output format). + .TP \fB\-t <state_list>\fR, \fB\-\-states=<state_list>\fR Specify the states of jobs to view. Accepts a comma separated list of diff --git a/src/api/job_info.c b/src/api/job_info.c index 61bf810097b0c37d4fe1b14e2c5e96b67ca70678..30cbbbce2083d26cc097210a31f4c184ad29bf00 100644 --- a/src/api/job_info.c +++ b/src/api/job_info.c @@ -222,16 +222,11 @@ slurm_sprint_job_info ( job_info_t * job_ptr, int one_liner ) xstrcat(out, "\n "); /****** Line 5 ******/ - if (IS_JOB_PENDING(job_ptr)) - tmp3_ptr = "EligibleTime"; - else - tmp3_ptr = "StartTime"; slurm_make_time_str((time_t *)&job_ptr->start_time, time_str, sizeof(time_str)); snprintf(tmp_line, sizeof(tmp_line), - "JobState=%s %s=%s EndTime=", - job_state_string(job_ptr->job_state), - tmp3_ptr, time_str); + "JobState=%s StartTime=%s EndTime=", + job_state_string(job_ptr->job_state), time_str); xstrcat(out, tmp_line); if ((job_ptr->time_limit == INFINITE) && (job_ptr->end_time > time(NULL))) diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c index 19c0e91b5593af616bc8496f9eadc582ea3864ac..634442502811843f98734de1c0299e3e1a565939 100644 --- a/src/slurmctld/job_mgr.c +++ b/src/slurmctld/job_mgr.c @@ -4212,9 +4212,12 @@ void pack_job(struct job_record *dump_job_ptr, uint16_t show_flags, Buf buffer) pack_time(dump_job_ptr->details->submit_time, buffer); else pack_time((time_t) 0, buffer); - if (IS_JOB_PENDING(dump_job_ptr) && dump_job_ptr->details) + if (IS_JOB_PENDING(dump_job_ptr) && dump_job_ptr->details && + dump_job_ptr->details->begin_time && + (dump_job_ptr->details->begin_time > time(NULL))) { + /* Earliest possible begin time */ pack_time(dump_job_ptr->details->begin_time, buffer); - else + } else /* Actual or expected start time */ pack_time(dump_job_ptr->start_time, buffer); pack_time(dump_job_ptr->end_time, buffer); pack_time(dump_job_ptr->suspend_time, buffer); diff --git a/src/squeue/opts.c b/src/squeue/opts.c index 42c384c38afd7efeaaf78883be7d4d647c89c310..36d3250a3c7c33f336cb693729ad1e1a968d679b 100644 --- a/src/squeue/opts.c +++ b/src/squeue/opts.c @@ -67,6 +67,7 @@ #define OPT_LONG_HELP 0x100 #define OPT_LONG_USAGE 0x101 #define OPT_LONG_HIDE 0x102 +#define OPT_LONG_START 0x103 /* FUNCTIONS */ static List _build_job_list( char* str ); @@ -97,25 +98,26 @@ parse_command_line( int argc, char* argv[] ) static struct option long_options[] = { {"accounts", required_argument, 0, 'A'}, {"all", no_argument, 0, 'a'}, - {"noheader", no_argument, 0, 'h'}, + {"format", required_argument, 0, 'o'}, + {"help", no_argument, 0, OPT_LONG_HELP}, + {"hide", no_argument, 0, OPT_LONG_HIDE}, {"iterate", required_argument, 0, 'i'}, {"jobs", optional_argument, 0, 'j'}, {"long", no_argument, 0, 'l'}, {"node", required_argument, 0, 'n'}, {"nodes", required_argument, 0, 'n'}, - {"format", required_argument, 0, 'o'}, + {"noheader", no_argument, 0, 'h'}, {"partitions", required_argument, 0, 'p'}, {"qos", required_argument, 0, 'q'}, - {"steps", optional_argument, 0, 's'}, {"sort", required_argument, 0, 'S'}, + {"start", no_argument, 0, OPT_LONG_START}, + {"steps", optional_argument, 0, 's'}, {"states", required_argument, 0, 't'}, + {"usage", no_argument, 0, OPT_LONG_USAGE}, {"user", required_argument, 0, 'u'}, {"users", required_argument, 0, 'u'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, OPT_LONG_HELP}, - {"usage", no_argument, 0, OPT_LONG_USAGE}, - {"hide", no_argument, 0, OPT_LONG_HIDE}, {NULL, 0, 0, 0} }; @@ -226,12 +228,15 @@ parse_command_line( int argc, char* argv[] ) case OPT_LONG_HELP: _help(); exit(0); - case OPT_LONG_USAGE: - _usage(); - exit(0); case OPT_LONG_HIDE: params.all_flag = false; break; + case OPT_LONG_START: + params.start_flag = true; + break; + case OPT_LONG_USAGE: + _usage(); + exit(0); } } @@ -323,6 +328,18 @@ parse_command_line( int argc, char* argv[] ) params.user_list = _build_user_list( params.users ); } + if ( params.start_flag && !params.step_flag ) { + /* Set more defaults */ + if (params.format == NULL) + params.format = xstrdup("%.7i %.9P %.8j %.8u %.2t %.19S %.6D %R"); + if (params.sort == NULL) + params.sort = xstrdup("S"); + if (params.states == NULL) { + params.states = xstrdup("PD"); + params.state_list = _build_state_list( params.states ); + } + } + params.max_procs = _max_procs_per_node(); if ( params.verbose ) @@ -788,6 +805,7 @@ _print_options() printf( "nodes = %s\n", hostlist ) ; printf( "partitions = %s\n", params.partitions ) ; printf( "sort = %s\n", params.sort ) ; + printf( "start_flag = %d\n", params.start_flag ); printf( "states = %s\n", params.states ) ; printf( "step_flag = %d\n", params.step_flag ); printf( "steps = %s\n", params.steps ); @@ -1052,8 +1070,10 @@ static void _print_version(void) static void _usage(void) { - printf("Usage: squeue [-i seconds] [-S fields] [-t states] [-p partitions]\n"); - printf(" [-n node] [-o format] [-u user_name] [--usage] [-ahjlsv]\n"); + printf("\ +Usage: squeue [-i seconds] [-S fields] [--start] [-t states]\n\ + [-p partitions] [-n node] [-o format] [-u user_name]\n\ + [--usage] [-ahjlsv]\n"); } static void _help(void) @@ -1064,7 +1084,7 @@ Usage: squeue [OPTIONS]\n\ to view, default is all accounts\n\ -a, --all display jobs in hidden partitions\n\ -h, --noheader no headers on output\n\ - --hide do not display jobs in hidden partitions\n\ + --hide do not display jobs in hidden partitions\n\ -i, --iterate=seconds specify an interation period\n\ -j, --job=job(s) comma separated list of jobs IDs\n\ to view, default is all\n\ @@ -1079,6 +1099,7 @@ Usage: squeue [OPTIONS]\n\ -s, --step=step(s) comma separated list of job steps\n\ to view, default is all\n\ -S, --sort=field(s) comma separated list of fields to sort on\n\ + --start print expected start times of pending jobs\n\ -t, --state=state(s) comma separated list of states to view,\n\ default is pending and running,\n\ '--states=all' reports all states\n\ diff --git a/src/squeue/sort.c b/src/squeue/sort.c index 6f975d8f9a13b77098aea172729fd7bc1021eb4c..1b34556dbc5764102f186ec06bdad7ec9fd57f8e 100644 --- a/src/squeue/sort.c +++ b/src/squeue/sort.c @@ -531,13 +531,33 @@ static int _sort_job_by_time_limit(void *void1, void *void2) return diff; } +static uint32_t _get_start_time(job_info_t *job) +{ + time_t now = time(NULL); + + if (job->start_time == (time_t) 0) + return 0xffffffff; + if ((job->job_state == JOB_PENDING) && (job->start_time < now)) + return (uint32_t) now; + return (uint32_t) job->start_time; +} + static int _sort_job_by_time_start(void *void1, void *void2) { int diff; job_info_t *job1 = (job_info_t *) void1; job_info_t *job2 = (job_info_t *) void2; + uint32_t start_time1, start_time2; + + start_time1 = _get_start_time(job1); + start_time2 = _get_start_time(job2); - diff = job1->start_time - job2->start_time; + if (start_time1 > start_time2) + diff = 1; + else if (start_time1 < start_time2) + diff = -1; + else + diff = 0; if (reverse_order) diff = -diff; diff --git a/src/squeue/squeue.h b/src/squeue/squeue.h index d448a064eaebd501b6ffd4c875d311ce0cf9f403..afdda319dae14d4b9d3e90236132a363c7a54775 100644 --- a/src/squeue/squeue.h +++ b/src/squeue/squeue.h @@ -1,7 +1,8 @@ /****************************************************************************\ * squeue.h - definitions used for printing job queue state ***************************************************************************** - * Copyright (C) 2002 The Regents of the University of California. + * Copyright (C) 2002-2007 The Regents of the University of California. + * Copyright (C) 2008-2009 Lawrence Livermore National Security. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Joey Ekstrom <ekstrom1@llnl.gov> * CODE-OCEC-09-009. All rights reserved. @@ -77,6 +78,7 @@ typedef struct job_step squeue_job_step_t; struct squeue_parameters { bool all_flag; bool job_flag; + bool start_flag; bool step_flag; bool long_list; bool no_header;