Files
neuron/src/core/node_manager.c
T
fengzeroz 44dd8bd44c Merge pull request #2933 from ZhouBox/v2.15
[v2.15]restful: support querying nodes by multiple plugins
2026-08-21 09:55:36 +08:00

589 lines
16 KiB
C

/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#include <stdlib.h>
#include <string.h>
#include "errcodes.h"
#include "adapter/adapter_internal.h"
#include "node_manager.h"
typedef struct node_entity {
char *name;
neu_adapter_t * adapter;
bool is_static;
bool display;
bool single;
bool is_monitor;
struct sockaddr_un addr;
char *tags;
UT_hash_handle hh;
} node_entity_t;
struct neu_node_manager {
node_entity_t *nodes;
UT_array * monitors;
};
int neu_node_manager_update_tags(neu_node_manager_t *mgr, const char *name,
const char *tags)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
if (NULL == node) {
return NEU_ERR_NODE_NOT_EXIST;
}
if (node->tags) {
free(node->tags);
}
node->tags = strdup(tags);
return 0;
}
neu_node_manager_t *neu_node_manager_create()
{
neu_node_manager_t *node_manager = calloc(1, sizeof(neu_node_manager_t));
if (node_manager) {
utarray_new(node_manager->monitors, &ut_ptr_icd);
}
return node_manager;
}
void neu_node_manager_destroy(neu_node_manager_t *mgr)
{
node_entity_t *el = NULL, *tmp = NULL;
HASH_ITER(hh, mgr->nodes, el, tmp)
{
HASH_DEL(mgr->nodes, el);
free(el->name);
free(el);
}
utarray_free(mgr->monitors);
free(mgr);
}
int neu_node_manager_add(neu_node_manager_t *mgr, neu_adapter_t *adapter,
const char *tags)
{
node_entity_t *node = calloc(1, sizeof(node_entity_t));
node->adapter = adapter;
node->name = strdup(adapter->name);
node->display = true;
node->is_monitor =
(0 == strcmp(node->adapter->module->module_name, "Monitor"));
node->tags = tags ? strdup(tags) : NULL;
HASH_ADD_STR(mgr->nodes, name, node);
if (node->is_monitor) {
utarray_push_back(mgr->monitors, &node);
}
return 0;
}
int neu_node_manager_add_static(neu_node_manager_t *mgr, neu_adapter_t *adapter)
{
node_entity_t *node = calloc(1, sizeof(node_entity_t));
node->adapter = adapter;
node->name = strdup(adapter->name);
node->is_static = true;
node->display = true;
HASH_ADD_STR(mgr->nodes, name, node);
return 0;
}
int neu_node_manager_add_single(neu_node_manager_t *mgr, neu_adapter_t *adapter,
bool display)
{
node_entity_t *node = calloc(1, sizeof(node_entity_t));
node->adapter = adapter;
node->name = strdup(adapter->name);
node->display = display;
node->single = true;
HASH_ADD_STR(mgr->nodes, name, node);
return 0;
}
int neu_node_manager_update_name(neu_node_manager_t *mgr, const char *node_name,
const char *new_node_name)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, node_name, node);
if (NULL == node) {
return NEU_ERR_NODE_NOT_EXIST;
}
char *new_name = strdup(new_node_name);
if (NULL == new_name) {
return NEU_ERR_EINTERNAL;
}
HASH_DEL(mgr->nodes, node);
free(node->name);
node->name = new_name;
HASH_ADD_STR(mgr->nodes, name, node);
return 0;
}
int neu_node_manager_update(neu_node_manager_t *mgr, const char *name,
struct sockaddr_un addr)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
if (NULL == node) {
return -1;
}
node->addr = addr;
return 0;
}
void neu_node_manager_del(neu_node_manager_t *mgr, const char *name)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
if (node != NULL) {
HASH_DEL(mgr->nodes, node);
if (node->is_monitor) {
utarray_erase(mgr->monitors, utarray_eltidx(mgr->monitors, node),
1);
}
free(node->name);
if (node->tags) {
free(node->tags);
}
free(node);
}
}
uint16_t neu_node_manager_size(neu_node_manager_t *mgr)
{
return HASH_COUNT(mgr->nodes);
}
bool neu_node_manager_exist_uninit(neu_node_manager_t *mgr)
{
node_entity_t *el = NULL, *tmp = NULL;
HASH_ITER(hh, mgr->nodes, el, tmp)
{
if (el->addr.sun_path[1] == 0) {
return true;
}
}
return false;
}
UT_array *neu_node_manager_get(neu_node_manager_t *mgr, int type)
{
UT_array * array = NULL;
UT_icd icd = { sizeof(neu_resp_node_info_t), NULL, NULL, NULL };
node_entity_t *el = NULL, *tmp = NULL;
utarray_new(array, &icd);
HASH_ITER(hh, mgr->nodes, el, tmp)
{
if (!el->is_static && el->display) {
if (el->adapter->module->type & type) {
neu_resp_node_info_t info = { 0 };
snprintf(info.node, sizeof(info.node), "%s", el->adapter->name);
snprintf(info.plugin, sizeof(info.plugin), "%s",
el->adapter->module->module_name);
utarray_push_back(array, &info);
}
}
}
return array;
}
static int neu_resp_node_info_sort(const void *a, const void *b)
{
const neu_resp_node_info_t *info_a = (const neu_resp_node_info_t *) a;
const neu_resp_node_info_t *info_b = (const neu_resp_node_info_t *) b;
if (info_a->delay < info_b->delay) {
return -1;
} else if (info_a->delay > info_b->delay) {
return 1;
}
return 0;
}
static bool find_tag_in_tags(const char *tags, const char *tag)
{
if (strlen(tags) == 0) {
return false;
}
char *tags_copy = strdup(tags);
char *saveptr = NULL;
char *token = strtok_r(tags_copy, ",", &saveptr);
while (token != NULL) {
if (strcmp(token, tag) == 0) {
free(tags_copy);
return true;
}
token = strtok_r(NULL, ",", &saveptr);
}
free(tags_copy);
return false;
}
UT_array *neu_node_manager_filter(neu_node_manager_t *mgr, int type,
const char (*plugins)[NEU_PLUGIN_NAME_LEN],
int n_plugins, const char *node,
bool sort_delay, bool q_state, int state,
bool q_link, int link,
const char *q_group_name)
{
UT_array * array = NULL;
UT_icd icd = { sizeof(neu_resp_node_info_t), NULL, NULL, NULL };
node_entity_t *el = NULL, *tmp = NULL;
utarray_new(array, &icd);
HASH_ITER(hh, mgr->nodes, el, tmp)
{
if (!el->is_static && el->display) {
if (el->adapter->module->type & type) {
if (n_plugins > 0) {
bool matched = false;
for (int i = 0; i < n_plugins; i++) {
if (strcmp(el->adapter->module->module_name,
plugins[i]) == 0) {
matched = true;
break;
}
}
if (!matched) {
continue;
}
}
if (strlen(node) > 0) {
char *name_find = strstr(el->adapter->name, node);
if (name_find == NULL &&
(el->tags == NULL || strlen(el->tags) == 0)) {
continue;
}
if (el->tags != NULL) {
char node_tmp[NEU_NODE_NAME_LEN] = { 0 };
strncpy(node_tmp, node, NEU_NODE_NAME_LEN - 1);
size_t index = 0;
char tag_split_array[10][NEU_NODE_TAGS_LEN] = { 0 };
char * token = strtok(node_tmp, ",");
while (token != NULL && index < 10) {
snprintf(tag_split_array[index],
sizeof(tag_split_array[index]), "%s",
token);
index++;
token = strtok(NULL, ",");
}
bool tag_found = true;
for (size_t i = 0; i < index; i++) {
if (find_tag_in_tags(el->tags,
tag_split_array[i]) == false) {
tag_found = false;
break;
}
}
if (!tag_found && name_find == NULL) {
continue;
}
}
}
if (q_state) {
if (el->adapter->state !=
(neu_node_running_state_e) state) {
continue;
}
}
if (q_link) {
neu_node_state_t node_state =
neu_adapter_get_state(el->adapter);
if (node_state.link != (neu_node_link_state_e) link) {
continue;
}
}
if (strlen(q_group_name) > 0) {
if (strstr(el->adapter->name, q_group_name) == NULL) {
UT_array *groups =
neu_adapter_get_groups(el->adapter, q_group_name);
if (NULL == groups || utarray_len(groups) == 0) {
if (groups != NULL) {
utarray_free(groups);
}
continue;
} else {
utarray_free(groups);
}
}
}
neu_resp_node_info_t info = { 0 };
snprintf(info.node, sizeof(info.node), "%s", el->adapter->name);
snprintf(info.tags, sizeof(info.tags), "%s",
el->tags ? el->tags : "");
snprintf(info.plugin, sizeof(info.plugin), "%s",
el->adapter->module->module_name);
if (sort_delay) {
neu_metric_entry_t *e = NULL;
if (NULL != el->adapter->metrics) {
HASH_FIND_STR(el->adapter->metrics->entries,
NEU_METRIC_LAST_RTT_MS, e);
}
info.delay = NULL != e ? e->value : 0;
} else {
info.delay = 0;
}
utarray_push_back(array, &info);
}
}
}
if (sort_delay) {
utarray_sort(array, neu_resp_node_info_sort);
}
return array;
}
UT_array *neu_node_manager_get_all(neu_node_manager_t *mgr)
{
UT_array * array = NULL;
UT_icd icd = { sizeof(neu_resp_node_info_t), NULL, NULL, NULL };
node_entity_t *el = NULL, *tmp = NULL;
utarray_new(array, &icd);
HASH_ITER(hh, mgr->nodes, el, tmp)
{
neu_resp_node_info_t info = { 0 };
snprintf(info.node, sizeof(info.node), "%s", el->adapter->name);
snprintf(info.plugin, sizeof(info.plugin), "%s",
el->adapter->module->module_name);
utarray_push_back(array, &info);
}
return array;
}
UT_array *neu_node_manager_get_adapter(neu_node_manager_t *mgr, int type)
{
UT_array * array = NULL;
node_entity_t *el = NULL, *tmp = NULL;
utarray_new(array, &ut_ptr_icd);
HASH_ITER(hh, mgr->nodes, el, tmp)
{
if (!el->is_static && el->display) {
if (el->adapter->module->type & type) {
utarray_push_back(array, &el->adapter);
}
}
}
return array;
}
neu_adapter_t *neu_node_manager_find(neu_node_manager_t *mgr, const char *name)
{
neu_adapter_t *adapter = NULL;
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
if (node != NULL) {
adapter = node->adapter;
}
return adapter;
}
bool neu_node_manager_is_single(neu_node_manager_t *mgr, const char *name)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
if (node != NULL) {
return node->single;
}
return false;
}
bool neu_node_manager_is_driver(neu_node_manager_t *mgr, const char *name)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
if (node != NULL) {
return NEU_NA_TYPE_DRIVER == node->adapter->module->type;
}
return false;
}
bool neu_node_manager_is_exist(neu_node_manager_t *mgr, const char *name)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
if (node != NULL) {
return true;
}
return false;
}
UT_array *neu_node_manager_get_addrs(neu_node_manager_t *mgr, int type)
{
UT_icd icd = { sizeof(struct sockaddr_un), NULL, NULL, NULL };
UT_array * addrs = NULL;
node_entity_t *el = NULL, *tmp = NULL;
utarray_new(addrs, &icd);
HASH_ITER(hh, mgr->nodes, el, tmp)
{
if (!el->is_static) {
if (el->adapter->module->type & type) {
utarray_push_back(addrs, &el->addr);
}
}
}
return addrs;
}
UT_array *neu_node_manager_get_addrs_all(neu_node_manager_t *mgr)
{
UT_icd icd = { sizeof(struct sockaddr_un), NULL, NULL, NULL };
UT_array * addrs = NULL;
node_entity_t *el = NULL, *tmp = NULL;
utarray_new(addrs, &icd);
HASH_ITER(hh, mgr->nodes, el, tmp) { utarray_push_back(addrs, &el->addr); }
return addrs;
}
struct sockaddr_un neu_node_manager_get_addr(neu_node_manager_t *mgr,
const char * name)
{
struct sockaddr_un addr = { 0 };
node_entity_t * node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
if (node != NULL) {
addr = node->addr;
}
return addr;
}
bool neu_node_manager_is_monitor(neu_node_manager_t *mgr, const char *name)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
return node ? node->is_monitor : false;
}
/*int neu_node_manager_for_each_monitor(neu_node_manager_t *mgr,
int (*cb)(const char * name,
struct sockaddr_un addr,
void * data),
void *data)
{
int rv = 0;
utarray_foreach(mgr->monitors, node_entity_t **, node)
{
rv = cb((*node)->name, (*node)->addr, data);
if (0 != rv) {
break;
}
}
return rv;
}*/
UT_array *neu_node_manager_get_state(neu_node_manager_t *mgr)
{
UT_icd icd = { sizeof(neu_nodes_state_t), NULL, NULL, NULL };
UT_array * states = NULL;
node_entity_t *el = NULL, *tmp = NULL;
utarray_new(states, &icd);
HASH_ITER(hh, mgr->nodes, el, tmp)
{
neu_nodes_state_t state = { 0 };
if (!el->is_static && el->display) {
snprintf(state.node, sizeof(state.node), "%s", el->adapter->name);
state.state.running = el->adapter->state;
state.state.link =
neu_plugin_to_plugin_common(el->adapter->plugin)->link_state;
state.state.log_level = el->adapter->log_level;
state.is_driver = (el->adapter->module->type == NEU_NA_TYPE_DRIVER)
? true
: false;
neu_metric_entry_t *e = NULL;
if (NULL != el->adapter->metrics) {
HASH_FIND_STR(el->adapter->metrics->entries,
NEU_METRIC_LAST_RTT_MS, e);
}
state.rtt = NULL != e ? e->value : 0;
utarray_push_back(states, &state);
}
}
return states;
}