From 366160623bd7e10769f63f252964869487032b9e Mon Sep 17 00:00:00 2001 From: Don Lipari <lipari1@llnl.gov> Date: Tue, 24 Mar 2009 17:16:08 +0000 Subject: [PATCH] svn merge -r16878:16969 https://eris.llnl.gov/svn/slurm/branches/sprio --- configure | 3 +- doc/html/priority_multifactor.shtml | 13 + doc/html/priority_plugins.shtml | 34 +- doc/man/Makefile.am | 1 + doc/man/Makefile.in | 1 + doc/man/man1/sprio.1 | 220 +++++++ doc/man/man1/squeue.1 | 10 +- src/Makefile.am | 3 +- src/Makefile.in | 5 +- src/common/slurm_priority.c | 13 + src/common/slurm_priority.h | 2 + src/common/slurm_protocol_defs.c | 40 ++ src/common/slurm_protocol_defs.h | 29 + src/common/slurm_protocol_pack.c | 222 ++++++- src/plugins/priority/basic/priority_basic.c | 6 + .../multifactor/priority_multifactor.c | 283 ++++++--- src/slurmctld/proc_req.c | 31 + src/slurmctld/slurmctld.h | 1 + src/sprio/Makefile.am | 20 + src/sprio/Makefile.in | 566 ++++++++++++++++++ src/sprio/opts.c | 475 +++++++++++++++ src/sprio/print.c | 438 ++++++++++++++ src/sprio/print.h | 138 +++++ src/sprio/sprio.c | 222 +++++++ src/sprio/sprio.h | 94 +++ 25 files changed, 2784 insertions(+), 86 deletions(-) create mode 100644 doc/man/man1/sprio.1 create mode 100644 src/sprio/Makefile.am create mode 100644 src/sprio/Makefile.in create mode 100644 src/sprio/opts.c create mode 100644 src/sprio/print.c create mode 100644 src/sprio/print.h create mode 100644 src/sprio/sprio.c create mode 100644 src/sprio/sprio.h diff --git a/configure b/configure index a315a57b298..83967e89c27 100755 --- a/configure +++ b/configure @@ -27772,7 +27772,7 @@ fi -ac_config_files="$ac_config_files Makefile config.xml auxdir/Makefile contribs/Makefile contribs/perlapi/Makefile contribs/perlapi/libslurm-perl/Makefile.PL contribs/torque/Makefile contribs/phpext/Makefile contribs/phpext/slurm_php/config.m4 contribs/python/Makefile contribs/python/hostlist/Makefile contribs/python/hostlist/test/Makefile contribs/slurmdb-direct/Makefile src/Makefile src/api/Makefile src/common/Makefile src/database/Makefile src/sacct/Makefile src/sacctmgr/Makefile src/sreport/Makefile src/sstat/Makefile src/sshare/Makefile src/salloc/Makefile src/sbatch/Makefile src/sattach/Makefile src/srun/Makefile src/srun_cr/Makefile src/slurmd/Makefile src/slurmd/slurmd/Makefile src/slurmd/slurmstepd/Makefile src/slurmdbd/Makefile src/slurmctld/Makefile src/sbcast/Makefile src/scontrol/Makefile src/scancel/Makefile src/squeue/Makefile src/sinfo/Makefile src/smap/Makefile src/strigger/Makefile src/sview/Makefile src/plugins/Makefile src/plugins/accounting_storage/Makefile src/plugins/accounting_storage/filetxt/Makefile src/plugins/accounting_storage/mysql/Makefile src/plugins/accounting_storage/pgsql/Makefile src/plugins/accounting_storage/none/Makefile src/plugins/accounting_storage/slurmdbd/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile src/plugins/auth/munge/Makefile src/plugins/auth/none/Makefile src/plugins/checkpoint/Makefile src/plugins/checkpoint/aix/Makefile src/plugins/checkpoint/none/Makefile src/plugins/checkpoint/ompi/Makefile src/plugins/checkpoint/xlch/Makefile src/plugins/checkpoint/blcr/Makefile src/plugins/checkpoint/blcr/cr_checkpoint.sh src/plugins/checkpoint/blcr/cr_restart.sh src/plugins/crypto/Makefile src/plugins/crypto/munge/Makefile src/plugins/crypto/openssl/Makefile src/plugins/jobacct_gather/Makefile src/plugins/jobacct_gather/linux/Makefile src/plugins/jobacct_gather/aix/Makefile src/plugins/jobacct_gather/none/Makefile src/plugins/jobcomp/Makefile src/plugins/jobcomp/filetxt/Makefile src/plugins/jobcomp/none/Makefile src/plugins/jobcomp/script/Makefile src/plugins/jobcomp/mysql/Makefile src/plugins/jobcomp/pgsql/Makefile src/plugins/priority/Makefile src/plugins/priority/basic/Makefile src/plugins/priority/multifactor/Makefile src/plugins/proctrack/Makefile src/plugins/proctrack/aix/Makefile src/plugins/proctrack/pgid/Makefile src/plugins/proctrack/linuxproc/Makefile src/plugins/proctrack/rms/Makefile src/plugins/proctrack/sgi_job/Makefile src/plugins/sched/Makefile src/plugins/sched/backfill/Makefile src/plugins/sched/builtin/Makefile src/plugins/sched/gang/Makefile src/plugins/sched/hold/Makefile src/plugins/sched/wiki/Makefile src/plugins/sched/wiki2/Makefile src/plugins/select/Makefile src/plugins/select/bluegene/Makefile src/plugins/select/bluegene/block_allocator/Makefile src/plugins/select/bluegene/plugin/Makefile src/plugins/select/cons_res/Makefile src/plugins/select/linear/Makefile src/plugins/switch/Makefile src/plugins/switch/elan/Makefile src/plugins/switch/none/Makefile src/plugins/switch/federation/Makefile src/plugins/mpi/Makefile src/plugins/mpi/mpich1_p4/Makefile src/plugins/mpi/mpich1_shmem/Makefile src/plugins/mpi/mpichgm/Makefile src/plugins/mpi/mpichmx/Makefile src/plugins/mpi/mvapich/Makefile src/plugins/mpi/lam/Makefile src/plugins/mpi/none/Makefile src/plugins/mpi/openmpi/Makefile src/plugins/task/Makefile src/plugins/task/affinity/Makefile src/plugins/task/none/Makefile doc/Makefile doc/man/Makefile doc/html/Makefile doc/html/configurator.html testsuite/Makefile testsuite/expect/Makefile testsuite/slurm_unit/Makefile testsuite/slurm_unit/api/Makefile testsuite/slurm_unit/api/manual/Makefile testsuite/slurm_unit/common/Makefile testsuite/slurm_unit/slurmctld/Makefile testsuite/slurm_unit/slurmd/Makefile testsuite/slurm_unit/slurmdbd/Makefile" +ac_config_files="$ac_config_files Makefile config.xml auxdir/Makefile contribs/Makefile contribs/perlapi/Makefile contribs/perlapi/libslurm-perl/Makefile.PL contribs/torque/Makefile contribs/phpext/Makefile contribs/phpext/slurm_php/config.m4 contribs/python/Makefile contribs/python/hostlist/Makefile contribs/python/hostlist/test/Makefile contribs/slurmdb-direct/Makefile src/Makefile src/api/Makefile src/common/Makefile src/database/Makefile src/sacct/Makefile src/sacctmgr/Makefile src/sreport/Makefile src/sstat/Makefile src/sshare/Makefile src/sprio/Makefile src/salloc/Makefile src/sbatch/Makefile src/sattach/Makefile src/srun/Makefile src/srun_cr/Makefile src/slurmd/Makefile src/slurmd/slurmd/Makefile src/slurmd/slurmstepd/Makefile src/slurmdbd/Makefile src/slurmctld/Makefile src/sbcast/Makefile src/scontrol/Makefile src/scancel/Makefile src/squeue/Makefile src/sinfo/Makefile src/smap/Makefile src/strigger/Makefile src/sview/Makefile src/plugins/Makefile src/plugins/accounting_storage/Makefile src/plugins/accounting_storage/filetxt/Makefile src/plugins/accounting_storage/mysql/Makefile src/plugins/accounting_storage/pgsql/Makefile src/plugins/accounting_storage/none/Makefile src/plugins/accounting_storage/slurmdbd/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile src/plugins/auth/munge/Makefile src/plugins/auth/none/Makefile src/plugins/checkpoint/Makefile src/plugins/checkpoint/aix/Makefile src/plugins/checkpoint/none/Makefile src/plugins/checkpoint/ompi/Makefile src/plugins/checkpoint/xlch/Makefile src/plugins/checkpoint/blcr/Makefile src/plugins/checkpoint/blcr/cr_checkpoint.sh src/plugins/checkpoint/blcr/cr_restart.sh src/plugins/crypto/Makefile src/plugins/crypto/munge/Makefile src/plugins/crypto/openssl/Makefile src/plugins/jobacct_gather/Makefile src/plugins/jobacct_gather/linux/Makefile src/plugins/jobacct_gather/aix/Makefile src/plugins/jobacct_gather/none/Makefile src/plugins/jobcomp/Makefile src/plugins/jobcomp/filetxt/Makefile src/plugins/jobcomp/none/Makefile src/plugins/jobcomp/script/Makefile src/plugins/jobcomp/mysql/Makefile src/plugins/jobcomp/pgsql/Makefile src/plugins/priority/Makefile src/plugins/priority/basic/Makefile src/plugins/priority/multifactor/Makefile src/plugins/proctrack/Makefile src/plugins/proctrack/aix/Makefile src/plugins/proctrack/pgid/Makefile src/plugins/proctrack/linuxproc/Makefile src/plugins/proctrack/rms/Makefile src/plugins/proctrack/sgi_job/Makefile src/plugins/sched/Makefile src/plugins/sched/backfill/Makefile src/plugins/sched/builtin/Makefile src/plugins/sched/gang/Makefile src/plugins/sched/hold/Makefile src/plugins/sched/wiki/Makefile src/plugins/sched/wiki2/Makefile src/plugins/select/Makefile src/plugins/select/bluegene/Makefile src/plugins/select/bluegene/block_allocator/Makefile src/plugins/select/bluegene/plugin/Makefile src/plugins/select/cons_res/Makefile src/plugins/select/linear/Makefile src/plugins/switch/Makefile src/plugins/switch/elan/Makefile src/plugins/switch/none/Makefile src/plugins/switch/federation/Makefile src/plugins/mpi/Makefile src/plugins/mpi/mpich1_p4/Makefile src/plugins/mpi/mpich1_shmem/Makefile src/plugins/mpi/mpichgm/Makefile src/plugins/mpi/mpichmx/Makefile src/plugins/mpi/mvapich/Makefile src/plugins/mpi/lam/Makefile src/plugins/mpi/none/Makefile src/plugins/mpi/openmpi/Makefile src/plugins/task/Makefile src/plugins/task/affinity/Makefile src/plugins/task/none/Makefile doc/Makefile doc/man/Makefile doc/html/Makefile doc/html/configurator.html testsuite/Makefile testsuite/expect/Makefile testsuite/slurm_unit/Makefile testsuite/slurm_unit/api/Makefile testsuite/slurm_unit/api/manual/Makefile testsuite/slurm_unit/common/Makefile testsuite/slurm_unit/slurmctld/Makefile testsuite/slurm_unit/slurmd/Makefile testsuite/slurm_unit/slurmdbd/Makefile" cat >confcache <<\_ACEOF @@ -28524,6 +28524,7 @@ do "src/sreport/Makefile") CONFIG_FILES="$CONFIG_FILES src/sreport/Makefile" ;; "src/sstat/Makefile") CONFIG_FILES="$CONFIG_FILES src/sstat/Makefile" ;; "src/sshare/Makefile") CONFIG_FILES="$CONFIG_FILES src/sshare/Makefile" ;; + "src/sprio/Makefile") CONFIG_FILES="$CONFIG_FILES src/sprio/Makefile" ;; "src/salloc/Makefile") CONFIG_FILES="$CONFIG_FILES src/salloc/Makefile" ;; "src/sbatch/Makefile") CONFIG_FILES="$CONFIG_FILES src/sbatch/Makefile" ;; "src/sattach/Makefile") CONFIG_FILES="$CONFIG_FILES src/sattach/Makefile" ;; diff --git a/doc/html/priority_multifactor.shtml b/doc/html/priority_multifactor.shtml index fe24394f197..b0fbb0d90cf 100644 --- a/doc/html/priority_multifactor.shtml +++ b/doc/html/priority_multifactor.shtml @@ -14,6 +14,7 @@ <LI> <a href=#partition>Partition Factor</a> <LI> <a href=#qos>Quality of Service (QOS) Factor</a> <LI> <a href=#fairshare>Fair-share Factor</a> +<LI> <a href=#sprio>The <i>sprio</i> utility</a> <LI> <a href=#config>Configuration</a> <LI> <a href=#configexample>Configuration Example</a> </UL> @@ -401,6 +402,18 @@ Account A's effective usage is therefore equal to .45. Account D's effective us <P> Based on the fair-share factor alone, if all 5 users were to submit a job charging their respective accounts, user 5's job would be granted the highest scheduling priority.</P> +<!--------------------------------------------------------------------------> +<a name=sprio> +<h2>The <i>sprio</i> utility</h2></a> + +<P> The <i>sprio</i> command provides a summary of the five factors +that comprise each job's scheduling priority. While <i>squeue</i> has +format options (%p and %Q) that display a job's composite priority, +sprio can be used to display a breakdown of the priority components +for each job. In addition, the <i>sprio -w</i> option displays the +weights (PriorityWeightAge, PriorityWeightFairshare, etc.) for each +factor as it is currently configured.</P> + <!--------------------------------------------------------------------------> <a name=config> <h2>Configuration</h2></a> diff --git a/doc/html/priority_plugins.shtml b/doc/html/priority_plugins.shtml index 8128d879f21..222e494ece6 100644 --- a/doc/html/priority_plugins.shtml +++ b/doc/html/priority_plugins.shtml @@ -47,6 +47,28 @@ information by whatever means is practical. Successful API calls are not required to reset any errno to a known value. However, the initial value of any errno, prior to any error condition arising, should be SLURM_SUCCESS. </p> +<p class="commandline"> job_record</p> +<p style="margin-left:.2in"><b>Description</b>: A slurmctld structure that +contains details about a job.</p> + +<p class="commandline"> acct_association_rec_t</p> +<p style="margin-left:.2in"><b>Description</b>: A slurm_accounting_storage +structure that contains details about an association.</p> + +<p class="commandline"> priority_factors_object_t</p> +<p style="margin-left:.2in"><b>Description</b>: A structure that contains a +job's priority factors.</p> + +<p class="commandline"> priority_factors_request_msg_t</p> +<p style="margin-left:.2in"><b>Description</b>: Used to request job priority +factors. Contains a list of specific job and user ids of the jobs the user +wants to see.</p> + +<p class="commandline"> priority_factors_response_msg_t</p> +<p style="margin-left:.2in"><b>Description</b>: Used to return the list of +priority_factors_object_t's containing the job priority factors the user has +asked to see.</p> + <p class="footer"><a href="#top">top</a></p> <h2>API Functions</h2> @@ -75,7 +97,8 @@ which each job's usage can be normalized.</p> <p style="margin-left:.2in"><b>Arguments</b>:<br> <span class="commandline">procs</span> (input) the machine's processor count<br> <span class="commandline">half_life</span> (input) the configured half-life</p> -<p style="margin-left:.2in"><b>Returns</b>: SLURM_SUCCESS if successful, otherwise SLURM_ERROR</p> +<p style="margin-left:.2in"><b>Returns</b>: SLURM_SUCCESS if successful, +otherwise SLURM_ERROR</p> <p class="commandline">void priority_p_set_assoc_usage(acct_association_rec_t *assoc)</p> <p style="margin-left:.2in"><b>Description</b>: Set the normalized and @@ -84,6 +107,15 @@ effective usage for an association.</p> <span class="commandline">assoc</span> (input/output) pointer to the association.</p> <p style="margin-left:.2in"><b>Returns</b>: void</p> +<p class="commandline">List priority_p_get_priority_factors_list(priority_factors_request_msg_t *req_msg)</p> +<p style="margin-left:.2in"><b>Description</b>: Retrieves the priority factors +for all or specified jobs.</p> +<p style="margin-left:.2in"><b>Arguments</b>: +<span class="commandline">req_msg</span> (input) pointer to the message request +that contains the specific jobs or users of interest (of any).</p> +<p style="margin-left:.2in"><b>Returns</b>: a list of priority_factors_object_t's +containing the requested job priority factors</p> + <h2>Versioning</h2> <p> This document describes version 100 of the SLURM Priority API. Future releases of SLURM may revise this API. A priority plugin conveys its ability diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index af810d0e3ee..8b01b23f173 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -13,6 +13,7 @@ man1_MANS = \ man1/sinfo.1 \ man1/slurm.1 \ man1/smap.1 \ + man1/sprio.1 \ man1/squeue.1 \ man1/sreport.1 \ man1/srun.1 \ diff --git a/doc/man/Makefile.in b/doc/man/Makefile.in index bb2ae242227..4ebde30f606 100644 --- a/doc/man/Makefile.in +++ b/doc/man/Makefile.in @@ -265,6 +265,7 @@ man1_MANS = \ man1/sinfo.1 \ man1/slurm.1 \ man1/smap.1 \ + man1/sprio.1 \ man1/squeue.1 \ man1/sreport.1 \ man1/srun.1 \ diff --git a/doc/man/man1/sprio.1 b/doc/man/man1/sprio.1 new file mode 100644 index 00000000000..c1841422717 --- /dev/null +++ b/doc/man/man1/sprio.1 @@ -0,0 +1,220 @@ +.TH SPRIO "1" "March 2009" "sprio 2.0" "SLURM commands" + +.SH "NAME" +sprio \- view the factors that comprise a job's scheduling priority + +.SH "SYNOPSIS" +\fBsprio\fR [\fIOPTIONS\fR...] + +.SH "DESCRIPTION" +\fBsprio\fR is used to view the components of a job's scheduling +priority when the multi-factor priority plugin is installed. +\fBsprio\fR is a read-only utility that extracts information from the +multi-factor priority plugin. By default, \fBsprio\fR returns +information for all pending jobs. Options exist to display specific +jobs by job ID and user name. + +.SH "OPTIONS" + +.TP +\fB\-h\fR, \fB\-\-noheader\fR +Do not print a header on the output. + +.TP +\fB\-\-help\fR +Print a help message describing all options \fBsprio\fR. + +.TP +\fB\-j <job_id_list>\fR, \fB\-\-jobs=<job_id_list>\fR +Requests a comma separated list of job ids to display. Defaults to all jobs. + +.TP +\fB\-l\fR, \fB\-\-long\fR +Report more of the available information for the selected jobs. + +.TP +\fB\-n\fR, \fB\-\-norm\fR +Display the normalized priority factors for the selected jobs. + +.TP +\fB\-o <output_format>\fR, \fB\-\-format=<output_format>\fR +Specify the information to be displayed, its size and position +(right or left justified). +The default formats with various options are + +.RS +.TP 15 +\fIdefault\fR +"%.7i %.8u %.10A %.10F %.10J %.10P %.10Q" +.TP +\fI\-l, \-\-long\fR +"%.7i %.8u %.10Y %.10A %.10F %.10J %.10P %.10Q %.6N" +.RE + +.IP +The format of each field is "%[.][size]type". +.RS +.TP 8 +\fIsize\fR +is the minimum field size. +If no size is specified, whatever is needed to print the information will be used. +.TP +\fI .\fR +indicates the output should be left justified. +By default, output is right justified. +.RE + +.IP +Valid \fItype\fR specifications include: + +.RS +.TP 4 +\fB%a\fR +Normalized age priority +.TP +\fB%A\fR +Weighted age priority +.TP +\fB%f\fR +Normalized fair-share priority +.TP +\fB%F\fR +Weighted fair-share priority +.TP +\fB%i\fR +Job ID +.TP +\fB%j\fR +Normalized job size priority +.TP +\fB%J\fR +Weighted job size priority +.TP +\fB%N\fR +Nice adjustment +.TP +\fB%p\fR +Normalized partition priority +.TP +\fB%P\fR +Weighted partition priority +.TP +\fB%q\fR +Normalized quality of service priority +.TP +\fB%Q\fR +Weighted quality of service priority +.TP +\fB%u\fR +User name for a job +.TP +\fB%Y\fR +Job priority +.TP +\fB%y\fR +Normalized job priority +.RE + +.TP +\fB\-u <user_list>\fR, \fB\-\-user=<user_list>\fR +Request jobs from a comma separated list of users. The list can +consist of user names or user id numbers. + +.TP +\fB\-\-usage\fR +Print a brief help message listing the \fBsprio\fR options. + +.TP +\fB\-v\fR, \fB\-\-verbose\fR +Report details of sprios actions. + +.TP +\fB\-V\fR , \fB\-\-version\fR +Print version information and exit. + +.TP +\fB\-w\fR , \fB\-\-weights\fR Display the configured weights for each +factor. This is for information purposes only. Actual job data is +suppressed. + +.SH "EXAMPLES" +.eo +Print the list of all pending jobs with their weighted priorities +.br +> sprio + JOBID PRIORITY AGE FAIRSHARE JOBSIZE PARTITION QOS +.br + 65539 62664 0 51664 1000 10000 0 +.br + 65540 62663 0 51663 1000 10000 0 +.br + 65541 62662 0 51662 1000 10000 0 +.ec + +.eo +Print the list of all pending jobs with their normalized priorities +.br +> sprio \-n +.br + JOBID PRIORITY AGE FAIRSHARE JOBSIZE PARTITION QOS +.br + 65539 0.00001459 0.0007180 0.5166470 1.0000000 1.0000000 0.0000000 +.br + 65540 0.00001459 0.0007180 0.5166370 1.0000000 1.0000000 0.0000000 +.br + 65541 0.00001458 0.0007180 0.5166270 1.0000000 1.0000000 0.0000000 +.ec + +.eo +Print the job priorities for specific jobs +.br +> sprio \-\-jobs=65548,65547 +.br + JOBID PRIORITY AGE FAIRSHARE JOBSIZE PARTITION QOS +.br + 65547 62078 0 51078 1000 10000 0 +.br + 65548 62077 0 51077 1000 10000 0 +.ec + +.eo +Print the job priorities for jobs of specific users +.br +> sprio \-\-users=fred,sally +.br + JOBID USER PRIORITY AGE FAIRSHARE JOBSIZE PARTITION QOS +.br + 65548 fred 62079 1 51077 1000 10000 0 +.br + 65549 sally 62080 1 51078 1000 10000 0 +.ec + +.eo +Print the configured weights for each priority component +.br +> sprio \-w +.br + JOBID PRIORITY AGE FAIRSHARE JOBSIZE PARTITION QOS +.br + Weights 1000 100000 1000 10000 1 +.ec + +.SH "COPYING" +Copyright (C) 2009 Lawrence Livermore National Security. +Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). +CODE\-OCEC\-09\-009. All rights reserved. +.LP +This file is part of SLURM, a resource management program. +For details, see <https://computing.llnl.gov/linux/slurm/>. +.LP +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. +.LP +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. +.SH "SEE ALSO" +\fBsqueue\fR(1), \fBsshare\fR(1) diff --git a/doc/man/man1/squeue.1 b/doc/man/man1/squeue.1 index b1d29a9a1a8..349da10d5f9 100644 --- a/doc/man/man1/squeue.1 +++ b/doc/man/man1/squeue.1 @@ -39,10 +39,8 @@ specified (in seconds). By default, prints a time stamp with the header. .TP -\fB\-j\fR, \fB\-\-jobs\fR -Specify the jobs to view. This flag indicates that a comma separated list -of jobs to view follows without an equal sign (see examples). -Defaults to all jobs. +\fB\-j <job_id_list>\fR, \fB\-\-jobs=<job_id_list>\fR +Requests a comma separated list of job ids to display. Defaults to all jobs. .TP \fB\-l\fR, \fB\-\-long\fR @@ -313,8 +311,8 @@ See the \fBJOB STATE CODES\fR section below for more information. .TP \fB\-u <user_list>\fR, \fB\-\-user=<user_list>\fR -Specifies a comma separated list of users whose jobs or job steps are to be -reported. The list can consist of user names or user id numbers. +Request jobs or job steps from a comma separated list of users. The +list can consist of user names or user id numbers. .TP \fB\-\-usage\fR diff --git a/src/Makefile.am b/src/Makefile.am index c47d8d0e660..4392926da66 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,8 @@ endif SUBDIRS = common api database \ slurmctld slurmd slurmdbd plugins srun sbcast \ scontrol scancel squeue sinfo smap sview salloc \ - sbatch sattach strigger sacct sacctmgr sreport sstat sshare $(SRUN_CR) + sbatch sattach strigger sacct sacctmgr sreport sstat \ + sshare sprio $(SRUN_CR) diff --git a/src/Makefile.in b/src/Makefile.in index dd77002e21d..1a818e95374 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -84,7 +84,7 @@ CTAGS = ctags DIST_SUBDIRS = common api database slurmctld slurmd slurmdbd plugins \ srun sbcast scontrol scancel squeue sinfo smap sview salloc \ sbatch sattach strigger sacct sacctmgr sreport sstat sshare \ - srun_cr + sprio srun_cr DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -264,7 +264,8 @@ top_srcdir = @top_srcdir@ SUBDIRS = common api database \ slurmctld slurmd slurmdbd plugins srun sbcast \ scontrol scancel squeue sinfo smap sview salloc \ - sbatch sattach strigger sacct sacctmgr sreport sstat sshare $(SRUN_CR) + sbatch sattach strigger sacct sacctmgr sreport sstat \ + sshare sprio $(SRUN_CR) all: all-recursive diff --git a/src/common/slurm_priority.c b/src/common/slurm_priority.c index 4430a2c7a0a..093718973fd 100644 --- a/src/common/slurm_priority.c +++ b/src/common/slurm_priority.c @@ -47,6 +47,9 @@ typedef struct slurm_priority_ops { void (*reconfig) (); int (*set_max_usage) (uint32_t procs, uint32_t half_life); void (*set_assoc_usage)(acct_association_rec_t *assoc); + List (*get_priority_factors) + (priority_factors_request_msg_t *req_msg); + } slurm_priority_ops_t; typedef struct slurm_priority_context { @@ -85,6 +88,7 @@ static slurm_priority_ops_t * _priority_get_ops( "priority_p_reconfig", "priority_p_set_max_cluster_usage", "priority_p_set_assoc_usage", + "priority_p_get_priority_factors_list", }; int n_syms = sizeof( syms ) / sizeof( char * ); @@ -262,3 +266,12 @@ extern void priority_g_set_assoc_usage(acct_association_rec_t *assoc) (*(g_priority_context->ops.set_assoc_usage))(assoc); return; } + +extern List priority_g_get_priority_factors_list( + priority_factors_request_msg_t *req_msg) +{ + if (slurm_priority_init() < 0) + return NULL; + + return (*(g_priority_context->ops.get_priority_factors))(req_msg); +} diff --git a/src/common/slurm_priority.h b/src/common/slurm_priority.h index b87a23a1589..2cbe02d07de 100644 --- a/src/common/slurm_priority.h +++ b/src/common/slurm_priority.h @@ -71,5 +71,7 @@ extern int priority_g_set_max_cluster_usage(uint32_t procs, uint32_t half_life); * IN/OUT: assoc - association to have usage set. */ extern void priority_g_set_assoc_usage(acct_association_rec_t *assoc); +extern List priority_g_get_priority_factors_list( + priority_factors_request_msg_t *req_msg); #endif /*_SLURM_PRIORIY_H */ diff --git a/src/common/slurm_protocol_defs.c b/src/common/slurm_protocol_defs.c index 1a02809c3dd..26f2ad820f2 100644 --- a/src/common/slurm_protocol_defs.c +++ b/src/common/slurm_protocol_defs.c @@ -115,6 +115,12 @@ extern void slurm_destroy_char(void *object) xfree(tmp); } +extern void slurm_destroy_uint32_ptr(void *object) +{ + uint32_t *tmp = (uint32_t *)object; + xfree(tmp); +} + /* returns number of objects added to list */ extern int slurm_addto_char_list(List char_list, char *names) { @@ -1517,6 +1523,34 @@ void inline slurm_free_shares_response_msg(shares_response_msg_t *msg) } } +void inline slurm_destroy_priority_factors_object(void *object) +{ + priority_factors_object_t *obj_ptr = + (priority_factors_object_t *)object; + xfree(obj_ptr); +} + +void inline slurm_free_priority_factors_request_msg( + priority_factors_request_msg_t *msg) +{ + if(msg) { + if(msg->job_id_list) + list_destroy(msg->job_id_list); + if(msg->uid_list) + list_destroy(msg->uid_list); + xfree(msg); + } +} + +void inline slurm_free_priority_factors_response_msg( + priority_factors_response_msg_t *msg) +{ + if(msg) { + if(msg->priority_factors_list) + list_destroy(msg->priority_factors_list); + xfree(msg); + } +} void inline slurm_free_accounting_update_msg(accounting_update_msg_t *msg) @@ -1624,6 +1658,12 @@ extern int slurm_free_msg_data(slurm_msg_type_t type, void *data) case RESPONSE_SHARE_INFO: slurm_free_shares_response_msg(data); break; + case REQUEST_PRIORITY_FACTORS: + slurm_free_priority_factors_request_msg(data); + break; + case RESPONSE_PRIORITY_FACTORS: + slurm_free_priority_factors_response_msg(data); + break; case REQUEST_NODE_SELECT_INFO: slurm_free_node_select_msg(data); break; diff --git a/src/common/slurm_protocol_defs.h b/src/common/slurm_protocol_defs.h index 9107a6d0d38..39e1ad61720 100644 --- a/src/common/slurm_protocol_defs.h +++ b/src/common/slurm_protocol_defs.h @@ -122,6 +122,8 @@ typedef enum { RESPONSE_SHARE_INFO, REQUEST_RESERVATION_INFO, RESPONSE_RESERVATION_INFO, + REQUEST_PRIORITY_FACTORS, + RESPONSE_PRIORITY_FACTORS, REQUEST_UPDATE_JOB = 3001, REQUEST_UPDATE_NODE, @@ -332,6 +334,28 @@ typedef struct shares_response_msg { uint64_t tot_shares; } shares_response_msg_t; +typedef struct priority_factors_object { + uint32_t job_id; + uint32_t user_id; + + double priority_age; + double priority_fs; + double priority_js; + double priority_part; + double priority_qos; + + uint16_t nice; +} priority_factors_object_t; + +typedef struct priority_factors_request_msg { + List job_id_list; + List uid_list; +} priority_factors_request_msg_t; + +typedef struct priority_factors_response_msg { + List priority_factors_list; /* priority_factors_object_t list */ +} priority_factors_response_msg_t; + typedef struct job_step_kill_msg { uint32_t job_id; uint32_t job_step_id; @@ -824,6 +848,11 @@ void inline slurm_free_set_debug_level_msg(set_debug_level_msg_t *msg); void inline slurm_destroy_association_shares_object(void *object); void inline slurm_free_shares_request_msg(shares_request_msg_t *msg); void inline slurm_free_shares_response_msg(shares_response_msg_t *msg); +void inline slurm_destroy_priority_factors_object(void *object); +void inline slurm_free_priority_factors_request_msg( + priority_factors_request_msg_t *msg); +void inline slurm_free_priority_factors_response_msg( + priority_factors_response_msg_t *msg); #define slurm_free_timelimit_msg(msg) \ slurm_free_kill_job_msg(msg) diff --git a/src/common/slurm_protocol_pack.c b/src/common/slurm_protocol_pack.c index f9fa8c09959..6dbe4a793ce 100644 --- a/src/common/slurm_protocol_pack.c +++ b/src/common/slurm_protocol_pack.c @@ -79,6 +79,16 @@ static int _unpack_shares_request_msg(shares_request_msg_t ** msg, Buf buffer); static void _pack_shares_response_msg(shares_response_msg_t * msg, Buf buffer); static int _unpack_shares_response_msg(shares_response_msg_t ** msg, Buf buffer); +static void _pack_priority_factors_object(void *in, Buf buffer); +static int _unpack_priority_factors_object(void **object, Buf buffer); +static void _pack_priority_factors_request_msg( + priority_factors_request_msg_t * msg, Buf buffer); +static int _unpack_priority_factors_request_msg( + priority_factors_request_msg_t ** msg, Buf buffer); +static void _pack_priority_factors_response_msg( + priority_factors_response_msg_t * msg, Buf buffer); +static int _unpack_priority_factors_response_msg( + priority_factors_response_msg_t ** msg, Buf buffer); static void _pack_update_node_msg(update_node_msg_t * msg, Buf buffer); static int _unpack_update_node_msg(update_node_msg_t ** msg, Buf buffer); @@ -747,7 +757,16 @@ pack_msg(slurm_msg_t const *msg, Buf buffer) _pack_shares_response_msg((shares_response_msg_t *)msg->data, buffer); break; - + case REQUEST_PRIORITY_FACTORS: + _pack_priority_factors_request_msg( + (priority_factors_request_msg_t*)msg->data, + buffer); + break; + case RESPONSE_PRIORITY_FACTORS: + _pack_priority_factors_response_msg( + (priority_factors_response_msg_t*)msg->data, + buffer); + break; case REQUEST_NODE_SELECT_INFO: _pack_node_select_info_req_msg( (node_info_select_request_msg_t *) msg->data, buffer); @@ -1129,6 +1148,16 @@ unpack_msg(slurm_msg_t * msg, Buf buffer) (shares_response_msg_t **)&msg->data, buffer); break; + case REQUEST_PRIORITY_FACTORS: + _unpack_priority_factors_request_msg( + (priority_factors_request_msg_t**)&msg->data, + buffer); + break; + case RESPONSE_PRIORITY_FACTORS: + _unpack_priority_factors_response_msg( + (priority_factors_response_msg_t**)&msg->data, + buffer); + break; case REQUEST_NODE_SELECT_INFO: rc = _unpack_node_select_info_req_msg( (node_info_select_request_msg_t **) &msg->data, @@ -1387,6 +1416,197 @@ unpack_error: } +static void _pack_priority_factors_object(void *in, Buf buffer) +{ + priority_factors_object_t *object = (priority_factors_object_t *)in; + + if(!object) { + pack32(0, buffer); + pack32(0, buffer); + + packdouble(0, buffer); + packdouble(0, buffer); + packdouble(0, buffer); + packdouble(0, buffer); + packdouble(0, buffer); + + pack16(0, buffer); + + return; + } + + pack32(object->job_id, buffer); + pack32(object->user_id, buffer); + + packdouble(object->priority_age, buffer); + packdouble(object->priority_fs, buffer); + packdouble(object->priority_js, buffer); + packdouble(object->priority_part, buffer); + packdouble(object->priority_qos, buffer); + + pack16(object->nice, buffer); +} + +static int _unpack_priority_factors_object(void **object, Buf buffer) +{ + priority_factors_object_t *object_ptr = + xmalloc(sizeof(priority_factors_object_t)); + + *object = (void *) object_ptr; + safe_unpack32(&object_ptr->job_id, buffer); + safe_unpack32(&object_ptr->user_id, buffer); + + safe_unpackdouble(&object_ptr->priority_age, buffer); + safe_unpackdouble(&object_ptr->priority_fs, buffer); + safe_unpackdouble(&object_ptr->priority_js, buffer); + safe_unpackdouble(&object_ptr->priority_part, buffer); + safe_unpackdouble(&object_ptr->priority_qos, buffer); + + safe_unpack16(&object_ptr->nice, buffer); + + return SLURM_SUCCESS; + +unpack_error: + xfree(object); + *object = NULL; + return SLURM_ERROR; +} + +static void +_pack_priority_factors_request_msg(priority_factors_request_msg_t * msg, + Buf buffer) +{ + uint32_t count = NO_VAL; + uint32_t* tmp = NULL; + ListIterator itr = NULL; + + xassert(msg != NULL); + + if(msg->job_id_list) + count = list_count(msg->job_id_list); + pack32(count, buffer); + if(count && count != NO_VAL) { + itr = list_iterator_create(msg->job_id_list); + while((tmp = list_next(itr))) { + pack32(*tmp, buffer); + } + list_iterator_destroy(itr); + } + + count = NO_VAL; + if(msg->uid_list) + count = list_count(msg->uid_list); + pack32(count, buffer); + if(count && count != NO_VAL) { + itr = list_iterator_create(msg->uid_list); + while((tmp = list_next(itr))) { + pack32(*tmp, buffer); + } + list_iterator_destroy(itr); + } + +} + +static int +_unpack_priority_factors_request_msg(priority_factors_request_msg_t ** msg, + Buf buffer) +{ + uint32_t* uint32_tmp; + uint32_t count = NO_VAL; + int i; + priority_factors_request_msg_t *object_ptr = NULL; + + xassert(msg != NULL); + + object_ptr = xmalloc(sizeof(priority_factors_request_msg_t)); + *msg = object_ptr; + + safe_unpack32(&count, buffer); + if(count != NO_VAL) { + object_ptr->job_id_list = list_create(slurm_destroy_uint32_ptr); + for(i=0; i<count; i++) { + uint32_tmp = xmalloc(sizeof(uint32_t)); + safe_unpack32(uint32_tmp, buffer); + list_append(object_ptr->job_id_list, uint32_tmp); + } + } + + safe_unpack32(&count, buffer); + if(count != NO_VAL) { + object_ptr->uid_list = list_create(slurm_destroy_uint32_ptr); + for(i=0; i<count; i++) { + uint32_tmp = xmalloc(sizeof(uint32_t)); + safe_unpack32(uint32_tmp, buffer); + list_append(object_ptr->uid_list, uint32_tmp); + } + } + return SLURM_SUCCESS; + +unpack_error: + slurm_free_priority_factors_request_msg(object_ptr); + *msg = NULL; + return SLURM_ERROR; +} + +static void +_pack_priority_factors_response_msg(priority_factors_response_msg_t * msg, + Buf buffer) +{ + ListIterator itr = NULL; + priority_factors_object_t *factors = NULL; + uint32_t count = NO_VAL; + + xassert(msg != NULL); + if(msg->priority_factors_list) + count = list_count(msg->priority_factors_list); + pack32(count, buffer); + if(count && count != NO_VAL) { + itr = list_iterator_create(msg->priority_factors_list); + while((factors = list_next(itr))) + _pack_priority_factors_object(factors, buffer); + list_iterator_destroy(itr); + } +} + +static void _priority_factors_resp_list_del(void *x) +{ + xfree(x); +} + +static int +_unpack_priority_factors_response_msg(priority_factors_response_msg_t ** msg, + Buf buffer) +{ + uint32_t count = NO_VAL; + int i = 0; + void *tmp_info = NULL; + priority_factors_response_msg_t *object_ptr = NULL; + xassert(msg != NULL); + + object_ptr = xmalloc(sizeof(priority_factors_response_msg_t)); + *msg = object_ptr; + + safe_unpack32(&count, buffer); + if(count != NO_VAL) { + object_ptr->priority_factors_list = + list_create(_priority_factors_resp_list_del); + for(i=0; i<count; i++) { + if(_unpack_priority_factors_object(&tmp_info, buffer) + != SLURM_SUCCESS) + goto unpack_error; + list_append(object_ptr->priority_factors_list, + tmp_info); + } + } + return SLURM_SUCCESS; + +unpack_error: + slurm_free_priority_factors_response_msg(object_ptr); + *msg = NULL; + return SLURM_ERROR; + +} + static void _pack_update_node_msg(update_node_msg_t * msg, Buf buffer) { diff --git a/src/plugins/priority/basic/priority_basic.c b/src/plugins/priority/basic/priority_basic.c index f806d997498..93cf56837a4 100644 --- a/src/plugins/priority/basic/priority_basic.c +++ b/src/plugins/priority/basic/priority_basic.c @@ -138,3 +138,9 @@ extern void priority_p_set_assoc_usage(acct_association_rec_t *assoc) { return; } + +extern List priority_p_get_priority_factors_list( + priority_factors_request_msg_t *req_msg) +{ + return(list_create(NULL)); +} diff --git a/src/plugins/priority/multifactor/priority_multifactor.c b/src/plugins/priority/multifactor/priority_multifactor.c index c9201a03eb1..249ea5ec083 100644 --- a/src/plugins/priority/multifactor/priority_multifactor.c +++ b/src/plugins/priority/multifactor/priority_multifactor.c @@ -1,7 +1,7 @@ /*****************************************************************************\ * priority_multifactor.c - slurm multifactor priority plugin. ***************************************************************************** - * Copyright (C) 2008 Lawrence Livermore National Security. + * Copyright (C) 2008-2009 Lawrence Livermore National Security. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Danny Auble <da@llnl.gov> * CODE-OCEC-09-009. All rights reserved. @@ -302,11 +302,11 @@ static int _set_children_usage_efctv(List childern_list) /* job_ptr should already have the partition priority and such added * here before had we will be adding to it */ -static double _get_fairshare_priority( struct job_record *job_ptr ) +static double _get_fairshare_priority( struct job_record *job_ptr) { - acct_association_rec_t *assoc = + acct_association_rec_t *assoc = (acct_association_rec_t *)job_ptr->assoc_ptr; - double fs_priority = 0.0; + double priority_fs = 0.0; if(!calc_fairshare) return 0; @@ -332,111 +332,140 @@ static double _get_fairshare_priority( struct job_record *job_ptr ) } // Priority is 0 -> 1 - fs_priority = + priority_fs = (assoc->shares_norm - (double)assoc->usage_efctv + 1.0) / 2.0; debug4("Fairshare priority for user %s in acct %s" "((%f - %Lf) + 1) / 2 = %f", assoc->user, assoc->acct, assoc->shares_norm, - assoc->usage_efctv, fs_priority); + assoc->usage_efctv, priority_fs); slurm_mutex_unlock(&assoc_mgr_association_lock); debug3("job %u has a fairshare priority of %f", - job_ptr->job_id, fs_priority); + job_ptr->job_id, priority_fs); - return fs_priority; + return priority_fs; } -static uint32_t _get_priority_internal(time_t start_time, - struct job_record *job_ptr) +static void _get_priority_factors(time_t start_time, struct job_record *job_ptr, + priority_factors_object_t* factors, + bool status_only) { - double age_priority = 0.0; - double fs_priority = 0.0; - double js_priority = 0.0; - double part_priority = 0.0; - double priority = 0.0; - double qos_priority = 0.0; - acct_qos_rec_t *qos_ptr = (acct_qos_rec_t *)job_ptr->qos_ptr; - - if(job_ptr->direct_set_prio) - return job_ptr->priority; + acct_qos_rec_t *qos_ptr = NULL; - if(!job_ptr->details) { - error("_get_priority_internal: job %u does not have a " - "details symbol set, can't set priority"); - return 0; - } - /* - * This means the job is not eligible yet - */ - if(!job_ptr->details->begin_time > start_time) - return 1; + xassert(factors); + xassert(job_ptr); + + qos_ptr = (acct_qos_rec_t *)job_ptr->qos_ptr; - /* figure out the priority */ + memset(factors, 0, sizeof(priority_factors_object_t)); if(weight_age) { - uint32_t diff = start_time - job_ptr->details->begin_time; - double norm_diff = 1; - - if(diff < max_age) - norm_diff = (double)diff / (double)max_age; - - if(norm_diff > 0) { - age_priority = norm_diff * (double)weight_age; - debug3("Weighted Age priority is %f * %u = %.2f", - norm_diff, weight_age, age_priority); + uint32_t diff = start_time - job_ptr->details->begin_time; + if(job_ptr->details->begin_time) { + if(diff < max_age) + factors->priority_age = + (double)diff / (double)max_age; + else + factors->priority_age = 1.0; } } if(job_ptr->assoc_ptr && weight_fs) { - double fs_temp = _get_fairshare_priority(job_ptr); - fs_priority = fs_temp * (double)weight_fs; - debug3("Weighted Fairshare priority is %f * %u = %.2f", - fs_temp, weight_fs, fs_priority); + if (status_only) + factors->priority_fs = job_ptr->priority_fs; + else { + factors->priority_fs = _get_fairshare_priority(job_ptr); + job_ptr->priority_fs = factors->priority_fs; + debug3("sprio job %u has a fairshare priority of %f", + job_ptr->job_id, job_ptr->priority_fs); + } } if(weight_js) { - double norm_js = 0; if(favor_small) { - norm_js = (double)(node_record_count + factors->priority_js = (double)(node_record_count - job_ptr->details->min_nodes) / (double)node_record_count; - } else - norm_js = (double)job_ptr->details->min_nodes + } else + factors->priority_js = + (double)job_ptr->details->min_nodes / (double)node_record_count; - if(norm_js > 0) { - js_priority = norm_js * (double)weight_js; - debug3("Weighted JobSize priority is %f * %u = %.2f", - norm_js, weight_js, js_priority); - } + if (factors->priority_js < .0) + factors->priority_js = 0.0; + else if (factors->priority_js > 1.0) + factors->priority_js = 1.0; } if(job_ptr->part_ptr && job_ptr->part_ptr->priority && weight_part) { - part_priority = job_ptr->part_ptr->norm_priority - * (double)weight_part; - debug3("Weighted Partition priority is %f * %u = %.2f", - job_ptr->part_ptr->norm_priority, weight_part, - part_priority); + factors->priority_part = job_ptr->part_ptr->norm_priority; } if(qos_ptr && qos_ptr->priority && weight_qos) { - qos_priority = qos_ptr->norm_priority - * (double)weight_qos; - debug3("Weighted QOS priority is %f * %u = %.2f", - qos_ptr->norm_priority, weight_qos, - qos_priority); + factors->priority_qos = qos_ptr->norm_priority; + } + + factors->nice = job_ptr->details->nice; +} + +static uint32_t _get_priority_internal(time_t start_time, + struct job_record *job_ptr) +{ + double priority = 0.0; + double priority_age = 0.0; + double priority_fs = 0.0; + double priority_js = 0.0; + double priority_part = 0.0; + double priority_qos = 0.0; + priority_factors_object_t factors; + + if(job_ptr->direct_set_prio) + return job_ptr->priority; + + if(!job_ptr->details) { + error("_get_priority_internal: job %u does not have a " + "details symbol set, can't set priority"); + return 0; } + /* + * This means the job is not eligible yet + */ + if(!job_ptr->details->begin_time + || (job_ptr->details->begin_time > start_time)) + return 1; + + /* figure out the priority */ + _get_priority_factors(start_time, job_ptr, &factors, false); + + priority_age = factors.priority_age * (double)weight_age; + debug3("Weighted Age priority is %f * %u = %.2f", + factors.priority_age, weight_age, priority_age); - priority = age_priority + fs_priority + js_priority + part_priority + - qos_priority; - debug3("Job %u priority: %.2f + %.2f + %.2f + %.2f + %.2f = %.2f", - job_ptr->job_id, age_priority, fs_priority, js_priority, - part_priority, qos_priority, priority); + priority_fs = factors.priority_fs * (double)weight_fs; + debug3("Weighted Fairshare priority is %f * %u = %.2f", + factors.priority_fs, weight_fs, priority_fs); - priority -= ((double)job_ptr->details->nice - (double)NICE_OFFSET); - debug3("Nice offset is %u", job_ptr->details->nice - NICE_OFFSET); + priority_js = factors.priority_js * (double)weight_js; + debug3("Weighted JobSize priority is %f * %u = %.2f", + factors.priority_js, weight_js, priority_js); - if(priority < 1) + priority_part = factors.priority_part * (double)weight_part; + debug3("Weighted Partition priority is %f * %u = %.2f", + factors.priority_part, weight_part, priority_part); + + priority_qos = factors.priority_qos * (double)weight_qos; + debug3("Weighted QOS priority is %f * %u = %.2f", + factors.priority_qos, weight_qos, priority_qos); + + priority = priority_age + priority_fs + priority_js + priority_part + + priority_qos - (double)(factors.nice - NICE_OFFSET); + + debug3("Job %u priority: %.2f + %.2f + %.2f + %.2f + %.2f - %d = %.2f", + job_ptr->job_id, priority_age, priority_fs, priority_js, + priority_part, priority_qos, (factors.nice - NICE_OFFSET), + priority); + + if(priority < 1) priority = 1; return (uint32_t)priority; @@ -451,11 +480,12 @@ static void *_decay_thread(void *no_data) /* int sigarray[] = {SIGUSR1, 0}; */ struct tm tm; time_t last_ran = 0; - double decay_factor = + double decay_factor = 1 - (0.693 / (double)slurm_get_priority_decay_hl()); + /* Write lock on jobs, read lock on nodes and partitions */ slurmctld_lock_t job_write_lock = - { READ_LOCK, WRITE_LOCK, WRITE_LOCK, READ_LOCK }; + { NO_LOCK, WRITE_LOCK, READ_LOCK, READ_LOCK }; (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); @@ -607,6 +637,49 @@ static void *_decay_thread(void *no_data) return NULL; } +/* Selects the specific jobs that the user wanted to see + * Requests that include job id(s) and user id(s) must match both to be passed. + * Returns 1 if job should be omitted */ +static int _filter_job(struct job_record *job_ptr, List req_job_list, + List req_user_list) +{ + int filter = 0; + ListIterator iterator; + uint32_t *job_id; + uint32_t *user_id; + + if (req_job_list) { + filter = 1; + iterator = list_iterator_create(req_job_list); + while ((job_id = list_next(iterator))) { + if (*job_id == job_ptr->job_id) { + filter = 0; + break; + } + } + list_iterator_destroy(iterator); + if (filter == 1) { + return 1; + } + } + + if (req_user_list) { + filter = 1; + iterator = list_iterator_create(req_user_list); + while ((user_id = list_next(iterator))) { + if (*user_id == job_ptr->user_id) { + filter = 0; + break; + } + } + list_iterator_destroy(iterator); + if (filter == 1) + return 1; + } + + return filter; +} + static void *_cleanup_thread(void *no_data) { pthread_join(decay_handler_thread, NULL); @@ -800,3 +873,65 @@ extern void priority_p_set_assoc_usage(acct_association_rec_t *assoc) } } +extern List priority_p_get_priority_factors_list( + priority_factors_request_msg_t *req_msg) +{ + List req_job_list; + List req_user_list; + List ret_list = NULL; + ListIterator itr; + priority_factors_object_t *obj = NULL; + struct job_record *job_ptr = NULL; + time_t start_time = time(NULL); + + xassert(req_msg); + req_job_list = req_msg->job_id_list; + req_user_list = req_msg->uid_list; + + /* Read lock on jobs, nodes, and partitions */ + slurmctld_lock_t job_read_lock = + { NO_LOCK, READ_LOCK, READ_LOCK, READ_LOCK }; + + if (job_list && list_count(job_list)) { + ret_list = list_create(slurm_destroy_priority_factors_object); + lock_slurmctld(job_read_lock); + itr = list_iterator_create(job_list); + while ((job_ptr = list_next(itr))) { + /* + * We are only looking for pending jobs + */ + if(!IS_JOB_PENDING(job_ptr)) + continue; + /* + * This means the job is not eligible yet + */ + if(!job_ptr->details->begin_time + || (job_ptr->details->begin_time > start_time)) + continue; + + /* + * 0 means the job is held; 1 means system hold + */ + if(job_ptr->priority <= 1) + continue; + + if (_filter_job(job_ptr, req_job_list, req_user_list)) + continue; + + obj = xmalloc(sizeof(priority_factors_object_t)); + + _get_priority_factors(start_time, job_ptr, obj, true); + obj->job_id = job_ptr->job_id; + obj->user_id = job_ptr->user_id; + list_append(ret_list, obj); + } + list_iterator_destroy(itr); + unlock_slurmctld(job_read_lock); + if (!list_count(ret_list)) { + list_destroy(ret_list); + ret_list = NULL; + } + } + + return ret_list; +} diff --git a/src/slurmctld/proc_req.c b/src/slurmctld/proc_req.c index 5534f636a73..bc8c34a2f12 100644 --- a/src/slurmctld/proc_req.c +++ b/src/slurmctld/proc_req.c @@ -100,6 +100,7 @@ inline static void _slurm_rpc_dump_conf(slurm_msg_t * msg); inline static void _slurm_rpc_dump_jobs(slurm_msg_t * msg); inline static void _slurm_rpc_dump_job_single(slurm_msg_t * msg); inline static void _slurm_rpc_get_shares(slurm_msg_t *msg); +inline static void _slurm_rpc_get_priority_factors(slurm_msg_t *msg); inline static void _slurm_rpc_dump_nodes(slurm_msg_t * msg); inline static void _slurm_rpc_dump_partitions(slurm_msg_t * msg); inline static void _slurm_rpc_epilog_complete(slurm_msg_t * msg); @@ -175,6 +176,10 @@ void slurmctld_req (slurm_msg_t * msg) _slurm_rpc_get_shares(msg); slurm_free_shares_request_msg(msg->data); break; + case REQUEST_PRIORITY_FACTORS: + _slurm_rpc_get_priority_factors(msg); + slurm_free_priority_factors_request_msg(msg->data); + break; case REQUEST_JOB_END_TIME: _slurm_rpc_end_time(msg); slurm_free_job_alloc_info_msg(msg->data); @@ -873,6 +878,32 @@ static void _slurm_rpc_get_shares(slurm_msg_t *msg) debug2("_slurm_rpc_get_shares %s", TIME_STR); } +static void _slurm_rpc_get_priority_factors(slurm_msg_t *msg) +{ + DEF_TIMERS; + priority_factors_request_msg_t *req_msg = + (priority_factors_request_msg_t *) msg->data; + priority_factors_response_msg_t resp_msg; + slurm_msg_t response_msg; + + uid_t uid = g_slurm_auth_get_uid(msg->auth_cred, NULL); + + START_TIMER; + debug2("Processing RPC: REQUEST GET PRIORITY FACTORS from uid=%u", + (unsigned int)uid); + resp_msg.priority_factors_list = priority_g_get_priority_factors_list( + req_msg); + slurm_msg_t_init(&response_msg); + response_msg.address = msg->address; + response_msg.msg_type = RESPONSE_PRIORITY_FACTORS; + response_msg.data = &resp_msg; + slurm_send_node_msg(msg->conn_fd, &response_msg); + if(resp_msg.priority_factors_list) + list_destroy(resp_msg.priority_factors_list); + END_TIMER2("_slurm_rpc_get_priority_factors"); + debug2("_slurm_rpc_get_priority_factors %s", TIME_STR); +} + /* _slurm_rpc_end_time - Process RPC for job end time */ static void _slurm_rpc_end_time(slurm_msg_t * msg) { diff --git a/src/slurmctld/slurmctld.h b/src/slurmctld/slurmctld.h index b4c03ebd176..8db643a89e0 100644 --- a/src/slurmctld/slurmctld.h +++ b/src/slurmctld/slurmctld.h @@ -504,6 +504,7 @@ struct job_record { time_t pre_sus_time; /* time job ran prior to last suspend */ uint32_t priority; /* relative priority of the job, * zero == held (don't initiate) */ + double priority_fs; /* cached value used by sprio command */ uint16_t qos; /* quality of service, * used only by Moab */ void *qos_ptr; /* pointer to the quality of diff --git a/src/sprio/Makefile.am b/src/sprio/Makefile.am new file mode 100644 index 00000000000..abadc1aa1ed --- /dev/null +++ b/src/sprio/Makefile.am @@ -0,0 +1,20 @@ +# +# Makefile for sprio + +AUTOMAKE_OPTIONS = foreign + +INCLUDES = -I$(top_srcdir) + +bin_PROGRAMS = sprio + +sprio_LDADD = $(top_builddir)/src/api/libslurm.o -ldl + +noinst_HEADERS = sprio.h print.h +sprio_SOURCES = sprio.c print.c opts.c + +force: +$(sprio_LDADD) : force + @cd `dirname $@` && $(MAKE) `basename $@` + +sprio_LDFLAGS = -export-dynamic $(CMD_LDFLAGS) + diff --git a/src/sprio/Makefile.in b/src/sprio/Makefile.in new file mode 100644 index 00000000000..50527925da5 --- /dev/null +++ b/src/sprio/Makefile.in @@ -0,0 +1,566 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Makefile for sprio + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = sprio$(EXEEXT) +subdir = src/sprio +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/auxdir/acx_pthread.m4 \ + $(top_srcdir)/auxdir/slurm.m4 \ + $(top_srcdir)/auxdir/x_ac__system_configuration.m4 \ + $(top_srcdir)/auxdir/x_ac_affinity.m4 \ + $(top_srcdir)/auxdir/x_ac_aix.m4 \ + $(top_srcdir)/auxdir/x_ac_bluegene.m4 \ + $(top_srcdir)/auxdir/x_ac_cflags.m4 \ + $(top_srcdir)/auxdir/x_ac_cray.m4 \ + $(top_srcdir)/auxdir/x_ac_databases.m4 \ + $(top_srcdir)/auxdir/x_ac_debug.m4 \ + $(top_srcdir)/auxdir/x_ac_elan.m4 \ + $(top_srcdir)/auxdir/x_ac_env.m4 \ + $(top_srcdir)/auxdir/x_ac_federation.m4 \ + $(top_srcdir)/auxdir/x_ac_gpl_licensed.m4 \ + $(top_srcdir)/auxdir/x_ac_gtk.m4 \ + $(top_srcdir)/auxdir/x_ac_iso.m4 \ + $(top_srcdir)/auxdir/x_ac_munge.m4 \ + $(top_srcdir)/auxdir/x_ac_ncurses.m4 \ + $(top_srcdir)/auxdir/x_ac_pam.m4 \ + $(top_srcdir)/auxdir/x_ac_ptrace.m4 \ + $(top_srcdir)/auxdir/x_ac_readline.m4 \ + $(top_srcdir)/auxdir/x_ac_setpgrp.m4 \ + $(top_srcdir)/auxdir/x_ac_setproctitle.m4 \ + $(top_srcdir)/auxdir/x_ac_sgi_job.m4 \ + $(top_srcdir)/auxdir/x_ac_slurm_ssl.m4 \ + $(top_srcdir)/auxdir/x_ac_sun_const.m4 \ + $(top_srcdir)/auxdir/x_ac_xcpu.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/slurm/slurm.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_sprio_OBJECTS = sprio.$(OBJEXT) print.$(OBJEXT) opts.$(OBJEXT) + +sprio_OBJECTS = $(am_sprio_OBJECTS) +sprio_DEPENDENCIES = $(top_builddir)/src/api/libslurm.o +sprio_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(sprio_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/slurm +depcomp = $(SHELL) $(top_srcdir)/auxdir/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(sprio_SOURCES) +DIST_SOURCES = $(sprio_SOURCES) +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTHD_CFLAGS = @AUTHD_CFLAGS@ +AUTHD_LIBS = @AUTHD_LIBS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BG_INCLUDES = @BG_INCLUDES@ +BLUEGENE_LOADED = @BLUEGENE_LOADED@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CMD_LDFLAGS = @CMD_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ELAN_LIBS = @ELAN_LIBS@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FEDERATION_LDFLAGS = @FEDERATION_LDFLAGS@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +HAVEMYSQLCONFIG = @HAVEMYSQLCONFIG@ +HAVEPGCONFIG = @HAVEPGCONFIG@ +HAVEPKGCONFIG = @HAVEPKGCONFIG@ +HAVE_AIX = @HAVE_AIX@ +HAVE_ELAN = @HAVE_ELAN@ +HAVE_FEDERATION = @HAVE_FEDERATION@ +HAVE_OPENSSL = @HAVE_OPENSSL@ +HAVE_SOME_CURSES = @HAVE_SOME_CURSES@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_LDFLAGS = @LIB_LDFLAGS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MUNGE_CPPFLAGS = @MUNGE_CPPFLAGS@ +MUNGE_LDFLAGS = @MUNGE_LDFLAGS@ +MUNGE_LIBS = @MUNGE_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NCURSES = @NCURSES@ +NMEDIT = @NMEDIT@ +NUMA_LIBS = @NUMA_LIBS@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAM_LIBS = @PAM_LIBS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PLPA_LIBS = @PLPA_LIBS@ +PROCTRACKDIR = @PROCTRACKDIR@ +PROJECT = @PROJECT@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE = @RELEASE@ +SED = @SED@ +SEMAPHORE_LIBS = @SEMAPHORE_LIBS@ +SEMAPHORE_SOURCES = @SEMAPHORE_SOURCES@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SLURMCTLD_PORT = @SLURMCTLD_PORT@ +SLURMDBD_PORT = @SLURMDBD_PORT@ +SLURMD_PORT = @SLURMD_PORT@ +SLURM_API_AGE = @SLURM_API_AGE@ +SLURM_API_CURRENT = @SLURM_API_CURRENT@ +SLURM_API_MAJOR = @SLURM_API_MAJOR@ +SLURM_API_REVISION = @SLURM_API_REVISION@ +SLURM_API_VERSION = @SLURM_API_VERSION@ +SLURM_MAJOR = @SLURM_MAJOR@ +SLURM_MICRO = @SLURM_MICRO@ +SLURM_MINOR = @SLURM_MINOR@ +SLURM_PREFIX = @SLURM_PREFIX@ +SLURM_VERSION = @SLURM_VERSION@ +SO_LDFLAGS = @SO_LDFLAGS@ +SSL_CPPFLAGS = @SSL_CPPFLAGS@ +SSL_LDFLAGS = @SSL_LDFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +UTIL_LIBS = @UTIL_LIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +INCLUDES = -I$(top_srcdir) +sprio_LDADD = $(top_builddir)/src/api/libslurm.o -ldl +noinst_HEADERS = sprio.h print.h +sprio_SOURCES = sprio.c print.c opts.c +sprio_LDFLAGS = -export-dynamic $(CMD_LDFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/sprio/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/sprio/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +sprio$(EXEEXT): $(sprio_OBJECTS) $(sprio_DEPENDENCIES) + @rm -f sprio$(EXEEXT) + $(sprio_LINK) $(sprio_OBJECTS) $(sprio_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opts.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sprio.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS + + +force: +$(sprio_LDADD) : force + @cd `dirname $@` && $(MAKE) `basename $@` +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/sprio/opts.c b/src/sprio/opts.c new file mode 100644 index 00000000000..f4c0c92765c --- /dev/null +++ b/src/sprio/opts.c @@ -0,0 +1,475 @@ +/****************************************************************************\ + * opts.c - sprio command line option parsing + ***************************************************************************** + * Copyright (C) 2009 Lawrence Livermore National Security. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Don Lipari <lipari1@llnl.gov> + * CODE-OCEC-09-009. All rights reserved. + * + * This file is part of SLURM, a resource management program. + * For details, see <https://computing.llnl.gov/linux/slurm/>. + * Please also read the included file: DISCLAIMER. + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. You must obey the GNU + * General Public License in all respects for all of the code used other than + * OpenSSL. If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not obligated to do + * so. If you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files in + * the program, then also delete it here. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if HAVE_GETOPT_H +# include <getopt.h> +#else +# include "src/common/getopt.h" +#endif + +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> + +#include "src/common/read_config.h" +#include "src/common/uid.h" +#include "src/common/xstring.h" +#include "src/sprio/sprio.h" + +/* getopt_long options, integers but not characters */ +#define OPT_LONG_HELP 0x100 +#define OPT_LONG_USAGE 0x101 + +/* FUNCTIONS */ +static List _build_job_list( char* str ); +static List _build_user_list( char* str ); +static char *_get_prefix(char *token); +static void _help( void ); +static void _parse_token( char *token, char *field, int *field_size, + bool *right_justify, char **suffix); +static void _print_options( void ); +static void _print_version( void ); +static void _usage( void ); + +/* + * parse_command_line + */ +extern void +parse_command_line( int argc, char* argv[] ) +{ + int opt_char; + int option_index; + static struct option long_options[] = { + {"noheader", no_argument, 0, 'h'}, + {"jobs", optional_argument, 0, 'j'}, + {"long", no_argument, 0, 'l'}, + {"norm", no_argument, 0, 'n'}, + {"format", required_argument, 0, 'o'}, + {"user", required_argument, 0, 'u'}, + {"users", required_argument, 0, 'u'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {"weights", no_argument, 0, 'w'}, + {"help", no_argument, 0, OPT_LONG_HELP}, + {"usage", no_argument, 0, OPT_LONG_USAGE}, + {NULL, 0, 0, 0} + }; + + while((opt_char = getopt_long(argc, argv, "hj::lno:u:vVw", + long_options, &option_index)) != -1) { + switch (opt_char) { + case (int)'?': + fprintf(stderr, "Try \"sprio --help\" " + "for more information\n"); + exit(1); + case (int)'h': + params.no_header = true; + break; + case (int) 'j': + if (optarg) { + params.jobs = xstrdup(optarg); + params.job_list = _build_job_list(params.jobs); + } + params.job_flag = true; + break; + case (int) 'l': + params.long_list = true; + break; + case (int) 'n': + params.normalized = true; + break; + case (int) 'o': + xfree(params.format); + params.format = xstrdup(optarg); + break; + case (int) 'u': + xfree(params.users); + params.users = xstrdup(optarg); + params.user_list = _build_user_list(params.users); + break; + case (int) 'v': + params.verbose++; + break; + case (int) 'V': + _print_version(); + exit(0); + case (int) 'w': + params.weights = true; + break; + case OPT_LONG_HELP: + _help(); + exit(0); + case OPT_LONG_USAGE: + _usage(); + exit(0); + } + } + + if (optind < argc) { + if (params.job_flag) { + params.jobs = xstrdup(argv[optind++]); + params.job_list = _build_job_list(params.jobs); + } + if (optind < argc) { + error("Unrecognized option: %s",argv[optind]); + _usage(); + exit(1); + } + } + + if ( params.verbose ) + _print_options(); +} + +/* + * parse_format - Take the user's format specification and use it to build + * build the format specifications (internalize it to print.c data + * structures) + * IN format - user's format specification + * RET zero or error code + */ +extern int parse_format( char* format ) +{ + int field_size; + bool right_justify; + char *prefix = NULL, *suffix = NULL, *token = NULL; + char *tmp_char = NULL, *tmp_format = NULL; + char field[1]; + + if (format == NULL) { + error ("Format option lacks specification."); + exit( 1 ); + } + + params.format_list = list_create( NULL ); + if ((prefix = _get_prefix(format))) { + job_format_add_prefix( params.format_list, 0, 0, prefix); + } + + field_size = strlen( format ); + tmp_format = xmalloc( field_size + 1 ); + strcpy( tmp_format, format ); + + token = strtok_r( tmp_format, "%", &tmp_char); + if (token && (format[0] != '%')) /* toss header */ + token = strtok_r( NULL, "%", &tmp_char ); + while (token) { + _parse_token( token, field, &field_size, &right_justify, + &suffix); + if (field[0] == 'a') + job_format_add_age_priority_normalized(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'A') + job_format_add_age_priority_weighted(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'f') + job_format_add_fs_priority_normalized(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'F') + job_format_add_fs_priority_weighted(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'i') + job_format_add_job_id(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'j') + job_format_add_js_priority_normalized(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'J') + job_format_add_js_priority_weighted(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'N') + job_format_add_job_nice(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'p') + job_format_add_part_priority_normalized(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'P') + job_format_add_part_priority_weighted(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'q') + job_format_add_qos_priority_normalized(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'Q') + job_format_add_qos_priority_weighted(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'u') + job_format_add_user_name(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'y') + job_format_add_job_priority_normalized(params.format_list, + field_size, + right_justify, + suffix ); + else if (field[0] == 'Y') + job_format_add_job_priority_weighted(params.format_list, + field_size, + right_justify, + suffix ); + else + error( "Invalid job format specification: %c", + field[0] ); + + token = strtok_r( NULL, "%", &tmp_char); + } + + xfree( tmp_format ); + return SLURM_SUCCESS; +} + +/* Take a format specification and copy out it's prefix + * IN/OUT token - input specification, everything before "%" is removed + * RET - everything before "%" in the token + */ +static char * +_get_prefix( char *token ) +{ + char *pos, *prefix; + + if (token == NULL) + return NULL; + + pos = strchr(token, (int) '%'); + if (pos == NULL) /* everything is prefix */ + return xstrdup(token); + if (pos == token) /* no prefix */ + return NULL; + + pos[0] = '\0'; /* some prefix */ + prefix = xstrdup(token); + pos[0] = '%'; + memmove(token, pos, (strlen(pos)+1)); + return prefix; +} + +/* Take a format specification and break it into its components + * IN token - input specification without leading "%", eg. ".5u" + * OUT field - the letter code for the data type + * OUT field_size - byte count + * OUT right_justify - true of field to be right justified + * OUT suffix - string containing everthing after the field specification + */ +static void +_parse_token( char *token, char *field, int *field_size, bool *right_justify, + char **suffix) +{ + int i = 0; + + assert (token != NULL); + + if (token[i] == '.') { + *right_justify = true; + i++; + } else + *right_justify = false; + + *field_size = 0; + while ((token[i] >= '0') && (token[i] <= '9')) + *field_size = (*field_size * 10) + (token[i++] - '0'); + + field[0] = token[i++]; + + *suffix = xstrdup(&token[i]); +} + +/* print the parameters specified */ +static void +_print_options() +{ + ListIterator iterator; + int i; + uint32_t *job_id; + uint32_t *user; + + printf( "-----------------------------\n" ); + printf( "format = %s\n", params.format ); + printf( "job_flag = %d\n", params.job_flag ); + printf( "jobs = %s\n", params.jobs ); + printf( "users = %s\n", params.users ); + printf( "verbose = %d\n", params.verbose ); + + if ((params.verbose > 1) && params.job_list) { + i = 0; + iterator = list_iterator_create( params.job_list ); + while ( (job_id = list_next( iterator )) ) { + printf( "job_list[%d] = %u\n", i++, *job_id); + } + list_iterator_destroy( iterator ); + } + + if ((params.verbose > 1) && params.user_list) { + i = 0; + iterator = list_iterator_create( params.user_list ); + while ( (user = list_next( iterator )) ) { + printf( "user_list[%d] = %u\n", i++, *user); + } + list_iterator_destroy( iterator ); + } + + printf( "-----------------------------\n\n\n" ); +} ; + + +/* + * _build_job_list- build a list of job_ids + * IN str - comma separated list of job_ids + * RET List of job_ids (uint32_t) + */ +static List +_build_job_list( char* str ) +{ + List my_list; + char *job = NULL, *tmp_char = NULL, *my_job_list = NULL; + int i; + uint32_t *job_id = NULL; + + if ( str == NULL) + return NULL; + my_list = list_create( NULL ); + my_job_list = xstrdup( str ); + job = strtok_r( my_job_list, ",", &tmp_char ); + while (job) + { + i = strtol( job, (char **) NULL, 10 ); + if (i <= 0) { + error( "Invalid job id: %s", job ); + exit( 1 ); + } + job_id = xmalloc( sizeof( uint32_t ) ); + *job_id = (uint32_t) i; + list_append( my_list, job_id ); + job = strtok_r (NULL, ",", &tmp_char); + } + return my_list; +} + +/* + * _build_user_list- build a list of UIDs + * IN str - comma separated list of user names + * RET List of UIDs (uint32_t) + */ +static List +_build_user_list( char* str ) +{ + List my_list; + char *user = NULL; + char *tmp_char = NULL, *my_user_list = NULL; + uint32_t *uid = NULL; + + if ( str == NULL) + return NULL; + my_list = list_create( NULL ); + my_user_list = xstrdup( str ); + user = strtok_r( my_user_list, ",", &tmp_char ); + while (user) { + uid = xmalloc( sizeof( uint32_t )); + *uid = uid_from_string(user); + if (*uid == -1) { + error( "Invalid user: %s\n", user); + xfree(uid); + } else { + list_append( my_list, uid ); + } + user = strtok_r (NULL, ",", &tmp_char); + } + return my_list; +} + +static void _print_version(void) +{ + printf("%s %s\n", PACKAGE, SLURM_VERSION); +} + +static void _usage(void) +{ + printf("Usage: sprio [-j jid[s]] [-u user_name[s]] [-o format] [--usage] [-hlnvVw]\n"); +} + +static void _help(void) +{ + printf("\ +Usage: sprio [OPTIONS]\n\ + -h, --noheader no headers on output\n\ + -j, --jobs comma separated list of jobs\n\ + to view, default is all\n\ + -l, --long long report\n\ + -n, --norm display normalized values\n\ + -o, --format=format format specification\n\ + -u, --user=user_name comma separated list of users to view\n\ + -v, --verbose verbosity level\n\ + -V, --version output version information and exit\n\ + -w, --weights show the weights for each priority factor\n\ +\nHelp options:\n\ + --help show this help message\n\ + --usage display a brief summary of sprio options\n"); +} diff --git a/src/sprio/print.c b/src/sprio/print.c new file mode 100644 index 00000000000..c46789ed475 --- /dev/null +++ b/src/sprio/print.c @@ -0,0 +1,438 @@ +/*****************************************************************************\ + * print.c - sprio print job functions + ***************************************************************************** + * Copyright (C) 2009 Lawrence Livermore National Security. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Don Lipari <lipari1@llnl.gov> + * CODE-OCEC-09-009. All rights reserved. + * + * This file is part of SLURM, a resource management program. + * For details, see <https://computing.llnl.gov/linux/slurm/>. + * Please also read the included file: DISCLAIMER. + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. You must obey the GNU + * General Public License in all respects for all of the code used other than + * OpenSSL. If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not obligated to do + * so. If you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files in + * the program, then also delete it here. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> + +#include "src/common/list.h" +#include "src/common/macros.h" +#include "src/slurmctld/slurmctld.h" +#include "src/sprio/print.h" +#include "src/sprio/sprio.h" +#include "src/common/uid.h" +#include "src/common/xmalloc.h" +#include "src/common/xstring.h" + +static int _print_str(char *str, int width, bool right, bool cut_output); + +/******************** + * Global Variables * + ********************/ +extern uint32_t max_age; /* time when not to add any more */ +extern uint32_t weight_age; /* weight for age factor */ +extern uint32_t weight_fs; /* weight for Fairshare factor */ +extern uint32_t weight_js; /* weight for Job Size factor */ +extern uint32_t weight_part; /* weight for Partition factor */ +extern uint32_t weight_qos; /* weight for QOS factor */ + + +/***************************************************************************** + * Global Print Functions + *****************************************************************************/ + +int print_jobs_array(List jobs, List format) +{ + if (!params.no_header) + print_job_from_format(NULL, format); + + if (params.weights) { + print_job_from_format((priority_factors_object_t *) -1, format); + return SLURM_SUCCESS; + } + + /* Print the jobs of interest */ + if (jobs) + list_for_each (jobs, (ListForF) print_job_from_format, + (void *) format); + + return SLURM_SUCCESS; +} + +static int _print_str(char *str, int width, bool right, bool cut_output) +{ + char format[64]; + int printed = 0; + + if (right == true && width != 0) + snprintf(format, 64, "%%%ds", width); + else if (width != 0) + snprintf(format, 64, "%%.%ds", width); + else { + format[0] = '%'; + format[1] = 's'; + format[2] = '\0'; + } + + if ((width == 0) || (cut_output == false)) { + if ((printed = printf(format, str)) < 0) + return printed; + } else { + char temp[width + 1]; + snprintf(temp, width + 1, format, str); + if ((printed = printf("%s",temp)) < 0) + return printed; + } + + while (printed++ < width) + printf(" "); + + return printed; +} + +int _print_int(int number, int width, bool right, bool cut_output) +{ + char buf[32]; + + snprintf(buf, 32, "%d", number); + return _print_str(buf, width, right, cut_output); +} + +int _print_norm(double number, int width, bool right, bool cut_output) +{ + char buf[32]; + + snprintf(buf, 32, "%.7lf", number); + return _print_str(buf, width, right, cut_output); +} + + +/***************************************************************************** + * Job Print Functions + *****************************************************************************/ +int print_job_from_format(priority_factors_object_t * job, List list) +{ + ListIterator i = list_iterator_create(list); + job_format_t *current; + int total_width = 0; + + while ((current = (job_format_t *) list_next(i)) != NULL) { + if (current-> + function(job, current->width, current->right_justify, + current->suffix) + != SLURM_SUCCESS) + return SLURM_ERROR; + if (current->width) + total_width += (current->width + 1); + else + total_width += 10; + } + list_iterator_destroy(i); + + printf("\n"); + + return SLURM_SUCCESS; +} + +int job_format_add_function(List list, int width, bool right, char *suffix, + int (*function) (priority_factors_object_t *, + int, bool, char*)) +{ + job_format_t *tmp = (job_format_t *) xmalloc(sizeof(job_format_t)); + tmp->function = function; + tmp->width = width; + tmp->right_justify = right; + tmp->suffix = suffix; + + if (list_append(list, tmp) == NULL) { + fprintf(stderr, "Memory exhausted\n"); + exit(1); + } + return SLURM_SUCCESS; +} + + +int _print_job_job_id(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("JOBID", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_str("Weights", width, right, true); + else { + char id[FORMAT_STRING_SIZE]; + snprintf(id, FORMAT_STRING_SIZE, "%u", job->job_id); + _print_str(id, width, right, true); + } + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_job_prefix(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_age_priority_normalized(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("AGE", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_age, width, right, true); + else + _print_norm(job->priority_age, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_age_priority_weighted(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("AGE", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_age, width, right, true); + else + _print_int(job->priority_age * weight_age, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_fs_priority_normalized(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("FAIRSHARE", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_fs, width, right, true); + else + _print_norm(job->priority_fs, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_fs_priority_weighted(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("FAIRSHARE", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_fs, width, right, true); + else + _print_int(job->priority_fs * weight_fs, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_job_priority_normalized(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + char temp[FORMAT_STRING_SIZE]; + if (job == NULL) /* Print the Header instead */ + _print_str("PRIORITY", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_str("", width, right, true); + else { + double age_priority = job->priority_age * (double)weight_age; + double fs_priority = job->priority_fs * (double)weight_fs; + double js_priority = job->priority_js * (double)weight_js; + double part_priority = job->priority_part * (double)weight_part; + double qos_priority = job->priority_qos * (double)weight_qos; + double priority = age_priority + fs_priority + js_priority + + part_priority + qos_priority; + priority -= (double)(job->nice - NICE_OFFSET); + double prio = priority / (double) ((uint32_t) 0xffffffff); + + sprintf(temp, "%16.14f", prio); + _print_str(temp, width, right, true); + } + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_job_priority_weighted(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + char temp[FORMAT_STRING_SIZE]; + if (job == NULL) /* Print the Header instead */ + _print_str("PRIORITY", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_str("", width, right, true); + else { + double age_priority = job->priority_age * (double)weight_age; + double fs_priority = job->priority_fs * (double)weight_fs; + double js_priority = job->priority_js * (double)weight_js; + double part_priority = job->priority_part * (double)weight_part; + double qos_priority = job->priority_qos * (double)weight_qos; + uint32_t priority = (uint32_t) (age_priority + fs_priority + + js_priority + part_priority + + qos_priority); + priority -= (uint32_t)(job->nice - NICE_OFFSET); + + sprintf(temp, "%u", priority); + _print_str(temp, width, right, true); + } + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_js_priority_normalized(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("JOBSIZE", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_js, width, right, true); + else { + _print_norm(job->priority_js, width, right, true); + } + if (suffix) + printf("%s", suffix); + + return SLURM_SUCCESS; +} + +int _print_js_priority_weighted(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("JOBSIZE", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_js, width, right, true); + else { + _print_int(job->priority_js * weight_js, width, right, true); + } + if (suffix) + printf("%s", suffix); + + return SLURM_SUCCESS; +} + +int _print_part_priority_normalized(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("PARTITION", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_part, width, right, true); + else + _print_norm(job->priority_part, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_part_priority_weighted(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("PARTITION", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_part, width, right, true); + else + _print_int(job->priority_part * weight_part, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_qos_priority_normalized(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("QOS", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_qos, width, right, true); + else + _print_norm(job->priority_qos, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_qos_priority_weighted(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("QOS", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_int(weight_qos, width, right, true); + else + _print_int(job->priority_qos * weight_qos, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_job_nice(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("NICE", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_str("", width, right, true); + else + _print_int(job->nice - NICE_OFFSET, width, right, true); + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + +int _print_job_user_name(priority_factors_object_t * job, int width, + bool right, char* suffix) +{ + if (job == NULL) /* Print the Header instead */ + _print_str("USER", width, right, true); + else if (job == (priority_factors_object_t *) -1) + _print_str("", width, right, true); + else { + char *uname = uid_to_string((uid_t) job->user_id); + _print_str(uname, width, right, true); + xfree(uname); + } + if (suffix) + printf("%s", suffix); + return SLURM_SUCCESS; +} + diff --git a/src/sprio/print.h b/src/sprio/print.h new file mode 100644 index 00000000000..fa334268858 --- /dev/null +++ b/src/sprio/print.h @@ -0,0 +1,138 @@ +/*****************************************************************************\ + * print.h - sprio print job definitions + ***************************************************************************** + * Copyright (C) 2002-2006 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Joey Ekstrom <ekstrom1@llnl.gov> + * CODE-OCEC-09-009. All rights reserved. + * + * This file is part of SLURM, a resource management program. + * For details, see <https://computing.llnl.gov/linux/slurm/>. + * Please also read the included file: DISCLAIMER. + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. You must obey the GNU + * General Public License in all respects for all of the code used other than + * OpenSSL. If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not obligated to do + * so. If you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files in + * the program, then also delete it here. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#ifndef _SPRIO_PRINT_H_ +#define _SPRIO_PRINT_H_ + +#include <slurm/slurm.h> + +#include "src/common/list.h" + +#define FORMAT_STRING_SIZE 32 + +/***************************************************************************** + * Format Structures + *****************************************************************************/ +typedef struct job_format { + int (*function) (priority_factors_object_t *, int, bool, char*); + uint32_t width; + bool right_justify; + char *suffix; +} job_format_t; + +int print_jobs_array(List factors, List format); +int print_job_from_format(priority_factors_object_t * job, List list); + +/***************************************************************************** + * Job Line Format Options + *****************************************************************************/ +int job_format_add_function(List list, int width, bool right_justify, + char *suffix, + int (*function) (priority_factors_object_t *, + int, bool, char*)); + +#define job_format_add_job_id(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_job_job_id) +#define job_format_add_prefix(list,wid,right,suffix) \ + job_format_add_function(list,0,0,suffix,_print_job_prefix) +#define job_format_add_age_priority_normalized(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_age_priority_normalized) +#define job_format_add_age_priority_weighted(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_age_priority_weighted) +#define job_format_add_fs_priority_normalized(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_fs_priority_normalized) +#define job_format_add_fs_priority_weighted(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_fs_priority_weighted) +#define job_format_add_job_priority_normalized(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_job_priority_normalized) +#define job_format_add_job_priority_weighted(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_job_priority_weighted) +#define job_format_add_js_priority_normalized(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_js_priority_normalized) +#define job_format_add_js_priority_weighted(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_js_priority_weighted) +#define job_format_add_part_priority_normalized(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_part_priority_normalized) +#define job_format_add_part_priority_weighted(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_part_priority_weighted) +#define job_format_add_qos_priority_normalized(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_qos_priority_normalized) +#define job_format_add_qos_priority_weighted(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_qos_priority_weighted) +#define job_format_add_job_nice(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_job_nice) +#define job_format_add_user_name(list,wid,right,suffix) \ + job_format_add_function(list,wid,right,suffix,_print_job_user_name) + +/***************************************************************************** + * Job Line Print Functions + *****************************************************************************/ +int _print_job_job_id(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_job_prefix(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_age_priority_normalized(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_age_priority_weighted(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_fs_priority_normalized(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_fs_priority_weighted(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_job_priority_normalized(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_job_priority_weighted(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_js_priority_normalized(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_js_priority_weighted(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_part_priority_normalized(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_part_priority_weighted(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_qos_priority_normalized(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_qos_priority_weighted(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_job_nice(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); +int _print_job_user_name(priority_factors_object_t * job, int width, + bool right_justify, char* suffix); + +#endif diff --git a/src/sprio/sprio.c b/src/sprio/sprio.c new file mode 100644 index 00000000000..80a8f271a96 --- /dev/null +++ b/src/sprio/sprio.c @@ -0,0 +1,222 @@ +/*****************************************************************************\ + * sprio.c - Display the priority components of jobs in the slurm system + ***************************************************************************** + * Copyright (C) 2009 Lawrence Livermore National Security. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Don Lipari <lipari1@llnl.gov> + * CODE-OCEC-09-009. All rights reserved. + * + * This file is part of SLURM, a resource management program. + * For details, see <https://computing.llnl.gov/linux/slurm/>. + * Please also read the included file: DISCLAIMER. + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. You must obey the GNU + * General Public License in all respects for all of the code used other than + * OpenSSL. If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not obligated to do + * so. If you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files in + * the program, then also delete it here. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if HAVE_STDINT_H +# include <stdint.h> +#endif + +#if HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#ifdef HAVE_TERMCAP_H +# include <termcap.h> +#endif + +#include <sys/ioctl.h> +#include <termios.h> + +#include "src/common/slurm_priority.h" +#include "src/common/xstring.h" +#include "src/sprio/sprio.h" + + +/******************** + * Global Variables * + ********************/ +struct sprio_parameters params; +uint32_t weight_age; /* weight for age factor */ +uint32_t weight_fs; /* weight for Fairshare factor */ +uint32_t weight_js; /* weight for Job Size factor */ +uint32_t weight_part; /* weight for Partition factor */ +uint32_t weight_qos; /* weight for QOS factor */ + +static int _get_info(priority_factors_request_msg_t *factors_req, + priority_factors_response_msg_t **factors_resp); + +int main (int argc, char *argv[]) +{ + char *temp = NULL; + int error_code = SLURM_SUCCESS; + priority_factors_request_msg_t req_msg; + priority_factors_response_msg_t *resp_msg = NULL; + log_options_t opts = LOG_OPTS_STDERR_ONLY ; + + /* Check to see if we are running a supported accounting plugin */ + temp = slurm_get_priority_type(); + if(strcasecmp(temp, "priority/multifactor")) { + fprintf (stderr, "You are not running a supported " + "priority plugin\n(%s).\n" + "Only 'priority/multifactor' is supported.\n", + temp); + xfree(temp); + exit(1); + } + xfree(temp); + + log_init(xbasename(argv[0]), opts, SYSLOG_FACILITY_USER, NULL); + + weight_age = slurm_get_priority_weight_age(); + weight_fs = slurm_get_priority_weight_fairshare(); + weight_js = slurm_get_priority_weight_job_size(); + weight_part = slurm_get_priority_weight_partition(); + weight_qos = slurm_get_priority_weight_qos(); + + parse_command_line( argc, argv ); + if (params.verbose) { + opts.stderr_level += params.verbose; + log_alter(opts, SYSLOG_FACILITY_USER, NULL); + } + + memset(&req_msg, 0, sizeof(priority_factors_request_msg_t)); + + if (params.jobs) + req_msg.job_id_list = params.job_list; + else + req_msg.job_id_list = NULL; + + if (params.users) + req_msg.uid_list = params.user_list; + else + req_msg.uid_list = NULL; + + error_code = _get_info(&req_msg, &resp_msg); + + if (params.format == NULL) { + if (params.normalized) { + if (params.long_list) + params.format = "%.7i %.8u %10y %10a %10f %10j " + "%10p %10q"; + else{ + params.format = xstrdup("%.7i"); + if (params.users) + xstrcat(params.format, " %.8u"); + xstrcat(params.format, " %10y"); + if (weight_age) + xstrcat(params.format, " %10a"); + if (weight_fs) + xstrcat(params.format, " %10f"); + if (weight_js) + xstrcat(params.format, " %10j"); + if (weight_part) + xstrcat(params.format, " %10p"); + if (weight_qos) + xstrcat(params.format, " %10q"); + } + } else { + if (params.long_list) + params.format = "%.7i %.8u %.10Y %.10A %.10F " + "%.10J %.10P %.10Q %.6N"; + else{ + params.format = xstrdup("%.7i"); + if (params.users) + xstrcat(params.format, " %.8u"); + xstrcat(params.format, " %.10Y"); + if (weight_age) + xstrcat(params.format, " %.10A"); + if (weight_fs) + xstrcat(params.format, " %.10F"); + if (weight_js) + xstrcat(params.format, " %.10J"); + if (weight_part) + xstrcat(params.format, " %.10P"); + if (weight_qos) + xstrcat(params.format, " %.10Q"); + } + } + } + + /* create the format list from the format */ + parse_format(params.format); + + if (params.jobs && (!resp_msg->priority_factors_list || + !list_count(resp_msg->priority_factors_list))) + printf("Unable to find jobs matching user/id(s) specified\n"); + else + print_jobs_array(resp_msg->priority_factors_list, + params.format_list); + +#if 0 + /* Free storage here if we want to verify that logic. + * Since we exit next, this is not important */ + list_destroy(params.format_list); + slurm_free_priority_factors_response_msg(resp_msg); +#endif + + exit (error_code); +} + +static int _get_info(priority_factors_request_msg_t *factors_req, + priority_factors_response_msg_t **factors_resp) +{ + int rc; + slurm_msg_t req_msg; + slurm_msg_t resp_msg; + + slurm_msg_t_init(&req_msg); + slurm_msg_t_init(&resp_msg); + + req_msg.msg_type = REQUEST_PRIORITY_FACTORS; + req_msg.data = factors_req; + + if (slurm_send_recv_controller_msg(&req_msg, &resp_msg) < 0) + return SLURM_ERROR; + + switch (resp_msg.msg_type) { + case RESPONSE_PRIORITY_FACTORS: + *factors_resp = + (priority_factors_response_msg_t *) resp_msg.data; + break; + case RESPONSE_SLURM_RC: + rc = ((return_code_msg_t *) resp_msg.data)->return_code; + slurm_free_return_code_msg(resp_msg.data); + if (rc) + slurm_seterrno_ret(rc); + *factors_resp = NULL; + break; + default: + slurm_seterrno_ret(SLURM_UNEXPECTED_MSG_ERROR); + break; + } + + return SLURM_PROTOCOL_SUCCESS; +} diff --git a/src/sprio/sprio.h b/src/sprio/sprio.h new file mode 100644 index 00000000000..d98503f6018 --- /dev/null +++ b/src/sprio/sprio.h @@ -0,0 +1,94 @@ +/****************************************************************************\ + * sprio.h - definitions used for printing job queue state + ***************************************************************************** + * Copyright (C) 2009 Lawrence Livermore National Security. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Don Lipari <lipari1@llnl.gov> + * CODE-OCEC-09-009. All rights reserved. + * + * This file is part of SLURM, a resource management program. + * For details, see <https://computing.llnl.gov/linux/slurm/>. + * Please also read the included file: DISCLAIMER. + * + * 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. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. You must obey the GNU + * General Public License in all respects for all of the code used other than + * OpenSSL. If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not obligated to do + * so. If you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files in + * the program, then also delete it here. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#ifndef __SPRIO_H__ +#define __SPRIO_H__ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <ctype.h> +#include <stdio.h> + +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else /* !HAVE_INTTYPES_H */ +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif /* HAVE_INTTYPES_H */ + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <slurm/slurm.h> + +#include "src/common/hostlist.h" +#include "src/common/list.h" +#include "src/common/log.h" +#include "src/common/slurm_protocol_api.h" +#include "src/common/xmalloc.h" +#include "src/sprio/print.h" + +struct sprio_parameters { + bool job_flag; + bool long_list; + bool no_header; + bool normalized; + bool weights; + + int verbose; + + char* format; + char* jobs; + char* users; + + List format_list; + List job_list; + List user_list; +}; + +extern struct sprio_parameters params; + +extern void parse_command_line( int argc, char* argv[] ); +extern int parse_format( char* format ); + +#endif -- GitLab