/*****************************************************************************\ * entity.c - layouts entities data structures and main functions ***************************************************************************** * Initially written by Francois Chevallier * at Bull for slurm-2.6. * Adapted by Matthieu Hautreux for slurm-14.11. * * This file is part of Slurm, a resource management program. * For details, see . * 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 void _entity_data_identify(void* item, const char** key, uint32_t* key_len) { entity_data_t* data_item = (entity_data_t*)item; *key = data_item->key; *key_len = strlen(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_str(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_str(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_str(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); } void entity_hashable_identify(void* item, const char** key, uint32_t* key_len) { entity_t* entity = (entity_t*)item; *key = entity->name; *key_len = strlen(entity->name); }