blob: 52b37c1f379ab26d3d61af61b6a8beeeb8e21504 [file] [log] [blame] [edit]
/*****************************************************************************\
* 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 <https://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 "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"
#include "src/common/xstring.h"
#include "src/common/xtree.h"
/*****************************************************************************\
* HELPERS *
\*****************************************************************************/
static const char* _entity_data_identify(void* item)
{
entity_data_t* data_item = (entity_data_t*)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;
if (entity_node) {
/* layout and node should be freed elsewhere */
xfree(entity_node);
}
}
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, _entity_data_destroy);
entity->nodes = list_create(_entity_node_destroy);
entity->ptr = NULL;
}
void entity_free(entity_t* entity)
{
if (entity) {
xfree(entity->name);
xfree(entity->type);
xhash_free(entity->data);
FREE_NULL_LIST(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;
}
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 NULL;
}
int entity_set_data(const entity_t* entity, const char* key,
void* value, size_t size)
{
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)
{
xhash_delete(entity->data, key);
}
void entity_clear_data(entity_t* entity)
{
xhash_clear(entity->data);
}
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->entity = entity;
entity_node->node = NULL;
entity_node = list_append(entity->nodes, entity_node);
return entity_node;
}
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_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;
}
}
entity_node_t* entity_get_node(entity_t* entity, layout_t* layout)
{
_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;
}
static int _entity_node_find(void* x, void* key)
{
entity_node_t* entity_node = (entity_node_t*)x;
return entity_node->node == key;
}
int entity_delete_node(entity_t* entity, layout_t* layout)
{
int rc = SLURM_ERROR;
entity_node_t* node;
ListIterator i;
node = entity_get_node(entity, layout);
if (node == NULL)
return rc;
i = list_iterator_create(entity->nodes);
if (list_find(i, _entity_node_find, node)) {
list_delete_item(i);
rc = SLURM_SUCCESS;
}
list_iterator_destroy(i);
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, entity_node_t* 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,
real_arg->arg);
return 0;
}
void entity_nodes_walk(entity_t* entity,
void (*callback)(layout_t* layout,
entity_node_t* 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;
}