From fcee6898f1685c7ff3cc79a7696bf504fb6fff7c Mon Sep 17 00:00:00 2001
From: Francois Chevallier <chevallierfrancois@free.fr>
Date: Mon, 25 Aug 2014 13:57:40 -0700
Subject: [PATCH] [PATCH 4/5] Introduce layouts core primitives

This commit introduces the entity, layout and layouts manager related structures
corresponding to the core of the layouts logic.

The layouts manager is responsible for initializing and loading the layouts
specified in the slurm.conf "Layouts=" pragma retrieved using
slurm_get_layouts().

(Adapted for slurm-14.11 by Matthieu Hautreux <matthieu.hautreux@cea.fr>)
---
 src/common/Makefile.am   |    5 +-
 src/common/Makefile.in   |   14 +-
 src/common/entity.c      |  208 +++++++
 src/common/entity.h      |  228 +++++++
 src/common/layout.c      |  110 ++++
 src/common/layout.h      |  145 +++++
 src/common/layouts_mgr.c | 1278 ++++++++++++++++++++++++++++++++++++++
 src/common/layouts_mgr.h |  151 +++++
 8 files changed, 2135 insertions(+), 4 deletions(-)
 create mode 100644 src/common/entity.c
 create mode 100644 src/common/entity.h
 create mode 100644 src/common/layout.c
 create mode 100644 src/common/layout.h
 create mode 100644 src/common/layouts_mgr.c
 create mode 100644 src/common/layouts_mgr.h

diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 59757878a3c..1dc1f603633 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -122,7 +122,10 @@ libcommon_la_SOURCES = 			\
 	proc_args.c proc_args.h		\
 	slurm_strcasestr.c slurm_strcasestr.h \
 	node_conf.h node_conf.c		\
-	gres.h gres.c
+	gres.h gres.c			\
+	entity.h entity.c		\
+	layout.h layout.c		\
+	layouts_mgr.h layouts_mgr.c
 
 EXTRA_libcommon_la_SOURCES = 		\
 	$(extra_unsetenv_src)		\
diff --git a/src/common/Makefile.in b/src/common/Makefile.in
index ebdcd765052..9182a82c470 100644
--- a/src/common/Makefile.in
+++ b/src/common/Makefile.in
@@ -186,7 +186,8 @@ am__libcommon_la_SOURCES_DIST = cpu_frequency.c cpu_frequency.h \
 	global_defaults.c timers.c timers.h slurm_xlator.h stepd_api.c \
 	stepd_api.h write_labelled_message.c write_labelled_message.h \
 	proc_args.c proc_args.h slurm_strcasestr.c slurm_strcasestr.h \
-	node_conf.h node_conf.c gres.h gres.c
+	node_conf.h node_conf.c gres.h gres.c entity.h entity.c \
+	layout.h layout.c layouts_mgr.h layouts_mgr.c
 @HAVE_UNSETENV_FALSE@am__objects_1 = unsetenv.lo
 am_libcommon_la_OBJECTS = cpu_frequency.lo assoc_mgr.lo xmalloc.lo \
 	xassert.lo xstring.lo xsignal.lo strnatcmp.lo forward.lo \
@@ -210,7 +211,8 @@ am_libcommon_la_OBJECTS = cpu_frequency.lo assoc_mgr.lo xmalloc.lo \
 	slurm_step_layout.lo checkpoint.lo job_resources.lo \
 	parse_time.lo job_options.lo global_defaults.lo timers.lo \
 	stepd_api.lo write_labelled_message.lo proc_args.lo \
-	slurm_strcasestr.lo node_conf.lo gres.lo
+	slurm_strcasestr.lo node_conf.lo gres.lo entity.lo layout.lo \
+	layouts_mgr.lo
 am__EXTRA_libcommon_la_SOURCES_DIST = unsetenv.c unsetenv.h \
 	uthash/LICENSE uthash/README uthash/uthash.h
 libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS)
@@ -649,7 +651,10 @@ libcommon_la_SOURCES = \
 	proc_args.c proc_args.h		\
 	slurm_strcasestr.c slurm_strcasestr.h \
 	node_conf.h node_conf.c		\
-	gres.h gres.c
+	gres.h gres.c			\
+	entity.h entity.c		\
+	layout.h layout.c		\
+	layouts_mgr.h layouts_mgr.c
 
 EXTRA_libcommon_la_SOURCES = \
 	$(extra_unsetenv_src)		\
