diff --git a/NEWS b/NEWS index c562912fd84ef46e1a2992d9bced7affada67017..8e081cf2a0943558d7a294440e593d41e825a674 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,7 @@ documents those changes that are of interest to users and administrators. getenv where the name was given a prefix of "SPANK_". That prefix has been removed for consistency with the environment variables available in the Prolog and Epilog scripts. + -- Major additions to the layouts framework code. * Changes in Slurm 15.08.0pre3 ============================== diff --git a/configure b/configure index fd51929e075579cd3ea4fe6e1338ba45a252c845..447c48b889649afb457973502b5a6a3c193d13a4 100755 --- a/configure +++ b/configure @@ -23994,7 +23994,7 @@ fi -ac_config_files="$ac_config_files Makefile config.xml auxdir/Makefile contribs/Makefile contribs/cray/Makefile contribs/lua/Makefile contribs/mic/Makefile contribs/pam/Makefile contribs/perlapi/Makefile contribs/perlapi/libslurm/Makefile contribs/perlapi/libslurm/perl/Makefile.PL contribs/perlapi/libslurmdb/Makefile contribs/perlapi/libslurmdb/perl/Makefile.PL contribs/torque/Makefile contribs/phpext/Makefile contribs/phpext/slurm_php/config.m4 contribs/sgather/Makefile contribs/sgi/Makefile contribs/sjobexit/Makefile contribs/slurmdb-direct/Makefile contribs/pmi2/Makefile doc/Makefile doc/man/Makefile doc/man/man1/Makefile doc/man/man3/Makefile doc/man/man5/Makefile doc/man/man8/Makefile doc/html/Makefile doc/html/configurator.html doc/html/configurator.easy.html etc/cgroup.release_common.example etc/init.d.slurm etc/init.d.slurmdbd etc/slurmctld.service etc/slurmd.service etc/slurmdbd.service src/Makefile src/api/Makefile src/common/Makefile src/db_api/Makefile src/database/Makefile src/sacct/Makefile src/sacctmgr/Makefile src/sreport/Makefile src/salloc/Makefile src/sbatch/Makefile src/sbcast/Makefile src/sattach/Makefile src/scancel/Makefile src/scontrol/Makefile src/sdiag/Makefile src/sinfo/Makefile src/slurmctld/Makefile src/slurmd/Makefile src/slurmd/common/Makefile src/slurmd/slurmd/Makefile src/slurmd/slurmstepd/Makefile src/slurmdbd/Makefile src/smap/Makefile src/smd/Makefile src/sprio/Makefile src/squeue/Makefile src/srun/Makefile src/srun/libsrun/Makefile src/srun_cr/Makefile src/sshare/Makefile src/sstat/Makefile src/strigger/Makefile src/sview/Makefile src/plugins/Makefile src/plugins/accounting_storage/Makefile src/plugins/accounting_storage/common/Makefile src/plugins/accounting_storage/filetxt/Makefile src/plugins/accounting_storage/mysql/Makefile src/plugins/accounting_storage/none/Makefile src/plugins/accounting_storage/slurmdbd/Makefile src/plugins/acct_gather_energy/Makefile src/plugins/acct_gather_energy/cray/Makefile src/plugins/acct_gather_energy/rapl/Makefile src/plugins/acct_gather_energy/ipmi/Makefile src/plugins/acct_gather_energy/none/Makefile src/plugins/acct_gather_infiniband/Makefile src/plugins/acct_gather_infiniband/ofed/Makefile src/plugins/acct_gather_infiniband/none/Makefile src/plugins/acct_gather_filesystem/Makefile src/plugins/acct_gather_filesystem/lustre/Makefile src/plugins/acct_gather_filesystem/none/Makefile src/plugins/acct_gather_profile/Makefile src/plugins/acct_gather_profile/hdf5/Makefile src/plugins/acct_gather_profile/hdf5/sh5util/Makefile src/plugins/acct_gather_profile/none/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile src/plugins/auth/munge/Makefile src/plugins/auth/none/Makefile src/plugins/burst_buffer/Makefile src/plugins/burst_buffer/common/Makefile src/plugins/burst_buffer/cray/Makefile src/plugins/burst_buffer/generic/Makefile src/plugins/checkpoint/Makefile src/plugins/checkpoint/aix/Makefile src/plugins/checkpoint/blcr/Makefile src/plugins/checkpoint/blcr/cr_checkpoint.sh src/plugins/checkpoint/blcr/cr_restart.sh src/plugins/checkpoint/none/Makefile src/plugins/checkpoint/ompi/Makefile src/plugins/checkpoint/poe/Makefile src/plugins/core_spec/Makefile src/plugins/core_spec/cray/Makefile src/plugins/core_spec/none/Makefile src/plugins/crypto/Makefile src/plugins/crypto/munge/Makefile src/plugins/crypto/openssl/Makefile src/plugins/ext_sensors/Makefile src/plugins/ext_sensors/rrd/Makefile src/plugins/ext_sensors/none/Makefile src/plugins/gres/Makefile src/plugins/gres/gpu/Makefile src/plugins/gres/nic/Makefile src/plugins/gres/mic/Makefile src/plugins/jobacct_gather/Makefile src/plugins/jobacct_gather/common/Makefile src/plugins/jobacct_gather/linux/Makefile src/plugins/jobacct_gather/aix/Makefile src/plugins/jobacct_gather/cgroup/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/job_container/Makefile src/plugins/job_container/cncu/Makefile src/plugins/job_container/none/Makefile src/plugins/job_submit/Makefile src/plugins/job_submit/all_partitions/Makefile src/plugins/job_submit/cnode/Makefile src/plugins/job_submit/cray/Makefile src/plugins/job_submit/defaults/Makefile src/plugins/job_submit/logging/Makefile src/plugins/job_submit/lua/Makefile src/plugins/job_submit/partition/Makefile src/plugins/job_submit/pbs/Makefile src/plugins/job_submit/require_timelimit/Makefile src/plugins/job_submit/throttle/Makefile src/plugins/launch/Makefile src/plugins/launch/aprun/Makefile src/plugins/launch/poe/Makefile src/plugins/launch/runjob/Makefile src/plugins/launch/slurm/Makefile src/plugins/power/Makefile src/plugins/power/common/Makefile src/plugins/power/cray/Makefile src/plugins/power/none/Makefile src/plugins/preempt/Makefile src/plugins/preempt/job_prio/Makefile src/plugins/preempt/none/Makefile src/plugins/preempt/partition_prio/Makefile src/plugins/preempt/qos/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/cray/Makefile src/plugins/proctrack/cgroup/Makefile src/plugins/proctrack/pgid/Makefile src/plugins/proctrack/linuxproc/Makefile src/plugins/proctrack/sgi_job/Makefile src/plugins/proctrack/lua/Makefile src/plugins/route/Makefile src/plugins/route/default/Makefile src/plugins/route/topology/Makefile src/plugins/sched/Makefile src/plugins/sched/backfill/Makefile src/plugins/sched/builtin/Makefile src/plugins/sched/hold/Makefile src/plugins/sched/wiki/Makefile src/plugins/sched/wiki2/Makefile src/plugins/select/Makefile src/plugins/select/alps/Makefile src/plugins/select/alps/libalps/Makefile src/plugins/select/alps/libemulate/Makefile src/plugins/select/bluegene/Makefile src/plugins/select/bluegene/ba/Makefile src/plugins/select/bluegene/ba_bgq/Makefile src/plugins/select/bluegene/bl/Makefile src/plugins/select/bluegene/bl_bgq/Makefile src/plugins/select/bluegene/sfree/Makefile src/plugins/select/cons_res/Makefile src/plugins/select/cray/Makefile src/plugins/select/linear/Makefile src/plugins/select/other/Makefile src/plugins/select/serial/Makefile src/plugins/slurmctld/Makefile src/plugins/slurmctld/nonstop/Makefile src/plugins/slurmd/Makefile src/plugins/switch/Makefile src/plugins/switch/cray/Makefile src/plugins/switch/generic/Makefile src/plugins/switch/none/Makefile src/plugins/switch/nrt/Makefile src/plugins/switch/nrt/libpermapi/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/mpi/pmi2/Makefile src/plugins/task/Makefile src/plugins/task/affinity/Makefile src/plugins/task/cgroup/Makefile src/plugins/task/cray/Makefile src/plugins/task/none/Makefile src/plugins/topology/Makefile src/plugins/topology/3d_torus/Makefile src/plugins/topology/hypercube/Makefile src/plugins/topology/node_rank/Makefile src/plugins/topology/none/Makefile src/plugins/topology/tree/Makefile 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" +ac_config_files="$ac_config_files Makefile config.xml auxdir/Makefile contribs/Makefile contribs/cray/Makefile contribs/lua/Makefile contribs/mic/Makefile contribs/pam/Makefile contribs/perlapi/Makefile contribs/perlapi/libslurm/Makefile contribs/perlapi/libslurm/perl/Makefile.PL contribs/perlapi/libslurmdb/Makefile contribs/perlapi/libslurmdb/perl/Makefile.PL contribs/torque/Makefile contribs/phpext/Makefile contribs/phpext/slurm_php/config.m4 contribs/sgather/Makefile contribs/sgi/Makefile contribs/sjobexit/Makefile contribs/slurmdb-direct/Makefile contribs/pmi2/Makefile doc/Makefile doc/man/Makefile doc/man/man1/Makefile doc/man/man3/Makefile doc/man/man5/Makefile doc/man/man8/Makefile doc/html/Makefile doc/html/configurator.html doc/html/configurator.easy.html etc/cgroup.release_common.example etc/init.d.slurm etc/init.d.slurmdbd etc/slurmctld.service etc/slurmd.service etc/slurmdbd.service src/Makefile src/api/Makefile src/common/Makefile src/db_api/Makefile src/layouts/Makefile src/layouts/unit/Makefile src/database/Makefile src/sacct/Makefile src/sacctmgr/Makefile src/sreport/Makefile src/salloc/Makefile src/sbatch/Makefile src/sbcast/Makefile src/sattach/Makefile src/scancel/Makefile src/scontrol/Makefile src/sdiag/Makefile src/sinfo/Makefile src/slurmctld/Makefile src/slurmd/Makefile src/slurmd/common/Makefile src/slurmd/slurmd/Makefile src/slurmd/slurmstepd/Makefile src/slurmdbd/Makefile src/smap/Makefile src/smd/Makefile src/sprio/Makefile src/squeue/Makefile src/srun/Makefile src/srun/libsrun/Makefile src/srun_cr/Makefile src/sshare/Makefile src/sstat/Makefile src/strigger/Makefile src/sview/Makefile src/plugins/Makefile src/plugins/accounting_storage/Makefile src/plugins/accounting_storage/common/Makefile src/plugins/accounting_storage/filetxt/Makefile src/plugins/accounting_storage/mysql/Makefile src/plugins/accounting_storage/none/Makefile src/plugins/accounting_storage/slurmdbd/Makefile src/plugins/acct_gather_energy/Makefile src/plugins/acct_gather_energy/cray/Makefile src/plugins/acct_gather_energy/rapl/Makefile src/plugins/acct_gather_energy/ipmi/Makefile src/plugins/acct_gather_energy/none/Makefile src/plugins/acct_gather_infiniband/Makefile src/plugins/acct_gather_infiniband/ofed/Makefile src/plugins/acct_gather_infiniband/none/Makefile src/plugins/acct_gather_filesystem/Makefile src/plugins/acct_gather_filesystem/lustre/Makefile src/plugins/acct_gather_filesystem/none/Makefile src/plugins/acct_gather_profile/Makefile src/plugins/acct_gather_profile/hdf5/Makefile src/plugins/acct_gather_profile/hdf5/sh5util/Makefile src/plugins/acct_gather_profile/none/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile src/plugins/auth/munge/Makefile src/plugins/auth/none/Makefile src/plugins/burst_buffer/Makefile src/plugins/burst_buffer/common/Makefile src/plugins/burst_buffer/cray/Makefile src/plugins/burst_buffer/generic/Makefile src/plugins/checkpoint/Makefile src/plugins/checkpoint/aix/Makefile src/plugins/checkpoint/blcr/Makefile src/plugins/checkpoint/blcr/cr_checkpoint.sh src/plugins/checkpoint/blcr/cr_restart.sh src/plugins/checkpoint/none/Makefile src/plugins/checkpoint/ompi/Makefile src/plugins/checkpoint/poe/Makefile src/plugins/core_spec/Makefile src/plugins/core_spec/cray/Makefile src/plugins/core_spec/none/Makefile src/plugins/crypto/Makefile src/plugins/crypto/munge/Makefile src/plugins/crypto/openssl/Makefile src/plugins/ext_sensors/Makefile src/plugins/ext_sensors/rrd/Makefile src/plugins/ext_sensors/none/Makefile src/plugins/gres/Makefile src/plugins/gres/gpu/Makefile src/plugins/gres/nic/Makefile src/plugins/gres/mic/Makefile src/plugins/jobacct_gather/Makefile src/plugins/jobacct_gather/common/Makefile src/plugins/jobacct_gather/linux/Makefile src/plugins/jobacct_gather/aix/Makefile src/plugins/jobacct_gather/cgroup/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/job_container/Makefile src/plugins/job_container/cncu/Makefile src/plugins/job_container/none/Makefile src/plugins/job_submit/Makefile src/plugins/job_submit/all_partitions/Makefile src/plugins/job_submit/cnode/Makefile src/plugins/job_submit/cray/Makefile src/plugins/job_submit/defaults/Makefile src/plugins/job_submit/logging/Makefile src/plugins/job_submit/lua/Makefile src/plugins/job_submit/partition/Makefile src/plugins/job_submit/pbs/Makefile src/plugins/job_submit/require_timelimit/Makefile src/plugins/job_submit/throttle/Makefile src/plugins/launch/Makefile src/plugins/launch/aprun/Makefile src/plugins/launch/poe/Makefile src/plugins/launch/runjob/Makefile src/plugins/launch/slurm/Makefile src/plugins/power/Makefile src/plugins/power/common/Makefile src/plugins/power/cray/Makefile src/plugins/power/none/Makefile src/plugins/preempt/Makefile src/plugins/preempt/job_prio/Makefile src/plugins/preempt/none/Makefile src/plugins/preempt/partition_prio/Makefile src/plugins/preempt/qos/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/cray/Makefile src/plugins/proctrack/cgroup/Makefile src/plugins/proctrack/pgid/Makefile src/plugins/proctrack/linuxproc/Makefile src/plugins/proctrack/sgi_job/Makefile src/plugins/proctrack/lua/Makefile src/plugins/route/Makefile src/plugins/route/default/Makefile src/plugins/route/topology/Makefile src/plugins/sched/Makefile src/plugins/sched/backfill/Makefile src/plugins/sched/builtin/Makefile src/plugins/sched/hold/Makefile src/plugins/sched/wiki/Makefile src/plugins/sched/wiki2/Makefile src/plugins/select/Makefile src/plugins/select/alps/Makefile src/plugins/select/alps/libalps/Makefile src/plugins/select/alps/libemulate/Makefile src/plugins/select/bluegene/Makefile src/plugins/select/bluegene/ba/Makefile src/plugins/select/bluegene/ba_bgq/Makefile src/plugins/select/bluegene/bl/Makefile src/plugins/select/bluegene/bl_bgq/Makefile src/plugins/select/bluegene/sfree/Makefile src/plugins/select/cons_res/Makefile src/plugins/select/cray/Makefile src/plugins/select/linear/Makefile src/plugins/select/other/Makefile src/plugins/select/serial/Makefile src/plugins/slurmctld/Makefile src/plugins/slurmctld/nonstop/Makefile src/plugins/slurmd/Makefile src/plugins/switch/Makefile src/plugins/switch/cray/Makefile src/plugins/switch/generic/Makefile src/plugins/switch/none/Makefile src/plugins/switch/nrt/Makefile src/plugins/switch/nrt/libpermapi/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/mpi/pmi2/Makefile src/plugins/task/Makefile src/plugins/task/affinity/Makefile src/plugins/task/cgroup/Makefile src/plugins/task/cray/Makefile src/plugins/task/none/Makefile src/plugins/topology/Makefile src/plugins/topology/3d_torus/Makefile src/plugins/topology/hypercube/Makefile src/plugins/topology/node_rank/Makefile src/plugins/topology/none/Makefile src/plugins/topology/tree/Makefile 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" cat >confcache <<\_ACEOF @@ -25331,6 +25331,8 @@ do "src/api/Makefile") CONFIG_FILES="$CONFIG_FILES src/api/Makefile" ;; "src/common/Makefile") CONFIG_FILES="$CONFIG_FILES src/common/Makefile" ;; "src/db_api/Makefile") CONFIG_FILES="$CONFIG_FILES src/db_api/Makefile" ;; + "src/layouts/Makefile") CONFIG_FILES="$CONFIG_FILES src/layouts/Makefile" ;; + "src/layouts/unit/Makefile") CONFIG_FILES="$CONFIG_FILES src/layouts/unit/Makefile" ;; "src/database/Makefile") CONFIG_FILES="$CONFIG_FILES src/database/Makefile" ;; "src/sacct/Makefile") CONFIG_FILES="$CONFIG_FILES src/sacct/Makefile" ;; "src/sacctmgr/Makefile") CONFIG_FILES="$CONFIG_FILES src/sacctmgr/Makefile" ;; diff --git a/configure.ac b/configure.ac index ca6810fb7d3beeb0198aca5f3cf53a6cd3b6528c..9b381924df0aba43e258a9261e913da7e1a9e205 100644 --- a/configure.ac +++ b/configure.ac @@ -463,6 +463,8 @@ AC_CONFIG_FILES([Makefile src/api/Makefile src/common/Makefile src/db_api/Makefile + src/layouts/Makefile + src/layouts/unit/Makefile src/database/Makefile src/sacct/Makefile src/sacctmgr/Makefile diff --git a/slurm.spec b/slurm.spec index 052e96e505051768dc5005c5ac05876b110733f6..9849389442f29b7319f8786e6d2122346414ce1b 100644 --- a/slurm.spec +++ b/slurm.spec @@ -896,6 +896,7 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/slurm/jobcomp_filetxt.so %{_libdir}/slurm/jobcomp_none.so %{_libdir}/slurm/jobcomp_script.so +%{_libdir}/slurm/layouts_unit_default.so %if ! %{slurm_with bluegene} %{_libdir}/slurm/mpi_lam.so %{_libdir}/slurm/mpi_mpich1_p4.so diff --git a/src/Makefile.am b/src/Makefile.am index 24bd9624f8336ac644da843981bc4422a340cfd7..47807fc658ad0badbb3b1e9f16a6cc2f373cadba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,6 +3,7 @@ SUBDIRS = \ common \ database \ db_api \ + layouts \ plugins \ sacct \ sacctmgr \ diff --git a/src/Makefile.in b/src/Makefile.in index d0133a3d116c8c4d396092b2534d5e8585181bc3..80ddf555838637f0af30a570115918a48261decc 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -184,9 +184,9 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = api common database db_api plugins sacct sacctmgr \ - salloc sattach sbatch sbcast scancel scontrol sdiag sinfo \ - slurmctld slurmd slurmdbd smap smd sprio squeue sreport \ +DIST_SUBDIRS = api common database db_api layouts plugins sacct \ + sacctmgr salloc sattach sbatch sbcast scancel scontrol sdiag \ + sinfo slurmctld slurmd slurmdbd smap smd sprio squeue sreport \ srun_cr sshare sstat strigger sview srun DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ @@ -455,10 +455,10 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = api common database db_api plugins sacct sacctmgr salloc \ - sattach sbatch sbcast scancel scontrol sdiag sinfo slurmctld \ - slurmd slurmdbd smap smd sprio squeue sreport srun_cr sshare \ - sstat strigger sview $(am__append_1) +SUBDIRS = api common database db_api layouts plugins sacct sacctmgr \ + salloc sattach sbatch sbcast scancel scontrol sdiag sinfo \ + slurmctld slurmd slurmdbd smap smd sprio squeue sreport \ + srun_cr sshare sstat strigger sview $(am__append_1) all: all-recursive .SUFFIXES: diff --git a/src/common/entity.c b/src/common/entity.c index d8587a078b7ed394c7f93edcd4004a409dc2bb61..c7e31ddfb9dbe97ff0b10347a7ca1ab61808934a 100644 --- a/src/common/entity.c +++ b/src/common/entity.c @@ -35,6 +35,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. \*****************************************************************************/ +#include "string.h" + +#include "slurm/slurm.h" +#include "slurm/slurm_errno.h" + #include "src/common/entity.h" #include "src/common/layout.h" #include "src/common/xmalloc.h" @@ -43,7 +48,7 @@ /*****************************************************************************\ - * FUNCTIONS * + * HELPERS * \*****************************************************************************/ static const char* _entity_data_identify(void* item) @@ -52,6 +57,15 @@ static const char* _entity_data_identify(void* item) return data_item->key; } +static void _entity_data_destroy(void* x) +{ + entity_data_t* entity_data = (entity_data_t*)x; + if (entity_data) { + xfree(entity_data->value); + xfree(entity_data); + } +} + static void _entity_node_destroy(void* x) { entity_node_t* entity_node = (entity_node_t*)x; @@ -61,11 +75,58 @@ static void _entity_node_destroy(void* x) } } +static int _entity_add_data(const entity_t* entity, const char* key, + void* value, size_t size, + void (*_free)(void*), bool byreference) +{ + entity_data_t* result; + entity_data_t* new_data_item; + + if (!key || !*key || !value) + return SLURM_ERROR; + + result = (entity_data_t*)xhash_get(entity->data, key); + if (result != NULL) { + /* update existing value by ref or by override */ + if (byreference) { + if (_free) + _free(result->value); + result->value = value; + } else { + memcpy(result->value, value, size); + } + return SLURM_SUCCESS; + } + + /* add a new KV if not already existing, by ref or allocating + * a new buffer and dumping the provided input */ + new_data_item = (entity_data_t*)xmalloc(sizeof(entity_data_t)); + new_data_item->key = key; + if (byreference) { + new_data_item->value = value; + } else { + new_data_item->value = (void*) xmalloc(size); + memcpy(new_data_item->value, value, size); + } + result = xhash_add(entity->data, new_data_item); + if (result == NULL) { + xfree(new_data_item); + return SLURM_ERROR; + } + return SLURM_SUCCESS; +} + +/*****************************************************************************\ + * FUNCTIONS * +\*****************************************************************************/ + void entity_init(entity_t* entity, const char* name, const char* type) { entity->name = xstrdup(name); entity->type = xstrdup(type); - entity->data = xhash_init(_entity_data_identify, NULL, NULL, 0); + entity->data = xhash_init(_entity_data_identify, + (xhash_freefunc_t)_entity_data_destroy, + NULL, 0); entity->nodes = list_create(_entity_node_destroy); entity->ptr = NULL; } @@ -90,38 +151,37 @@ const char* entity_get_type(const entity_t* entity) return entity->type; } -void** entity_get_data(const entity_t* entity, const char* key) +int entity_get_data(const entity_t* entity, const char* key, + void* value, size_t size) +{ + void* data = NULL; + data = entity_get_data_ref(entity, key); + if (data != NULL) { + memcpy(value, data, size); + return SLURM_SUCCESS; + } + return SLURM_ERROR; +} + +void* entity_get_data_ref(const entity_t* entity, const char* key) { entity_data_t* data = (entity_data_t*)xhash_get(entity->data, key); if (data) { - return &data->value; + return data->value; } return NULL; } -int entity_add_data(entity_t* entity, const char* key, void* value, - void (*_free)(void*)) +int entity_set_data(const entity_t* entity, const char* key, + void* value, size_t size) { - entity_data_t* result; - entity_data_t* new_data_item; - if (!key || !*key || !value) - return 0; - result = (entity_data_t*)xhash_get(entity->data, key); - if (result != NULL) { - if (_free) - _free(result->value); - result->value = value; - return 1; - } - new_data_item = (entity_data_t*)xmalloc(sizeof(entity_data_t)); - new_data_item->key = key; - new_data_item->value = value; - result = xhash_add(entity->data, new_data_item); - if (result == NULL) { - xfree(new_data_item); - return 0; - } - return 1; + return _entity_add_data(entity, key, value, size, NULL, false); +} + +int entity_set_data_ref(const entity_t* entity, const char* key, void* value, + void (*_free)(void*)) +{ + return _entity_add_data(entity, key, value, 0, _free, true); } void entity_delete_data(entity_t* entity, const char* key) @@ -134,47 +194,76 @@ void entity_clear_data(entity_t* entity) xhash_clear(entity->data); } -void entity_add_node(entity_t* entity, layout_t* layout, void* node) +entity_node_t* entity_add_node(entity_t* entity, layout_t* layout) { entity_node_t* entity_node = (entity_node_t*)xmalloc( sizeof(entity_node_t)); entity_node->layout = layout; - entity_node->node = node; - list_append(entity->nodes, entity_node); + entity_node->entity = entity; + entity_node->node = NULL; + entity_node = list_append(entity->nodes, entity_node); + return entity_node; } -static int _entity_node_find(void* x, void* key) +typedef struct _entity_get_node_walk_st { + layout_t* layout; + entity_node_t* node; +} _entity_get_node_walk_t; + +static void _entity_get_node_walkfunc(layout_t* layout, + entity_node_t* node, void* arg) { - entity_node_t* entity_node = (entity_node_t*)x; - return entity_node->node == key; + _entity_get_node_walk_t* real_arg = + (_entity_get_node_walk_t*) arg; + /* Note that if multiple nodes of the same layout are added + * to a single entity, the last one will be returned. + * An entity MUST NOT be added more than once /!\ */ + if (layout == real_arg->layout) { + real_arg->node = node; + } } -void entity_delete_node(entity_t* entity, void* node) +entity_node_t* entity_get_node(entity_t* entity, layout_t* layout) { - ListIterator i = list_iterator_create(entity->nodes); - if (list_find(i, _entity_node_find, node)) - list_delete_item(i); - list_iterator_destroy(i); + _entity_get_node_walk_t arg; + arg.layout = layout; + arg.node = NULL; + entity_nodes_walk(entity, _entity_get_node_walkfunc, (void*) &arg); + return arg.node; } -void entity_clear_nodes(entity_t* entity) +static int _entity_node_find(void* x, void* key) { - list_flush(entity->nodes); + entity_node_t* entity_node = (entity_node_t*)x; + return entity_node->node == key; } -int entity_has_node(entity_t* entity, void* node) +int entity_delete_node(entity_t* entity, layout_t* layout) { + int rc = SLURM_ERROR; + entity_node_t* node; ListIterator i; - void* result; + node = entity_get_node(entity, layout); + if (node == NULL) + return rc; i = list_iterator_create(entity->nodes); - result = list_find(i, _entity_node_find, node); + if (list_find(i, _entity_node_find, node)) { + list_delete_item(i); + rc = SLURM_SUCCESS; + } list_iterator_destroy(i); - return result != NULL; + return rc; +} + +int entity_clear_nodes(entity_t* entity) +{ + list_flush(entity->nodes); + return SLURM_SUCCESS; } typedef struct _entity_nodes_walkstruct_st { - void (*callback)(layout_t* layout, void* node, void* arg); + void (*callback)(layout_t* layout, entity_node_t* node, void* arg); void* arg; } _entity_nodes_walkstruct_t; @@ -184,14 +273,14 @@ static int _entity_nodes_walkfunc(void* x, void* arg) _entity_nodes_walkstruct_t* real_arg = (_entity_nodes_walkstruct_t*)arg; real_arg->callback(entity_node->layout, - entity_node->node, + entity_node, real_arg->arg); return 0; } void entity_nodes_walk(entity_t* entity, void (*callback)(layout_t* layout, - void* node, + entity_node_t* node, void* arg), void* arg) { diff --git a/src/common/entity.h b/src/common/entity.h index 03650a6af2af62143dbbfe65b4f7e515e3306d29..c43c10be1382caf2fee8e4bef7880c29eb48c886 100644 --- a/src/common/entity.h +++ b/src/common/entity.h @@ -67,9 +67,10 @@ typedef struct entity_data_st { * to represent the layout nodes that are linked to them */ typedef struct entity_node_st { layout_t* layout; /* layout containing a relationnal structure holding - * a reference to this entity */ + * a reference to the entity */ + entity_t* entity; /* pointer to the associated entity */ void* node; /* pointer to the relational node referencing - this entity */ + this entity node */ } entity_node_t; /*****************************************************************************\ @@ -111,7 +112,21 @@ const char* entity_get_name(const entity_t* entity); const char* entity_get_type(const entity_t* entity); /* - * entity_get_data - get the address of the pointer to the data associated + * entity_get_data - copy the content of the data associated to a particular key + * of an entity into a buffer up to the requested size + * + * IN entity - the entity struct to use + * IN key - the targeted key + * IN value - ponter to the mem area to fill + * IN size - size of the mem area to copy + * + * Return SLURM_SUCCESS or SLURM_ERROR if no element found + */ +int entity_get_data(const entity_t* entity, const char* key, + void* value, size_t size); + +/* + * entity_get_data_ref - get the address of the pointer to the data associated * with a particular key of an entity * * IN entity - the entity struct to use @@ -120,10 +135,28 @@ const char* entity_get_type(const entity_t* entity); * Return value is the address of the (void*) pointer to the data associated to * the key or NULL in case of error */ -void** entity_get_data(const entity_t* entity, const char* key); +void* entity_get_data_ref(const entity_t* entity, const char* key); /* - * entity_add_data - associate data to a particular key of an entity + * entity_set_data - copy the content of the input buffer up to the requested + * size into the the buffer associated to a particular key of an entity + * (note that the entity key value's buffer is allocated internally if + * necessary) + * + * IN entity - the entity struct to use + * IN key - the targeted key + * IN value - ponter to the mem area to fill with + * IN size - size of the mem area to copy + * + * Return SLURM_SUCCESS or SLURM_ERROR if no element found + */ +int entity_set_data(const entity_t* entity, const char* key, + void* value, size_t size); + +/* + * entity_set_data_ref - associate a particular key of an entity with the + * input buffer, + * with a particular key of an entity * * IN entity - the entity struct to use * IN key - the key the data must be associated to @@ -132,10 +165,10 @@ void** entity_get_data(const entity_t* entity, const char* key); * IN _free - a function to apply on the former value in case it exists * before overriding * - * Return 1 if the value was successfully associated or 0 otherwise + * Return SLURM_SUCCESS or SLURM_ERROR in case of error */ -int entity_add_data(entity_t* entity, const char* key, void* value, - void (*_free)(void*)); +int entity_set_data_ref(const entity_t* entity, const char* key, void* value, + void (*_free)(void*)); /* * entity_delete_data - delete the data associated with a particular key @@ -157,48 +190,49 @@ void entity_delete_data(entity_t* entity, const char* key); void entity_clear_data(entity_t* entity); /* - * entity_add_node - add a relational node to the list of nodes referring to - * this entity + * entity_add_node - add a per layout entity node to the list of nodes referring + * to this entity * * IN entity - the entity struct to use - * IN layout - the layout having a node referring to this entity - * IN node - the node referring to it + * IN layout - the layout to create an entity node referring to this entity * - * Notes: the entity does not own the memory of the relationnal nodes. + * Notes: - the returned entity_node does not point to anything at that point. + * it will be added to a relational structure and will then have to + * be associated to the underlying relational node afterwards. + * - the entity node will not own the memory of the relationnal node. */ -void entity_add_node(entity_t* entity, layout_t* layout, void* node); +entity_node_t* entity_add_node(entity_t* entity, layout_t* layout); /* - * entity_delete_node - remove a relational node from the list of nodes - * referring to this entity + * entity_get_node - get the entity node referring to a particular layout in + * the list of entity nodes associated to an entity. * * IN entity - the entity struct to use - * IN node - the node referring to it + * IN layout - the layout having an entity node referring to this entity * - * Notes: the memory of the node data is not freed. + * Return value is the entity node of the layout or NULL if not found */ -void entity_delete_node(entity_t* entity, void* node); +entity_node_t* entity_get_node(entity_t* entity, layout_t* layout); /* - * entity_clear_nodes - remove all the relational node from the list of nodes - * referring to this entity + * entity_delete_node - remove the entity node referring to a particular layout + * from the list of entity nodes associated to an entity * * IN entity - the entity struct to use + * IN layout - the layout having an entity node referring to this entity * - * Notes: the memory of the nodes data is not freed. + * Return SLURM_SUCCESS or SLURM_ERROR */ -void entity_clear_nodes(entity_t* entity); +int entity_delete_node(entity_t* entity, layout_t* layout); /* - * entity_has_node - check wether or not a relational node is in the - * list of nodes referring to this entity + * entity_clear_nodes - remove all the entity node associated to an entity * * IN entity - the entity struct to use - * IN node - the node to check for * - * Return 1 if found, 0 otherwise + * Return SLURM_SUCCESS or SLURM_ERROR */ -int entity_has_node(entity_t* entity, void* node); +int entity_clear_nodes(entity_t* entity); /* * entity_nodes_walk - iterate over the nodes referring to this entity @@ -213,7 +247,7 @@ int entity_has_node(entity_t* entity, void* node); * IN arg - the arg to pass to the callback function for every node. */ void entity_nodes_walk(entity_t* entity, - void (*callback)(layout_t*, void*, void*), + void (*callback)(layout_t*, entity_node_t*, void*), void* arg); /* diff --git a/src/common/hostlist.h b/src/common/hostlist.h index 6f7be2593f4cf2540224c4e008a5206ab553dd09..cea134bf2ac54ee548ea40931e6ce0b088591698 100644 --- a/src/common/hostlist.h +++ b/src/common/hostlist.h @@ -50,7 +50,7 @@ * expressions that can consume all of the memory on a system and crash the * daemons (e.g. "a[0-999999999].b[0-9]", which generates 1 billion distinct * prefix records in the hostlist) */ -#define MAX_PREFIX_CNT 1024 +#define MAX_PREFIX_CNT 64*1024 #if (SYSTEM_DIMENSIONS > 1) #define HOSTLIST_BASE 36 diff --git a/src/common/layouts_mgr.c b/src/common/layouts_mgr.c index 857f82ced4e65dc18ccb0f4a830ea4403b5f737e..1eaf0d1098e331f38887b787b40203fefda36239 100644 --- a/src/common/layouts_mgr.c +++ b/src/common/layouts_mgr.c @@ -4,6 +4,7 @@ * Initially written by Francois Chevallier <chevallierfrancois@free.fr> * at Bull for slurm-2.6. * Adapted by Matthieu Hautreux <matthieu.hautreux@cea.fr> for slurm-14.11. + * Enhanced by Matthieu Hautreux <matthieu.hautreux@cea.fr> for slurm-15.x. * * This file is part of SLURM, a resource management program. * For details, see <http://slurm.schedmd.com/>. @@ -39,6 +40,7 @@ #include <string.h> #include <strings.h> #include <ctype.h> +#include <sys/stat.h> #include "layouts_mgr.h" @@ -50,15 +52,24 @@ #include "src/common/hostlist.h" #include "src/common/list.h" #include "src/common/node_conf.h" +#include "src/common/pack.h" #include "src/common/plugin.h" #include "src/common/read_config.h" #include "src/common/slurm_protocol_api.h" +#include "src/common/timers.h" #include "src/common/xstring.h" #include "src/common/xtree.h" #include "src/common/xmalloc.h" #define PATHLEN 256 +/* use to specify which layout callbacks to perform while loading data + * from conf files, state files or input buffers */ +#define CONF_DONE 0x00000001 +#define PARSE_ENTITY 0x00000002 +#define UPDATE_DONE 0x00000004 +#define PARSE_RELATIONS 0x00000008 + /*****************************************************************************\ * STRUCTURES AND TYPES * \*****************************************************************************/ @@ -86,12 +97,12 @@ static void layouts_conf_spec_free(void* x) /* * layout ops - operations associated to layout plugins * - * This struct is populated while opening the plugin and linking the + * This struct is populated while opening the plugin and linking the * associated symbols. See layout_syms description for the name of the "public" * symbols associated to this structure fields. * * Notes : the layouts plugins are able to access the entities hashtable in order - * to read/create/modify entities as necessary during the load_entities and + * to read/create/modify entities as necessary during the load_entities and * build_layout API calls. * */ @@ -101,6 +112,8 @@ typedef struct layout_ops_st { s_p_hashtbl_t* tbl); void (*entity_parsing) (entity_t* e, s_p_hashtbl_t* etbl, layout_t* layout); + int (*update_done) (layout_t* layout, entity_t** e_array, + int e_cnt); } layout_ops_t; /* @@ -112,6 +125,7 @@ const char *layout_syms[] = { "plugin_spec", /* holds constants, definitions, ... */ "layouts_p_conf_done", /* */ "layouts_p_entity_parsing", + "layouts_p_update_done", }; /* @@ -127,13 +141,12 @@ typedef struct layout_plugin_st { layout_ops_t* ops; } layout_plugin_t; -static void _layout_plugins_destroy(layout_plugin_t *lp) { +static void _layout_plugins_destroy(layout_plugin_t *lp) +{ plugin_context_destroy(lp->context); /* it might be interesting to also dlclose the ops here */ - layout_free(lp->layout); xfree(lp->name); xfree(lp->ops); - xfree(lp->layout); } /* * layouts_keydef_t - entities similar keys share a same key definition @@ -141,18 +154,29 @@ static void _layout_plugins_destroy(layout_plugin_t *lp) { * like the key str itself and custom destroy/dump functions. * * The layouts manager keeps an hash table of the various keydefs and use - * the factorized details while parsing the configuration and creating the + * the factorized details while parsing the configuration and creating the * entity_data_t structs associated to the entities. * - * Note custom_* functions are used if they are not NULL* and type equals + * Note custom_* functions are used if they are not NULL* and type equals * L_T_CUSTOM */ typedef struct layouts_keydef_st { - char* key; /* normalize to lower or upper case */ + char* key; /* lower case key prefixed by the + "%layout_type%." string */ + char* shortkey; /* original key as defined in + the layout keys definition */ layouts_keydef_types_t type; + uint32_t flags; void (*custom_destroy)(void* value); char* (*custom_dump)(void* value); layout_plugin_t* plugin; + char* ref_key; /* lower case reference key prefixed by + the "%layout_type%." might be NULL + if not defined. */ + char* ref_shortkey; /* original ref key as defined in + the layout keys definition, + might be null too. */ + } layouts_keydef_t; /* @@ -166,7 +190,7 @@ static const char* layouts_keydef_idfunc(void* item) } /* - * layouts_mgr_t - the main structure holding all the layouts, entities and + * layouts_mgr_t - the main structure holding all the layouts, entities and * shared keydefs as well as conf elements and plugins details. */ typedef struct layouts_mgr_st { @@ -215,6 +239,9 @@ static void _layouts_keydef_free(void* x) { layouts_keydef_t* keydef = (layouts_keydef_t*)x; xfree(keydef->key); + xfree(keydef->shortkey); + xfree(keydef->ref_key); + xfree(keydef->ref_shortkey); xfree(keydef); } @@ -318,24 +345,455 @@ static void _normalize_keydef_mgrkey(char* buffer, uint32_t size, static void _entity_add_data(entity_t* e, const char* key, void* data) { - int rc; layouts_keydef_t* hkey = xhash_get(mgr->keydefs, key); xassert(hkey); void (*freefunc)(void* p) = xfree_as_callback; - if (hkey->type == L_T_CUSTOM) { + if (hkey && hkey->type == L_T_CUSTOM) { freefunc = hkey->custom_destroy; } - rc = entity_add_data(e, hkey->key, data, freefunc); - xassert(rc); + entity_set_data_ref(e, hkey->key, data, freefunc); +} + +/* + * used in both automerge and autoupdate calls when dealing with + * advanced operations (SUM,MIN,MAX,AVG,...) while setting new key values + */ +#define _entity_update_kv_helper(type_t, operator) \ + type_t* lvalue = (type_t*) oldvalue; \ + type_t* rvalue = (type_t*) value; \ + uint32_t* divider; \ + switch (operator) { \ + case S_P_OPERATOR_SET: \ + *lvalue = *rvalue; \ + break; \ + case S_P_OPERATOR_ADD: \ + *lvalue += *rvalue; \ + break; \ + case S_P_OPERATOR_SUB: \ + *lvalue -= *rvalue; \ + break; \ + case S_P_OPERATOR_MUL: \ + *lvalue *= *rvalue; \ + break; \ + case S_P_OPERATOR_DIV: \ + if (*rvalue != (type_t) 0) \ + *lvalue /= *rvalue; \ + else { \ + error("layouts: entity_update: " \ + "key=%s val=0 operator=" \ + "DIV !! skipping !!", \ + keydef->key); \ + } \ + break; \ + case S_P_OPERATOR_AVG: \ + divider = (uint32_t*) value; \ + if (*divider != (uint32_t) 0) \ + *lvalue /= (type_t) *divider; \ + else { \ + error("layouts: entity_update: " \ + "key=%s val=0 operator=" \ + "AVG !! skipping !!", \ + keydef->key); \ + } \ + break; \ + case S_P_OPERATOR_SET_IF_MIN: \ + if (*rvalue < *lvalue) \ + *lvalue = *rvalue; \ + break; \ + case S_P_OPERATOR_SET_IF_MAX: \ + if (*rvalue > *lvalue) \ + *lvalue = *rvalue; \ + break; \ + default: \ + break; \ + } + +static int _layouts_autoupdate_layout(layout_t* layout); +static int _layouts_autoupdate_layout_if_allowed(layout_t* layout); + +/*****************************************************************************\ + * LAYOUTS INTERNAL LOCKLESS API * +\*****************************************************************************/ + +layouts_keydef_t* _layouts_entity_get_kv_keydef(layout_t* l, entity_t* e, + char* key) +{ + char keytmp[PATHLEN]; + if (l == NULL || e == NULL || key == NULL) + return NULL; + _normalize_keydef_key(keytmp, PATHLEN, key, l->type); + return xhash_get(mgr->keydefs, keytmp); +} + +int _layouts_entity_get_kv_type(layout_t* l, entity_t* e, char* key) +{ + layouts_keydef_t* keydef; + keydef = _layouts_entity_get_kv_keydef(l, e, key); + if (keydef != NULL) { + return keydef->type; + } + return SLURM_ERROR; +} + +int _layouts_entity_get_kv_flags(layout_t* l, entity_t* e, char* key) +{ + layouts_keydef_t* keydef; + keydef = _layouts_entity_get_kv_keydef(l, e, key); + if (keydef != NULL) { + return keydef->flags; + } + return SLURM_ERROR; +} + +int _layouts_entity_get_kv_size(layout_t* l, entity_t* e, char* key, size_t *size) +{ + layouts_keydef_t* keydef; + keydef = _layouts_entity_get_kv_keydef(l, e, key); + if (keydef != NULL) { + switch(keydef->type) { + case L_T_ERROR: + return SLURM_ERROR; + case L_T_STRING: + *size = sizeof(void*); + break; + case L_T_CUSTOM: + *size = sizeof(void*); + break; + case L_T_LONG: + *size = sizeof(long); + break; + case L_T_UINT16: + *size = sizeof(uint16_t); + break; + case L_T_UINT32: + *size = sizeof(uint32_t); + break; + case L_T_BOOLEAN: + *size = sizeof(bool); + break; + case L_T_FLOAT: + *size = sizeof(float); + break; + case L_T_DOUBLE: + *size = sizeof(double); + break; + case L_T_LONG_DOUBLE: + *size = sizeof(long double); + break; + } + } else + return SLURM_ERROR; + return SLURM_SUCCESS; +} + +bool _layouts_entity_check_kv_keytype(layout_t* l, entity_t* e, char* key, + layouts_keydef_types_t key_type) +{ + layouts_keydef_types_t real_type; + if (l == NULL || e == NULL || key == NULL) + return SLURM_ERROR; + if (key_type) { + real_type = _layouts_entity_get_kv_type(l, e, key); + return (real_type == key_type); + } + /* no key type provided, consider that as a no-check request */ + return true; +} + +int _layouts_entity_push_kv(layout_t* l, entity_t* e, char* key) +{ + /* a more advanced implementation should only pull what is necessary + * instead of forcing a full autoupdate */ + return _layouts_autoupdate_layout_if_allowed(l); +} + +int _layouts_entity_pull_kv(layout_t* l, entity_t* e, char* key) +{ + /* a more advanced implementation should only pull what is necessary + * instead of forcing a full autoupdate */ + return _layouts_autoupdate_layout_if_allowed(l); +} + +int _layouts_entity_set_kv(layout_t* l, entity_t* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + void* data; + size_t size; + layouts_keydef_types_t real_type; + char key_keydef[PATHLEN]; + + if (l == NULL || e == NULL || key == NULL || value == NULL) + return SLURM_ERROR; + + real_type = _layouts_entity_get_kv_type(l, e, key); + if (key_type > 0 && real_type != key_type) + return SLURM_ERROR; + + _normalize_keydef_key(key_keydef, PATHLEN, key, l->type); + + switch(real_type) { + case L_T_ERROR: + return SLURM_ERROR; + case L_T_STRING: + data = xstrdup(value); + return entity_set_data_ref(e, key_keydef, data, + xfree_as_callback); + case L_T_CUSTOM: + /* TBD : add a custom_set call */ + value = NULL; + return SLURM_ERROR; + case L_T_LONG: + size = sizeof(long); + break; + case L_T_UINT16: + size = sizeof(uint16_t); + break; + case L_T_UINT32: + size = sizeof(uint32_t); + break; + case L_T_BOOLEAN: + size = sizeof(bool); + break; + case L_T_FLOAT: + size = sizeof(float); + break; + case L_T_DOUBLE: + size = sizeof(double); + break; + case L_T_LONG_DOUBLE: + size = sizeof(long double); + break; + } + return entity_set_data(e, key_keydef, value, size); +} + +int _layouts_entity_set_kv_ref(layout_t* l, entity_t* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + int rc = SLURM_ERROR; + char key_keydef[PATHLEN]; + + if (l == NULL || e == NULL || key == NULL || value == NULL) + return rc; + + if (!_layouts_entity_check_kv_keytype(l, e, key, key_type)) + return rc; + + _normalize_keydef_key(key_keydef, PATHLEN, key, l->type); + return entity_set_data_ref(e, key_keydef, value, xfree_as_callback); +} + +int _layouts_entity_setpush_kv(layout_t* l, entity_t* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + int rc = SLURM_ERROR; + if (_layouts_entity_set_kv(l, e, key, value, key_type) == SLURM_SUCCESS) + rc = _layouts_entity_push_kv(l, e, key); + return rc; +} + +int _layouts_entity_setpush_kv_ref(layout_t* l, entity_t* e, char* key, + void* value, layouts_keydef_types_t key_type) +{ + int rc = SLURM_ERROR; + if (_layouts_entity_set_kv_ref(l, e, key, value, key_type) == + SLURM_SUCCESS) + rc = _layouts_entity_push_kv(l, e, key); + return rc; +} + +int _layouts_entity_get_kv(layout_t* l, entity_t* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + void* data; + size_t size; + layouts_keydef_types_t real_type; + char key_keydef[PATHLEN]; + char ** pstr; + + if (l == NULL || e == NULL || key == NULL || value == NULL) + return SLURM_ERROR; + + real_type = _layouts_entity_get_kv_type(l, e, key); + if (key_type > 0 && real_type != key_type) + return SLURM_ERROR; + + _normalize_keydef_key(key_keydef, PATHLEN, key, l->type); + + data = entity_get_data_ref(e, key_keydef); + if (data == NULL) { + return SLURM_ERROR; + } + + switch(real_type) { + case L_T_ERROR: + return SLURM_ERROR; + case L_T_STRING: + pstr = (char**) value; + if (data) + *pstr = xstrdup(data); + else + *pstr = NULL; + return SLURM_SUCCESS; + case L_T_CUSTOM: + /* TBD : add a custom_get call */ + pstr = (char**) value; + *pstr = NULL; + return SLURM_ERROR; + case L_T_LONG: + size = sizeof(long); + break; + case L_T_UINT16: + size = sizeof(uint16_t); + break; + case L_T_UINT32: + size = sizeof(uint32_t); + break; + case L_T_BOOLEAN: + size = sizeof(bool); + break; + case L_T_FLOAT: + size = sizeof(float); + break; + case L_T_DOUBLE: + size = sizeof(double); + break; + case L_T_LONG_DOUBLE: + size = sizeof(long double); + break; + } + memcpy(value, data, size); + return SLURM_SUCCESS; +} + +int _layouts_entity_get_mkv(layout_t* l, entity_t* e, char* keys, void* value, + size_t length, layouts_keydef_types_t key_type) +{ + char *key = NULL; + hostlist_t kl; + size_t processed = 0; + size_t elt_size = sizeof(void*);; + int rc = 0; + + /* expand in order the requested keys (in hostlist format) + * and iterate over each one of them, collecting the different + * values into the provided buffer. + * if no more space is available in the buffer, then just count + * the missing elements for the exit code. + * the first error encountered fakes a full buffer to just add + * the remaining keys to the missing elements count before + * exiting. */ + kl = hostlist_create(keys); + while ((key = hostlist_shift(kl))) { + if (processed >= length) { + rc++; + continue; + } + if (_layouts_entity_get_kv_size(l, e, key, &elt_size) || + (processed + elt_size) > length || + _layouts_entity_get_kv(l, e, key, value, key_type)) { + rc++; + processed = length; + continue; + } + value += elt_size; + processed += elt_size; + } + hostlist_destroy(kl); + + return rc; +} + +int _layouts_entity_get_kv_ref(layout_t* l, entity_t* e, + char* key, void** value, + layouts_keydef_types_t key_type) +{ + int rc = SLURM_ERROR; + char key_keydef[PATHLEN]; + void* data; + + if (l == NULL || e == NULL || key == NULL || value == NULL) + return rc; + + if (!_layouts_entity_check_kv_keytype(l, e, key, key_type)) + return rc; + + _normalize_keydef_key(key_keydef, PATHLEN, key, l->type); + data = entity_get_data_ref(e, key_keydef); + if (data != NULL) { + *value = data; + rc = SLURM_SUCCESS; + } + return rc; +} + +int _layouts_entity_get_mkv_ref(layout_t* l, entity_t* e, char* keys, + void* value, size_t length, + layouts_keydef_types_t key_type) +{ + char *key = NULL; + hostlist_t kl; + size_t processed = 0; + size_t elt_size = sizeof(void*); + int rc = 0; + + /* expand in order the requested keys (in hostlist format) + * and iterate over each one of them, collecting the different + * references into the provided buffer. + * if no more space is available in the buffer, then just count + * the missing elements for the exit code. + * the first error encountered fakes a full buffer to just add + * the remaining keys to the missing elements count before + * exiting. */ + kl = hostlist_create(keys); + while ((key = hostlist_shift(kl))) { + if (processed >= length) { + rc++; + continue; + } + if (_layouts_entity_get_kv_ref(l, e, key, value, key_type)) { + rc++; + processed = length; + continue; + } + value += elt_size; + processed += elt_size; + } + hostlist_destroy(kl); + + return rc; +} + +int _layouts_entity_pullget_kv(layout_t* l, entity_t* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + int rc = SLURM_ERROR; + if (!_layouts_entity_check_kv_keytype(l, e, key, key_type)) + return rc; + if (_layouts_entity_pull_kv(l, e, key) == SLURM_SUCCESS) + rc = _layouts_entity_get_kv(l, e, key, value, key_type); + return rc; +} + +int _layouts_entity_pullget_kv_ref(layout_t* l, entity_t* e, + char* key, void** value, + layouts_keydef_types_t key_type) +{ + int rc = SLURM_ERROR; + if (!_layouts_entity_check_kv_keytype(l, e, key, key_type)) + return rc; + if (_layouts_entity_pull_kv(l, e, key) == SLURM_SUCCESS) + rc = _layouts_entity_get_kv_ref(l, e, key, value, key_type); + return rc; } /*****************************************************************************\ * MANAGER INIT * \*****************************************************************************/ -static void _slurm_layouts_init_keydef(xhash_t* keydefs, - const layouts_keyspec_t* plugin_keyspec, - layout_plugin_t* plugin) +static void _layouts_init_keydef(xhash_t* keydefs, + const layouts_keyspec_t* plugin_keyspec, + layout_plugin_t* plugin) { char keytmp[PATHLEN]; @@ -356,10 +814,21 @@ static void _slurm_layouts_init_keydef(xhash_t* keydefs, nkeydef = (layouts_keydef_t*) xmalloc(sizeof(layouts_keydef_t)); nkeydef->key = xstrdup(keytmp); + nkeydef->shortkey = xstrdup(current->key); nkeydef->type = current->type; + nkeydef->flags = current->flags; nkeydef->custom_destroy = current->custom_destroy; nkeydef->custom_dump = current->custom_dump; nkeydef->plugin = plugin; + if (current->ref_key != NULL) { + _normalize_keydef_key(keytmp, PATHLEN, current->ref_key, + plugin->layout->type); + nkeydef->ref_key = xstrdup(keytmp); + nkeydef->ref_shortkey = xstrdup(current->ref_key); + } else { + nkeydef->ref_key = NULL; + nkeydef->ref_shortkey = NULL; + } xhash_add(keydefs, nkeydef); } @@ -372,6 +841,7 @@ static void _slurm_layouts_init_keydef(xhash_t* keydefs, nkeydef = (layouts_keydef_t*) xmalloc(sizeof(layouts_keydef_t)); nkeydef->key = xstrdup(keytmp); + nkeydef->shortkey = xstrdup("Enclosed"); nkeydef->type = L_T_STRING; nkeydef->plugin = plugin; xhash_add(keydefs, nkeydef); @@ -379,7 +849,7 @@ static void _slurm_layouts_init_keydef(xhash_t* keydefs, } } -static int _slurm_layouts_init_layouts_walk_helper(void* x, void* arg) +static int _layouts_init_layouts_walk_helper(void* x, void* arg) { layouts_conf_spec_t* spec = (layouts_conf_spec_t*)x; int* i = (int*)arg; @@ -388,6 +858,7 @@ static int _slurm_layouts_init_layouts_walk_helper(void* x, void* arg) char plugin_name[PATHLEN]; void* inserted_item; plugin_context_t* plugin_context; + snprintf(plugin_name, PATHLEN, "layouts/%s_%s", spec->type, spec->name); plugin->ops = (layout_ops_t*)xmalloc(sizeof(layout_ops_t)); @@ -414,9 +885,9 @@ static int _slurm_layouts_init_layouts_walk_helper(void* x, void* arg) plugin->ops->spec->struct_type); inserted_item = xhash_add(mgr->layouts, plugin->layout); xassert(inserted_item == plugin->layout); - _slurm_layouts_init_keydef(mgr->keydefs, - plugin->ops->spec->keyspec, - plugin); + _layouts_init_keydef(mgr->keydefs, + plugin->ops->spec->keyspec, + plugin); ++*i; return SLURM_SUCCESS; } @@ -491,6 +962,13 @@ static char* _conf_get_filename(const char* type) return final_path; } +static char* _state_get_filename(const char* type) +{ + return xstrdup_printf("%s/layouts_state_%s", + slurmctld_conf.state_save_location, + type); +} + static s_p_hashtbl_t* _conf_make_hashtbl(int struct_type, const s_p_options_t* layout_options) { @@ -529,7 +1007,7 @@ static s_p_hashtbl_t* _conf_make_hashtbl(int struct_type, relational_options = tree_options; break; default: - fatal("layouts: does not know what relation structure to" + fatal("layouts: does not know what relation structure to " "use for type %d", struct_type); } @@ -546,28 +1024,32 @@ static s_p_hashtbl_t* _conf_make_hashtbl(int struct_type, return tbl; } -#define _layouts_load_merge(type_t, s_p_get_type) { \ - type_t newvalue; \ - type_t** oldvalue; \ - if (!s_p_get_type(&newvalue, option_key, etbl)) { \ - /* no value to merge/create */ \ - continue; \ - } \ - oldvalue = (type_t**)entity_get_data(e, key_keydef); \ - if (oldvalue) { \ - **oldvalue = newvalue; \ - } else { \ - type_t* newalloc = (type_t*)xmalloc(sizeof(type_t)); \ - *newalloc = newvalue; \ - _entity_add_data(e, key_keydef, newalloc); \ - } \ -} - -#define _layouts_merge_check(type1, type2) \ +#define _layouts_load_merge(type_t, s_p_get_type) { \ + type_t rvalue; \ + type_t* value = &rvalue; \ + type_t* oldvalue; \ + slurm_parser_operator_t operator = S_P_OPERATOR_SET; \ + if (!s_p_get_type(&rvalue, option_key, etbl)) { \ + /* no value to merge/create */ \ + continue; \ + } \ + s_p_get_operator(&operator, option_key, etbl); \ + oldvalue = (type_t*)entity_get_data_ref(e, key_keydef); \ + if (oldvalue) { \ + _entity_update_kv_helper(type_t, operator); \ + } else { \ + type_t* newalloc = (type_t*) \ + xmalloc(sizeof(type_t)); \ + *newalloc = *value; \ + _entity_add_data(e, key_keydef, newalloc); \ + } \ + } \ + +#define _layouts_merge_check(type1, type2) \ (entity_option->type == type1 && keydef->type == type2) static void _layouts_load_automerge(layout_plugin_t* plugin, entity_t* e, - s_p_hashtbl_t* etbl) + s_p_hashtbl_t* etbl, uint32_t flags) { const s_p_options_t* layout_option; const s_p_options_t* entity_option; @@ -576,22 +1058,29 @@ static void _layouts_load_automerge(layout_plugin_t* plugin, entity_t* e, char* option_key; for (layout_option = plugin->ops->spec->options; - layout_option && strcasecmp("Entity", layout_option->key); - ++layout_option); + layout_option && strcasecmp("Entity", layout_option->key); + ++layout_option); xassert(layout_option); for (entity_option = layout_option->line_options; - entity_option->key; - ++entity_option) { + entity_option->key; + ++entity_option) { option_key = entity_option->key; _normalize_keydef_key(key_keydef, PATHLEN, option_key, - plugin->layout->type); + plugin->layout->type); keydef = xhash_get(mgr->keydefs, key_keydef); if (!keydef) { /* key is not meant to be automatically handled, * ignore it for this function */ continue; } + /* do not perform automerge on updates for read-only keys */ + if (flags & UPDATE_DONE && + keydef->flags & KEYSPEC_RDONLY) { + debug4("layouts: do not try to merge RDONLY key '%s'", + keydef->key); + continue; + } if (_layouts_merge_check(S_P_LONG, L_T_LONG)) { _layouts_load_merge(long, s_p_get_long); } else if (_layouts_merge_check(S_P_UINT16, L_T_UINT16)) { @@ -602,6 +1091,13 @@ static void _layouts_load_automerge(layout_plugin_t* plugin, entity_t* e, _layouts_load_merge(bool, s_p_get_boolean); } else if (_layouts_merge_check(S_P_LONG, L_T_LONG)) { _layouts_load_merge(long, s_p_get_long); + } else if (_layouts_merge_check(S_P_FLOAT, L_T_FLOAT)) { + _layouts_load_merge(float, s_p_get_float); + } else if (_layouts_merge_check(S_P_DOUBLE, L_T_DOUBLE)) { + _layouts_load_merge(double, s_p_get_double); + } else if (_layouts_merge_check(S_P_LONG_DOUBLE, + L_T_LONG_DOUBLE)) { + _layouts_load_merge(long double, s_p_get_long_double); } else if (_layouts_merge_check(S_P_STRING, L_T_STRING)) { char* newvalue; if (s_p_get_string(&newvalue, option_key, etbl)) { @@ -616,38 +1112,39 @@ static void _layouts_parse_relations(layout_plugin_t* plugin, entity_t* e, s_p_hashtbl_t* entity_tbl) { char* e_enclosed; - char** e_already_enclosed; + char* e_already_enclosed; + char* e_new_enclosed; char key[PATHLEN]; switch(plugin->layout->struct_type) { case LAYOUT_STRUCT_TREE: if (s_p_get_string(&e_enclosed, "Enclosed", entity_tbl)) { _normalize_keydef_mgrkey(key, PATHLEN, "enclosed", - plugin->layout->type); - e_already_enclosed = (char**)entity_get_data(e, key); + plugin->layout->type); + e_already_enclosed = (char*) + entity_get_data_ref(e, key); if (e_already_enclosed) { - /* FC expressed warnings about that section, - * should be checked more */ - *e_already_enclosed = xrealloc( - *e_already_enclosed, - strlen(*e_already_enclosed) + - strlen(e_enclosed) + 2); - strcat(*e_already_enclosed, ","); - strcat(*e_already_enclosed, e_enclosed); + e_new_enclosed = (char*) xmalloc( + strlen(e_already_enclosed) + + strlen(e_enclosed) + 2); + strcat(e_new_enclosed, e_already_enclosed); + strcat(e_new_enclosed, ","); + strcat(e_new_enclosed, e_enclosed); xfree(e_enclosed); - } else { - _entity_add_data(e, key, e_enclosed); + e_enclosed = e_new_enclosed; } + _entity_add_data(e, key, e_enclosed); } break; } } static int _layouts_read_config_post(layout_plugin_t* plugin, - s_p_hashtbl_t* tbl) + s_p_hashtbl_t* tbl) { char* root_nodename; entity_t* e; - xtree_node_t* root_node,* inserted_node; + entity_node_t* enode; + xtree_node_t* root_node; xtree_t* tree; switch(plugin->layout->struct_type) { case LAYOUT_STRUCT_TREE: @@ -667,36 +1164,32 @@ static int _layouts_read_config_post(layout_plugin_t* plugin, return SLURM_ERROR; } xfree(root_nodename); - root_node = xtree_add_child(tree, NULL, e, XTREE_APPEND); + enode = entity_add_node(e, plugin->layout); + xassert(enode); + root_node = xtree_add_child(tree, NULL, enode, XTREE_APPEND); xassert(root_node); - inserted_node = list_append(e->nodes, root_node); - xassert(inserted_node == root_node); + enode->node = (void*) root_node; break; } return SLURM_SUCCESS; } /* - * _layouts_read_config - called after base entities are loaded successfully - * - * This function is the stage 1 of the layouts loading stage, where we collect - * info on all the entities and store them in a global hash table. - * Entities that do not already exist are created, otherwise updated. - * - * Information concerning the relations among entities provided by the - * 'Enclosed' conf pragma are also extracted here for further usage in stage 2. - * - * When layout plugins callbacks are called, relational structures among - * entities are not yet built. + * _layouts_load_config_common - called by layouts_read_config, + * layouts_read_state or layouts_update_config with either a + * filename or a buffer as well as a flag to indicate if it + * is a full load or not (state save only) */ -static int _layouts_read_config(layout_plugin_t* plugin) +static int _layouts_load_config_common(layout_plugin_t* plugin, + char* filename, Buf buffer, + uint32_t flags) { s_p_hashtbl_t* tbl = NULL; s_p_hashtbl_t** entities_tbl = NULL; s_p_hashtbl_t* entity_tbl = NULL; int entities_tbl_count = 0, i; + entity_t** updated_entities = NULL; int rc = SLURM_ERROR; - char* filename = NULL; uint32_t l_priority; @@ -711,16 +1204,25 @@ static int _layouts_read_config(layout_plugin_t* plugin) tbl = _conf_make_hashtbl(plugin->layout->struct_type, plugin->ops->spec->options); - filename = _conf_get_filename(plugin->layout->type); - if (!filename) { - fatal("layouts: cannot find configuration file for " - "required layout '%s'", plugin->name); - } - if (s_p_parse_file(tbl, NULL, filename, false) == SLURM_ERROR) { - fatal("layouts: something went wrong when opening/reading " - "'%s': %m", filename); + if (filename) { + if (s_p_parse_file(tbl, NULL, filename, false) == SLURM_ERROR) { + fatal("layouts: something went wrong when opening/reading " + "'%s': %m", filename); + } + debug3("layouts: configuration file '%s' is loaded", filename); + } else if (buffer) { + if (s_p_parse_buffer(tbl, NULL, buffer, false) == SLURM_ERROR) { + error("layouts: something went wrong when parsing " + "buffer : %m"); + rc = SLURM_ERROR; + goto cleanup; + } + debug3("layouts: buffer loaded"); + } else { + error("layouts: invalid usage of _layouts_load_config_common"); + rc = SLURM_ERROR; + goto cleanup; } - debug3("layouts: configuration file '%s' is loaded", filename); if (s_p_get_uint32(&l_priority, "Priority", tbl)) { plugin->layout->priority = l_priority; @@ -728,15 +1230,21 @@ static int _layouts_read_config(layout_plugin_t* plugin) /* get the config hash tables of the defined entities */ if (!s_p_get_expline(&entities_tbl, &entities_tbl_count, - "Entity", tbl)) { + "Entity", tbl)) { error("layouts: no valid Entity found, can not append any " "information nor construct relations for %s/%s", plugin->layout->type, plugin->layout->name); goto cleanup; } + /* stage 0: xmalloc an array of entity_t* to save the updated entity_t + * and give their references in the update_done layout callback */ + updated_entities = (entity_t**) + xmalloc(entities_tbl_count*sizeof(entity_t*)); + /* stage 1: create the described entities or update them */ for (i = 0; i < entities_tbl_count; ++i) { + updated_entities[i] = NULL; entity_tbl = entities_tbl[i]; xfree(e_name); xfree(e_type); @@ -745,7 +1253,7 @@ static int _layouts_read_config(layout_plugin_t* plugin) "skipping...", i); continue; } - + /* look for the entity in the entities hash table*/ e = xhash_get(mgr->entities, e_name); if (!e) { @@ -775,18 +1283,20 @@ static int _layouts_read_config(layout_plugin_t* plugin) "invalid, skipping", e_name, e_type); continue; } - if (!strcmp(e_type, e->type)) { + if (!e->type || strcmp(e_type, e->type)) { error("layouts: entity '%s' type (%s) differs " "from already registered entity type (%s)" - "skipping", e_name, e_type, e->type); + " skipping", e_name, e_type, e->type); continue; } } - /* look for "Enclosed" pragmas identifying the relations + /* ** Full load config only (flags==0) ** + * look for "Enclosed" pragmas identifying the relations * among entities and kep that along with the entity for * stage 2 */ - _layouts_parse_relations(plugin, e, entity_tbl); + if (flags & PARSE_RELATIONS) + _layouts_parse_relations(plugin, e, entity_tbl); /* * if the layout plugin requests automerge, try to automatically @@ -795,33 +1305,41 @@ static int _layouts_read_config(layout_plugin_t* plugin) * type and adding them to the entity key hash table. */ if (plugin->ops->spec->automerge) { - _layouts_load_automerge(plugin, e, entity_tbl); + _layouts_load_automerge(plugin, e, entity_tbl, flags); } /* * in case the automerge was not sufficient, the layout parsing * callback is called for further actions. */ - if (plugin->ops->entity_parsing) { + if ((flags & PARSE_ENTITY) && plugin->ops->entity_parsing) { plugin->ops->entity_parsing(e, entity_tbl, plugin->layout); } + + /* add the entity ref to the array for further usage when + * calling the update_done layout callback */ + updated_entities[i] = e; } + xfree(e_name); + xfree(e_type); - /* post-read-and-build (post stage 1) + /* ** Full load config only (flags==0) ** + * post-read-and-build (post stage 1) * ensure that a Root entity was defined and set it as the root of * the relational structure of the layout. * fails in case of error as a root is mandatory to walk the relational * structure of the layout */ - if (_layouts_read_config_post(plugin, tbl) != SLURM_SUCCESS) { + if ((flags & CONF_DONE) && + _layouts_read_config_post(plugin, tbl) != SLURM_SUCCESS) { goto cleanup; } - /* + /* ** Full load config only (flags==0) ** * call the layout plugin conf_done callback for further * layout specific actions. */ - if (plugin->ops->conf_done) { + if ((flags & CONF_DONE) && plugin->ops->conf_done) { if (!plugin->ops->conf_done(mgr->entities, plugin->layout, tbl)) { error("layouts: plugin %s/%s has an error parsing its" @@ -830,37 +1348,141 @@ static int _layouts_read_config(layout_plugin_t* plugin) goto cleanup; } } - + + /* + * In case we are processing an update (not a startup configuration) + * if the layout plugin requests autoupdate, call the autoupdate + * function on the current layout in order to set the inherited values + * according to the newly modified ones. + * (in startup configuration, the autoupdate is performed in stage 3 + * when the relational structures are available) + */ + if ((flags & UPDATE_DONE) && plugin->ops->spec->autoupdate) { + _layouts_autoupdate_layout(plugin->layout); + } + + /* + * Call the layout plugin update_done callback for further + * layout specific actions. + * Note : some entries of the updated_entities array might be NULL + * reflecting an issue while trying to analyze the corresponding + * parsed hash table. + */ + if ((flags & UPDATE_DONE) && plugin->ops->update_done) { + if (!plugin->ops->update_done(plugin->layout, updated_entities, + entities_tbl_count)) { + error("layouts: plugin %s/%s has an error reacting to" + " entities update", plugin->layout->type, + plugin->layout->name); + goto cleanup; + } + } + xfree(updated_entities); + rc = SLURM_SUCCESS; cleanup: s_p_hashtbl_destroy(tbl); - xfree(filename); return rc; } -typedef struct _layouts_build_xtree_walk_st { - char* enclosed_key; - xtree_t* tree; -} _layouts_build_xtree_walk_t; - -uint8_t _layouts_build_xtree_walk(xtree_node_t* node, - uint8_t which, - uint32_t level, - void* arg) +/* + * _layouts_read_config - called after base entities are loaded successfully + * + * This function is the stage 1 of the layouts loading stage, where we collect + * info on all the entities and store them in a global hash table. + * Entities that do not already exist are created, otherwise updated. + * + * Information concerning the relations among entities provided by the + * 'Enclosed' conf pragma are also extracted here for further usage in stage 2. + * + * When layout plugins callbacks are called, relational structures among + * entities are not yet built. + */ +static int _layouts_read_config(layout_plugin_t* plugin) { - _layouts_build_xtree_walk_t* p = (_layouts_build_xtree_walk_t*)arg; - entity_t* e; - char** enclosed_str; + int rc; + char* filename = _conf_get_filename(plugin->layout->type); + if (!filename) { + fatal("layouts: cannot find configuration file for " + "required layout '%s'", plugin->name); + } + rc = _layouts_load_config_common(plugin, filename, NULL, + CONF_DONE | + PARSE_ENTITY | PARSE_RELATIONS); + xfree(filename); + return rc; +} + +/* + * _layouts_read_state - called to restore saved state of layout entities + * + * This function is the stage 1.1 of the layouts loading stage, where we collect + * info on all the entities stored in the state of the layout and store/update + * them in the global hash table. + * + * Information concerning the relations among entities provided by the + * 'Enclosed' conf pragma are not taken into account for now and will be those + * loaded during stage 1. + * + * No layout plugins callbacks are called when doing that for now. + */ +static int _layouts_read_state(layout_plugin_t* plugin) +{ + int rc = SLURM_SUCCESS; + struct stat stat_buf; + char *filename = _state_get_filename(plugin->layout->type); + if (!filename) { + error("layouts: unable to build read state filename of layout" + " '%s/%s'", plugin->layout->type, plugin->layout->name); + return SLURM_ERROR; + } + /* check availability of the file otherwise it will later block + * waiting for a file to appear (in s_p_parse_file) */ + if (stat(filename, &stat_buf) < 0) { + debug("layouts: skipping non existent state file for '%s/%s'", + plugin->layout->type, plugin->layout->name); + } else { + rc = _layouts_load_config_common(plugin, filename, NULL, + PARSE_ENTITY); + } + xfree(filename); + return rc; +} + +static int _layouts_update_state(layout_plugin_t* plugin, Buf buffer) +{ + return _layouts_load_config_common(plugin, NULL, buffer, + PARSE_ENTITY | UPDATE_DONE); +} + +typedef struct _layouts_build_xtree_walk_st { + layout_t* layout; + char* enclosed_key; + xtree_t* tree; +} _layouts_build_xtree_walk_t; + +uint8_t _layouts_build_xtree_walk(xtree_node_t* node, + uint8_t which, + uint32_t level, + void* arg) +{ + _layouts_build_xtree_walk_t* p = (_layouts_build_xtree_walk_t*)arg; + entity_t* e; + entity_node_t* enode; + char* enclosed_str; char* enclosed_name; hostlist_t enclosed_hostlist; entity_t* enclosed_e; - xtree_node_t* enclosed_node,* inserted_node; + xtree_node_t* enclosed_node; xassert(arg); - e = xtree_node_get_data(node); + /* get the entity from the entity node associated with the tree node */ + enode = (entity_node_t*) xtree_node_get_data(node); + xassert(enode); + e = enode->entity; xassert(e); /* @@ -873,11 +1495,10 @@ uint8_t _layouts_build_xtree_walk(xtree_node_t* node, if (which != XTREE_GROWING && which != XTREE_PREORDER) return 1; - enclosed_str = (char**)entity_get_data(e, p->enclosed_key); + enclosed_str = (char*) entity_get_data_ref(e, p->enclosed_key); if (enclosed_str) { - enclosed_hostlist = hostlist_create(*enclosed_str); - xfree(*enclosed_str); + enclosed_hostlist = hostlist_create(enclosed_str); entity_delete_data(e, p->enclosed_key); while ((enclosed_name = hostlist_shift(enclosed_hostlist))) { enclosed_e = xhash_get(mgr->entities, enclosed_name); @@ -890,13 +1511,18 @@ uint8_t _layouts_build_xtree_walk(xtree_node_t* node, continue; } free(enclosed_name); + /* create an entity node associated to the entity + * for this layout */ + enode = entity_add_node(enclosed_e, p->layout); + xassert(enode); + /* add it to the tree, getting an xtree_node_t ref */ enclosed_node = xtree_add_child(p->tree, node, - enclosed_e, - XTREE_APPEND); + enode, XTREE_APPEND); xassert(enclosed_node); - inserted_node = list_append(enclosed_e->nodes, - enclosed_node); - xassert(inserted_node == enclosed_node); + /* store the xtree_node_t ref in the entity node. It + * will be used to access this layout tree from the + * entity when necessary through the entity node */ + enode->node = enclosed_node; } hostlist_destroy(enclosed_hostlist); } @@ -928,6 +1554,7 @@ static int _layouts_build_relations(layout_plugin_t* plugin) _normalize_keydef_mgrkey(key, PATHLEN, "enclosed", plugin->layout->type); _layouts_build_xtree_walk_t p = { + plugin->layout, key, tree }; @@ -942,6 +1569,526 @@ static int _layouts_build_relations(layout_plugin_t* plugin) return SLURM_SUCCESS; } +/*****************************************************************************\ + * STATE DUMP * +\*****************************************************************************/ + +/* + * _pack_args_t : helper struct/type used when passing args among the various + * functions used when packing layouts into a buffer as a set of strings. + */ +typedef struct _pack_args { + Buf buffer; + char *current_line; + layout_t* layout; +} _pack_args_t; + +/* + * _pack_data_key : internal function used to get the key=val + * string representation of a particular entity data value + */ +static char* _pack_data_key(layouts_keydef_t* keydef, void* value) +{ + char val; + if (!keydef) { + return NULL; + } + switch(keydef->type) { + case L_T_ERROR: + return NULL; + case L_T_STRING: + return xstrdup_printf("%s=%s", keydef->shortkey, + (char*)value); + case L_T_LONG: + return xstrdup_printf("%s=%ld", keydef->shortkey, + *(long*)value); + case L_T_UINT16: + return xstrdup_printf("%s=%u", keydef->shortkey, + *(uint16_t*)value); + case L_T_UINT32: + return xstrdup_printf("%s=%"PRIu32, keydef->shortkey, + *(uint32_t*)value); + case L_T_BOOLEAN: + val = *(bool*)value; + return xstrdup_printf("%s=%s", keydef->shortkey, + val ? "true" : "false"); + case L_T_FLOAT: + return xstrdup_printf("%s=%f", keydef->shortkey, + *(float*)value); + case L_T_DOUBLE: + return xstrdup_printf("%s=%f", keydef->shortkey, + *(double*)value); + case L_T_LONG_DOUBLE: + return xstrdup_printf("%s=%Lf", keydef->shortkey, + *(long double*)value); + case L_T_CUSTOM: + if (keydef->custom_dump) { + return keydef->custom_dump(value); + } else + return NULL; + } + return NULL; +} + +/* + * _pack_entity_layout_data : internal function used to append the + * key/value of a entity data element corresponding to the targeted + * layout when walking an entity list of entity data elements + * + * - append the " %key%=%val%" to the char* received as an input arg member + * + */ +static void _pack_entity_layout_data(void* item, void* arg) +{ + entity_data_t* data; + _pack_args_t *pargs; + + layouts_keydef_t* keydef; + char *data_dump; + + xassert(item); + xassert(arg); + + data = (entity_data_t*) item; + pargs = (_pack_args_t *) arg; + + /* the pack args must contain a valid char* to append to */ + xassert(pargs->current_line); + + /* we must be able to get the keydef associated to the data key */ + xassert(data); + keydef = xhash_get(mgr->keydefs, data->key); + xassert(keydef); + + /* only dump keys related to the targeted layout */ + if (!strncmp(keydef->plugin->name, pargs->layout->type, PATHLEN)) { + data_dump = _pack_data_key(keydef, data->value); + /* avoid printing any error in case of NULL pointer returned */ + if (data_dump) { + xstrcat(pargs->current_line, " "); + xstrcat(pargs->current_line, data_dump); + xfree(data_dump); + } + } + + return; +} + +/* + * _pack_layout_tree : internal function used when walking a layout tree + * + * - print one line per entity with the following pattern : + * Entity=%name% [Type=%type%] [Enclosed=%childrens%] [key1=val1 ...] + * + * - potentially print an header line if the entity is the root like : + * Root=%name% + * + */ +static uint8_t _pack_layout_tree(xtree_node_t* node, uint8_t which, + uint32_t level, void* arg) +{ + _pack_args_t *pargs; + xtree_node_t* child; + entity_node_t* enode; + hostlist_t enclosed; + char *enclosed_str = NULL, *e_name = NULL, *e_type = NULL; + Buf buffer; + char *strdump, *str; + + /* only need to work for preorder and leaf cases */ + if (which != XTREE_PREORDER && which != XTREE_LEAF) { + return 1; + } + + /* get the buffer we need to pack the data too */ + pargs = (_pack_args_t *) arg; + buffer = pargs->buffer; + + /* aggregate children names to build the Enclosed=.. value */ + if (which == XTREE_PREORDER) { + enclosed = hostlist_create(NULL); + child = node->start; + while (child) { + enode = (entity_node_t*) xtree_node_get_data(child); + if (!enode || !enode->entity) { + hostlist_push(enclosed, "NULL"); + } else { + hostlist_push(enclosed, enode->entity->name); + } + child = child->next; + } + hostlist_uniq(enclosed); + if (hostlist_count(enclosed) > 0) { + enclosed_str = hostlist_ranged_string_xmalloc(enclosed); + } + hostlist_destroy(enclosed); + } + + /* get the entity associated to this xtree node */ + enode = (entity_node_t*) xtree_node_get_data(node); + if (!enode || !enode->entity) { + e_name = (char*) "NULL"; + e_type = NULL; + } + else { + e_name = enode->entity->name; + e_type = enode->entity->type; + } + + /* print this entity as root if necessary */ + if (level == 0) { + str = xstrdup_printf("Root=%s\n", e_name); + packstr(str, buffer); + xfree(str); + } + + /* print entity name and type when possible */ + str = xstrdup_printf("Entity=%s", e_name); + if (e_type) { + strdump = xstrdup_printf("%s Type=%s", str, e_type); + xfree(str); + str = strdump; + } + + /* add entity keys matching the layout to the current str */ + pargs->current_line = str; + if (enode && enode->entity) + xhash_walk(enode->entity->data, _pack_entity_layout_data, + pargs); + /* the current line might have been extended/remalloced, so + * we need to sync it again in str for further actions */ + str = pargs->current_line; + pargs->current_line = NULL; + + /* print enclosed entities if any */ + if (!enclosed_str) { + xstrcat(str, "\n"); + } else { + strdump = xstrdup_printf("%s Enclosed=%s\n", str, enclosed_str); + xfree(enclosed_str); + xfree(str); + str = strdump; + } + packstr(str, buffer); + xfree(str); + + return 1; +} + +/* helper function used by layouts_save_state when walking through + * the various layouts to save their state in Slurm state save location */ +static void _state_save_layout(void* item, void* arg) +{ + layout_t* layout = (layout_t*)item; + layouts_state_save_layout(layout->type); +} + +/*****************************************************************************\ + * ENTITIES KVs AUTOUPDATE * +\*****************************************************************************/ + +/* + * helper structure used when walking the tree of relational nodes in order + * to automatically update the entities KVs based on their inheritance + * relationships + */ +typedef struct _autoupdate_tree_args { + entity_node_t* enode; + uint8_t which; + uint32_t level; +} _autoupdate_tree_args_t; + +/* + * helper function used to update a particular KV value of an entity according + * to a particular operator looking for the right type to apply during the + * operation + */ +static int _autoupdate_entity_kv(layouts_keydef_t* keydef, + layouts_keydef_t* ref_keydef, + slurm_parser_operator_t operator, + void* oldvalue, void* value) +{ + int rc = SLURM_ERROR; + + if (keydef->type != ref_keydef->type) + return rc; + + if (keydef->type == L_T_LONG) { + _entity_update_kv_helper(long, operator); + } else if (keydef->type == L_T_UINT16) { + _entity_update_kv_helper(uint16_t, operator); + } else if (keydef->type == L_T_UINT32) { + _entity_update_kv_helper(uint32_t, operator); + } else if (keydef->type == L_T_FLOAT) { + _entity_update_kv_helper(float, operator); + } else if (keydef->type == L_T_DOUBLE) { + _entity_update_kv_helper(double, operator); + } else if (keydef->type == L_T_LONG_DOUBLE) { + _entity_update_kv_helper(long double, operator); + } else { + // L_T_BOOLEAN, L_T_STRING, L_T_CUSTOM not yet supported + return rc; + } + + return SLURM_SUCCESS; +} + +/* + * helper function used to update KVs of an entity using its xtree_node + * looking for known inheritance in the neighborhood (parents/children) */ +static void _tree_update_node_entity_data(void* item, void* arg) { + + uint32_t action; + entity_data_t* data; + _autoupdate_tree_args_t *pargs; + layouts_keydef_t* keydef; + layouts_keydef_t* ref_keydef; + slurm_parser_operator_t operator; + xtree_node_t *node, *child; + entity_node_t *enode, *cnode; + void* oldvalue; + void* value; + uint32_t count; + int setter; + + xassert(item); + xassert(arg); + + data = (entity_data_t*) item; + pargs = (_autoupdate_tree_args_t *) arg; + cnode = pargs->enode; + + /* we must be able to get the keydef associated to the data key */ + xassert(data); + keydef = xhash_get(mgr->keydefs, data->key); + xassert(keydef); + + /* only work on keys that depend of their neighborhood */ + if (!(keydef->flags & KEYSPEC_UPDATE_CHILDREN_MASK) && + !(keydef->flags & KEYSPEC_UPDATE_PARENTS_MASK)) { + return; + } + + /* if children dependant and we are at leaf level, nothing to do */ + if (keydef->flags & KEYSPEC_UPDATE_CHILDREN_MASK && + pargs->which == XTREE_LEAF) + return; + + /* only work on keys related to the targeted layout */ + if (strncmp(keydef->plugin->name, pargs->enode->layout->type, + PATHLEN)) { + return; + } + + /* get ref_key (identical if not defined) */ + if (keydef->ref_key != NULL) { + ref_keydef = xhash_get(mgr->keydefs, keydef->ref_key); + if (!ref_keydef) { + debug2("layouts: autoupdate: key='%s': invalid " + "ref_key='%s'", keydef->key, keydef->ref_key); + return; + } + } else { + ref_keydef = keydef; + } + + /* process parents aggregation + * for now, xtree only provides one parent so any update op + * (MAX, MIN, FSHARE, ...) is a setter */ + if ((action = keydef->flags & KEYSPEC_UPDATE_PARENTS_MASK) && + (pargs->which == XTREE_PREORDER || pargs->which == XTREE_LEAF) && + (node = ((xtree_node_t*)pargs->enode->node)->parent) != NULL ) { + + /* get current node value reference */ + oldvalue = entity_get_data_ref(cnode->entity, keydef->key); + + /* get siblings count */ + child = node->start; + count = 0; + while (child) { + count++; + child = child->next; + } + + /* get parent node KV data ref */ + enode = (entity_node_t*) xtree_node_get_data(node); + value = entity_get_data_ref(enode->entity, ref_keydef->key); + if (!value) + return; + + /* only set operation currently provided for parents except + * for fshare action */ + _autoupdate_entity_kv(keydef, ref_keydef, S_P_OPERATOR_SET, + oldvalue, value); + if (action == KEYSPEC_UPDATE_PARENTS_FSHARE) { + _autoupdate_entity_kv(keydef, ref_keydef, + S_P_OPERATOR_AVG, + oldvalue, (void*) &count); + } + + return; + } + + /* process children aggregation */ + if ((action = keydef->flags & KEYSPEC_UPDATE_CHILDREN_MASK) && + pargs->which == XTREE_ENDORDER) { + + /* get current node value reference */ + oldvalue = entity_get_data_ref(cnode->entity, keydef->key); + + /* get children count */ + node = (xtree_node_t*)cnode->node; + child = node->start; + count = 0; + while (child) { + count++; + child = child->next; + } + + /* no action if no children */ + if (count == 0) + return; + + /* if count action, do what is necessary and return */ + if (action == KEYSPEC_UPDATE_CHILDREN_COUNT) { + _autoupdate_entity_kv(keydef, ref_keydef, + S_P_OPERATOR_SET, + oldvalue, (void*) &count); + return; + } + + /* iterate on the children */ + setter = 1; + child = node->start; + while (child) { + /* get child node KV data ref */ + enode = (entity_node_t*) xtree_node_get_data(child); + value = entity_get_data_ref(enode->entity, + ref_keydef->key); + + if (!value) { + /* try next child */ + child = child-> next; + continue; + } + + switch (action) { + case KEYSPEC_UPDATE_CHILDREN_SUM: + case KEYSPEC_UPDATE_CHILDREN_AVG: + /* first child is a setter */ + if (setter) { + operator = S_P_OPERATOR_SET; + setter = 0; + } + else + operator = S_P_OPERATOR_ADD; + break; + case KEYSPEC_UPDATE_CHILDREN_MIN: + operator = S_P_OPERATOR_SET_IF_MIN; + break; + case KEYSPEC_UPDATE_CHILDREN_MAX: + operator = S_P_OPERATOR_SET_IF_MAX; + break; + default: + /* should not be called! */ + return; + } + + /* update the value according to the operator */ + _autoupdate_entity_kv(keydef, ref_keydef, operator, + oldvalue, value); + + /* then next child */ + child = child-> next; + } + + /* if average action, do what is necessary before return */ + if (action == KEYSPEC_UPDATE_CHILDREN_AVG) { + _autoupdate_entity_kv(keydef, ref_keydef, + S_P_OPERATOR_AVG, + oldvalue, (void*) &count); + return; + } + + return; + } + +} + +/* + * _autoupdate_layout_tree : internal function used when automatically + * updating elements of a layout tree using _layouts_autoupdate_layout */ +static uint8_t _autoupdate_layout_tree(xtree_node_t* node, uint8_t which, + uint32_t level, void* arg) +{ + entity_node_t* cnode; + _autoupdate_tree_args_t sync_args; + + /* only need to work for preorder, leaf and endorder cases */ + if (which != XTREE_PREORDER && + which != XTREE_LEAF && + which != XTREE_ENDORDER) { + return 1; + } + + /* extract current node entity_node to next browsing */ + cnode = (entity_node_t*) xtree_node_get_data(node); + if (!cnode) + return 1; + + /* prepare downcall args */ + sync_args.enode = cnode; + sync_args.which = which; + sync_args.level = level; + + /* iterate over the K/V of the entity, syncing them according + * to their autoupdate flags */ + xhash_walk(cnode->entity->data, _tree_update_node_entity_data, + &sync_args); + + return 1; +} + +/* helper function used to automatically update a layout internal + * entities KVs based on inheritance relations (parents/children) */ +static int _layouts_autoupdate_layout(layout_t* layout) +{ + /* autoupdate according to the layout struct type */ + switch(layout->struct_type) { + case LAYOUT_STRUCT_TREE: + xtree_walk(layout->tree, NULL, 0, + XTREE_LEVEL_MAX, + _autoupdate_layout_tree, NULL); + break; + } + + return SLURM_SUCCESS; +} + +/* helper function used to automatically update a layout internal + * entities KVs based on inheritance relations (parents/children) + * only when allowed by the associated plugin */ +static int _layouts_autoupdate_layout_if_allowed(layout_t* layout) +{ + int i, rc = SLURM_ERROR; + /* look if the corresponding layout plugin enables autoupdate */ + for (i = 0; i < mgr->plugins_count; i++) { + if (mgr->plugins[i].layout == layout) { + /* no autoupdate allowed, return success */ + if (!mgr->plugins[i].ops->spec->autoupdate) + rc = SLURM_SUCCESS; + else + rc = _layouts_autoupdate_layout(layout); + break; + } + } + return rc; +} + +/*****************************************************************************\ + * DEBUG DUMP * +\*****************************************************************************/ + /* * For debug purposes, dump functions helping to print the layout mgr * internal states in a file after the load. @@ -1015,15 +2162,16 @@ static uint8_t _dump_layout_tree(xtree_node_t* node, uint8_t which, { FILE* fdump = (FILE*)arg; entity_t* e; + entity_node_t* enode; if (which != XTREE_PREORDER && which != XTREE_LEAF) { return 1; } - e = xtree_node_get_data(node); - if (!e) { + enode = (entity_node_t*) xtree_node_get_data(node); + if (!enode || !enode->entity) { fprintf(fdump, "NULL_entity\n"); } else { - fprintf(fdump, "%*s%s\n", level, " ", e->name); + fprintf(fdump, "%*s%s\n", level, " ", enode->entity->name); } return 1; } @@ -1054,16 +2202,17 @@ static void _dump_layouts(void* item, void* arg) } #endif + /*****************************************************************************\ * SLURM LAYOUTS API * \*****************************************************************************/ -int slurm_layouts_init(void) +int layouts_init(void) { int i = 0; uint32_t layouts_count; - debug3("layouts: slurm_layouts_init()..."); + debug3("layouts: layouts_init()..."); if (mgr->plugins) { return SLURM_SUCCESS; @@ -1080,8 +2229,8 @@ int slurm_layouts_init(void) mgr->plugins = xmalloc(sizeof(layout_plugin_t) * layouts_count); list_for_each(layouts_mgr.layouts_desc, - _slurm_layouts_init_layouts_walk_helper, - &i); + _layouts_init_layouts_walk_helper, + &i); mgr->plugins_count = i; if (mgr->plugins_count != layouts_count) { @@ -1093,7 +2242,7 @@ int slurm_layouts_init(void) xfree(mgr->plugins); mgr->plugins = NULL; } else if (layouts_count > 0) { - info("layouts: slurm_layouts_init done : %d layout(s) " + info("layouts: layouts_init done : %d layout(s) " "initialized", layouts_count); } @@ -1103,14 +2252,22 @@ int slurm_layouts_init(void) SLURM_SUCCESS : SLURM_ERROR; } -int slurm_layouts_fini(void) +int layouts_fini(void) { int i; - debug3("layouts: slurm_layouts_fini()..."); + debug3("layouts: layouts_fini()..."); + + /* push layouts states to the state save location */ + layouts_state_save(); slurm_mutex_lock(&mgr->lock); + /* free the layouts before destroying the plugins, + * otherwise we will get trouble xfreeing the layouts whose + * memory is owned by the plugins structs */ + layouts_mgr_free(mgr); + for (i = 0; i < mgr->plugins_count; i++) { _layout_plugins_destroy(&mgr->plugins[i]); } @@ -1118,8 +2275,6 @@ int slurm_layouts_fini(void) mgr->plugins = NULL; mgr->plugins_count = 0; - layouts_mgr_free(mgr); - slurm_mutex_unlock(&mgr->lock); info("layouts: all layouts are now unloaded."); @@ -1127,13 +2282,14 @@ int slurm_layouts_fini(void) return SLURM_SUCCESS; } -int slurm_layouts_load_config(void) +int layouts_load_config(int recover) { int i, rc, inx; struct node_record *node_ptr; layout_t *layout; uint32_t layouts_count; entity_t *entity; + entity_node_t *enode; void *ptr; info("layouts: loading entities/relations information"); @@ -1164,12 +2320,13 @@ int slurm_layouts_load_config(void) */ for (inx = 0, node_ptr = node_record_table_ptr; inx < node_record_count; inx++, node_ptr++) { + debug3("layouts: loading node %s", node_ptr->name); xassert (node_ptr->magic == NODE_MAGIC); xassert (node_ptr->config_ptr->magic == CONFIG_MAGIC); /* init entity structure on the heap */ entity = (entity_t*) xmalloc(sizeof(struct entity_st)); - entity_init(entity, node_ptr->name, 0); + entity_init(entity, node_ptr->name, "Node"); entity->ptr = node_ptr; /* add to mgr entity hashtable */ @@ -1184,8 +2341,9 @@ int slurm_layouts_load_config(void) /* add to the base layout (storing a callback ref to the * layout node pointing to it) */ + enode = entity_add_node(entity, layout); ptr = xtree_add_child(layout->tree, layout->tree->root, - (void*)entity, XTREE_APPEND); + (void*)enode, XTREE_APPEND); if (!ptr) { error("layouts: unable to add entity of node %s" "in the hashtable, aborting", node_ptr->name); @@ -1194,8 +2352,7 @@ int slurm_layouts_load_config(void) rc = SLURM_ERROR; break; } else { - debug3("layouts: loading node %s", node_ptr->name); - entity_add_node(entity, layout, ptr); + enode->node = ptr; } } debug("layouts: %d/%d nodes in hash table, rc=%d", @@ -1241,6 +2398,14 @@ exit: break; } } + if (recover) { + debug("layouts: loading stage 1.1 (restore state)"); + for (i = 0; i < mgr->plugins_count; ++i) { + debug3("layouts: reading state of %s", + mgr->plugins[i].name); + _layouts_read_state(&mgr->plugins[i]); + } + } debug("layouts: loading stage 2"); for (i = 0; i < mgr->plugins_count; ++i) { debug3("layouts: creating relations for %s", @@ -1251,6 +2416,19 @@ exit: break; } } + debug("layouts: loading stage 3"); + for (i = 0; i < mgr->plugins_count; ++i) { + debug3("layouts: autoupdating %s", + mgr->plugins[i].name); + if (mgr->plugins[i].ops->spec->autoupdate) { + if (_layouts_autoupdate_layout(mgr->plugins[i]. + layout) != + SLURM_SUCCESS) { + rc = SLURM_ERROR; + break; + } + } + } } /* @@ -1273,14 +2451,292 @@ exit: return rc; } -layout_t* slurm_layouts_get_layout(const char* type) +layout_t* layouts_get_layout_nolock(const char* type) { - layout_t* layout = (layout_t*)xhash_get(mgr->layouts, type); + return (layout_t*)xhash_get(mgr->layouts, type); +} + +layout_t* layouts_get_layout(const char* type) +{ + layout_t *layout = NULL; + slurm_mutex_lock(&mgr->lock); + layout = layouts_get_layout_nolock(type); + slurm_mutex_unlock(&mgr->lock); return layout; } -entity_t* slurm_layouts_get_entity(const char* name) +entity_t* layouts_get_entity_nolock(const char* name) +{ + return (entity_t*)xhash_get(mgr->entities, name); +} + +entity_t* layouts_get_entity(const char* name) { - entity_t* e = (entity_t*)xhash_get(mgr->entities, name); + entity_t* e; + slurm_mutex_lock(&mgr->lock); + e = layouts_get_entity_nolock(name); + slurm_mutex_unlock(&mgr->lock); return e; } + +int layouts_pack_layout(char *l_type, Buf buffer) +{ + _pack_args_t pargs; + layout_t* layout; + char *str; + + slurm_mutex_lock(&mgr->lock); + + layout = layouts_get_layout_nolock(l_type); + if (layout == NULL) { + error("unable to get layout of type '%s'", l_type); + return SLURM_ERROR; + } + + /* initialize args for recursive packing */ + pargs.buffer = buffer; + pargs.layout = layout; + pargs.current_line = NULL; + + /* start by packing the layout priority */ + str = xstrdup_printf("Priority=%u\n", layout->priority); + packstr(str, buffer); + xfree(str); + + /* pack according to the layout struct type */ + switch(layout->struct_type) { + case LAYOUT_STRUCT_TREE: + xtree_walk(layout->tree, NULL, 0, XTREE_LEVEL_MAX, + _pack_layout_tree, &pargs); + break; + } + + /* EOF */ + packstr("", buffer); + + slurm_mutex_unlock(&mgr->lock); + + return SLURM_SUCCESS; +} + +int layouts_update_layout(char *l_type, Buf buffer) +{ + int i, rc; + slurm_mutex_lock(&mgr->lock); + for (i = 0; i < mgr->plugins_count; i++) { + if (!strcmp(mgr->plugins[i].name, l_type)) { + rc = _layouts_update_state((layout_plugin_t*) + &mgr->plugins[i], + buffer); + slurm_mutex_unlock(&mgr->lock); + return rc; + } + } + error("layouts: update layout : no plugin matching layout=%s, skipping", + l_type); + slurm_mutex_unlock(&mgr->lock); + return SLURM_ERROR; +} + +int layouts_autoupdate_layout(char *l_type) +{ + int rc = SLURM_ERROR; + layout_t* layout; + + slurm_mutex_lock(&mgr->lock); + layout = layouts_get_layout_nolock(l_type); + if (layout == NULL) { + error("unable to get layout of type '%s'", l_type); + } else { + rc = _layouts_autoupdate_layout(layout); + } + slurm_mutex_unlock(&mgr->lock); + + return rc; +} + +int layouts_state_save_layout(char* l_type) +{ + int error_code = 0, log_fd; + char *old_file = NULL, *new_file = NULL, *reg_file = NULL; + static int high_buffer_size = (1024 * 1024); + Buf buffer = init_buf(high_buffer_size); + FILE* fdump; + uint32_t utmp32; + char *tmp_str = NULL; + + DEF_TIMERS; + START_TIMER; + + /* pack the targeted layout into a tmp buffer */ + error_code = layouts_pack_layout(l_type, buffer); + if (error_code != SLURM_SUCCESS) { + error("unable to save layout[%s] state", l_type); + return error_code; + } + + /* rewind the freshly created buffer to unpack it into a file */ + set_buf_offset(buffer, 0); + + /* create working files */ + reg_file = _state_get_filename(l_type); + old_file = xstrdup_printf("%s.old", reg_file); + new_file = xstrdup_printf("%s.new", reg_file); + log_fd = creat(new_file, 0600); + if (log_fd < 0 || !(fdump = fdopen(log_fd, "w"))) { + error("Can't save state, create file %s error %m", + new_file); + error_code = errno; + } else { + /* start dumping packed strings into the temporary file */ + while (remaining_buf(buffer) > 0) { + safe_unpackstr_xmalloc(&tmp_str, &utmp32, buffer); + if (tmp_str != NULL) { + if (*tmp_str == '\0') { + xfree(tmp_str); + break; + } + fprintf(fdump, "%s", tmp_str); + xfree(tmp_str); + continue; + } + unpack_error: + break; + } + fflush(fdump); + fsync(log_fd); + fclose(fdump); + } + if (error_code) + (void) unlink(new_file); + else { /* file shuffle */ + (void) unlink(old_file); + if (link(reg_file, old_file)) + debug4("unable to create link for %s -> %s: %m", + reg_file, old_file); + (void) unlink(reg_file); + if (link(new_file, reg_file)) + debug4("unable to create link for %s -> %s: %m", + new_file, reg_file); + (void) unlink(new_file); + } + xfree(old_file); + xfree(reg_file); + xfree(new_file); + + free_buf(buffer); + + END_TIMER2("layouts_state_save_layout"); + + return SLURM_SUCCESS; +} + +int layouts_state_save(void) +{ + DEF_TIMERS; + START_TIMER; + xhash_walk(mgr->layouts, _state_save_layout, NULL); + END_TIMER2("layouts_state_save"); + return SLURM_SUCCESS; +} + +#define _layouts_entity_wrapper(func, l, e, r...) \ + layout_t* layout; \ + entity_t* entity; \ + int rc; \ + slurm_mutex_lock(&mgr->lock); \ + layout = layouts_get_layout_nolock(l); \ + entity = layouts_get_entity_nolock(e); \ + rc = func(layout, entity, ##r); \ + slurm_mutex_unlock(&mgr->lock); \ + return rc; \ + +int layouts_entity_get_kv_type(char* l, char* e, char* key) +{ + _layouts_entity_wrapper(_layouts_entity_get_kv_type,l,e,key); +} + +int layouts_entity_get_kv_flags(char* l, char* e, char* key) +{ + _layouts_entity_wrapper(_layouts_entity_get_kv_flags, l, e, key); +} + +int layouts_entity_push_kv(char* l, char* e, char* key) +{ + _layouts_entity_wrapper(_layouts_entity_push_kv, l, e, key); +} + +int layouts_entity_pull_kv(char* l, char* e, char* key) +{ + _layouts_entity_wrapper(_layouts_entity_pull_kv, l, e, key); +} + +int layouts_entity_set_kv(char* l, char* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_set_kv, l, e, + key, value, key_type); +} + +int layouts_entity_set_kv_ref(char* l, char* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_set_kv_ref, l, e, + key, value, key_type); +} + +int layouts_entity_setpush_kv(char* l, char* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_setpush_kv, l, e, + key, value, key_type); +} + +int layouts_entity_setpush_kv_ref(char* l, char* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_setpush_kv_ref, l, e, + key, value, key_type); +} + +int layouts_entity_get_kv(char* l, char* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_get_kv, l, e, + key, value, key_type); +} + +int layouts_entity_get_mkv(char* l, char* e, char* keys, void* value, + size_t size, layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_get_mkv, l, e, + keys, value, size, key_type); +} + +int layouts_entity_get_kv_ref(char* l, char* e, char* key, void** value, + layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_get_kv_ref, l, e, + key, value, key_type); +} + +int layouts_entity_get_mkv_ref(char* l, char* e, char* keys, void* value, + size_t size, layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_get_mkv_ref, l, e, + keys, value, size, key_type); +} + +int layouts_entity_pullget_kv(char* l, char* e, char* key, void* value, + layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_pullget_kv, l, e, + key, value, key_type); +} + +int layouts_entity_pullget_kv_ref(char* l, char* e, char* key, void** value, + layouts_keydef_types_t key_type) +{ + _layouts_entity_wrapper(_layouts_entity_pullget_kv_ref, l, e, + key, value, key_type); +} diff --git a/src/common/layouts_mgr.h b/src/common/layouts_mgr.h index 357ab5f19bc032ceca31d9a58d81dad6a8c58418..51218c601fc680645014eabc9854a811d271af01 100644 --- a/src/common/layouts_mgr.h +++ b/src/common/layouts_mgr.h @@ -4,6 +4,7 @@ * Initially written by Francois Chevallier <chevallierfrancois@free.fr> * at Bull for slurm-2.6. * Adapted by Matthieu Hautreux <matthieu.hautreux@cea.fr> for slurm-14.11. + * Enhanced by Matthieu Hautreux <matthieu.hautreux@cea.fr> for slurm-15.x. * * This file is part of SLURM, a resource management program. * For details, see <http://slurm.schedmd.com/>. @@ -41,6 +42,7 @@ #include "src/common/list.h" #include "src/common/xhash.h" #include "src/common/xtree.h" +#include "src/common/pack.h" #include "src/common/parse_config.h" #include "src/common/layout.h" @@ -52,12 +54,12 @@ * The layouts_mgr_t manages the layouts and entities loaded through the list * of layouts specified in the Slurm configuration file (slurm.conf) * - * At startup, Slurm initialize one layouts_mgr_t using slurm_layouts_init() + * At startup, Slurm initialize one layouts_mgr_t using layouts_init() * and then load the required layouts defined in the configuration using - * slurm_layouts_load_config(). + * layouts_load_config(). * * The different layouts and entities can then be queried using either - * slurm_layouts_get_layout() and slurm_layouts_get_entity(). + * layouts_get_layout() and layouts_get_entity(). * * Note that each entity contains a list of nodes appearing inside the * associated layouts. @@ -82,9 +84,30 @@ typedef enum layouts_keydef_types_en { L_T_CUSTOM, } layouts_keydef_types_t; +/* keyspec flags */ +#define KEYSPEC_RDONLY 0x00000001 + +#define KEYSPEC_UPDATE_CHILDREN_SUM 0x00010000 +#define KEYSPEC_UPDATE_CHILDREN_AVG 0x00020000 +#define KEYSPEC_UPDATE_CHILDREN_MIN 0x00040000 +#define KEYSPEC_UPDATE_CHILDREN_MAX 0x00080000 +#define KEYSPEC_UPDATE_CHILDREN_COUNT 0x00110000 +#define KEYSPEC_UPDATE_CHILDREN_MASK 0x00FF0000 + +#define KEYSPEC_UPDATE_PARENTS_SUM 0x01000000 +#define KEYSPEC_UPDATE_PARENTS_AVG 0x02000000 +#define KEYSPEC_UPDATE_PARENTS_MIN 0x04000000 +#define KEYSPEC_UPDATE_PARENTS_MAX 0x08000000 +#define KEYSPEC_UPDATE_PARENTS_FSHARE 0x11000000 +#define KEYSPEC_UPDATE_PARENTS_MASK 0xFF000000 + typedef struct layouts_keyspec_st { char* key; layouts_keydef_types_t type; + uint32_t flags; + char* ref_key; /* reference key to use for update + * NULL means use the same key in my + * neighborhood */ void (*custom_destroy)(void*); char* (*custom_dump)(void*); } layouts_keyspec_t; @@ -95,6 +118,7 @@ typedef struct layouts_plugin_spec_st { int struct_type; const char** etypes; bool automerge; + bool autoupdate; } layouts_plugin_spec_t; /*****************************************************************************\ @@ -102,7 +126,7 @@ typedef struct layouts_plugin_spec_st { \*****************************************************************************/ /* - * slurm_layouts_init - intialize the layouts mgr, load the required plugins + * layouts_init - intialize the layouts mgr, load the required plugins * and initialize the internal hash tables for entities, keydefs and * layouts. * @@ -112,40 +136,362 @@ typedef struct layouts_plugin_spec_st { * Notes: this call do not try to read and parse the layouts configuration * files. It only loads the layouts plugins, dlsym the layout API and conf * elements to prepare the reading and parsing performed in the adhoc call - * slurm_layouts_load_config() + * layouts_load_config() * */ -int slurm_layouts_init(void); +int layouts_init(void); /* - * slurm_layouts_fini - uninitialize the layouts mgr and free the internal + * layouts_fini - uninitialize the layouts mgr and free the internal * hash tables. */ -int slurm_layouts_fini(void); +int layouts_fini(void); /* - * slurm_layouts_load_config - use the layouts plugins details loaded during - * slurm_layouts_init() and read+parse the different layouts + * layouts_load_config - use the layouts plugins details loaded during + * layouts_init() and read+parse the different layouts * configuration files, creating the entities and the relational * structures associated the eaf of them. * + * IN recover - update entities information with the latest available + * information depending upon value + * 0 = use no saved state information, rebuild everything from + * layouts conf files contents + * 1 = recover saved entities information + * 2 = recover saved entities information + * * Return SLURM_SUCCESS or SLURM_ERROR if all the required layouts were not * loaded correctly. */ -int slurm_layouts_load_config(void); +int layouts_load_config(int recover); /* - * slurm_layouts_get_layout - return the layout from a given type + * layouts_get_layout - return the layout from a given type * * Return a pointer to the layout_t struct of the layout or NULL if not found */ -layout_t* slurm_layouts_get_layout(const char* type); +layout_t* layouts_get_layout(const char* type); /* - * slurm_layouts_get_entity - return the entity from a given name + * layouts_get_entity - return the entity from a given name * * Return a pointer to the entity_t struct of the entity or NULL if not found */ -entity_t* slurm_layouts_get_entity(const char* name); +entity_t* layouts_get_entity(const char* name); + +/* + * layouts_pack_layout - pack the layout of the target type into the provided + * buffer. + * + * The buffer will be appended with multiple strings representing an expanded + * form of its configuration element, terminated by a "\0" string. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_pack_layout(char *l_type, Buf buffer); + +/* + * layouts_update_layout - update a particular layout loading the information + * provided in the input buffer. + * + * The buffer must contain multiple strings corresponding to the different + * configuration lines similar to those that can be put in a configuration + * file that will be parsed and integrated. + * + * Note that the entities key/value entries will be updated only. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_update_layout(char *l_type, Buf buffer); + +/* + * layouts_state_save_layout - save the state of a particular layout + * in the adhoc file in slurm state save location. + * + * The file produced will be an ASCII file created from the configuration + * strings packed using layouts_pack_layout(). Thus it will be the expanded + * form of the current configuration of the layout that could be used as + * a perfect updated replacement of the layout configuration file. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_state_save_layout(char* l_type); + +/* + * layouts_state_save - save the state of all the loaded layouts iterating + * over each one of them and applying layouts_state_save_layout(). + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_state_save(void); + +/* + * layouts_entity_get_kv_type - get the type of the value associated with a key + * of an entity in a particular layout. + * + * The returned type is a member of the layouts_keydef_types_t enum : + * L_T_ERROR, L_T_STRING, L_T_LONG, L_T_UINT16, ... + * + * Return the requested type or SLURM_ERROR in case of failure + */ +int layouts_entity_get_kv_type(char* layout, char* entity, + char* key); + +/* + * layouts_entity_get_kv_flags - get the keyspec flags associated with the + * targeted key/value pair of an entity in a particular layout. + * + * Return the associated flags or SLURM_ERROR in case of failure + */ +int layouts_entity_get_kv_flags(char* layout, char* entity, + char* key); + +/* + * layouts_entity_push_kv - update the layout internal states to take into + * account the current state of the targeted key/value pair. + * + * This ensures that the child and/or parents of the targeted entity in the + * targeted layout are synchronized with the current value associated with + * the key. + * + * Note: this call only makes sense when the targeted k/v is a k/v that helps + * to dynamically compute its parents and/or children. It is a + * no-op otherwise that just returns SLURM_SUCCESS. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_push_kv(char* layout, char* entity, + char* key); + +/* + * layouts_entity_pull_kv - synchronize the targeted key/value pair based on + * the states of their neighborhood in the targeted layout. + * + * This ensures that the K/V is up-to-date and correspond to the values that + * its neighborhood in the layout think it should have. + * + * Note: this call only makes sense when the targeted k/v is a k/v that is + * dynamically computed based on its parents and/or children. It is a + * no-op otherwise that just returns SLURM_SUCCESS. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_pull_kv(char* layout, char* entity, + char* key); + +/* + * layouts_entity_set_kv - update an entity with a new value for a particular + * key in the targeted layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. + * + * Note : in case the key/value is already set for the entity, the content of + * the provided buffer will override the current content. In case the key/value + * already exists, it will be xfree and a new memory allocation will be + * performed and the content of the provided buffer dumped into it. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_set_kv(char* layout, char* entity, + char* key, void* value, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_set_kv_ref - replace an entity key value with a new memory + * area for a particular key in the targeted layout + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. + * + * Note : in case the key/value is already set for the entity, the older value + * will be free and the provided buffer will be associated to the new value. + * Once done, the caller must not free the provided buffer has it will then + * be owned by the layout logic and will be free automatically when the layout + * framework will be unloaded or at a next call to that function. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_set_kv_ref(char* layout, char* entity, + char* key, void* value, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_setpush_kv - combination of layouts_entity_set_kv and + * layouts_entity_push_kv to update an entity with a new value and force + * the synchronization of its neighborhood in the layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. + * + * Note: see layouts_entity_push_kv. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_setpush_kv(char* layout, char* entity, + char* key, void* value, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_setpush_kv - combination of layouts_entity_set_kv_ref and + * layouts_entity_push_kv to replace an entity key value with a new + * memory area and force the synchronization of its neighborhood in + * the layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. + * + * Note: see layouts_entity_push_kv. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_setpush_kv_ref(char* layout, char* entity, + char* key, void* value, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_get_kv - get the value associated with a key of an entity + * in a particular layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. + * + * Note : the destination buffer will be filled with the content of the + * value associated with the requested key in the entity except for these + * types for which : + * L_T_STRING : value must be the address of the char* that will be + * xstrduped with the key value. The char* will have to be + * xfree() after that. + * L_T_CUSTOM : value must be the address of the char* that will result + * of the custom_dump function. The char* will have to be + * xfree() after that. + * L_T_ERROR : will return SLURM_ERROR in all cases. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_get_kv(char* layout, char* entity, + char* key, void* value, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_get_kv_ref - get a pointer to the value associated with a key + * of an entity in a particular layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. + * + * Note : this call must be used with caution as the pointer could be free + * sooner or later by the underlying layout engine in reply to the execution + * of the layouts_entity_set_kv_ref(). + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_get_kv_ref(char* layout, char* entity, + char* key, void** pvalue, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_pullget_kv - combination of layouts_entity_pull_kv and + * layouts_entity_get_kv to retrieve the up-to-date value of a particular + * entity key in the targeted layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. + * + * Note: see layouts_entity_pull_kv. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_pullget_kv(char* layout, char* entity, + char* key, void* value, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_pullget_kv - combination of layouts_entity_pull_kv_ref and + * layouts_entity_get_kv to retrieve a reference to the up-to-date value + * of a particular entity key in the targeted layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. + * + * Note: see layouts_entity_pull_kv_ref. + * + * Return SLURM_SUCCES or SLURM_ERROR in case of failure + */ +int layouts_entity_pullget_kv_ref(char* layout, char* entity, + char* key, void** value, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_get_mkv - get the values associated with a set of keys of an + * entity in a particular layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspec associated with the key. To skip + * that check the caller will have to pass a 0 value. This is mandatory for + * cases where the keyspecs of the requested keys do not share the same type. + * + * Note : the destination buffer will be sequentially filled with the content of + * the values associated with the requested keys in the entity. + * If the length of the buffer is too small, the remaining references will not + * be added and the counter of missed keys incremented as necessary. + * The first encountered error terminates the logic and the missing elements + * counter will reflect all the unprocessed elements including the faulty one. + + * Special care must be taken for the following types of key : + * L_T_STRING : a char* will be added to the buffer. It will be xstrduped + * with the associated key value. The char* will have to be + * xfree() after that. + * L_T_CUSTOM : a char* will be added to the buffer. It will be xstrduped + * with the result of the custom_dump function. It will have to + * be xfree() after that. + * L_T_ERROR : will generate an error that will force the function to return + * the count of missing elements (at least 1, depending on where + * this type first appeared in the ordered list of keys to get. + * + * Note: keys correspond to a list of keys that can be represented as + * an hostlist expression (i.e. keys[1-10]). + * + * Return SLURM_SUCCES or the count of missed keys/references + */ +int layouts_entity_get_mkv(char* layout, char* entity, + char* keys, void* value, size_t length, + layouts_keydef_types_t key_type); + +/* + * layouts_entity_get_mkv_ref - get a set of pointers to the values associated + * with a set of keys of an entity in a particular layout. + * + * The input key_type will force the call to check types consistency between + * the requester and the underlying keyspecs associated with the keys. To skip + * that check the caller will have to pass a 0 value. This is mandatory for cases + * where the keyspecs of the requested keys do not share the same type. + * + * The output buffer will be filled with the different references. + * If the length of the buffer is too small, the remaining references will not + * be added and the counter of missed keys incremented as necessary. + * The first encountered error terminates the logic and the missing elements + * counter will reflect all the unprocessed elements including the faulty one. + * + * Note: this call must be used with caution as the pointers could be free + * sooner or later by the underlying layout engine in reply to the execution + * of the layouts_entity_set_kv_ref(). + * + * Note: keys correspond to a list of keys that can be represented as + * an hostlist expression (i.e. keys[1-10]). + * + * Return SLURM_SUCCES or the count of missed keys/references + */ +int layouts_entity_get_mkv_ref(char* layout, char* entity, + char* keys, void* buffer, size_t length, + layouts_keydef_types_t key_type); #endif /* end of include guard: __LAYOUTS_MGR_1NRINRSD__INC__ */ diff --git a/src/common/parse_config.c b/src/common/parse_config.c index eec0cb1a4b23d9e84659789960b80cb30eff5e5f..5ca756d95fe59db0d30fb0e5a58a03948fac77c8 100644 --- a/src/common/parse_config.c +++ b/src/common/parse_config.c @@ -55,6 +55,7 @@ #include "src/common/hostlist.h" #include "src/common/log.h" #include "src/common/macros.h" +#include "src/common/pack.h" #include "src/common/parse_config.h" #include "src/common/parse_value.h" #include "src/common/read_config.h" @@ -67,6 +68,7 @@ strong_alias(s_p_hashtbl_create, slurm_s_p_hashtbl_create); strong_alias(s_p_hashtbl_destroy, slurm_s_p_hashtbl_destroy); +strong_alias(s_p_parse_buffer, slurm_s_p_parse_buffer); strong_alias(s_p_parse_file, slurm_s_p_parse_file); strong_alias(s_p_parse_pair, slurm_s_p_parse_pair); strong_alias(s_p_parse_line, slurm_s_p_parse_line); @@ -75,6 +77,9 @@ strong_alias(s_p_get_string, slurm_s_p_get_string); strong_alias(s_p_get_long, slurm_s_p_get_long); strong_alias(s_p_get_uint16, slurm_s_p_get_uint16); strong_alias(s_p_get_uint32, slurm_s_p_get_uint32); +strong_alias(s_p_get_float, slurm_s_p_get_float); +strong_alias(s_p_get_double, slurm_s_p_get_double); +strong_alias(s_p_get_long_double, slurm_s_p_get_long_double); strong_alias(s_p_get_pointer, slurm_s_p_get_pointer); strong_alias(s_p_get_array, slurm_s_p_get_array); strong_alias(s_p_get_boolean, slurm_s_p_get_boolean); @@ -88,8 +93,8 @@ strong_alias(transfer_s_p_options, slurm_transfer_s_p_options); static regex_t keyvalue_re; static char *keyvalue_pattern = "^[[:space:]]*" - "([[:alnum:]]+)" /* key */ - "[[:space:]]*=[[:space:]]*" + "([[:alnum:]_.]+)" /* key */ + "[[:space:]]*([-*+/]?)=[[:space:]]*" "((\"([^\"]*)\")|([^[:space:]]+))" /* value: quoted with whitespace, * or unquoted and no whitespace */ "([[:space:]]|$)"; @@ -98,6 +103,7 @@ static bool keyvalue_initialized = false; struct s_p_values { char *key; int type; + slurm_parser_operator_t operator; int data_count; void *data; int (*handler)(void **data, slurm_parser_enum_t type, @@ -172,6 +178,7 @@ s_p_hashtbl_t *s_p_hashtbl_create(const s_p_options_t options[]) for (op = options; op->key != NULL; op++) { value = xmalloc(sizeof(s_p_values_t)); value->key = xstrdup(op->key); + value->operator = S_P_OPERATOR_SET; value->type = op->type; value->data_count = 0; value->data = NULL; @@ -240,6 +247,7 @@ static void _conf_file_values_free(s_p_values_t *p) for (i = 0; i < p->data_count; ++i) { s_p_hashtbl_destroy(v->values[i]); } + xfree(v->values); xfree(p->data); break; default: @@ -292,14 +300,17 @@ static void _keyvalue_regex_init(void) * Return 0 when a key-value pair is found, and -1 otherwise. */ static int _keyvalue_regex(const char *line, - char **key, char **value, char **remaining) + char **key, char **value, char **remaining, + slurm_parser_operator_t *operator) { size_t nmatch = 8; regmatch_t pmatch[8]; + char op; *key = NULL; *value = NULL; *remaining = (char *)line; + *operator = S_P_OPERATOR_SET; memset(pmatch, 0, sizeof(regmatch_t)*nmatch); if (regexec(&keyvalue_re, line, nmatch, pmatch, 0) @@ -309,18 +320,30 @@ static int _keyvalue_regex(const char *line, *key = (char *)(xstrndup(line + pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so)); - - if (pmatch[4].rm_so != -1) { - *value = (char *)(xstrndup(line + pmatch[4].rm_so, - pmatch[4].rm_eo - pmatch[4].rm_so)); - } else if (pmatch[5].rm_so != -1) { + if (pmatch[2].rm_so != -1 && + (pmatch[2].rm_so != pmatch[2].rm_eo)) { + op = *(line + pmatch[2].rm_so); + if (op == '+') { + *operator = S_P_OPERATOR_ADD; + } else if (op == '-') { + *operator = S_P_OPERATOR_SUB; + } else if (op == '*') { + *operator = S_P_OPERATOR_MUL; + } else if (op == '/') { + *operator = S_P_OPERATOR_DIV; + } + } + if (pmatch[5].rm_so != -1) { *value = (char *)(xstrndup(line + pmatch[5].rm_so, pmatch[5].rm_eo - pmatch[5].rm_so)); + } else if (pmatch[6].rm_so != -1) { + *value = (char *)(xstrndup(line + pmatch[6].rm_so, + pmatch[6].rm_eo - pmatch[6].rm_so)); } else { *value = xstrdup(""); } - *remaining = (char *)(line + pmatch[2].rm_eo); + *remaining = (char *)(line + pmatch[3].rm_eo); return 0; } @@ -488,16 +511,16 @@ s_p_hashtbl_t* _hashtbl_copy_keys(const s_p_hashtbl_t* from_hashtbl, int len, i; xassert(from_hashtbl); - xassert(to_hashtbl); len = CONF_HASH_LEN * sizeof(s_p_values_t *); to_hashtbl = (s_p_hashtbl_t *)xmalloc(len); for (i = 0; i < CONF_HASH_LEN; ++i) { - for (val_ptr = from_hashtbl[i]; val_ptr; val_ptr = - val_ptr->next) { + for (val_ptr = from_hashtbl[i]; val_ptr; + val_ptr = val_ptr->next) { val_copy = xmalloc(sizeof(s_p_values_t)); val_copy->key = xstrdup(val_ptr->key); + val_copy->operator = val_ptr->operator; val_copy->type = val_ptr->type; val_copy->handler = val_ptr->handler; val_copy->destroy = val_ptr->destroy; @@ -584,6 +607,29 @@ static void* _handle_boolean(const char* key, const char* value) return data; } +static void* _handle_float(const char* key, const char* value) +{ + float* data = (float*)xmalloc(sizeof(float)); + if (s_p_handle_float(data, key, value) == SLURM_ERROR) + return NULL; + return data; +} + +static void* _handle_double(const char* key, const char* value) +{ + double* data = (double*)xmalloc(sizeof(double)); + if (s_p_handle_double(data, key, value) == SLURM_ERROR) + return NULL; + return data; +} + +static void* _handle_ldouble(const char* key, const char* value) +{ + long double* data = (long double*)xmalloc(sizeof(long double)); + if (s_p_handle_long_double(data, key, value) == SLURM_ERROR) + return NULL; + return data; +} static int _handle_pointer(s_p_values_t *v, const char *value, const char *line, char **leftover) @@ -679,6 +725,18 @@ static int _handle_expline_cmp_uint32(const void* v1, const void* v2) { return *((uint32_t*)v1) != *((uint32_t*)v2); } +static int _handle_expline_cmp_float(const void* v1, const void* v2) +{ + return *((float*)v1) != *((float*)v2); +} +static int _handle_expline_cmp_double(const void* v1, const void* v2) +{ + return *((double*)v1) != *((double*)v2); +} +static int _handle_expline_cmp_ldouble(const void* v1, const void* v2) +{ + return *((long double*)v1) != *((long double*)v2); +} /* ac = array case * the master key type is not string. Iterate over the tables looking @@ -752,6 +810,21 @@ static void _handle_expline_merge(_expline_values_t* v_data, _handle_expline_cmp_uint32, &v_data->values, tables_count); break; + case S_P_FLOAT: + _handle_expline_ac(current_tbl, master_key, matchp->data, + _handle_expline_cmp_float, &v_data->values, + tables_count); + break; + case S_P_DOUBLE: + _handle_expline_ac(current_tbl, master_key, matchp->data, + _handle_expline_cmp_double, &v_data->values, + tables_count); + break; + case S_P_LONG_DOUBLE: + _handle_expline_ac(current_tbl, master_key, matchp->data, + _handle_expline_cmp_ldouble, &v_data->values, + tables_count); + break; } } @@ -841,7 +914,15 @@ static void _handle_keyvalue_match(s_p_values_t *v, case S_P_EXPLINE: _handle_expline(v, value, line, leftover); break; - + case S_P_FLOAT: + _handle_common(v, value, line, leftover, _handle_float); + break; + case S_P_DOUBLE: + _handle_common(v, value, line, leftover, _handle_double); + break; + case S_P_LONG_DOUBLE: + _handle_common(v, value, line, leftover, _handle_ldouble); + break; } } @@ -876,11 +957,13 @@ int s_p_parse_line(s_p_hashtbl_t *hashtbl, const char *line, char **leftover) char *ptr = (char *)line; s_p_values_t *p; char *new_leftover; + slurm_parser_operator_t op; _keyvalue_regex_init(); - while (_keyvalue_regex(ptr, &key, &value, &new_leftover) == 0) { + while (_keyvalue_regex(ptr, &key, &value, &new_leftover, &op) == 0) { if ((p = _conf_hashtbl_lookup(hashtbl, key))) { + p->operator = op; _handle_keyvalue_match(p, value, new_leftover, &new_leftover); *leftover = ptr = new_leftover; @@ -907,11 +990,13 @@ static int _parse_next_key(s_p_hashtbl_t *hashtbl, char *key, *value; s_p_values_t *p; char *new_leftover; + slurm_parser_operator_t op; _keyvalue_regex_init(); - if (_keyvalue_regex(line, &key, &value, &new_leftover) == 0) { + if (_keyvalue_regex(line, &key, &value, &new_leftover, &op) == 0) { if ((p = _conf_hashtbl_lookup(hashtbl, key))) { + p->operator = op; _handle_keyvalue_match(p, value, new_leftover, &new_leftover); *leftover = new_leftover; @@ -1176,6 +1261,59 @@ int s_p_parse_file(s_p_hashtbl_t *hashtbl, uint32_t *hash_val, char *filename, return rc; } +int s_p_parse_buffer(s_p_hashtbl_t *hashtbl, uint32_t *hash_val, + Buf buffer, bool ignore_new) +{ + char *leftover = NULL; + int rc = SLURM_SUCCESS; + int line_number; + uint32_t utmp32; + char *tmp_str = NULL; + + if (!buffer) { + error("s_p_parse_buffer: No buffer given."); + return SLURM_ERROR; + } + + line_number = 0; + _keyvalue_regex_init(); + while (remaining_buf(buffer) > 0) { + safe_unpackstr_xmalloc(&tmp_str, &utmp32, buffer); + if (tmp_str != NULL) { + line_number++; + if (*tmp_str == '\0') { + xfree(tmp_str); + continue; + } + _parse_next_key(hashtbl, tmp_str, &leftover, ignore_new); + /* Make sure that after parsing only whitespace + is left over */ + if (!_line_is_space(leftover)) { + char *ptr = xstrdup(leftover); + _strip_cr_nl(ptr); + if (ignore_new) { + debug("s_p_parse_buffer : error in line" + " %d: \"%s\"", line_number, ptr); + } else { + error("s_p_parse_buffer : error in line" + " %d: \"%s\"", line_number, ptr); + rc = SLURM_ERROR; + } + xfree(ptr); + } + xfree(tmp_str); + if (rc == SLURM_SUCCESS) + continue; + } + unpack_error: + debug3("s_p_parse_buffer: ending after line %u", + line_number); + break; + } + + return rc; +} + /* * s_p_hashtbl_merge * @@ -1288,6 +1426,11 @@ void s_p_hashtbl_merge_keys(s_p_hashtbl_t *to_hashtbl, s_p_hashtbl_merge_keys( t_expline->template, f_expline->template); + /* Keys merged, free container memory */ + s_p_hashtbl_destroy(f_expline->template); + s_p_hashtbl_destroy(f_expline->index); + //FIXME: Destroy "values" ? + xfree(f_expline); } pp = &p->next; p = p->next; @@ -1368,6 +1511,7 @@ static s_p_hashtbl_t* _parse_expline_adapt_table(const s_p_hashtbl_t* hashtbl) for (val_ptr = hashtbl[i]; val_ptr; val_ptr = val_ptr->next) { val_copy = xmalloc(sizeof(s_p_values_t)); val_copy->key = xstrdup(val_ptr->key); + val_copy->operator = val_ptr->operator; if (val_ptr->type == S_P_PLAIN_STRING) { val_copy->type = S_P_STRING; } else { @@ -1467,17 +1611,26 @@ static int _parse_expline_doexpand(s_p_hashtbl_t** tables, for (i = 0; i < tables_count; ++i) { if (item_count > 0) { --item_count; - free(item_str); + if (item_str) + free(item_str); item_str = hostlist_shift(item_hl); } - if (!s_p_parse_pair(tables[i], item->key, item_str)) { + /* + * The destination tables are created without any info on the + * operator associated with the key in s_p_parse_line_expanded. + * So, parse the targeted pair injecting that information to + * push it into the destination table. + */ + if (!s_p_parse_pair_with_op(tables[i], item->key, item_str, + item->operator)) { error("Error parsing %s = %s.", item->key, item_str); free(item_str); return 0; } } - free(item_str); + if (item_str) + free(item_str); return 1; } @@ -1526,7 +1679,7 @@ int s_p_parse_line_expanded(const s_p_hashtbl_t *hashtbl, */ tables = (s_p_hashtbl_t**)xmalloc(tables_count * sizeof(s_p_hashtbl_t*)); - for (i = 0; i < tables_count; ++i) { + for (i = 0; i < tables_count; i++) { free(value_str); value_str = hostlist_shift(value_hl); tables[i] = _hashtbl_copy_keys(hashtbl, @@ -1564,9 +1717,10 @@ cleanup: if (strhashtbl) s_p_hashtbl_destroy(strhashtbl); - if (status == SLURM_ERROR) { - for (i = 0; i < tables_count; ++i) - s_p_hashtbl_destroy(tables[i]); + if (status == SLURM_ERROR && tables) { + for (i = 0; i < tables_count; i++) + if (tables[i]) + s_p_hashtbl_destroy(tables[i]); xfree(tables); } else { @@ -1578,16 +1732,24 @@ cleanup: /* * Returns 1 if the line is parsed cleanly, and 0 otherwise. + * Set the operator of the targeted s_p_values_t to the provided value. */ -int s_p_parse_pair(s_p_hashtbl_t *hashtbl, const char *key, const char *value) +int s_p_parse_pair_with_op(s_p_hashtbl_t *hashtbl, const char *key, + const char *value, slurm_parser_operator_t operator) { s_p_values_t *p; char *leftover, *v; if ((p = _conf_hashtbl_lookup(hashtbl, key)) == NULL) { - error("Parsing error at unrecognized key: %s", key); + error("%s: Parsing error at unrecognized key: %s", + __func__, key); + return 0; + } + if (!value) { + error("%s: Value pointer is NULL for key %s", __func__, key); return 0; } + p-> operator = operator; /* we have value separated from key here so parse it different way */ while (*value != '\0' && isspace(*value)) value++; /* skip spaces at start if any */ @@ -1614,6 +1776,14 @@ int s_p_parse_pair(s_p_hashtbl_t *hashtbl, const char *key, const char *value) return 1; } +/* + * Returns 1 if the line is parsed cleanly, and 0 otherwise. + */ +int s_p_parse_pair(s_p_hashtbl_t *hashtbl, const char *key, const char *value) +{ + return s_p_parse_pair_with_op(hashtbl, key, value, S_P_OPERATOR_SET); +} + /* common checks for s_p_get_* returns NULL if invalid. * * Information concerning theses function can be found in the header file. @@ -1689,6 +1859,21 @@ int s_p_get_uint32(uint32_t *num, const char *key, return 0; } +int s_p_get_operator(slurm_parser_operator_t *operator, const char *key, + const s_p_hashtbl_t *hashtbl) +{ + s_p_values_t *p; + if (!hashtbl) + return 0; + p = _conf_hashtbl_lookup(hashtbl, key); + if (p) { + *operator = p->operator; + return 1; + } + error("Invalid key \"%s\"", key); + return 0; +} + int s_p_get_pointer(void **ptr, const char *key, const s_p_hashtbl_t *hashtbl) { s_p_values_t *p = _get_check(S_P_POINTER, key, hashtbl); @@ -1756,6 +1941,44 @@ int s_p_get_boolean(bool *flag, const char *key, const s_p_hashtbl_t *hashtbl) return 0; } +int s_p_get_float(float *num, const char *key, + const s_p_hashtbl_t *hashtbl) +{ + s_p_values_t *p = _get_check(S_P_FLOAT, key, hashtbl); + + if (p) { + *num = *(float *)p->data; + return 1; + } + + return 0; +} + +int s_p_get_double(double *num, const char *key, + const s_p_hashtbl_t *hashtbl) +{ + s_p_values_t *p = _get_check(S_P_DOUBLE, key, hashtbl); + + if (p) { + *num = *(double *)p->data; + return 1; + } + + return 0; +} + +int s_p_get_long_double(long double *num, const char *key, + const s_p_hashtbl_t *hashtbl) +{ + s_p_values_t *p = _get_check(S_P_LONG_DOUBLE, key, hashtbl); + + if (p) { + *num = *(long double *)p->data; + return 1; + } + + return 0; +} /* * Given an "options" array, print the current values of all @@ -1770,6 +1993,9 @@ void s_p_dump_values(const s_p_hashtbl_t *hashtbl, long num; uint16_t num16; uint32_t num32; + float numf; + double numd; + long double numld; char *str; void *ptr; void **ptr_array; @@ -1843,6 +2069,24 @@ void s_p_dump_values(const s_p_hashtbl_t *hashtbl, verbose("%s", op->key); } break; + case S_P_FLOAT: + if (s_p_get_float(&numf, op->key, hashtbl)) + verbose("%s = %f", op->key, numf); + else + verbose("%s", op->key); + break; + case S_P_DOUBLE: + if (s_p_get_double(&numd, op->key, hashtbl)) + verbose("%s = %f", op->key, numd); + else + verbose("%s", op->key); + break; + case S_P_LONG_DOUBLE: + if (s_p_get_long_double(&numld, op->key, hashtbl)) + verbose("%s = %Lf", op->key, numld); + else + verbose("%s", op->key); + break; case S_P_IGNORE: break; } diff --git a/src/common/parse_config.h b/src/common/parse_config.h index 39e9888164be4885b331774f867469fcc1bed32b..b0900c53d80e58e60bc953b0f4bb4cee75e029c7 100644 --- a/src/common/parse_config.h +++ b/src/common/parse_config.h @@ -45,6 +45,7 @@ #include <stdint.h> #include "slurm/slurm.h" +#include "src/common/pack.h" /* * This slurm file parser provides a method for parsing a file @@ -253,9 +254,38 @@ typedef enum slurm_parser_enum { S_P_BOOLEAN, S_P_LINE, S_P_EXPLINE, - S_P_PLAIN_STRING /* useful only within S_P_EXPLINE */ + S_P_PLAIN_STRING /* useful only within S_P_EXPLINE */, + S_P_FLOAT, + S_P_DOUBLE, + S_P_LONG_DOUBLE + } slurm_parser_enum_t; +/* + * Standard Slurm conf files use key=value elements. + * slurm_parser_operator_t extends that concept to cover additionnal + * use cases like : + * key+=value + * key-=value + * key*=value + * key/=value + * + * this feature is for now dedicated to the layouts framework. It enables + * to have advanced modifications of entities reusing the traditional + * Slurm parser with the new operator information to manage updates. + * + */ +typedef enum slurm_parser_operator { + S_P_OPERATOR_SET = 0, + S_P_OPERATOR_ADD, + S_P_OPERATOR_SUB, + S_P_OPERATOR_MUL, + S_P_OPERATOR_DIV, + S_P_OPERATOR_SET_IF_MIN, + S_P_OPERATOR_SET_IF_MAX, + S_P_OPERATOR_AVG +} slurm_parser_operator_t; + typedef struct conf_file_options { char *key; slurm_parser_enum_t type; @@ -279,11 +309,29 @@ void s_p_hashtbl_destroy(s_p_hashtbl_t *hashtbl); int s_p_parse_file(s_p_hashtbl_t *hashtbl, uint32_t *hash_val, char *filename, bool ignore_new); +/* Returns SLURM_SUCCESS if buffer was opened and parse correctly. + * buffer must be a valid Buf bufferonly containing strings.The parsing + * stops at the first non string content extracted. + * OUT hash_val - cyclic redundancy check (CRC) character-wise value + * of file. + * IN ignore_new - do not treat unrecognized keywords as a fatal error, + * print debug() message and continue + */ +int s_p_parse_buffer(s_p_hashtbl_t *hashtbl, uint32_t *hash_val, + Buf buffer, bool ignore_new); + /* * Returns 1 if the line is parsed cleanly, and 0 otherwise. */ int s_p_parse_pair(s_p_hashtbl_t *hashtbl, const char *key, const char *value); +/* + * Returns 1 if the line is parsed cleanly, and 0 otherwise. + * Set the operator of the updated s_p_values_t to the provided one. + */ +int s_p_parse_pair_with_op(s_p_hashtbl_t *hashtbl, const char *key, + const char *value, slurm_parser_operator_t operator); + /* * Returns 1 if the line is parsed cleanly, and 0 otherwise. */ @@ -416,6 +464,75 @@ int s_p_get_uint16(uint16_t *num, const char *key, int s_p_get_uint32(uint32_t *num, const char *key, const s_p_hashtbl_t *hashtbl); +/* + * s_p_get_float + * + * Search for a key in a s_p_hashtbl_t with value of type + * float. If the key is found and has a set value, the + * value is retuned in "num". + * + * OUT num - pointer to a float where the value is returned + * IN key - hash table key + * IN hashtbl - hash table created by s_p_hashtbl_create() + * + * Returns 1 when a value was set for "key" during parsing and "num" + * was successfully set, otherwise returns 0; + */ +int s_p_get_float(float *num, const char *key, + const s_p_hashtbl_t *hashtbl); + +/* + * s_p_get_double + * + * Search for a key in a s_p_hashtbl_t with value of type + * double. If the key is found and has a set value, the + * value is retuned in "num". + * + * OUT num - pointer to a double where the value is returned + * IN key - hash table key + * IN hashtbl - hash table created by s_p_hashtbl_create() + * + * Returns 1 when a value was set for "key" during parsing and "num" + * was successfully set, otherwise returns 0; + */ +int s_p_get_double(double *num, const char *key, + const s_p_hashtbl_t *hashtbl); + +/* + * s_p_get_long_double + * + * Search for a key in a s_p_hashtbl_t with value of type + * long double. If the key is found and has a set value, the + * value is retuned in "num". + * + * OUT num - pointer to a long double where the value is returned + * IN key - hash table key + * IN hashtbl - hash table created by s_p_hashtbl_create() + * + * Returns 1 when a value was set for "key" during parsing and "num" + * was successfully set, otherwise returns 0; + */ +int s_p_get_long_double(long double *num, const char *key, + const s_p_hashtbl_t *hashtbl); + +/* + * s_p_get_operator + * + * Search for a key in a s_p_hashtbl_t and return the operator + * associated with that key in the configuration file. The operator + * is one of the slurm_parser_operator_t enum possible values. + * + * OUT operator - pointer to a slurm_parser_operator_t where the + * operator is returned + * IN key - hash table key + * IN hashtbl - hash table created by s_p_hashtbl_create() + * + * Returns 1 when a operator was set for "key" during parsing and + * "operator" was successfully set, otherwise returns 0; + */ +int s_p_get_operator(slurm_parser_operator_t *operator, const char *key, + const s_p_hashtbl_t *hashtbl); + /* * s_p_get_pointer * diff --git a/src/common/parse_value.c b/src/common/parse_value.c index 4243af2b324037156bd7bbd3e94902cef9c41f4c..5e1e1ed4eedb2e1c691e4c7892f5d5f06bc4ded7 100644 --- a/src/common/parse_value.c +++ b/src/common/parse_value.c @@ -157,11 +157,13 @@ int s_p_handle_boolean(bool* data, const char* key, const char* value) if (!strcasecmp(value, "yes") || !strcasecmp(value, "up") + || !strcasecmp(value, "true") || !strcasecmp(value, "1")) { flag = true; } else if (!strcasecmp(value, "no") - || !strcasecmp(value, "down") - || !strcasecmp(value, "0")) { + || !strcasecmp(value, "down") + || !strcasecmp(value, "false") + || !strcasecmp(value, "0")) { flag = false; } else { error("\"%s\" is not a valid option for \"%s\"", @@ -223,7 +225,8 @@ int s_p_handle_double(double* data, const char* key, const char* value) return SLURM_SUCCESS; } -int s_p_handle_ldouble(long double* data, const char* key, const char* value) +int s_p_handle_long_double(long double* data, const char* key, + const char* value) { char *endptr; long double num; diff --git a/src/common/parse_value.h b/src/common/parse_value.h index b7dc223e02f7d297fa82ed16a8b250edae1c7f75..5326a9c2400a940f9e6cf1f17c5106215d706bca 100644 --- a/src/common/parse_value.h +++ b/src/common/parse_value.h @@ -49,6 +49,7 @@ int s_p_handle_uint32(uint32_t* data, const char* key, const char* value); int s_p_handle_boolean(bool* data, const char* key, const char* value); int s_p_handle_float(float* data, const char* key, const char* value); int s_p_handle_double(double* data, const char* key, const char* value); -int s_p_handle_ldouble(long double* data, const char* key, const char* value); +int s_p_handle_long_double(long double* data, const char* key, + const char* value); #endif /* !_PARSE_VALUE_H */ diff --git a/src/layouts/Makefile.am b/src/layouts/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..54f8ba015f63a6bef632339d13bce850f687ee65 --- /dev/null +++ b/src/layouts/Makefile.am @@ -0,0 +1,4 @@ +# Makefile for layouts plugins + +SUBDIRS = unit +#basic racking energy power topology diff --git a/src/layouts/Makefile.in b/src/layouts/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..2aa360e1231cbcebabf72b2b2a6f926da58b5694 --- /dev/null +++ b/src/layouts/Makefile.in @@ -0,0 +1,771 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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 layouts plugins +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@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@ +subdir = src/layouts +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/auxdir/ax_lib_hdf5.m4 \ + $(top_srcdir)/auxdir/ax_pthread.m4 \ + $(top_srcdir)/auxdir/libtool.m4 \ + $(top_srcdir)/auxdir/ltoptions.m4 \ + $(top_srcdir)/auxdir/ltsugar.m4 \ + $(top_srcdir)/auxdir/ltversion.m4 \ + $(top_srcdir)/auxdir/lt~obsolete.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_blcr.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_dlfcn.m4 \ + $(top_srcdir)/auxdir/x_ac_env.m4 \ + $(top_srcdir)/auxdir/x_ac_freeipmi.m4 \ + $(top_srcdir)/auxdir/x_ac_gpl_licensed.m4 \ + $(top_srcdir)/auxdir/x_ac_hwloc.m4 \ + $(top_srcdir)/auxdir/x_ac_iso.m4 \ + $(top_srcdir)/auxdir/x_ac_json.m4 \ + $(top_srcdir)/auxdir/x_ac_lua.m4 \ + $(top_srcdir)/auxdir/x_ac_man2html.m4 \ + $(top_srcdir)/auxdir/x_ac_munge.m4 \ + $(top_srcdir)/auxdir/x_ac_ncurses.m4 \ + $(top_srcdir)/auxdir/x_ac_netloc.m4 \ + $(top_srcdir)/auxdir/x_ac_nrt.m4 \ + $(top_srcdir)/auxdir/x_ac_ofed.m4 \ + $(top_srcdir)/auxdir/x_ac_pam.m4 \ + $(top_srcdir)/auxdir/x_ac_printf_null.m4 \ + $(top_srcdir)/auxdir/x_ac_ptrace.m4 \ + $(top_srcdir)/auxdir/x_ac_readline.m4 \ + $(top_srcdir)/auxdir/x_ac_rrdtool.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)/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 = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTHD_CFLAGS = @AUTHD_CFLAGS@ +AUTHD_LIBS = @AUTHD_LIBS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BGL_LOADED = @BGL_LOADED@ +BGQ_LOADED = @BGQ_LOADED@ +BG_INCLUDES = @BG_INCLUDES@ +BG_LDFLAGS = @BG_LDFLAGS@ +BG_L_P_LOADED = @BG_L_P_LOADED@ +BLCR_CPPFLAGS = @BLCR_CPPFLAGS@ +BLCR_HOME = @BLCR_HOME@ +BLCR_LDFLAGS = @BLCR_LDFLAGS@ +BLCR_LIBS = @BLCR_LIBS@ +BLUEGENE_LOADED = @BLUEGENE_LOADED@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CMD_LDFLAGS = @CMD_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRAY_JOB_CPPFLAGS = @CRAY_JOB_CPPFLAGS@ +CRAY_JOB_LDFLAGS = @CRAY_JOB_LDFLAGS@ +CRAY_SELECT_CPPFLAGS = @CRAY_SELECT_CPPFLAGS@ +CRAY_SELECT_LDFLAGS = @CRAY_SELECT_LDFLAGS@ +CRAY_SWITCH_CPPFLAGS = @CRAY_SWITCH_CPPFLAGS@ +CRAY_SWITCH_LDFLAGS = @CRAY_SWITCH_LDFLAGS@ +CRAY_TASK_CPPFLAGS = @CRAY_TASK_CPPFLAGS@ +CRAY_TASK_LDFLAGS = @CRAY_TASK_LDFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FREEIPMI_CPPFLAGS = @FREEIPMI_CPPFLAGS@ +FREEIPMI_LDFLAGS = @FREEIPMI_LDFLAGS@ +FREEIPMI_LIBS = @FREEIPMI_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +H5CC = @H5CC@ +H5FC = @H5FC@ +HAVEMYSQLCONFIG = @HAVEMYSQLCONFIG@ +HAVE_AIX = @HAVE_AIX@ +HAVE_MAN2HTML = @HAVE_MAN2HTML@ +HAVE_NRT = @HAVE_NRT@ +HAVE_OPENSSL = @HAVE_OPENSSL@ +HAVE_SOME_CURSES = @HAVE_SOME_CURSES@ +HDF5_CC = @HDF5_CC@ +HDF5_CFLAGS = @HDF5_CFLAGS@ +HDF5_CPPFLAGS = @HDF5_CPPFLAGS@ +HDF5_FC = @HDF5_FC@ +HDF5_FFLAGS = @HDF5_FFLAGS@ +HDF5_FLIBS = @HDF5_FLIBS@ +HDF5_LDFLAGS = @HDF5_LDFLAGS@ +HDF5_LIBS = @HDF5_LIBS@ +HDF5_VERSION = @HDF5_VERSION@ +HWLOC_CPPFLAGS = @HWLOC_CPPFLAGS@ +HWLOC_LDFLAGS = @HWLOC_LDFLAGS@ +HWLOC_LIBS = @HWLOC_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JSON_CPPFLAGS = @JSON_CPPFLAGS@ +JSON_LDFLAGS = @JSON_LDFLAGS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_LDFLAGS = @LIB_LDFLAGS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MUNGE_CPPFLAGS = @MUNGE_CPPFLAGS@ +MUNGE_DIR = @MUNGE_DIR@ +MUNGE_LDFLAGS = @MUNGE_LDFLAGS@ +MUNGE_LIBS = @MUNGE_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NCURSES = @NCURSES@ +NETLOC_CPPFLAGS = @NETLOC_CPPFLAGS@ +NETLOC_LDFLAGS = @NETLOC_LDFLAGS@ +NETLOC_LIBS = @NETLOC_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NRT_CPPFLAGS = @NRT_CPPFLAGS@ +NUMA_LIBS = @NUMA_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OFED_CPPFLAGS = @OFED_CPPFLAGS@ +OFED_LDFLAGS = @OFED_LDFLAGS@ +OFED_LIBS = @OFED_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAM_DIR = @PAM_DIR@ +PAM_LIBS = @PAM_LIBS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROCTRACKDIR = @PROCTRACKDIR@ +PROJECT = @PROJECT@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +REAL_BGQ_LOADED = @REAL_BGQ_LOADED@ +REAL_BG_L_P_LOADED = @REAL_BG_L_P_LOADED@ +RELEASE = @RELEASE@ +RRDTOOL_CPPFLAGS = @RRDTOOL_CPPFLAGS@ +RRDTOOL_LDFLAGS = @RRDTOOL_LDFLAGS@ +RRDTOOL_LIBS = @RRDTOOL_LIBS@ +RUNJOB_LDFLAGS = @RUNJOB_LDFLAGS@ +SED = @SED@ +SEMAPHORE_LIBS = @SEMAPHORE_LIBS@ +SEMAPHORE_SOURCES = @SEMAPHORE_SOURCES@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SLURMCTLD_PORT = @SLURMCTLD_PORT@ +SLURMCTLD_PORT_COUNT = @SLURMCTLD_PORT_COUNT@ +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_NUMBER = @SLURM_VERSION_NUMBER@ +SLURM_VERSION_STRING = @SLURM_VERSION_STRING@ +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_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_have_man2html = @ac_have_man2html@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +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@ +lua_CFLAGS = @lua_CFLAGS@ +lua_LIBS = @lua_LIBS@ +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_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = unit +all: all-recursive + +.SUFFIXES: +$(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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/layouts/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/layouts/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 +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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 "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am 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 \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +#basic racking energy power topology + +# 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/layouts/unit/Makefile.am b/src/layouts/unit/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..ac5f50cc99c273e6cefe1072e98039f8461ea6d5 --- /dev/null +++ b/src/layouts/unit/Makefile.am @@ -0,0 +1,10 @@ +AUTOMAKE_OPTIONS = foreign + +PLUGIN_FLAGS = -module -avoid-version --export-dynamic + +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/src/common + +pkglib_LTLIBRARIES = layouts_unit_default.la + +layouts_unit_default_la_SOURCES = default.c +layouts_unit_default_la_LDFLAGS = $(SO_LDFLAGS) $(PLUGIN_FLAGS) diff --git a/src/layouts/unit/Makefile.in b/src/layouts/unit/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..0afc10b4231445decb314a2ccc537d0f32670e3c --- /dev/null +++ b/src/layouts/unit/Makefile.in @@ -0,0 +1,801 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@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@ +subdir = src/layouts/unit +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/auxdir/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/auxdir/ax_lib_hdf5.m4 \ + $(top_srcdir)/auxdir/ax_pthread.m4 \ + $(top_srcdir)/auxdir/libtool.m4 \ + $(top_srcdir)/auxdir/ltoptions.m4 \ + $(top_srcdir)/auxdir/ltsugar.m4 \ + $(top_srcdir)/auxdir/ltversion.m4 \ + $(top_srcdir)/auxdir/lt~obsolete.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_blcr.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_dlfcn.m4 \ + $(top_srcdir)/auxdir/x_ac_env.m4 \ + $(top_srcdir)/auxdir/x_ac_freeipmi.m4 \ + $(top_srcdir)/auxdir/x_ac_gpl_licensed.m4 \ + $(top_srcdir)/auxdir/x_ac_hwloc.m4 \ + $(top_srcdir)/auxdir/x_ac_iso.m4 \ + $(top_srcdir)/auxdir/x_ac_json.m4 \ + $(top_srcdir)/auxdir/x_ac_lua.m4 \ + $(top_srcdir)/auxdir/x_ac_man2html.m4 \ + $(top_srcdir)/auxdir/x_ac_munge.m4 \ + $(top_srcdir)/auxdir/x_ac_ncurses.m4 \ + $(top_srcdir)/auxdir/x_ac_netloc.m4 \ + $(top_srcdir)/auxdir/x_ac_nrt.m4 \ + $(top_srcdir)/auxdir/x_ac_ofed.m4 \ + $(top_srcdir)/auxdir/x_ac_pam.m4 \ + $(top_srcdir)/auxdir/x_ac_printf_null.m4 \ + $(top_srcdir)/auxdir/x_ac_ptrace.m4 \ + $(top_srcdir)/auxdir/x_ac_readline.m4 \ + $(top_srcdir)/auxdir/x_ac_rrdtool.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)/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 = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +layouts_unit_default_la_LIBADD = +am_layouts_unit_default_la_OBJECTS = default.lo +layouts_unit_default_la_OBJECTS = \ + $(am_layouts_unit_default_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +layouts_unit_default_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(layouts_unit_default_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/slurm +depcomp = $(SHELL) $(top_srcdir)/auxdir/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(layouts_unit_default_la_SOURCES) +DIST_SOURCES = $(layouts_unit_default_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTHD_CFLAGS = @AUTHD_CFLAGS@ +AUTHD_LIBS = @AUTHD_LIBS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BGL_LOADED = @BGL_LOADED@ +BGQ_LOADED = @BGQ_LOADED@ +BG_INCLUDES = @BG_INCLUDES@ +BG_LDFLAGS = @BG_LDFLAGS@ +BG_L_P_LOADED = @BG_L_P_LOADED@ +BLCR_CPPFLAGS = @BLCR_CPPFLAGS@ +BLCR_HOME = @BLCR_HOME@ +BLCR_LDFLAGS = @BLCR_LDFLAGS@ +BLCR_LIBS = @BLCR_LIBS@ +BLUEGENE_LOADED = @BLUEGENE_LOADED@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CMD_LDFLAGS = @CMD_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRAY_JOB_CPPFLAGS = @CRAY_JOB_CPPFLAGS@ +CRAY_JOB_LDFLAGS = @CRAY_JOB_LDFLAGS@ +CRAY_SELECT_CPPFLAGS = @CRAY_SELECT_CPPFLAGS@ +CRAY_SELECT_LDFLAGS = @CRAY_SELECT_LDFLAGS@ +CRAY_SWITCH_CPPFLAGS = @CRAY_SWITCH_CPPFLAGS@ +CRAY_SWITCH_LDFLAGS = @CRAY_SWITCH_LDFLAGS@ +CRAY_TASK_CPPFLAGS = @CRAY_TASK_CPPFLAGS@ +CRAY_TASK_LDFLAGS = @CRAY_TASK_LDFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FREEIPMI_CPPFLAGS = @FREEIPMI_CPPFLAGS@ +FREEIPMI_LDFLAGS = @FREEIPMI_LDFLAGS@ +FREEIPMI_LIBS = @FREEIPMI_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +H5CC = @H5CC@ +H5FC = @H5FC@ +HAVEMYSQLCONFIG = @HAVEMYSQLCONFIG@ +HAVE_AIX = @HAVE_AIX@ +HAVE_MAN2HTML = @HAVE_MAN2HTML@ +HAVE_NRT = @HAVE_NRT@ +HAVE_OPENSSL = @HAVE_OPENSSL@ +HAVE_SOME_CURSES = @HAVE_SOME_CURSES@ +HDF5_CC = @HDF5_CC@ +HDF5_CFLAGS = @HDF5_CFLAGS@ +HDF5_CPPFLAGS = @HDF5_CPPFLAGS@ +HDF5_FC = @HDF5_FC@ +HDF5_FFLAGS = @HDF5_FFLAGS@ +HDF5_FLIBS = @HDF5_FLIBS@ +HDF5_LDFLAGS = @HDF5_LDFLAGS@ +HDF5_LIBS = @HDF5_LIBS@ +HDF5_VERSION = @HDF5_VERSION@ +HWLOC_CPPFLAGS = @HWLOC_CPPFLAGS@ +HWLOC_LDFLAGS = @HWLOC_LDFLAGS@ +HWLOC_LIBS = @HWLOC_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JSON_CPPFLAGS = @JSON_CPPFLAGS@ +JSON_LDFLAGS = @JSON_LDFLAGS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_LDFLAGS = @LIB_LDFLAGS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MUNGE_CPPFLAGS = @MUNGE_CPPFLAGS@ +MUNGE_DIR = @MUNGE_DIR@ +MUNGE_LDFLAGS = @MUNGE_LDFLAGS@ +MUNGE_LIBS = @MUNGE_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NCURSES = @NCURSES@ +NETLOC_CPPFLAGS = @NETLOC_CPPFLAGS@ +NETLOC_LDFLAGS = @NETLOC_LDFLAGS@ +NETLOC_LIBS = @NETLOC_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NRT_CPPFLAGS = @NRT_CPPFLAGS@ +NUMA_LIBS = @NUMA_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OFED_CPPFLAGS = @OFED_CPPFLAGS@ +OFED_LDFLAGS = @OFED_LDFLAGS@ +OFED_LIBS = @OFED_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAM_DIR = @PAM_DIR@ +PAM_LIBS = @PAM_LIBS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROCTRACKDIR = @PROCTRACKDIR@ +PROJECT = @PROJECT@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +REAL_BGQ_LOADED = @REAL_BGQ_LOADED@ +REAL_BG_L_P_LOADED = @REAL_BG_L_P_LOADED@ +RELEASE = @RELEASE@ +RRDTOOL_CPPFLAGS = @RRDTOOL_CPPFLAGS@ +RRDTOOL_LDFLAGS = @RRDTOOL_LDFLAGS@ +RRDTOOL_LIBS = @RRDTOOL_LIBS@ +RUNJOB_LDFLAGS = @RUNJOB_LDFLAGS@ +SED = @SED@ +SEMAPHORE_LIBS = @SEMAPHORE_LIBS@ +SEMAPHORE_SOURCES = @SEMAPHORE_SOURCES@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SLURMCTLD_PORT = @SLURMCTLD_PORT@ +SLURMCTLD_PORT_COUNT = @SLURMCTLD_PORT_COUNT@ +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_NUMBER = @SLURM_VERSION_NUMBER@ +SLURM_VERSION_STRING = @SLURM_VERSION_STRING@ +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_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_have_man2html = @ac_have_man2html@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +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@ +lua_CFLAGS = @lua_CFLAGS@ +lua_LIBS = @lua_LIBS@ +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_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +PLUGIN_FLAGS = -module -avoid-version --export-dynamic +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/src/common +pkglib_LTLIBRARIES = layouts_unit_default.la +layouts_unit_default_la_SOURCES = default.c +layouts_unit_default_la_LDFLAGS = $(SO_LDFLAGS) $(PLUGIN_FLAGS) +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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/layouts/unit/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/layouts/unit/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 +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +layouts_unit_default.la: $(layouts_unit_default_la_OBJECTS) $(layouts_unit_default_la_DEPENDENCIES) $(EXTRA_layouts_unit_default_la_DEPENDENCIES) + $(AM_V_CCLD)$(layouts_unit_default_la_LINK) -rpath $(pkglibdir) $(layouts_unit_default_la_OBJECTS) $(layouts_unit_default_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/default.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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 "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$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 $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; 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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-generic clean-libtool clean-pkglibLTLIBRARIES \ + 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 + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +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-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-pkglibLTLIBRARIES 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 tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + + +# 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/layouts/unit/default.c b/src/layouts/unit/default.c new file mode 100644 index 0000000000000000000000000000000000000000..e88c733e57b078489fb4f09ef4dc2b85077453dd --- /dev/null +++ b/src/layouts/unit/default.c @@ -0,0 +1,225 @@ +/** TODO: copyright notice */ + +#include "slurm/slurm.h" + +#include "src/common/layouts_mgr.h" +#include "src/common/entity.h" +#include "src/common/log.h" + +const char plugin_name[] = "Unit Tests layouts plugin"; +const char plugin_type[] = "layouts/unit"; +const uint32_t plugin_version = SLURM_VERSION_NUMBER; + +/* specific options for unit tests layout */ +s_p_options_t entity_options[] = { + /* base keys */ + {"string", S_P_STRING}, + {"long", S_P_LONG}, + {"uint16", S_P_UINT16}, + {"uint32", S_P_UINT32}, + {"float", S_P_FLOAT}, + {"double", S_P_DOUBLE}, + {"ldouble", S_P_LONG_DOUBLE}, + {"readonly", S_P_BOOLEAN}, + /* parents aggregated keys */ + {"parents_sum_long", S_P_LONG}, + {"parents_fshare_long", S_P_LONG}, + {"parents_sum_uint16", S_P_UINT16}, + {"parents_fshare_uint16", S_P_UINT16}, + {"parents_sum_uint32", S_P_UINT32}, + {"parents_fshare_uint32", S_P_UINT32}, + {"parents_sum_float", S_P_FLOAT}, + {"parents_fshare_float", S_P_FLOAT}, + {"parents_sum_double", S_P_DOUBLE}, + {"parents_fshare_double", S_P_DOUBLE}, + {"parents_sum_ldouble", S_P_LONG_DOUBLE}, + {"parents_fshare_ldouble", S_P_LONG_DOUBLE}, + /* children aggregated keys */ + {"children_count", S_P_UINT32}, + {"children_sum_long", S_P_LONG}, + {"children_avg_long", S_P_LONG}, + {"children_min_long", S_P_LONG}, + {"children_max_long", S_P_LONG}, + {"children_sum_uint16", S_P_UINT16}, + {"children_avg_uint16", S_P_UINT16}, + {"children_min_uint16", S_P_UINT16}, + {"children_max_uint16", S_P_UINT16}, + {"children_sum_uint32", S_P_UINT32}, + {"children_avg_uint32", S_P_UINT32}, + {"children_min_uint32", S_P_UINT32}, + {"children_max_uint32", S_P_UINT32}, + {"children_sum_float", S_P_FLOAT}, + {"children_avg_float", S_P_FLOAT}, + {"children_min_float", S_P_FLOAT}, + {"children_max_float", S_P_FLOAT}, + {"children_sum_double", S_P_DOUBLE}, + {"children_avg_double", S_P_DOUBLE}, + {"children_min_double", S_P_DOUBLE}, + {"children_max_double", S_P_DOUBLE}, + {"children_sum_ldouble", S_P_LONG_DOUBLE}, + {"children_avg_ldouble", S_P_LONG_DOUBLE}, + {"children_min_ldouble", S_P_LONG_DOUBLE}, + {"children_max_ldouble", S_P_LONG_DOUBLE}, + {NULL} +}; +s_p_options_t options[] = { + {"Entity", S_P_EXPLINE, NULL, NULL, entity_options}, + {NULL} +}; + +const layouts_keyspec_t keyspec[] = { + /* base keys */ + {"string", L_T_STRING}, + {"long", L_T_LONG}, + {"uint16", L_T_UINT16}, + {"uint32", L_T_UINT32}, + {"float", L_T_FLOAT}, + {"double", L_T_DOUBLE}, + {"ldouble", L_T_LONG_DOUBLE}, + {"readonly", L_T_BOOLEAN, KEYSPEC_RDONLY}, + /* parents aggregated keys */ + {"parents_sum_long", L_T_LONG, + KEYSPEC_UPDATE_PARENTS_SUM, "long"}, + {"parents_fshare_long", L_T_LONG, + KEYSPEC_UPDATE_PARENTS_FSHARE, "long"}, + {"parents_sum_uint16", L_T_UINT16, + KEYSPEC_UPDATE_PARENTS_SUM, "uint16"}, + {"parents_fshare_uint16", L_T_UINT16, + KEYSPEC_UPDATE_PARENTS_FSHARE, "uint16"}, + {"parents_sum_uint32", L_T_UINT32, + KEYSPEC_UPDATE_PARENTS_SUM, "uint32"}, + {"parents_fshare_uint32", L_T_UINT32, + KEYSPEC_UPDATE_PARENTS_FSHARE, "uint32"}, + {"parents_sum_float", L_T_FLOAT, + KEYSPEC_UPDATE_PARENTS_SUM, "float"}, + {"parents_fshare_float", L_T_FLOAT, + KEYSPEC_UPDATE_PARENTS_FSHARE, "float"}, + {"parents_sum_double", L_T_DOUBLE, + KEYSPEC_UPDATE_PARENTS_SUM, "double"}, + {"parents_fshare_double", L_T_DOUBLE, + KEYSPEC_UPDATE_PARENTS_FSHARE, "double"}, + {"parents_sum_ldouble", L_T_LONG_DOUBLE, + KEYSPEC_UPDATE_PARENTS_SUM, "ldouble"}, + {"parents_fshare_ldouble", L_T_LONG_DOUBLE, + KEYSPEC_UPDATE_PARENTS_FSHARE, "ldouble"}, + /* children aggregated keys */ + {"children_count", L_T_UINT32, KEYSPEC_UPDATE_CHILDREN_COUNT}, + {"children_sum_long", L_T_LONG, + KEYSPEC_UPDATE_CHILDREN_SUM, "long"}, + {"children_avg_long", L_T_LONG, + KEYSPEC_UPDATE_CHILDREN_AVG, "long"}, + {"children_min_long", L_T_LONG, + KEYSPEC_UPDATE_CHILDREN_MIN, "long"}, + {"children_max_long", L_T_LONG, + KEYSPEC_UPDATE_CHILDREN_MAX, "long"}, + {"children_sum_uint16", L_T_UINT16, + KEYSPEC_UPDATE_CHILDREN_SUM, "uint16"}, + {"children_avg_uint16", L_T_UINT16, + KEYSPEC_UPDATE_CHILDREN_AVG, "uint16"}, + {"children_min_uint16", L_T_UINT16, + KEYSPEC_UPDATE_CHILDREN_MIN, "uint16"}, + {"children_max_uint16", L_T_UINT16, + KEYSPEC_UPDATE_CHILDREN_MAX, "uint16"}, + {"children_sum_uint32", L_T_UINT32, + KEYSPEC_UPDATE_CHILDREN_SUM, "uint32"}, + {"children_avg_uint32", L_T_UINT32, + KEYSPEC_UPDATE_CHILDREN_AVG, "uint32"}, + {"children_min_uint32", L_T_UINT32, + KEYSPEC_UPDATE_CHILDREN_MIN, "uint32"}, + {"children_max_uint32", L_T_UINT32, + KEYSPEC_UPDATE_CHILDREN_MAX, "uint32"}, + {"children_sum_float", L_T_FLOAT, + KEYSPEC_UPDATE_CHILDREN_SUM, "float"}, + {"children_avg_float", L_T_FLOAT, + KEYSPEC_UPDATE_CHILDREN_AVG, "float"}, + {"children_min_float", L_T_FLOAT, + KEYSPEC_UPDATE_CHILDREN_MIN, "float"}, + {"children_max_float", L_T_FLOAT, + KEYSPEC_UPDATE_CHILDREN_MAX, "float"}, + {"children_sum_double", L_T_DOUBLE, + KEYSPEC_UPDATE_CHILDREN_SUM, "double"}, + {"children_avg_double", L_T_DOUBLE, + KEYSPEC_UPDATE_CHILDREN_AVG, "double"}, + {"children_min_double", L_T_DOUBLE, + KEYSPEC_UPDATE_CHILDREN_MIN, "double"}, + {"children_max_double", L_T_DOUBLE, + KEYSPEC_UPDATE_CHILDREN_MAX, "double"}, + {"children_sum_ldouble", L_T_LONG_DOUBLE, + KEYSPEC_UPDATE_CHILDREN_SUM, "ldouble"}, + {"children_avg_ldouble", L_T_LONG_DOUBLE, + KEYSPEC_UPDATE_CHILDREN_AVG, "ldouble"}, + {"children_min_ldouble", L_T_LONG_DOUBLE, + KEYSPEC_UPDATE_CHILDREN_MIN, "ldouble"}, + {"children_max_ldouble", L_T_LONG_DOUBLE, + KEYSPEC_UPDATE_CHILDREN_MAX, "ldouble"}, + {NULL} +}; + +/* types allowed in the entity's "type" field */ +const char* etypes[] = { + "UnitTestPass", + "UnitTest", + NULL +}; + +const layouts_plugin_spec_t plugin_spec = { + options, + keyspec, + LAYOUT_STRUCT_TREE, + etypes, + true, /* if this evalued to true, keys inside plugin_keyspec present in + * plugin_options having corresponding types, are automatically + * handled by the layouts manager. + */ + true /* if this evalued to true, keys updates trigger an automatic + * update of their entities neighborhoods based on their + * KEYSPEC_UPDATE_* set flags + */ +}; + +/* manager is lock when this function is called */ +/* disable this callback by setting it to NULL, warn: not every callback can + * be desactivated this way */ +int layouts_p_conf_done( + xhash_t* entities, layout_t* layout, s_p_hashtbl_t* tbl) +{ + return 1; +} + + +/* disable this callback by setting it to NULL, warn: not every callback can + * be desactivated this way */ +void layouts_p_entity_parsing( + entity_t* e, s_p_hashtbl_t* etbl, layout_t* layout) +{ +} + +/* manager is lock then this function is called */ +/* disable this callback by setting it to NULL, warn: not every callback can + * be desactivated this way */ +int layouts_p_update_done(layout_t* layout, entity_t** e_array, int e_cnt) +{ + int i; + debug3("layouts/unit: receiving update callback for %d entities", + e_cnt); + for (i = 0; i < e_cnt; i++) { + if (e_array[i] == NULL) { + debug3("layouts/unit: skipping update of nullified" + "entity[%d]", i); + } else { + debug3("layouts/unit: updating entity[%d]=%s", + i, e_array[i]->name); + } + } + return 1; +} + +int init(void) +{ + return SLURM_SUCCESS; +} + +int fini(void) +{ + return SLURM_SUCCESS; +} diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c index 002fb335197a89a08d1f1e6bfac6d77da900172d..9e368a126df8f91b88986cd9a9a7c2718b50d76e 100644 --- a/src/slurmctld/controller.c +++ b/src/slurmctld/controller.c @@ -617,7 +617,7 @@ int main(int argc, char *argv[]) recover = 2; } - slurm_layouts_fini(); + layouts_fini(); /* Since pidfile is created as user root (its owner is * changed to SlurmUser) SlurmUser may not be able to diff --git a/src/slurmctld/read_config.c b/src/slurmctld/read_config.c index 47fb7d632974cb2356a71f4b4c3a740cdd59142d..e71ce3c8278c53f64d79574efc0f29f158c6acfa 100644 --- a/src/slurmctld/read_config.c +++ b/src/slurmctld/read_config.c @@ -912,7 +912,7 @@ int read_slurm_conf(int recover, bool reconfig) return error_code; } - if (slurm_layouts_init() != SLURM_SUCCESS) + if (layouts_init() != SLURM_SUCCESS) fatal("Failed to initialize the layouts framework"); if (slurm_topo_init() != SLURM_SUCCESS) @@ -986,7 +986,7 @@ int read_slurm_conf(int recover, bool reconfig) * Only load it at init time, not during reconfiguration stages. * It requires a full restart to switch to a new configuration for now. */ - if (!reconfig && (slurm_layouts_load_config() != SLURM_SUCCESS)) + if (!reconfig && (layouts_load_config(recover) != SLURM_SUCCESS)) fatal("Failed to load the layouts framework configuration"); if (reconfig) { /* Preserve state from memory */