@@ -764,6 +769,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu_frequency.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemonize.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entity.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forward.Plo@am__quote@
@@ -775,6 +781,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io_hdr.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job_options.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job_resources.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layout.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layouts_mgr.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Plo@am__quote@
diff --git a/src/common/entity.c b/src/common/entity.c
new file mode 100644
index 00000000000..aeefad11f75
--- /dev/null
+++ b/src/common/entity.c
@@ -0,0 +1,208 @@
+/*****************************************************************************\
+ *  entity.c - layouts entities data structures and main functions
+ *****************************************************************************
+ *  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.
+ *
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://slurm.schedmd.com/>.
+ *  Please also read the included file: DISCLAIMER.
+ *
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission
+ *  to link the code of portions of this program with the OpenSSL library under
+ *  certain conditions as described in each individual source file, and
+ *  distribute linked combinations including the two. You must obey the GNU
+ *  General Public License in all respects for all of the code used other than
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this
+ *  exception to your version of the file(s), but you are not obligated to do
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in
+ *  the program, then also delete it here.
+ *
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#include "src/common/entity.h"
+#include "src/common/layout.h"
+#include "src/common/xmalloc.h"
+#include "src/common/xstring.h"
+#include "src/common/xtree.h"
+
+
+/*****************************************************************************\
+ *                                 FUNCTIONS                                 *
+\*****************************************************************************/
+
+static const char* _entity_data_identify(void* item)
+{
+	entity_data_t* data_item = (entity_data_t*)item;
+	return data_item->key;
+}
+
+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->nodes = list_create(NULL);
+	entity->ptr = NULL;
+}
+
+void entity_free(entity_t* entity)
+{
+	if (entity) {
+		xfree(entity->name);
+		xfree(entity->type);
+		xhash_free(entity->data);
+		list_destroy(entity->nodes);
+	}
+}
+
+const char* entity_get_name(const entity_t* entity)
+{
+	return entity->name;
+}
+
+const char* entity_get_type(const entity_t* entity)
+{
+	return entity->type;
+}
+
+void** entity_get_data(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 NULL;
+}
+
+int entity_add_data(entity_t* entity, const char* key, void* value,
+		    void (*_free)(void*))
+{
+	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;
+}
+
+void entity_delete_data(entity_t* entity, const char* key)
+{
+	xhash_delete(entity->data, key);
+}
+
+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_node = (entity_node_t*)xmalloc(
+		sizeof(entity_node_t));
+	entity_node->layout = layout;
+	entity_node->node = node;
+	list_append(entity->nodes, entity_node);
+}
+
+static int _entity_node_find(void* x, void* key)
+{
+	entity_node_t* entity_node = (entity_node_t*)x;
+	return entity_node->node == key;
+}
+
+void entity_delete_node(entity_t* entity, void* node)
+{
+	ListIterator i;
+	void* result;
+	i = list_iterator_create(entity->nodes);
+	list_iterator_reset(i);
+	result = list_find(i, _entity_node_find, node);
+	do {
+		if (result == NULL)
+			break;
+		list_delete_item(i);
+		xfree(result);
+	} while(0);
+	list_iterator_destroy(i);
+}
+
+void entity_clear_nodes(entity_t* entity)
+{
+	list_flush(entity->nodes);
+}
+
+int entity_has_node(entity_t* entity, void* node)
+{
+	ListIterator i;
+	void* result;
+	i = list_iterator_create(entity->nodes);
+	list_iterator_reset(i);
+	result = list_find(i, _entity_node_find, node);
+	list_iterator_destroy(i);
+	return result != NULL;
+}
+
+typedef struct _entity_nodes_walkstruct_st {
+	void (*callback)(layout_t* layout, void* node, void* arg);
+	void* arg;
+} _entity_nodes_walkstruct_t;
+
+static int _entity_nodes_walkfunc(void* x, void* arg)
+{
+	entity_node_t* entity_node = (entity_node_t*)x;
+	_entity_nodes_walkstruct_t* real_arg =
+		(_entity_nodes_walkstruct_t*)arg;
+	real_arg->callback(entity_node->layout,
+			   entity_node->node,
+			   real_arg->arg);
+	return 0;
+}
+
+void entity_nodes_walk(entity_t* entity,
+		       void (*callback)(layout_t* layout,
+					void* node,
+					void* arg),
+		       void* arg)
+{
+	_entity_nodes_walkstruct_t real_arg;
+	real_arg.callback = callback;
+	real_arg.arg = arg;
+	list_for_each(entity->nodes, _entity_nodes_walkfunc, &real_arg);
+}
+
+const char* entity_hashable_identify(void* item)
+{
+	entity_t* entity = (entity_t*)item;
+	return entity->name;
+}
diff --git a/src/common/entity.h b/src/common/entity.h
new file mode 100644
index 00000000000..03650a6af2a
--- /dev/null
+++ b/src/common/entity.h
@@ -0,0 +1,228 @@
+/*****************************************************************************\
+ *  entity.h - layouts entities data structures and main functions
+ *****************************************************************************
+ *  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.
+ *
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://slurm.schedmd.com/>.
+ *  Please also read the included file: DISCLAIMER.
+ *
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission
+ *  to link the code of portions of this program with the OpenSSL library under
+ *  certain conditions as described in each individual source file, and
+ *  distribute linked combinations including the two. You must obey the GNU
+ *  General Public License in all respects for all of the code used other than
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this
+ *  exception to your version of the file(s), but you are not obligated to do
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in
+ *  the program, then also delete it here.
+ *
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#ifndef __ENTITY_GDBZJYZL_INC__
+#define __ENTITY_GDBZJYZL_INC__
+
+#include "src/common/list.h"
+#include "src/common/xhash.h"
+#include "src/common/xtree.h"
+#include "src/common/layout.h"
+
+/*****************************************************************************\
+ *                                 STRUCTURES                                *
+\*****************************************************************************/
+
+/* definition of the entity itself, main structure of this file. */
+typedef struct entity_st {
+	char* name;     /* unique name of this entity */
+	char* type;     /* basic type of entity */
+	xhash_t* data;  /* data table, stores data items */
+	List nodes;     /* list of nodes where this entity
+			   appears */
+	void *ptr;      /* private data for arbitraty ptr */
+} entity_t;
+
+/* definition of the key-value structure used internaly by entities */
+typedef struct entity_data_st {
+	const char* key; /* memory not owned, see layouts_keydef */
+	void* value;
+} entity_data_t;
+
+/* definition of the entity node structure used internaly by entities
+ * 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 */
+	void* node;       /* pointer to the relational node referencing
+			     this entity */
+} entity_node_t;
+
+/*****************************************************************************\
+ *                                 FUNCTIONS                                 *
+\*****************************************************************************/
+
+/*
+ * entity_init - initialize an entity
+ *
+ * IN entity - the entity struct to initialize
+ * IN name - the name of the entity
+ * IN type - the type of the entity
+ */
+void entity_init(entity_t* entity, const char* name, const char* type);
+
+/*
+ * entity_free - free entity internals
+ *
+ * IN entity - the entity struct to fee internals from
+ */
+void entity_free(entity_t* entity);
+
+/*
+ * entity_get_name - get the name of an entity
+ *
+ * IN entity - the entity struct to use
+ *
+ * Return value is the name of the entity
+ */
+const char* entity_get_name(const entity_t* entity);
+
+/*
+ * entity_get_type - get the type of an entity
+ *
+ * IN entity - the entity struct to use
+ *
+ * Return value is the type of the entity
+ */
+const char* entity_get_type(const entity_t* entity);
+
+/*
+ * entity_get_data - get the address of the pointer to the data associated
+ *       with a particular key of an entity
+ *
+ * IN entity - the entity struct to use
+ * IN key - the targeted key
+ *
+ * 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);
+
+/*
+ * entity_add_data - associate data to a particular key of an entity
+ *
+ * IN entity - the entity struct to use
+ * IN key - the key the data must be associated to
+ * IN value - the data to associate with the key (potentially overriding
+ *       previous value)
+ * 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
+ */
+int entity_add_data(entity_t* entity, const char* key, void* value,
+		    void (*_free)(void*));
+
+/*
+ * entity_delete_data - delete the data associated with a particular key
+ *       of an entity
+ *
+ * IN entity - the entity struct to use
+ * IN key - the key the data must be deleted from
+ */
+void entity_delete_data(entity_t* entity, const char* key);
+
+/*
+ * entity_clear_data - removes all the entity key/value pairs
+ *
+ * IN entity - the entity struct to use
+ *
+ * Notes: does not free value, user is responsible for it, if the data_freefunc
+ *       is null.
+ */
+void entity_clear_data(entity_t* entity);
+
+/*
+ * entity_add_node - add a relational 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
+ *
+ * Notes: the entity does not own the memory of the relationnal nodes.
+ */
+void entity_add_node(entity_t* entity, layout_t* layout, void* node);
+
+/*
+ * entity_delete_node - remove a relational node from the list of nodes
+ *       referring to this entity
+ *
+ * IN entity - the entity struct to use
+ * IN node - the node referring to it
+ *
+ * Notes: the memory of the node data is not freed.
+ */
+void entity_delete_node(entity_t* entity, void* node);
+
+/*
+ * entity_clear_nodes - remove all the relational node from the list of nodes
+ *       referring to this entity
+ *
+ * IN entity - the entity struct to use
+ *
+ * Notes: the memory of the nodes data is not freed.
+ */
+void entity_clear_nodes(entity_t* entity);
+
+/*
+ * entity_has_node - check wether or not a relational node is in the
+ *       list of nodes referring to this entity
+ *
+ * IN entity - the entity struct to use
+ * IN node - the node to check for
+ *
+ * Return 1 if found, 0 otherwise
+ */
+int entity_has_node(entity_t* entity, void* node);
+
+/*
+ * entity_nodes_walk - iterate over the nodes referring to this entity
+ *       applying a particular callback with a particular arg. It can be
+ *       used to search, compare, and do other general operation on each nodes
+ *       associated with an entity.
+ *
+ * IN entity - the entity struct to use
+ * IN callback - the callback function to use. The first arg will receive the
+ *       layout of the node being processed, the second will be the node itself
+ *       and the third one will be the arg passed to the function.
+ * 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* arg);
+
+/*
+ * entity_hashable_identify - defines a hashable identifying function to
+ *      use with xhash.
+ *
+ * Note: it currently just returns the name of the entity
+ */
+const char* entity_hashable_identify(void* item);
+
+#endif /* end of include guard: __ENTITY_GDBZJYZL_INC__ */
+
diff --git a/src/common/layout.c b/src/common/layout.c
new file mode 100644
index 00000000000..d4d4bb2f04b
--- /dev/null
+++ b/src/common/layout.c
@@ -0,0 +1,110 @@
+/*****************************************************************************\
+ *  layout.c - layout data structures and main functions
+ *****************************************************************************
+ *  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.
+ *
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://slurm.schedmd.com/>.
+ *  Please also read the included file: DISCLAIMER.
+ *
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission
+ *  to link the code of portions of this program with the OpenSSL library under
+ *  certain conditions as described in each individual source file, and
+ *  distribute linked combinations including the two. You must obey the GNU
+ *  General Public License in all respects for all of the code used other than
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this
+ *  exception to your version of the file(s), but you are not obligated to do
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in
+ *  the program, then also delete it here.
+ *
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#include "src/common/layout.h"
+#include "src/common/xstring.h"
+#include "src/common/xmalloc.h"
+
+void layout_init(layout_t* layout, const char* name, const char* type,
+		 uint32_t priority, int struct_type)
+{
+	layout->name = xstrdup(name);
+	layout->type = xstrdup(type);
+	layout->priority = priority;
+	layout->struct_type = struct_type;
+	switch(layout->struct_type) {
+	case LAYOUT_STRUCT_TREE:
+		layout->tree = (xtree_t*)xmalloc(sizeof(xtree_t));
+		xtree_init(layout->tree, NULL);
+		break;
+	}
+}
+
+void layout_free(layout_t* layout)
+{
+	xfree(layout->name);
+	xfree(layout->type);
+	switch(layout->struct_type) {
+	case LAYOUT_STRUCT_TREE:
+		xtree_free(layout->tree);
+		xfree(layout->tree);
+		break;
+	}
+}
+
+const char* layout_get_name(const layout_t* layout)
+{
+	return layout->name;
+}
+
+const char* layout_get_type(const layout_t* layout)
+{
+	return layout->type;
+}
+
+uint32_t layout_get_priority(const layout_t* layout)
+{
+	return layout->priority;
+}
+
+void layout_node_delete(layout_t* layout, void* node)
+{
+	switch(layout->struct_type) {
+	case LAYOUT_STRUCT_TREE:
+		xtree_delete(layout->tree, (xtree_node_t*)node);
+		break;
+	}
+}
+
+xtree_t* layout_get_tree(layout_t* layout)
+{
+	if (layout->struct_type == LAYOUT_STRUCT_TREE) {
+		return layout->tree;
+	}
+	fatal("layout has unknown relationnal structure type");
+	return NULL;
+}
+
+const char* layout_hashable_identify(void* item) {
+	layout_t* l = (layout_t*)item;
+	return l->name;
+}
+
+const char* layout_hashable_identify_by_type(void* item) {
+	layout_t* l = (layout_t*)item;
+	return l->type;
+}
diff --git a/src/common/layout.h b/src/common/layout.h
new file mode 100644
index 00000000000..1203a83a59a
--- /dev/null
+++ b/src/common/layout.h
@@ -0,0 +1,145 @@
+/*****************************************************************************\
+ *  layout.h - layout data structures and main functions
+ *****************************************************************************
+ *  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.
+ *
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://slurm.schedmd.com/>.
+ *  Please also read the included file: DISCLAIMER.
+ *
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission
+ *  to link the code of portions of this program with the OpenSSL library under
+ *  certain conditions as described in each individual source file, and
+ *  distribute linked combinations including the two. You must obey the GNU
+ *  General Public License in all respects for all of the code used other than
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this
+ *  exception to your version of the file(s), but you are not obligated to do
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in
+ *  the program, then also delete it here.
+ *
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#ifndef __LAYOUT_DGR6BCQ2_INC__
+#define __LAYOUT_DGR6BCQ2_INC__
+
+#include "src/common/xtree.h"
+
+/*
+ * NOTE FOR ADDING RELATIONNAL STRUCTURES:
+ *
+ * When adding a relationnal structure you must :
+ * - add definition to layout_st
+ * - add the LAYOUT_STRUCT_RELTYPE constant
+ * and then add logics in 3 functions:
+ * - layout_init
+ * - layout_free
+ * - layout_node_delete
+ *
+ */
+#define LAYOUT_STRUCT_TREE 1
+
+typedef struct layout_st {
+	char* name;        /* the name of the layout */
+	uint32_t priority; /* the priority of the layout among the others,
+			    * might be useful for selecting resources
+			    * refining the results through a list of layouts */
+	int struct_type;   /* type of relational structure (@see entity.h) */
+	char* type;        /* the type of the layout, exp: racking, power...*/
+	union {	           /* relational structure used by the layout */
+		xtree_t* tree;
+	};
+} layout_t;
+
+/*
+ * layout_init - initialize a particular layout struct 
+ * IN layout - the layout struct to initialize
+ * IN name - the layout struct to initialize
+ * IN type - the layout struct to initialize
+ * IN priority - the layout priority value among the other layouts
+ * IN struct_type - the type of relational structure to use to connect
+ *      the entities managed by this layout (tree structure is the only
+ *      relational structure supported for now)
+ */
+void layout_init(layout_t* layout, const char* name, const char* type,
+		 uint32_t priority, int struct_type);
+
+/*
+ * layout_free - destroy a particular layout struct 
+ * IN layout - the layout struct to free
+ */
+void layout_free(layout_t* layout);
+
+/*
+ * layout_get_name - return the name of a layout
+ * IN layout - the layout struct to use
+ *
+ * Return value is the name of the layout
+ */
+const char* layout_get_name(const layout_t* layout);
+
+/*
+ * layout_get_type - return the type of a layout
+ * IN layout - the layout struct to use
+ *
+ * Return value is the type of the layout
+ */
+const char* layout_get_type(const layout_t* layout);
+
+/*
+ * layout_get_priority - return the numeric priority of a layout
+ * IN layout - the layout struct to use
+ *
+ * Return value is the priority of the layout
+ */
+uint32_t layout_get_priority(const layout_t* layout);
+
+
+/*
+ * layout_node_delete - remove a particular node from the relational
+ *      structure of the layout
+ * IN layout - the layout struct to use
+ * IN node - a (void*) pointer to the relational struct node to remove
+ */
+void layout_node_delete(layout_t* layout, void* node);
+
+
+/*
+ * layout_get_tree - get the tree relational structure associated to a layout
+ * IN layout - the layout struct to use
+ *
+ * Return value is a pointer to the xtree_t struct or NULL if not available
+ */
+xtree_t* layout_get_tree(layout_t* layout);
+
+/*
+ * layout_hashable_identify - defines a hashable identifying function to
+ *      use with xhash.
+ *
+ * Note: it currently just returns the name of the layout
+ */
+const char* layout_hashable_identify(void* item);
+
+/* layout_hashable_identify_by_type - defines a per-type hashable identifying
+ *      function to use with xhash.
+ *
+ * Note: it currently just returns the type of the layout
+ */
+const char* layout_hashable_identify_by_type(void* item);
+
+#endif /* end of include guard: __LAYOUT_DGR6BCQ2_INC__ */
diff --git a/src/common/layouts_mgr.c b/src/common/layouts_mgr.c
new file mode 100644
index 00000000000..95eaf558376
--- /dev/null
+++ b/src/common/layouts_mgr.c
@@ -0,0 +1,1278 @@
+/*****************************************************************************\
+ *  layouts_mgr.c - layouts manager data structures and main functions
+ *****************************************************************************
+ *  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.
+ *
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://slurm.schedmd.com/>.
+ *  Please also read the included file: DISCLAIMER.
+ *
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission
+ *  to link the code of portions of this program with the OpenSSL library under
+ *  certain conditions as described in each individual source file, and
+ *  distribute linked combinations including the two. You must obey the GNU
+ *  General Public License in all respects for all of the code used other than
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this
+ *  exception to your version of the file(s), but you are not obligated to do
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in
+ *  the program, then also delete it here.
+ *
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#include <pthread.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+
+#include "layouts_mgr.h"
+
+#include "src/common/entity.h"
+#include "src/common/layout.h"
+
+#include "slurm/slurm.h"
+#include "slurm/slurm_errno.h"
+#include "src/common/list.h"
+#include "src/common/xtree.h"
+#include "src/common/xmalloc.h"
+#include "src/common/plugin.h"
+#include "src/common/xstring.h"
+#include "src/common/slurm_protocol_api.h"
+#include "src/common/read_config.h"
+#include "src/common/node_conf.h"
+#include "src/common/hostlist.h"
+
+#define PATHLEN 256
+
+/*****************************************************************************\
+ *                            STRUCTURES AND TYPES                           *
+\*****************************************************************************/
+
+void free(void*);
+
+/*
+ * layouts_conf_spec_t - structure used to keep track of layouts conf details
+ */
+typedef struct layouts_conf_spec_st {
+	char* whole_name;
+	char* name;
+	char* type;
+} layouts_conf_spec_t;
+
+static void layouts_conf_spec_free(void* x)
+{
+	layouts_conf_spec_t* spec = (layouts_conf_spec_t*)x;
+	xfree(spec->whole_name);
+	xfree(spec->type);
+	xfree(spec->name);
+	xfree(spec);
+}
+
+/*
+ * layout ops - operations associated to layout plugins
+ *
+ * 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 
+ * build_layout API calls.
+ *
+ */
+typedef struct layout_ops_st {
+	layouts_plugin_spec_t*	spec;
+	int (*conf_done) (xhash_t* entities, layout_t* layout,
+			  s_p_hashtbl_t* tbl);
+	void (*entity_parsing) (entity_t* e, s_p_hashtbl_t* etbl,
+				layout_t* layout);
+} layout_ops_t;
+
+/*
+ * layout plugin symbols - must be synchronized with ops structure definition
+ *        as previously detailed, that's why though being a global constant,
+ *        it is placed in this section.
+ */
+const char *layout_syms[] = {
+	"plugin_spec",             /* holds constants, definitions, ... */
+	"layouts_p_conf_done",     /* */
+	"layouts_p_entity_parsing",
+};
+
+/*
+ * layout_plugin_t - it is the structure holding the plugin context of the
+ *        associated layout plugin as well as the ptr to the dlsymed calls.
+ *        It is used by the layouts manager to operate on the different layouts
+ *        loaded during the layouts framework initialization
+ */
+typedef struct layout_plugin_st {
+	plugin_context_t* context;
+	layout_t* layout;
+	char* name;
+	layout_ops_t* ops;
+} layout_plugin_t;
+
+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
+ *       in order to avoid loosing too much memory duplicating similar data
+ *       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 
+ * entity_data_t structs associated to the entities.
+ *
+ * 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 */
+	layouts_keydef_types_t	type;
+	void			(*custom_destroy)(void* value);
+	char*			(*custom_dump)(void* value);
+	layout_plugin_t*	plugin;
+} layouts_keydef_t;
+
+/*
+ * layouts_keydef_idfunc - identity function to build an hash table of
+ *        layouts_keydef_t
+ */
+static const char* layouts_keydef_idfunc(void* item)
+{
+	layouts_keydef_t* keydef = (layouts_keydef_t*)item;
+	return keydef->key;
+}
+
+/*
+ * 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 {
+	pthread_mutex_t lock;
+	layout_plugin_t *plugins;
+	uint32_t plugins_count;
+	List    layouts_desc;  /* list of the layouts requested in conf */
+	xhash_t *layouts;      /* hash tbl of loaded layout structs (by type) */
+	xhash_t *entities;     /* hash tbl of loaded entity structs (by name) */
+	xhash_t *keydefs;      /* info on key types, how to free them etc */
+} layouts_mgr_t;
+
+/*****************************************************************************\
+ *                                  GLOBALS                                  *
+\*****************************************************************************/
+
+/** global structure holding layouts and entities */
+static layouts_mgr_t layouts_mgr = {PTHREAD_MUTEX_INITIALIZER};
+static layouts_mgr_t* mgr = &layouts_mgr;
+
+/*****************************************************************************\
+ *                                  HELPERS                                  *
+\*****************************************************************************/
+
+/* entities added to the layouts mgr hash table come from the heap,
+ * this funciton will help to free them while freeing the hash table */
+static void _entity_free(void* item)
+{
+	entity_t* entity = (entity_t*) item;
+	entity_free(entity);
+	xfree(entity);
+}
+
+/* layouts added to the layouts mgr hash table come from the heap,
+ * this funciton will help to free them while freeing the hash table */
+static void _layout_free(void* item)
+{
+	layout_t* layout = (layout_t*) item;
+	layout_free(layout);
+	xfree(layout);
+}
+
+/* keydef added to the layouts mgr hash table come from the heap,
+ * this funciton will help to free them while freeing the hash table */
+static void _layouts_keydef_free(void* x)
+{
+	layouts_keydef_t* keydef = (layouts_keydef_t*)x;
+	xfree(keydef->key);
+	xfree(keydef);
+}
+
+/* generic xfree callback */
+static void xfree_as_callback(void* p)
+{
+	xfree(p);
+}
+
+/* safer behavior than plain strncat */
+static char* _cat(char* dest, const char* src, size_t n)
+{
+	size_t len;
+	char* r;
+	if (n == 0) return dest;
+	len = strlen(dest);
+	if (n - len - 1 <= 0) {
+		dest[n - 1] = 0;
+		return dest;
+	}
+	r = strncat(dest, src, n - len - 1);
+	dest[n - 1] = 0;
+	return r;
+}
+
+/* safer behavior than plain strncpy */
+static char* _cpy(char* dest, const char* src, size_t n)
+{
+	char* r;
+	if (n == 0) return dest;
+	r = strncpy(dest, src, n - 1);
+	dest[n - 1] = 0;
+	return r;
+}
+
+static char* trim(char* str)
+{
+	char* str_modifier;
+	if (!str) return str;
+	while (*str && isspace(*str)) ++str;
+	str_modifier = str + strlen(str) - 1;
+	while (str_modifier >= str && isspace(*str_modifier)) {
+		*str_modifier = '\0';
+		--str_modifier;
+	}
+	return str;
+}
+
+/* check if str is in strings (null terminated string array) */
+/* TODO: replace this with a xhash instead for next modification */
+static int _string_in_array(const char* str, const char** strings)
+{
+	xassert(strings); /* if etypes no specified in plugin, no new entity
+			     should be created */
+	for (; *strings; ++strings) {
+		if (!strcmp(str, *strings))
+			return 1;
+	}
+	return 0;
+}
+
+static void _normalize_keydef_keycore(char* buffer, uint32_t size,
+				      const char* key, const char* plugtype,
+				      bool cat)
+{
+	int i;
+	char keytmp[PATHLEN];
+
+	for (i = 0; plugtype[i] && i < PATHLEN - 1; ++i) {
+		keytmp[i] = tolower(plugtype[i]);
+	}
+	keytmp[i] = 0;
+	if (cat) {
+		_cat(buffer, keytmp, size);
+	} else {
+		_cpy(buffer, keytmp, size);
+	}
+	_cat(buffer, ".", size);
+	for (i = 0; key[i] && i < PATHLEN - 1; ++i) {
+		keytmp[i] = tolower(key[i]);
+	}
+	keytmp[i] = 0;
+	_cat(buffer, keytmp, size);
+}
+
+static void _normalize_keydef_key(char* buffer, uint32_t size,
+				  const char* key, const char* plugtype)
+{
+	_normalize_keydef_keycore(buffer, size, key, plugtype, false);
+}
+
+static void _normalize_keydef_mgrkey(char* buffer, uint32_t size,
+				     const char* key, const char* plugtype)
+{
+	_cpy(buffer, "mgr.", size);
+	_normalize_keydef_keycore(buffer, size, key, plugtype, true);
+}
+
+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) {
+		freefunc = hkey->custom_destroy;
+	}
+	rc = entity_add_data(e, hkey->key, data, freefunc);
+	xassert(rc);
+}
+
+/*****************************************************************************\
+ *                                MANAGER INIT                               *
+\*****************************************************************************/
+
+static void _slurm_layouts_init_keydef(xhash_t* keydefs,
+				       const layouts_keyspec_t* plugin_keyspec,
+				       layout_plugin_t* plugin)
+{
+	char keytmp[PATHLEN];
+
+	const layouts_keyspec_t* current;
+	layouts_keydef_t* nkeydef;
+
+	/* A layout plugin may have no data to store to entities but still
+	 * being valid. */
+	if (!plugin_keyspec)
+		return;
+
+	/* iterate over the keys of the plugin */
+	for (current = plugin_keyspec; current->key; ++current) {
+		/* if not end of list, a keyspec key is mandatory */
+		_normalize_keydef_key(keytmp, PATHLEN, current->key,
+				      plugin->layout->type);
+		xassert(xhash_get(keydefs, keytmp) == NULL);
+		nkeydef = (layouts_keydef_t*)
+			xmalloc(sizeof(layouts_keydef_t));
+		nkeydef->key = xstrdup(keytmp);
+		nkeydef->type = current->type;
+		nkeydef->custom_destroy = current->custom_destroy;
+		nkeydef->custom_dump = current->custom_dump;
+		nkeydef->plugin = plugin;
+		xhash_add(keydefs, nkeydef);
+	}
+
+	/* then add keys managed by the layouts_mgr directly */
+	switch(plugin->layout->struct_type) {
+	case LAYOUT_STRUCT_TREE:
+		_normalize_keydef_mgrkey(keytmp, PATHLEN, "enclosed",
+					 plugin->layout->type);
+		xassert(xhash_get(keydefs, keytmp) == NULL);
+		nkeydef = (layouts_keydef_t*)
+			xmalloc(sizeof(layouts_keydef_t));
+		nkeydef->key = xstrdup(keytmp);
+		nkeydef->type = L_T_STRING;
+		nkeydef->plugin = plugin;
+		xhash_add(keydefs, nkeydef);
+		break;
+	}
+}
+
+static int _slurm_layouts_init_layouts_walk_helper(void* x, void* arg)
+{
+	layouts_conf_spec_t* spec = (layouts_conf_spec_t*)x;
+	int* i = (int*)arg;
+	layout_plugin_t* plugin = &mgr->plugins[*i];
+	const char* plugin_type = "layouts";
+	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));
+	debug2("layouts: loading %s...", spec->whole_name);
+	plugin->context = plugin_context = plugin_context_create(
+		plugin_type,
+		plugin_name,
+		(void**)plugin->ops,
+		layout_syms,
+		sizeof(layout_syms));
+	if (!plugin_context) {
+		error("layouts: error loading %s.", plugin_name);
+		return SLURM_ERROR;
+	}
+	if (!plugin->ops->spec) {
+		error("layouts: plugin_spec must be valid (%s plugin).",
+		      plugin_name);
+		return SLURM_ERROR;
+
+	}
+	plugin->name = xstrdup(spec->whole_name);
+	plugin->layout = (layout_t*)xmalloc(sizeof(layout_t));
+	layout_init(plugin->layout, spec->name, spec->type, 0,
+		    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);
+	++*i;
+	return SLURM_SUCCESS;
+}
+
+static void _layouts_mgr_parse_global_conf(layouts_mgr_t* mgr)
+{
+	char* layouts;
+	char* parser;
+	char* saveptr;
+	char* slash;
+	layouts_conf_spec_t* nspec;
+
+	mgr->layouts_desc = list_create(layouts_conf_spec_free);
+	layouts = slurm_get_layouts();
+	parser = strtok_r(layouts, ",", &saveptr);
+	while (parser) {
+		nspec = (layouts_conf_spec_t*)xmalloc(
+			sizeof(layouts_conf_spec_t));
+		nspec->whole_name = xstrdup(trim(parser));
+		slash = strchr(parser, '/');
+		if (slash) {
+			*slash = 0;
+			nspec->type = xstrdup(trim(parser));
+			nspec->name = xstrdup(trim(slash+1));
+		} else {
+			nspec->type = xstrdup(trim(parser));
+			nspec->name = xstrdup("default");
+		}
+		list_append(mgr->layouts_desc, nspec);
+		parser = strtok_r(NULL, ",", &saveptr);
+	}
+	xfree(layouts);
+}
+
+static void layouts_mgr_init(layouts_mgr_t* mgr)
+{
+	_layouts_mgr_parse_global_conf(mgr);
+
+	mgr->layouts = xhash_init(layout_hashable_identify_by_type,
+				  (xhash_freefunc_t)_layout_free, NULL, 0);
+	mgr->entities = xhash_init(entity_hashable_identify,
+				   (xhash_freefunc_t)_entity_free, NULL, 0);
+	mgr->keydefs = xhash_init(layouts_keydef_idfunc,
+				  _layouts_keydef_free, NULL, 0);
+}
+
+static void layouts_mgr_free(layouts_mgr_t* mgr)
+{
+	/* free the configuration details */
+	list_destroy(mgr->layouts_desc);
+
+	/* FIXME: can we do a faster free here ? since each node removal will
+	 * modify either the entities or layouts for back (or forward)
+	 * references. */
+	xhash_free(mgr->layouts);
+	xhash_free(mgr->entities);
+	xhash_free(mgr->keydefs);
+}
+
+/*****************************************************************************\
+ *                               CONFIGURATION                               *
+\*****************************************************************************/
+
+static char* _conf_get_filename(const char* type)
+{
+	char path[PATHLEN];
+	char* final_path;
+	_cpy(path, "layouts.d/", PATHLEN);
+	_cat(path, type, PATHLEN);
+	_cat(path, ".conf", PATHLEN);
+	final_path = get_extra_conf_path(path);
+	return final_path;
+}
+
+static s_p_hashtbl_t* _conf_make_hashtbl(int struct_type,
+					 const s_p_options_t* layout_options)
+{
+	s_p_hashtbl_t* tbl = NULL;
+	s_p_hashtbl_t* tbl_relational = NULL;
+	s_p_hashtbl_t* tbl_layout = NULL;
+	s_p_options_t* relational_options = NULL;
+
+	/* generic line option */
+	static s_p_options_t global_options_entity[] = {
+		{"Entity", S_P_STRING},
+		{"Type", S_P_STRING},
+		{NULL}
+	};
+	static s_p_options_t global_options[] = {
+		{"Priority", S_P_UINT32},
+		{"Entity", S_P_EXPLINE, NULL, NULL, global_options_entity},
+		{NULL}
+	};
+
+	/* available for constructing a tree */
+	static s_p_options_t tree_options_entity[] = {
+		{"Enclosed", S_P_PLAIN_STRING},
+		{NULL}
+	};
+	static s_p_options_t tree_options[] = {
+		{"Root", S_P_STRING},
+		{"Entity", S_P_EXPLINE, NULL, NULL, tree_options_entity},
+		{NULL}
+	};
+
+	xassert(layout_options);
+
+	switch(struct_type) {
+	case LAYOUT_STRUCT_TREE:
+		relational_options = tree_options;
+		break;
+	default:
+		fatal("layouts: does not know what relation structure to"
+		      "use.");
+	}
+
+	tbl = s_p_hashtbl_create(global_options);
+	tbl_relational = s_p_hashtbl_create(relational_options);
+	tbl_layout = s_p_hashtbl_create(layout_options);
+
+	s_p_hashtbl_merge_keys(tbl, tbl_relational);
+	s_p_hashtbl_merge_keys(tbl, tbl_layout);
+
+	s_p_hashtbl_destroy(tbl_relational);
+	s_p_hashtbl_destroy(tbl_layout);
+
+	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) \
+	(entity_option->type == type1 && keydef->type == type2)
+
+static void _layouts_load_automerge(layout_plugin_t* plugin, entity_t* e,
+		s_p_hashtbl_t* etbl)
+{
+	const s_p_options_t* layout_option;
+	const s_p_options_t* entity_option;
+	layouts_keydef_t* keydef;
+	char key_keydef[PATHLEN];
+	char* option_key;
+
+	for (layout_option = plugin->ops->spec->options;
+		layout_option && strcasecmp("Entity", layout_option->key);
+		++layout_option);
+	xassert(layout_option);
+
+	for (entity_option = layout_option->line_options;
+			entity_option->key;
+			++entity_option) {
+		option_key = entity_option->key;
+		_normalize_keydef_key(key_keydef, PATHLEN, option_key,
+				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;
+		}
+		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)) {
+			_layouts_load_merge(uint16_t, s_p_get_uint16);
+		} else if (_layouts_merge_check(S_P_UINT32, L_T_UINT32)) {
+			_layouts_load_merge(uint32_t, s_p_get_uint32);
+		} else if (_layouts_merge_check(S_P_BOOLEAN, L_T_BOOLEAN)) {
+			_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_STRING, L_T_STRING)) {
+			char* newvalue;
+			if (s_p_get_string(&newvalue, option_key, etbl)) {
+				_entity_add_data(e, key_keydef, newvalue);
+			}
+		}
+	}
+}
+
+/* extract Enlosed= attributes providing the relational structures info */
+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 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);
+			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);
+				xfree(e_enclosed);
+			} else {
+				_entity_add_data(e, key, e_enclosed);
+			}
+		}
+		break;
+	}
+}
+
+static int _layouts_read_config_post(layout_plugin_t* plugin,
+		s_p_hashtbl_t* tbl)
+{
+	char* root_nodename;
+	entity_t* e;
+	xtree_node_t* root_node,* inserted_node;
+	xtree_t* tree;
+	switch(plugin->layout->struct_type) {
+	case LAYOUT_STRUCT_TREE:
+		tree = layout_get_tree(plugin->layout);
+		xassert(tree);
+		if (!s_p_get_string(&root_nodename, "Root", tbl)) {
+			error("layouts: unable to construct the layout tree, "
+			      "no root node specified");
+			xfree(root_nodename);
+			return SLURM_ERROR;
+		}
+		e = xhash_get(mgr->entities, trim(root_nodename));
+		if (!e) {
+			error("layouts: unable to find specified root "
+			      "entity `%s'", trim(root_nodename));
+			xfree(root_nodename);
+			return SLURM_ERROR;
+		}
+		xfree(root_nodename);
+		root_node = xtree_add_child(tree, NULL, e, XTREE_APPEND);
+		xassert(root_node);
+		inserted_node = list_append(e->nodes, root_node);
+		xassert(inserted_node == 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.
+ */
+static int _layouts_read_config(layout_plugin_t* plugin)
+{
+	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;
+	int rc = SLURM_ERROR;
+	char* filename = NULL;
+
+	uint32_t l_priority;
+
+	entity_t* e;
+	char* e_name = NULL;
+	char* e_type = NULL;
+
+	if (!plugin->ops->spec->options) {
+		/* no option in this layout plugin, nothing to parse */
+		return SLURM_SUCCESS;
+	}
+
+	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);
+	}
+	debug3("layouts: configuration file '%s' is loaded", filename);
+
+	if (s_p_get_uint32(&l_priority, "Priority", tbl)) {
+		plugin->layout->priority = l_priority;
+	}
+
+	/* get the config hash tables of the defined entities */
+	if (!s_p_get_expline(&entities_tbl, &entities_tbl_count,
+				"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 1: create the described entities or update them */
+	for (i = 0; i < entities_tbl_count; ++i) {
+		entity_tbl = entities_tbl[i];
+		xfree(e_name);
+		xfree(e_type);
+		if (!s_p_get_string(&e_name, "Entity", entity_tbl)) {
+			error("layouts: no name associated to entity[%d], "
+			      "skipping...", i);
+			continue;
+		}
+		
+		/* look for the entity in the entities hash table*/
+		e = xhash_get(mgr->entities, e_name);
+		if (!e) {
+			/* if the entity does not already exists, create it */
+			if (!s_p_get_string(&e_type, "Type", entity_tbl)) {
+				error("layouts: entity '%s' does not already "
+				      "exists and no type was specified, "
+				      "skipping", e_name);
+				continue;
+			}
+			if (!_string_in_array(e_type,
+					      plugin->ops->spec->etypes)) {
+				error("layouts: entity '%s' type (%s) is "
+				      "invalid, skipping", e_name, e_type);
+				continue;
+			}
+
+			e = (entity_t*)xmalloc(sizeof(entity_t));
+			entity_init(e, e_name, e_type);
+			xhash_add(mgr->entities, e);
+
+		} else if (s_p_get_string(&e_type, "Type", entity_tbl)) {
+			/* if defined, check that the type is consistent */
+			if (!_string_in_array(e_type,
+					      plugin->ops->spec->etypes)) {
+				error("layouts: entity '%s' type (%s) is "
+				      "invalid, skipping", e_name, e_type);
+				continue;
+			}
+			if (!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);
+				continue;
+			}
+		}
+
+		/* 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 the layout plugin requests automerge, try to automatically
+		 * parse the conf hash table using the s_p_option_t description
+		 * of the plugin, creating the key/vlaue with the right value
+		 * type and adding them to the entity key hash table.
+		 */
+		if (plugin->ops->spec->automerge) {
+			_layouts_load_automerge(plugin, e, entity_tbl);
+		}
+
+		/*
+		 * in case the automerge was not sufficient, the layout parsing
+		 * callback is called for further actions.
+		 */
+		if (plugin->ops->entity_parsing) {
+			plugin->ops->entity_parsing(e, entity_tbl,
+						    plugin->layout);
+		}
+	}
+
+	/* 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) {
+		goto cleanup;
+	}
+
+	/*
+	 * call the layout plugin conf_done callback for further
+	 * layout specific actions.
+	 */
+	if (plugin->ops->conf_done) {
+		if (!plugin->ops->conf_done(mgr->entities, plugin->layout,
+					    tbl)) {
+			error("layouts: plugin %s/%s has an error parsing its"
+			      " configuration", plugin->layout->type,
+			      plugin->layout->name);
+			goto cleanup;
+		}
+	}
+	
+	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_build_xtree_walk_t* p = (_layouts_build_xtree_walk_t*)arg;
+	entity_t* e;
+	char** enclosed_str;
+	char* enclosed_name;
+	hostlist_t enclosed_hostlist;
+	entity_t* enclosed_e;
+	xtree_node_t* enclosed_node,* inserted_node;
+
+	xassert(arg);
+
+	e = xtree_node_get_data(node);
+	xassert(e);
+
+	/*
+	 * FIXME: something goes wrong with the order...
+	 * after a first growing, the first new child is called with preorder.
+	 *
+	 * for now, testing each time and use enclosed_str to know if it has
+	 * been processed.
+	 */
+	if (which != XTREE_GROWING && which != XTREE_PREORDER)
+		return 1;
+
+	enclosed_str = (char**)entity_get_data(e, p->enclosed_key);
+
+	if (enclosed_str) {
+		enclosed_hostlist = hostlist_create(*enclosed_str);
+		xfree(*enclosed_str);
+		entity_delete_data(e, p->enclosed_key);
+		while ((enclosed_name = hostlist_shift(enclosed_hostlist))) {
+			enclosed_e = xhash_get(mgr->entities, enclosed_name);
+			if (!enclosed_e) {
+				error("layouts: entity '%s' specified in "
+				      "enclosed entities of entity '%s' "
+				      "not found, ignoring.",
+				      enclosed_name, e->name);
+				free(enclosed_name);
+				continue;
+			}
+			free(enclosed_name);
+			enclosed_node = xtree_add_child(p->tree, node,
+							enclosed_e, 
+							XTREE_APPEND);
+			xassert(enclosed_node);
+			inserted_node = list_append(enclosed_e->nodes,
+						    enclosed_node);
+			xassert(inserted_node == enclosed_node);
+		}
+		hostlist_destroy(enclosed_hostlist);
+	}
+
+	return 1;
+}
+
+/*
+ * _layouts_build_relations - called after _layouts_read_config to create the
+ *        relational structure of the layout according to the topological
+ *        details parsed in stage 1. This is the stage 2 of the layouts
+ *        configuration load.
+ *
+ * This function is the stage 2 of the layouts loading stage, where we use
+ * the relational details extracted from the parsing stage (Enclosed pragmas
+ * and Root entity) to build the relational structure of the layout.
+ *
+ */
+static int _layouts_build_relations(layout_plugin_t* plugin)
+{
+	xtree_t* tree;
+	xtree_node_t* root_node;
+	char key[PATHLEN];
+	switch(plugin->layout->struct_type) {
+	case LAYOUT_STRUCT_TREE:
+		tree = layout_get_tree(plugin->layout);
+		xassert(tree);
+		root_node = xtree_get_root(tree);
+		_normalize_keydef_mgrkey(key, PATHLEN, "enclosed",
+					 plugin->layout->type);
+		_layouts_build_xtree_walk_t p = {
+			key,
+			tree
+		};
+		xtree_walk(tree,
+			   root_node,
+			   0,
+			   XTREE_LEVEL_MAX,
+			   _layouts_build_xtree_walk,
+			   &p);
+		break;
+	}
+	return SLURM_SUCCESS;
+}
+
+/*
+ * For debug purposes, dump functions helping to print the layout mgr
+ * internal states in a file after the load.
+ */
+#if 0
+static char* _dump_data_key(layouts_keydef_t* keydef, void* value)
+{
+	char val;
+	if (!keydef) {
+		return xstrdup("ERROR_bad_keydef");
+	}
+	switch(keydef->type) {
+	case L_T_ERROR:
+		return xstrdup("ERROR_keytype!");
+	case L_T_STRING:
+		return xstrdup((char*)value);
+	case L_T_LONG:
+		return xstrdup_printf("%ld", *(long*)value);
+	case L_T_UINT16:
+		return xstrdup_printf("%u", *(uint16_t*)value);
+	case L_T_UINT32:
+		return xstrdup_printf("%ul", *(uint32_t*)value);
+	case L_T_BOOLEAN:
+		val = *(bool*)value;
+		return xstrdup_printf("%s", val ? "true" : "false");
+	case L_T_FLOAT:
+		return xstrdup_printf("%f", *(float*)value);
+	case L_T_DOUBLE:
+		return xstrdup_printf("%f", *(double*)value);
+	case L_T_LONG_DOUBLE:
+		return xstrdup_printf("%Lf", *(long double*)value);
+	case L_T_CUSTOM:
+		if (keydef->custom_dump) {
+			return keydef->custom_dump(value);
+		}
+		return xstrdup_printf("custom_ptr(%p)", value);
+	}
+	return NULL;
+}
+
+static void _dump_entity_data(void* item, void* arg)
+{
+	entity_data_t* data = (entity_data_t*)item;
+	FILE* fdump = (FILE*)arg;
+	layouts_keydef_t* keydef;
+	char* data_dump;
+
+	xassert(data);
+	keydef = xhash_get(mgr->keydefs, data->key);
+	xassert(keydef);
+	data_dump = _dump_data_key(keydef, data->value);
+
+	fprintf(fdump, "data %s (type: %d): %s\n",
+		data->key, keydef->type, data_dump);
+
+	xfree(data_dump);
+}
+
+static void _dump_entities(void* item, void* arg)
+{
+	entity_t* entity = (entity_t*)item;
+	FILE* fdump = (FILE*)arg;
+	fprintf(fdump, "-- entity %s --\n", entity->name);
+	fprintf(fdump, "type: %s\nnode count: %d\nptr: %p\n",
+		entity->type, list_count(entity->nodes), entity->ptr);
+	xhash_walk(entity->data, _dump_entity_data, fdump);
+}
+
+static uint8_t _dump_layout_tree(xtree_node_t* node, uint8_t which,
+				 uint32_t level, void* arg)
+{
+	FILE* fdump = (FILE*)arg;
+	entity_t* e;
+	if (which != XTREE_PREORDER && which != XTREE_LEAF) {
+		return 1;
+	}
+	e = xtree_node_get_data(node);
+	if (!e) {
+		fprintf(fdump, "NULL_entity\n");
+	}
+	else {
+		fprintf(fdump, "%*s%s\n", level, " ", e->name);
+	}
+	return 1;
+}
+
+static void _dump_layouts(void* item, void* arg)
+{
+	layout_t* layout = (layout_t*)item;
+	FILE* fdump = (FILE*)arg;
+	fprintf(fdump, "-- layout %s --\n"
+		"type: %s\n"
+		"priority: %u\n"
+		"struct_type: %d\n"
+		"relational ptr: %p\n",
+		layout->name,
+		layout->type,
+		layout->priority,
+		layout->struct_type,
+		layout->tree);
+	switch(layout->struct_type) {
+	case LAYOUT_STRUCT_TREE:
+		fprintf(fdump, "struct_type(string): tree, count: %d\n"
+			"entities list:\n",
+			xtree_get_count(layout->tree));
+		xtree_walk(layout->tree, NULL, 0, XTREE_LEVEL_MAX,
+			   _dump_layout_tree, fdump);
+		break;
+	}
+}
+#endif
+
+/*****************************************************************************\
+ *                             SLURM LAYOUTS API                             *
+\*****************************************************************************/
+
+int slurm_layouts_init()
+{
+	int i = 0;
+	uint32_t layouts_count;
+
+	debug3("layouts: slurm_layouts_init()...");
+
+	if (mgr->plugins) {
+		return SLURM_SUCCESS;
+	}
+
+	slurm_mutex_lock(&layouts_mgr.lock);
+
+	layouts_mgr_init(&layouts_mgr);
+	layouts_count = list_count(layouts_mgr.layouts_desc);
+	if (layouts_count == 0)
+		info("layouts: no layout to initialize");
+	else
+		info("layouts: %d layout(s) to initialize", layouts_count);
+
+	mgr->plugins = xmalloc(sizeof(layout_plugin_t) * layouts_count);
+	list_for_each(layouts_mgr.layouts_desc,
+			_slurm_layouts_init_layouts_walk_helper,
+			&i);
+	mgr->plugins_count = i;
+
+	if (mgr->plugins_count != layouts_count) {
+		error("layouts: only %d/%d layouts loaded, aborting...",
+		      mgr->plugins_count, layouts_count);
+		for (i = 0; i < mgr->plugins_count; i++) {
+			_layout_plugins_destroy(&mgr->plugins[i]);
+		}
+		xfree(mgr->plugins);
+		mgr->plugins = NULL;
+	} else if (layouts_count > 0) {
+		info("layouts: slurm_layouts_init done : %d layout(s) "
+		     "initialized", layouts_count);
+	}
+
+	slurm_mutex_unlock(&layouts_mgr.lock);
+
+	return mgr->plugins_count == layouts_count ?
+		SLURM_SUCCESS : SLURM_ERROR;
+}
+
+int slurm_layouts_fini()
+{
+	int i;
+
+	debug3("layouts: slurm_layouts_fini()...");
+
+	slurm_mutex_lock(&mgr->lock);
+
+	for (i = 0; i < mgr->plugins_count; i++) {
+		_layout_plugins_destroy(&mgr->plugins[i]);
+	}
+	xfree(mgr->plugins);
+	mgr->plugins = NULL;
+
+	layouts_mgr_free(mgr);
+
+	slurm_mutex_unlock(&mgr->lock);
+
+	info("layouts: all layouts are now unloaded.");
+
+	return SLURM_SUCCESS;
+}
+
+int slurm_layouts_load_config()
+{
+	int i, rc, inx;
+	struct node_record *node_ptr;
+	layout_t *layout;
+	uint32_t layouts_count;
+	entity_t *entity;
+	void *ptr;
+
+	info("layouts: loading entities/relations information");
+	rc = SLURM_SUCCESS;
+
+	slurm_mutex_lock(&mgr->lock);
+
+	/*
+	 * create a base layout to contain the configured nodes
+	 * Notes : it might be moved to its own external layout in the
+	 * slurm source layouts directory.
+	 */
+	layout = (layout_t*) xmalloc(sizeof(layout_t));
+	layout_init(layout, "slurm", "base", 0, LAYOUT_STRUCT_TREE);
+	if (xtree_add_child(layout->tree, NULL, NULL, XTREE_APPEND) == NULL) {
+		error("layouts: unable to create base layout tree root"
+		      ", aborting");
+		goto exit;
+	}
+
+	/*
+	 * generate and store the slurm node entities,
+	 * add them to the base layout at the same time
+	 */
+	for (inx = 0, node_ptr = node_record_table_ptr; inx < node_record_count;
+	     inx++, node_ptr++) {
+		xassert (node_ptr->magic == NODE_MAGIC);
+		xassert (node_ptr->config_ptr->magic == CONFIG_MAGIC);
+		debug("layouts: loading node %s",node_ptr->name);
+
+		/* init entity structure on the heap */
+		entity = (entity_t*) xmalloc(sizeof(struct entity_st));
+		entity_init(entity, node_ptr->name, 0); 
+		entity->ptr = node_ptr;
+
+		/* add to mgr entity hashtable */
+		if (xhash_add(layouts_mgr.entities,(void*)entity) == NULL) {
+			error("layouts: unable to add entity of node %s"
+			      "in the hashtable, aborting", node_ptr->name);
+			entity_free(entity);
+			xfree(entity);
+			rc = SLURM_ERROR;
+			break;
+		}
+
+		/* add to the base layout (storing a callback ref to the
+		   layout node pointing to it) */
+		ptr = xtree_add_child(layout->tree, layout->tree->root,
+				      (void*)entity, XTREE_APPEND);
+		if (!ptr) {
+			error("layouts: unable to add entity of node %s"
+			      "in the hashtable, aborting", node_ptr->name);
+			entity_free(entity);
+			xfree(entity);
+			rc = SLURM_ERROR;
+			break;
+		} else
+			entity_add_node(entity, layout, ptr);
+
+	}
+	debug("layouts: %d/%d nodes in hash table, rc=%d", 
+	      xhash_count(layouts_mgr.entities), node_record_count, rc);
+
+	if (rc != SLURM_SUCCESS)
+		goto exit;
+
+	/* add the base layout to the layouts manager dedicated hashtable */
+	if (xhash_add(layouts_mgr.layouts, (void*)layout) == NULL) {
+		error("layouts: unable to add base layout into the hashtable");
+		layout_free(layout);
+		rc = SLURM_ERROR;
+	}
+
+	/* check that we get as many layouts as initiliazed plugins
+	 * as layouts are added and referenced by type.
+	 * do +1 in the operation as the base layout is currently managed
+	 * separately.
+	 * If this base layout is moved to a dedicated plugin and automatically
+	 * added to the mgr layouts_desc at init, the +1 will have to be
+	 * removed here as it will be counted as the other plugins in the sum
+	 */
+	layouts_count = xhash_count(layouts_mgr.layouts);
+	if ( layouts_count != mgr->plugins_count + 1) {
+		error("layouts: %d/%d layouts added to hashtable, aborting",
+		      layouts_count,mgr->plugins_count+1);
+		rc = SLURM_ERROR;
+	}
+
+exit:
+	if (rc != SLURM_SUCCESS) {
+		layout_free(layout);
+		xfree(layout);
+	} else {
+		debug("layouts: loading stage 1");
+		for (i = 0; i < mgr->plugins_count; ++i) {
+			debug3("layouts: reading config for %s",
+			       mgr->plugins[i].name);
+			if (_layouts_read_config(&mgr->plugins[i]) !=
+			    SLURM_SUCCESS) {
+				rc = SLURM_ERROR;
+				break;
+			}
+		}
+		debug("layouts: loading stage 2");
+		for (i = 0; i < mgr->plugins_count; ++i) {
+			debug3("layouts: creating relations for %s",
+			       mgr->plugins[i].name);
+			if (_layouts_build_relations(&mgr->plugins[i]) !=
+			    SLURM_SUCCESS) {
+				rc = SLURM_ERROR;
+				break;
+			}
+		}
+	}
+
+/*
+ * For debug purposes, print the layout mgr internal states
+ * in a file after the load.
+ */
+#if 0
+	/* temporary section to test layouts */
+	FILE* fdump = fopen("/tmp/slurm-layouts-dump.txt", "wb");
+
+	xhash_walk(mgr->entities, _dump_entities, fdump);
+	xhash_walk(mgr->layouts,  _dump_layouts,  fdump);
+
+	if (fdump)
+		fclose(fdump);
+#endif
+
+	slurm_mutex_unlock(&mgr->lock);
+
+	return rc;
+}
+
+layout_t* slurm_layouts_get_layout(const char* type)
+{
+	layout_t* layout = (layout_t*)xhash_get(mgr->layouts, type);
+	return layout;
+}
+
+entity_t* slurm_layouts_get_entity(const char* name)
+{
+	entity_t* e = (entity_t*)xhash_get(mgr->entities, name);
+	return e;
+}
diff --git a/src/common/layouts_mgr.h b/src/common/layouts_mgr.h
new file mode 100644
index 00000000000..51d997e3bbe
--- /dev/null
+++ b/src/common/layouts_mgr.h
@@ -0,0 +1,151 @@
+/*****************************************************************************\
+ *  layouts_mgr.h - layouts manager data structures and main functions
+ *****************************************************************************
+ *  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.
+ *
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://slurm.schedmd.com/>.
+ *  Please also read the included file: DISCLAIMER.
+ *
+ *  SLURM is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  In addition, as a special exception, the copyright holders give permission
+ *  to link the code of portions of this program with the OpenSSL library under
+ *  certain conditions as described in each individual source file, and
+ *  distribute linked combinations including the two. You must obey the GNU
+ *  General Public License in all respects for all of the code used other than
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this
+ *  exception to your version of the file(s), but you are not obligated to do
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in
+ *  the program, then also delete it here.
+ *
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#ifndef __LAYOUTS_MGR_1NRINRSD__INC__
+#define __LAYOUTS_MGR_1NRINRSD__INC__
+
+#include "src/common/list.h"
+#include "src/common/xhash.h"
+#include "src/common/xtree.h"
+#include "src/common/parse_config.h"
+
+#include "src/common/layout.h"
+#include "src/common/entity.h"
+
+/*
+ * Layouts are managed through a "layouts manager" of type layouts_mgr_t.
+ *
+ * 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()
+ * and then load the required layouts defined in the configuration using
+ * slurm_layouts_load_config().
+ *
+ * The different layouts and entities can then be queried using either
+ * slurm_layouts_get_layout() and slurm_layouts_get_entity().
+ *
+ * Note that each entity contains a list of nodes appearing inside the
+ * associated layouts.
+ */
+
+/*
+ * Potential enhancement to complete: agregate specified plugin etypes in a
+ *      xhash in the mgr, avoiding same string to be duplicated again and again.
+ *      (in short: apply the same logic for etypes as for entity data keys.)
+ */
+
+typedef enum layouts_keydef_types_en {
+	L_T_ERROR = 0,
+	L_T_STRING,
+	L_T_LONG,
+	L_T_UINT16,
+	L_T_UINT32,
+	L_T_BOOLEAN,
+	L_T_FLOAT,
+	L_T_DOUBLE,
+	L_T_LONG_DOUBLE,
+	L_T_CUSTOM,
+} layouts_keydef_types_t;
+
+typedef struct layouts_keyspec_st {
+	char*			key;
+	layouts_keydef_types_t	type;
+	void			(*custom_destroy)(void*);
+	char*			(*custom_dump)(void*);
+} layouts_keyspec_t;
+
+typedef struct layouts_plugin_spec_st {
+	const s_p_options_t*		options;
+	const layouts_keyspec_t*	keyspec;
+	int				struct_type;
+	const char**			etypes;
+	bool				automerge;
+} layouts_plugin_spec_t;
+
+/*****************************************************************************\
+ *                             PLUGIN FUNCTIONS                              *
+\*****************************************************************************/
+
+/*
+ * slurm_layouts_init - intialize the layouts mgr, load the required plugins
+ *        and initialize the internal hash tables for entities, keydefs and
+ *        layouts.
+ *
+ * Return SLURM_SUCCESS or SLURM_ERROR if all the required layouts were not
+ * loaded correctly.
+ *
+ * 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()
+ *
+ */
+int slurm_layouts_init();
+
+/*
+ * slurm_layouts_fini - uninitialize the layouts mgr and free the internal
+ *        hash tables.
+ */
+int slurm_layouts_fini();
+
+/*
+ * slurm_layouts_load_config - use the layouts plugins details loaded during
+ *        slurm_layouts_init() and read+parse the different layouts
+ *        configuration files, creating the entities and the relational
+ *        structures associated the eaf of them.
+ *
+ * Return SLURM_SUCCESS or SLURM_ERROR if all the required layouts were not
+ * loaded correctly.
+ */
+int slurm_layouts_load_config();
+
+/*
+ * slurm_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);
+
+/*
+ * slurm_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);
+
+#endif /* end of include guard: __LAYOUTS_MGR_1NRINRSD__INC__ */
-- 
GitLab