Files
neuron/src/core/manager.c
T
2026-07-02 03:03:39 +00:00

2108 lines
77 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 <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/un.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "event/event.h"
#include "persist/persist.h"
#include "utils/base64.h"
#include "utils/http.h"
#include "utils/log.h"
#include "utils/neu_path.h"
#include "utils/time.h"
#include "adapter.h"
#include "adapter/adapter_internal.h"
#include "adapter/driver/driver_internal.h"
#include "adapter/storage.h"
#include "argparse.h"
#include "base/msg_internal.h"
#include "errcodes.h"
#include "otel/otel_manager.h"
#include "node_manager.h"
#include "plugin_manager.h"
#include "storage.h"
#include "subscribe.h"
#include "manager.h"
#include "manager_internal.h"
// definition for adapter names
#define DEFAULT_DASHBOARD_ADAPTER_NAME DEFAULT_DASHBOARD_PLUGIN_NAME
static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data);
inline static void reply(neu_manager_t *manager, neu_reqresp_head_t *header,
void *data);
inline static void forward_msg(neu_manager_t * manager,
neu_reqresp_head_t *header, const char *node);
inline static void forward_msg_copy(neu_manager_t * manager,
neu_reqresp_head_t *header,
const char * node);
inline static void notify_monitor(neu_manager_t * manager,
neu_reqresp_type_e event, void *data);
static void start_static_adapter(neu_manager_t *manager, const char *name);
static int update_timestamp(void *usr_data);
static void start_single_adapter(neu_manager_t *manager, const char *name,
const char *plugin_name, bool display);
static char *file_save_tmp(const char *data, const char *suffix);
static bool mv_tmp_library_file(neu_plugin_kind_e kind, const char *tmp_path,
const char *library);
static bool mv_tmp_schema_file(neu_plugin_kind_e kind, const char *tmp_path,
const char *schema);
uint16_t neu_manager_get_port()
{
static uint16_t port = 10000;
return port++;
}
int neu_manager_get_global_log_level()
{
extern neu_manager_t *g_manager;
if (g_manager != NULL) {
return g_manager->log_level;
}
return ZLOG_LEVEL_INFO;
}
neu_manager_t *neu_manager_create()
{
int rv = 0;
neu_manager_t * manager = calloc(1, sizeof(neu_manager_t));
neu_event_io_param_t param = {
.usr_data = (void *) manager,
.cb = manager_loop,
};
neu_event_timer_param_t timestamp_timer_param = {
.second = 0,
.millisecond = 10,
.cb = update_timestamp,
.type = NEU_EVENT_TIMER_NOBLOCK,
};
manager->events = neu_event_new("manager");
manager->plugin_manager = neu_plugin_manager_create();
manager->node_manager = neu_node_manager_create();
manager->subscribe_manager = neu_subscribe_manager_create();
manager->log_level = default_log_level;
manager->server_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
assert(manager->server_fd > 0);
struct timeval sock_timeout = {
.tv_sec = 1,
.tv_usec = 0,
};
if (setsockopt(manager->server_fd, SOL_SOCKET, SO_SNDTIMEO, &sock_timeout,
sizeof(sock_timeout)) < 0 ||
setsockopt(manager->server_fd, SOL_SOCKET, SO_RCVTIMEO, &sock_timeout,
sizeof(sock_timeout)) < 0) {
assert(!"fail to set manager sock timeout");
}
// abstract domain socket is a Linux extension, thus not portable.
// use abstract domain socket here to avoid polluting the file system
struct sockaddr_un local = {
.sun_family = AF_UNIX,
.sun_path = "#neuron-manager",
};
local.sun_path[0] = '\0';
rv = bind(manager->server_fd, (struct sockaddr *) &local, sizeof(local));
assert(rv == 0);
param.fd = manager->server_fd;
manager->loop = neu_event_add_io(manager->events, param);
manager->timestamp_lev_manager = 0;
strncpy(g_status, "loading", sizeof(g_status));
neu_metrics_init();
start_static_adapter(manager, DEFAULT_DASHBOARD_PLUGIN_NAME);
if (manager_load_plugin(manager) != 0) {
nlog_warn("load plugin error");
}
UT_array *single_plugins =
neu_plugin_manager_get_single(manager->plugin_manager);
utarray_foreach(single_plugins, neu_resp_plugin_info_t *, plugin)
{
start_single_adapter(manager, plugin->single_name, plugin->name,
plugin->display);
}
utarray_free(single_plugins);
manager_load_node(manager);
while (neu_node_manager_exist_uninit(manager->node_manager)) {
usleep(1000 * 100);
}
manager_load_subscribe(manager);
timestamp_timer_param.usr_data = (void *) manager;
manager->timer_timestamp =
neu_event_add_timer(manager->events, timestamp_timer_param);
strncpy(g_status, "ready", sizeof(g_status));
nlog_notice("manager start");
return manager;
}
void neu_manager_destroy(neu_manager_t *manager)
{
neu_req_node_init_t uninit = { 0 };
int send_msg_success = 1;
UT_array *addrs = neu_node_manager_get_addrs_all(manager->node_manager);
neu_event_del_timer(manager->events, manager->timer_timestamp);
utarray_foreach(addrs, struct sockaddr_un *, addr)
{
neu_msg_t *msg = neu_msg_new(NEU_REQ_NODE_UNINIT, NULL, &uninit);
neu_reqresp_head_t *header = neu_msg_get_header(msg);
snprintf(header->sender, sizeof(header->sender), "%s", "manager");
if (0 != neu_send_msg_to(manager->server_fd, addr, msg)) {
nlog_error("manager -> %s uninit msg send fail",
&addr->sun_path[1]);
send_msg_success = 0;
neu_msg_free(msg);
break;
}
}
utarray_free(addrs);
if (send_msg_success) {
while (1) {
usleep(1000 * 100);
if (neu_node_manager_size(manager->node_manager) == 0) {
break;
}
}
}
neu_subscribe_manager_destroy(manager->subscribe_manager);
neu_node_manager_destroy(manager->node_manager);
neu_plugin_manager_destroy(manager->plugin_manager);
close(manager->server_fd);
neu_event_del_io(manager->events, manager->loop);
neu_event_close(manager->events);
free(manager);
nlog_notice("manager exit");
}
static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
{
int rv = 0;
neu_manager_t * manager = (neu_manager_t *) usr_data;
struct sockaddr_un src_addr = { 0 };
neu_msg_t * msg = NULL;
neu_reqresp_head_t *header = NULL;
if (type == NEU_EVENT_IO_CLOSED || type == NEU_EVENT_IO_HUP) {
nlog_warn("manager socket(%d) recv closed or hup %d.", fd, type);
return 0;
}
rv = neu_recv_msg_from(manager->server_fd, &src_addr, &msg);
if (rv == -1) {
nlog_warn("manager recv msg error: %s(%d)", strerror(errno), errno);
return 0;
}
header = neu_msg_get_header(msg);
header->monitor = neu_node_manager_find(manager->node_manager, "monitor");
nlog_info("manager recv msg from: %s to %s, type: %s, monitor: %d",
header->sender, header->receiver,
neu_reqresp_type_string(header->type), header->monitor);
switch (header->type) {
case NEU_REQ_NODE_INIT: {
neu_req_node_init_t *init = (neu_req_node_init_t *) &header[1];
if (0 !=
neu_node_manager_update(manager->node_manager, init->node,
src_addr)) {
nlog_warn("bind node %s to src addr(%s) fail", init->node,
&src_addr.sun_path[1]);
neu_msg_free(msg);
break;
}
if (init->state == NEU_NODE_RUNNING_STATE_READY ||
init->state == NEU_NODE_RUNNING_STATE_RUNNING ||
init->state == NEU_NODE_RUNNING_STATE_STOPPED) {
neu_adapter_t *adapter =
neu_node_manager_find(manager->node_manager, init->node);
neu_adapter_start(adapter);
if (init->state == NEU_NODE_RUNNING_STATE_STOPPED) {
neu_adapter_stop(adapter);
}
}
nlog_notice("bind node %s to src addr(%s)", init->node,
&src_addr.sun_path[1]);
neu_msg_free(msg);
break;
}
case NEU_REQ_UPDATE_NODE_TAG: {
neu_req_update_node_tag_t *cmd =
(neu_req_update_node_tag_t *) &header[1];
int ret = neu_node_manager_update_tags(manager->node_manager, cmd->node,
cmd->tags);
if (ret == 0) {
nlog_info("update node %s tags to %s", cmd->node, cmd->tags);
manager_storage_update_node_tags(manager, cmd->node, cmd->tags);
neu_resp_error_t e = { .error = NEU_ERR_SUCCESS };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
}
break;
}
case NEU_REQ_ADD_PLUGIN: {
neu_req_add_plugin_t *cmd = (neu_req_add_plugin_t *) &header[1];
neu_resp_error_t e = { 0 };
neu_plugin_kind_e kind = -1;
char schema[64] = { 0 };
char buffer[65] = { 0 };
// The library name is used to build a path under the plugin dir; reject
// any name with a path separator or '..' so it cannot escape that dir.
if (!neu_path_is_valid_component(cmd->library)) {
nlog_warn("reject library name with path separator: %s",
cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_NAME_NOT_CONFORM;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (sscanf(cmd->library, "libplugin-%64s.so", buffer) != 1) {
nlog_warn("library %s no conform", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_NAME_NOT_CONFORM;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (neu_persister_library_exists(cmd->library)) {
nlog_warn("library %s had exited", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_NAME_CONFLICT;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
char *so_tmp_path = file_save_tmp(cmd->so_file, "so");
if (so_tmp_path == NULL) {
nlog_warn("library %s so file save tmp fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_BODY_IS_WRONG;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
neu_plugin_instance_t ins = { 0 };
int error = NEU_ERR_SUCCESS;
if (neu_plugin_manager_create_instance_by_path(
manager->plugin_manager, so_tmp_path, &ins, &error)) {
char module_name[64] = { 0 };
kind = ins.module->kind;
strncpy(module_name, ins.module->module_name, sizeof(module_name));
strncpy(schema, ins.module->schema, sizeof(schema));
nlog_debug("library %s, module_name %s, schema:%s", cmd->library,
module_name, schema);
uint32_t major = NEU_GET_VERSION_MAJOR(ins.module->version);
uint32_t minor = NEU_GET_VERSION_MINOR(ins.module->version);
neu_plugin_manager_destroy_instance(manager->plugin_manager, &ins);
if (NEU_VERSION_MAJOR != major || NEU_VERSION_MINOR != minor) {
nlog_warn("library %s plugin version error, major:%d minor:%d",
module_name, major, minor);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_MODULE_VERSION_NOT_MATCH;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (neu_plugin_manager_exists(manager->plugin_manager,
module_name)) {
nlog_warn("%s module name had existed", module_name);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_MODULE_ALREADY_EXIST;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
} else {
nlog_warn("library %s so file is not a vaild file", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = error;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (kind != NEU_PLUGIN_KIND_CUSTOM && kind != NEU_PLUGIN_KIND_SYSTEM) {
nlog_warn("library %s kind no support", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_MODULE_KIND_NOT_SUPPORT;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
char *schema_tmp_path = file_save_tmp(cmd->schema_file, "json");
if (schema_tmp_path == NULL) {
nlog_warn("library %s schema file save tmp fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_BODY_IS_WRONG;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (!mv_tmp_library_file(kind, so_tmp_path, cmd->library)) {
nlog_warn("library %s mv library tmp file fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
free(schema_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_ADD_FAIL;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (!mv_tmp_schema_file(kind, schema_tmp_path, schema)) {
nlog_warn("library %s schema file save schema fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
free(schema_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_ADD_FAIL;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
error = neu_manager_add_plugin(manager, cmd->library);
if (error == NEU_ERR_SUCCESS) {
manager_strorage_plugin(manager);
// notify_monitor(manager, NEU_REQ_ADD_PLUGIN_EVENT, cmd);
}
free(so_tmp_path);
free(cmd->so_file);
free(cmd->schema_file);
free(schema_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = error;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
case NEU_REQ_DEL_PLUGIN: {
neu_req_del_plugin_t *cmd = (neu_req_del_plugin_t *) &header[1];
neu_resp_error_t e = { 0 };
UT_array *nodes = neu_manager_get_nodes(
manager, NEU_NA_TYPE_DRIVER | NEU_NA_TYPE_APP, cmd->plugin, "",
false, false, 0, false, 0, "");
if (nodes != NULL) {
if (utarray_len(nodes) > 0) {
utarray_free(nodes);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_IN_USE;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
utarray_free(nodes);
}
int error = neu_manager_del_plugin(manager, cmd->plugin);
e.error = error;
if (error == NEU_ERR_SUCCESS) {
manager_strorage_plugin(manager);
// notify_monitor(manager, NEU_REQ_DEL_PLUGIN_EVENT, cmd);
}
header->type = NEU_RESP_ERROR;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
case NEU_REQ_UPDATE_PLUGIN: {
neu_req_update_plugin_t *cmd = (neu_req_update_plugin_t *) &header[1];
neu_resp_error_t e = { 0 };
neu_plugin_kind_e kind = -1;
char module_name[64] = { 0 };
char schema[64] = { 0 };
char buffer[65] = { 0 };
if (sscanf(cmd->library, "libplugin-%64s.so", buffer) != 1) {
nlog_warn("library %s no conform", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_NAME_NOT_CONFORM;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (!neu_persister_library_exists(cmd->library)) {
nlog_warn("library %s no exited", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_NOT_FOUND;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
char *so_tmp_path = file_save_tmp(cmd->so_file, "so");
if (so_tmp_path == NULL) {
nlog_warn("library %s so file save tmp fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_BODY_IS_WRONG;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
neu_plugin_instance_t ins = { 0 };
int error = NEU_ERR_SUCCESS;
if (neu_plugin_manager_create_instance_by_path(
manager->plugin_manager, so_tmp_path, &ins, &error)) {
kind = ins.module->kind;
strncpy(module_name, ins.module->module_name, sizeof(module_name));
strncpy(schema, ins.module->schema, sizeof(schema));
nlog_debug("library %s, module_name %s, schema:%s", cmd->library,
module_name, schema);
uint32_t major = NEU_GET_VERSION_MAJOR(ins.module->version);
uint32_t minor = NEU_GET_VERSION_MINOR(ins.module->version);
neu_plugin_manager_destroy_instance(manager->plugin_manager, &ins);
if (NEU_VERSION_MAJOR != major || NEU_VERSION_MINOR != minor) {
nlog_warn("library %s plugin version error, major:%d minor:%d",
module_name, major, minor);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_MODULE_VERSION_NOT_MATCH;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (!neu_plugin_manager_create_instance_by_lib_name(
manager->plugin_manager, cmd->library, &ins)) {
nlog_warn("library %s not instance", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_UPDATE_FAIL;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (strcmp(module_name, ins.module->module_name) != 0) {
nlog_warn("library %s module name mismatch!", cmd->library);
neu_plugin_manager_destroy_instance(manager->plugin_manager,
&ins);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_UPDATE_FAIL;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
neu_plugin_manager_destroy_instance(manager->plugin_manager, &ins);
if (!neu_plugin_manager_exists(manager->plugin_manager,
module_name)) {
nlog_warn("library %s plugin name no existed", module_name);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_MODULE_NOT_EXISTS;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
} else {
nlog_warn("library %s so file is not a vaild file", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = error;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (kind != NEU_PLUGIN_KIND_CUSTOM && kind != NEU_PLUGIN_KIND_SYSTEM) {
nlog_warn("library %s kind no support", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_MODULE_KIND_NOT_SUPPORT;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
char *schema_tmp_path = file_save_tmp(cmd->schema_file, "json");
if (schema_tmp_path == NULL) {
nlog_warn("library %s schema file save tmp fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_BODY_IS_WRONG;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
UT_array *nodes = neu_manager_get_nodes(
manager, NEU_NA_TYPE_DRIVER | NEU_NA_TYPE_APP, module_name, "",
false, false, 0, false, 0, "");
if (nodes != NULL) {
if (utarray_len(nodes) > 0) {
utarray_free(nodes);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
free(schema_tmp_path);
nlog_warn("library %s is using", cmd->library);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_IN_USE;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
utarray_free(nodes);
}
if (!neu_plugin_manager_remove_library(manager->plugin_manager,
cmd->library)) {
nlog_warn("library %s src file remove fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
free(schema_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_UPDATE_FAIL;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (!mv_tmp_library_file(kind, so_tmp_path, cmd->library)) {
nlog_warn("library %s mv library tmp file fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
free(schema_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_UPDATE_FAIL;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (!mv_tmp_schema_file(kind, schema_tmp_path, schema)) {
nlog_warn("library %s schema file save schema fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
free(schema_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_UPDATE_FAIL;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
if (neu_plugin_manager_update(manager->plugin_manager, cmd->library) !=
NEU_ERR_SUCCESS) {
nlog_warn("update library %s fail", cmd->library);
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
free(schema_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_LIBRARY_UPDATE_FAIL;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
free(cmd->so_file);
free(cmd->schema_file);
free(so_tmp_path);
free(schema_tmp_path);
header->type = NEU_RESP_ERROR;
e.error = NEU_ERR_SUCCESS;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
case NEU_REQ_GET_PLUGIN: {
UT_array * plugins = neu_manager_get_plugins(manager);
neu_resp_get_plugin_t resp = { .plugins = plugins };
header->type = NEU_RESP_GET_PLUGIN;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &resp);
break;
}
case NEU_REQ_CHECK_SCHEMA: {
neu_req_check_schema_t *cmd = (neu_req_check_schema_t *) &header[1];
neu_resp_check_schema_t resp = { 0 };
snprintf(resp.schema, sizeof(resp.schema), "%s", cmd->schema);
resp.exist = neu_plugin_manager_schema_exist(manager->plugin_manager,
cmd->schema);
header->type = NEU_RESP_CHECK_SCHEMA;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &resp);
break;
}
case NEU_REQ_ADD_NODE: {
neu_req_add_node_t *cmd = (neu_req_add_node_t *) &header[1];
nlog_notice("add node name:%s plugin:%s", cmd->node, cmd->plugin);
int error =
neu_manager_add_node(manager, cmd->node, cmd->plugin, cmd->setting,
cmd->tags, NEU_NODE_RUNNING_STATE_INIT, false);
neu_resp_error_t e = { .error = error };
if (error == NEU_ERR_SUCCESS) {
manager_storage_add_node(manager, cmd->node, cmd->tags);
if (cmd->setting) {
adapter_storage_setting(cmd->node, cmd->setting);
}
notify_monitor(manager, NEU_REQ_ADD_NODE_EVENT, cmd);
}
neu_req_add_node_fini(cmd);
header->type = NEU_RESP_ERROR;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
case NEU_REQ_UPDATE_NODE: {
neu_req_update_node_t *cmd = (neu_req_update_node_t *) &header[1];
neu_resp_error_t e = { 0 };
nlog_notice("update node name:%s new_name:%s", cmd->node,
cmd->new_name);
if (NULL == neu_node_manager_find(manager->node_manager, cmd->node)) {
e.error = NEU_ERR_NODE_NOT_EXIST;
} else if (NULL !=
neu_node_manager_find(manager->node_manager,
cmd->new_name)) {
// this also makes renaming to the original name an error
e.error = NEU_ERR_NODE_EXIST;
}
if (0 == e.error) {
header->type = NEU_REQ_NODE_RENAME;
forward_msg(manager, header, header->receiver);
} else {
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
}
break;
}
case NEU_REQ_DEL_NODE: {
neu_req_del_node_t *cmd = (neu_req_del_node_t *) &header[1];
neu_resp_error_t error = { 0 };
nlog_notice("del node name:%s", cmd->node);
neu_adapter_t *adapter =
neu_node_manager_find(manager->node_manager, cmd->node);
bool single =
neu_node_manager_is_single(manager->node_manager, cmd->node);
snprintf(header->receiver, sizeof(header->receiver), "%s", cmd->node);
if (adapter == NULL) {
error.error = NEU_ERR_NODE_NOT_EXIST;
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &error);
break;
}
if (single) {
error.error = NEU_ERR_NODE_NOT_ALLOW_DELETE;
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &error);
break;
}
manager_storage_del_node(manager, cmd->node);
if (neu_adapter_get_type(adapter) == NEU_NA_TYPE_APP) {
UT_array *subscriptions = neu_subscribe_manager_get(
manager->subscribe_manager, cmd->node, NULL, NULL);
neu_subscribe_manager_unsub_all(manager->subscribe_manager,
cmd->node);
utarray_foreach(subscriptions, neu_resp_subscribe_info_t *, sub)
{
// NOTE: neu_req_unsubscribe_t and neu_resp_subscribe_info_t
// have compatible memory layout
msg = neu_msg_new(NEU_REQ_UNSUBSCRIBE_GROUP, NULL, sub);
if (NULL == msg) {
break;
}
neu_reqresp_head_t *hd = neu_msg_get_header(msg);
snprintf(hd->receiver, sizeof(hd->receiver), "%s", sub->driver);
snprintf(hd->sender, sizeof(hd->sender), "%s", "manager");
forward_msg(manager, hd, hd->receiver);
}
utarray_free(subscriptions);
}
notify_monitor(manager, NEU_REQ_DEL_NODE_EVENT, cmd);
neu_reqresp_node_deleted_t resp = { 0 };
snprintf(resp.node, sizeof(resp.node), "%s", header->receiver);
// notify MQTT about node removal
if (0 == strcmp(adapter->module->module_name, "MQTT")) {
msg = neu_msg_new(NEU_REQRESP_NODE_DELETED, NULL, &resp);
if (NULL != msg) {
neu_reqresp_head_t *hd = neu_msg_get_header(msg);
snprintf(hd->receiver, sizeof(hd->receiver), "%s", cmd->node);
snprintf(hd->sender, sizeof(hd->sender), "%s", "manager");
reply(manager, hd, &resp);
}
}
header->type = NEU_REQ_NODE_UNINIT;
forward_msg(manager, header, header->receiver);
if (neu_adapter_get_type(adapter) == NEU_NA_TYPE_DRIVER) {
UT_array *apps = neu_subscribe_manager_find_by_driver(
manager->subscribe_manager, resp.node);
utarray_foreach(apps, neu_app_subscribe_t *, app)
{
msg = neu_msg_new(NEU_REQRESP_NODE_DELETED, NULL, &resp);
if (NULL == msg) {
break;
}
header = neu_msg_get_header(msg);
snprintf(header->receiver, sizeof(header->receiver), "%s",
app->app_name);
snprintf(header->sender, sizeof(header->sender), "%s",
"manager");
reply(manager, header, &resp);
}
utarray_free(apps);
}
break;
}
case NEU_RESP_NODE_UNINIT: {
neu_resp_node_uninit_t *cmd = (neu_resp_node_uninit_t *) &header[1];
neu_manager_del_node(manager, cmd->node);
if (strlen(header->receiver) > 0 &&
strcmp(header->receiver, "manager") != 0) {
neu_resp_error_t error = { 0 };
header->type = NEU_RESP_ERROR;
reply(manager, header, &error);
} else {
neu_msg_free(msg);
}
break;
}
case NEU_REQ_GET_NODE: {
neu_req_get_node_t *cmd = (neu_req_get_node_t *) &header[1];
UT_array * nodes = neu_manager_get_nodes(
manager, cmd->type, cmd->plugin, cmd->node, cmd->query.s_delay,
cmd->query.q_state, cmd->query.state, cmd->query.q_link,
cmd->query.link, cmd->query.q_group_name);
neu_resp_get_node_t resp = { .nodes = nodes };
header->type = NEU_RESP_GET_NODE;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &resp);
break;
}
case NEU_REQ_SUBSCRIBE_GROUP: {
neu_req_subscribe_t *cmd = (neu_req_subscribe_t *) &header[1];
neu_resp_error_t error = { 0 };
uint16_t app_port = 0;
nlog_notice("add sub app_name:%s driver_node:%s group:%s params:%s",
cmd->app, cmd->driver, cmd->group,
cmd->params != NULL ? cmd->params : "");
error.error =
neu_manager_subscribe(manager, cmd->app, cmd->driver, cmd->group,
cmd->params, cmd->static_tags, &app_port);
if (error.error == NEU_ERR_SUCCESS) {
cmd->port = app_port;
forward_msg_copy(manager, header, cmd->app);
forward_msg_copy(manager, header, cmd->driver);
manager_storage_subscribe(manager, cmd->app, cmd->driver,
cmd->group, cmd->params,
cmd->static_tags);
} else {
free(cmd->params);
}
header->type = NEU_RESP_ERROR;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &error);
break;
}
case NEU_REQ_SUBSCRIBE_GROUPS: {
neu_req_subscribe_groups_t *cmd =
(neu_req_subscribe_groups_t *) &header[1];
neu_resp_error_t error = { 0 };
for (uint16_t i = 0; i < cmd->n_group; ++i) {
neu_req_subscribe_group_info_t *info = &cmd->groups[i];
nlog_notice("add sub app_name:%s driver_node:%s group:%s params:%s",
cmd->app, info->driver, info->group,
info->params != NULL ? info->params : "");
error.error = neu_manager_subscribe(manager, cmd->app, info->driver,
info->group, info->params,
info->static_tags, &info->port);
if (0 != error.error) {
break;
}
error.error = neu_manager_send_subscribe(
manager, cmd->app, info->driver, info->group, info->port,
info->params, info->static_tags);
if (0 != error.error) {
break;
}
manager_storage_subscribe(manager, cmd->app, info->driver,
info->group, info->params,
info->static_tags);
}
neu_req_subscribe_groups_fini(cmd);
header->type = NEU_RESP_ERROR;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &error);
break;
}
case NEU_REQ_UPDATE_SUBSCRIBE_GROUP: {
neu_req_subscribe_t *cmd = (neu_req_subscribe_t *) &header[1];
neu_resp_error_t error = { 0 };
nlog_notice("update sub app_name:%s driver_node:%s group:%s params:%s",
cmd->app, cmd->driver, cmd->group,
cmd->params != NULL ? cmd->params : "");
error.error = neu_manager_update_subscribe(
manager, cmd->app, cmd->driver, cmd->group, cmd->params,
cmd->static_tags);
if (error.error == NEU_ERR_SUCCESS) {
forward_msg_copy(manager, header, cmd->app);
manager_storage_update_subscribe(manager, cmd->app, cmd->driver,
cmd->group, cmd->params,
cmd->static_tags);
notify_monitor(manager, NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT, cmd);
} else {
free(cmd->params);
}
header->type = NEU_RESP_ERROR;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &error);
break;
}
case NEU_REQ_UNSUBSCRIBE_GROUP: {
neu_req_unsubscribe_t *cmd = (neu_req_unsubscribe_t *) &header[1];
neu_resp_error_t error = { 0 };
nlog_notice("del sub app_name:%s driver_node:%s group:%s", cmd->app,
cmd->driver, cmd->group);
error.error =
neu_manager_unsubscribe(manager, cmd->app, cmd->driver, cmd->group);
if (error.error == NEU_ERR_SUCCESS) {
forward_msg_copy(manager, header, cmd->app);
forward_msg_copy(manager, header, cmd->driver);
manager_storage_unsubscribe(manager, cmd->app, cmd->driver,
cmd->group);
notify_monitor(manager, NEU_REQ_UNSUBSCRIBE_GROUP_EVENT, cmd);
}
header->type = NEU_RESP_ERROR;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &error);
break;
}
case NEU_REQ_GET_SUBSCRIBE_GROUP: {
neu_req_get_subscribe_group_t *cmd =
(neu_req_get_subscribe_group_t *) &header[1];
UT_array *groups = neu_manager_get_sub_group_deep_copy(
manager, cmd->app, cmd->driver, cmd->group);
neu_resp_get_subscribe_group_t resp = { .groups = groups };
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
header->type = NEU_RESP_GET_SUBSCRIBE_GROUP;
reply(manager, header, &resp);
break;
}
case NEU_REQ_GET_DRIVER_SUBSCRIBE_GROUP: {
neu_req_get_driver_subscribe_group_t *cmd =
(neu_req_get_driver_subscribe_group_t *) &header[1];
UT_array *groups =
neu_manager_get_driver_groups(manager, cmd->app, cmd->name);
neu_resp_get_subscribe_group_t resp = { .groups = groups };
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
header->type = NEU_RESP_GET_DRIVER_SUBSCRIBE_GROUP;
reply(manager, header, &resp);
break;
}
case NEU_REQ_GET_SUB_DRIVER_TAGS: {
neu_req_get_sub_driver_tags_t *cmd =
(neu_req_get_sub_driver_tags_t *) &header[1];
neu_resp_get_sub_driver_tags_t resp = { 0 };
UT_array *groups = neu_manager_get_sub_group(manager, cmd->app);
utarray_new(resp.infos, neu_resp_get_sub_driver_tags_info_icd());
utarray_foreach(groups, neu_resp_subscribe_info_t *, info)
{
neu_resp_get_sub_driver_tags_info_t in = { 0 };
neu_adapter_t * driver =
neu_node_manager_find(manager->node_manager, info->driver);
assert(driver != NULL);
snprintf(in.driver, sizeof(in.driver), "%s", info->driver);
snprintf(in.group, sizeof(in.group), "%s", info->group);
neu_adapter_driver_get_value_tag((neu_adapter_driver_t *) driver,
info->group, &in.tags);
utarray_push_back(resp.infos, &in);
}
utarray_free(groups);
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
header->type = NEU_RESP_GET_SUB_DRIVER_TAGS;
reply(manager, header, &resp);
break;
}
case NEU_REQ_GET_DATALAYERS_GROUPS: {
neu_req_get_subscribe_group_t *cmd =
(neu_req_get_subscribe_group_t *) &header[1];
UT_array *groups = neu_manager_get_sub_group_deep_copy(
manager, cmd->app, cmd->driver, cmd->group);
neu_resp_get_subscribe_group_t resp = { .groups = groups };
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
header->type = NEU_RESP_GET_DATALAYERS_GROUPS;
reply(manager, header, &resp);
break;
}
case NEU_REQ_GET_DATALAYERS_TAGS: {
neu_req_get_sub_driver_tags_t *cmd =
(neu_req_get_sub_driver_tags_t *) &header[1];
neu_resp_get_sub_driver_tags_t resp = { 0 };
UT_array *groups = neu_manager_get_sub_group(manager, cmd->app);
bool found = false;
utarray_new(resp.infos, neu_resp_get_sub_driver_tags_info_icd());
utarray_foreach(groups, neu_resp_subscribe_info_t *, info)
{
if (strcmp(info->driver, cmd->driver) != 0 ||
strcmp(info->group, cmd->group) != 0) {
continue;
}
found = true;
neu_resp_get_sub_driver_tags_info_t in = { 0 };
neu_adapter_t * driver =
neu_node_manager_find(manager->node_manager, info->driver);
assert(driver != NULL);
snprintf(in.driver, sizeof(in.driver), "%s", info->driver);
snprintf(in.group, sizeof(in.group), "%s", info->group);
neu_adapter_driver_get_value_tag((neu_adapter_driver_t *) driver,
info->group, &in.tags);
utarray_push_back(resp.infos, &in);
}
utarray_free(groups);
if (!found) {
utarray_free(resp.infos);
neu_resp_error_t e = { .error = NEU_ERR_GROUP_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
break;
}
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
header->type = NEU_RESP_GET_DATALAYERS_TAGS;
reply(manager, header, &resp);
break;
}
case NEU_REQ_GET_DATALAYERS_TAG: {
neu_req_get_sub_driver_tags_t *cmd =
(neu_req_get_sub_driver_tags_t *) &header[1];
neu_resp_get_sub_driver_tags_t resp = { 0 };
UT_array *groups = neu_manager_get_sub_group(manager, cmd->app);
bool found = false;
utarray_new(resp.infos, neu_resp_get_sub_driver_tags_info_icd());
utarray_foreach(groups, neu_resp_subscribe_info_t *, info)
{
neu_resp_get_sub_driver_tags_info_t in = { 0 };
neu_adapter_t * driver =
neu_node_manager_find(manager->node_manager, info->driver);
assert(driver != NULL);
neu_adapter_driver_get_value_tag((neu_adapter_driver_t *) driver,
info->group, &in.tags);
if (in.tags) {
UT_array *filtered_tags = NULL;
utarray_new(filtered_tags, neu_tag_get_icd());
utarray_foreach(in.tags, neu_datatag_t *, tag)
{
if (strstr(tag->name, cmd->tag) != NULL) {
utarray_push_back(filtered_tags, tag);
}
}
utarray_free(in.tags);
if (utarray_len(filtered_tags) > 0) {
snprintf(in.driver, sizeof(in.driver), "%s", info->driver);
snprintf(in.group, sizeof(in.group), "%s", info->group);
in.tags = filtered_tags;
utarray_push_back(resp.infos, &in);
found = true;
} else {
utarray_free(filtered_tags);
}
}
}
utarray_free(groups);
if (!found) {
utarray_free(resp.infos);
neu_resp_error_t e = { .error = NEU_ERR_TAG_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
break;
}
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
header->type = NEU_RESP_GET_DATALAYERS_TAG;
reply(manager, header, &resp);
break;
}
case NEU_REQ_GET_NODES_STATE: {
neu_resp_get_nodes_state_t resp = { 0 };
UT_array *states = neu_node_manager_get_state(manager->node_manager);
neu_nodes_state_t *p_state = NULL;
while (
(p_state = (neu_nodes_state_t *) utarray_next(states, p_state))) {
p_state->sub_group_count = neu_subscribe_manager_group_count(
manager->subscribe_manager, p_state->node);
}
resp.states = utarray_clone(states);
resp.core_level = manager->log_level;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
snprintf(header->sender, sizeof(header->sender), "%s", "manager");
header->type = NEU_RESP_GET_NODES_STATE;
reply(manager, header, &resp);
utarray_free(states);
break;
}
case NEU_REQ_GET_DRIVER_GROUP: {
neu_resp_get_driver_group_t resp = { 0 };
resp.groups = neu_manager_get_driver_group(manager);
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
snprintf(header->sender, sizeof(header->sender), "%s", "manager");
header->type = NEU_RESP_GET_DRIVER_GROUP;
reply(manager, header, &resp);
break;
}
case NEU_REQ_SERVER_SECURITY_POLICY:
case NEU_REQ_SERVER_SECURITY_POLICY_STATUS:
case NEU_REQ_SERVER_AUTH_SWITCH_STATUS:
case NEU_REQ_SERVER_AUTH_USER_INFO:
case NEU_REQ_SERVER_AUTH_USER_DELETE:
case NEU_REQ_SERVER_AUTH_USER_UPDATE_PWD:
case NEU_REQ_SERVER_AUTH_USER_ADD:
case NEU_REQ_SERVER_AUTH_SWITCH:
case NEU_REQ_SERVER_CERT_INFO:
case NEU_REQ_SERVER_CERT_EXPORT:
case NEU_REQ_CLIENT_CERT_UPLOAD:
case NEU_REQ_CLIENT_CERT_TRUST:
case NEU_REQ_CLIENT_CERT_DELETE:
case NEU_REQ_CLIENT_CERT_INFO:
case NEU_REQ_SERVER_CERT_UPLOAD:
case NEU_REQ_SERVER_CERT_SELF_SIGN:
case NEU_REQ_GET_GROUP:
case NEU_REQ_GET_NODE_SETTING:
case NEU_REQ_READ_GROUP:
case NEU_REQ_READ_GROUP_PAGINATE:
case NEU_REQ_WRITE_TAG:
case NEU_REQ_WRITE_TAGS:
case NEU_REQ_WRITE_GTAGS:
case NEU_REQ_GET_TAG:
case NEU_REQ_NODE_CTL:
case NEU_REQ_DRIVER_ACTION:
case NEU_REQ_DRIVER_DIRECTORY:
case NEU_REQ_FUP_OPEN:
case NEU_REQ_FDOWN_OPEN:
case NEU_RESP_FDOWN_DATA:
case NEU_REQ_FUP_DATA:
case NEU_REQ_ADD_GROUP: {
neu_otel_trace_ctx trace = NULL;
neu_otel_scope_ctx scope = NULL;
if (neu_otel_control_is_started() &&
(NEU_REQ_WRITE_TAG == header->type ||
NEU_REQ_WRITE_TAGS == header->type ||
NEU_REQ_WRITE_GTAGS == header->type)) {
trace = neu_otel_find_trace(header->ctx);
if (trace) {
scope = neu_otel_add_span(trace);
if (NEU_REQ_WRITE_TAG == header->type) {
neu_otel_scope_set_span_name(scope, "manager write tag");
} else if (NEU_REQ_WRITE_TAGS == header->type) {
neu_otel_scope_set_span_name(scope, "manager write tags");
} else if (NEU_REQ_WRITE_GTAGS == header->type) {
neu_otel_scope_set_span_name(scope, "manager write gtags");
}
char new_span_id[36] = { 0 };
neu_otel_new_span_id(new_span_id);
neu_otel_scope_set_span_id(scope, new_span_id);
uint8_t *p_sp_id = neu_otel_scope_get_pre_span_id(scope);
if (p_sp_id) {
neu_otel_scope_set_parent_span_id2(scope, p_sp_id, 8);
}
neu_otel_scope_add_span_attr_int(scope, "thread id",
(int64_t) pthread_self());
neu_otel_scope_set_span_start_time(scope, neu_time_ns());
}
}
bool re_flag = false;
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
if (NEU_REQ_READ_GROUP == header->type) {
neu_req_read_group_fini((neu_req_read_group_t *) &header[1]);
} else if (NEU_REQ_READ_GROUP_PAGINATE == header->type) {
neu_req_read_group_paginate_fini(
(neu_req_read_group_paginate_t *) &header[1]);
} else if (NEU_REQ_WRITE_TAG == header->type) {
neu_req_write_tag_fini((neu_req_write_tag_t *) &header[1]);
} else if (NEU_REQ_WRITE_TAGS == header->type) {
neu_req_write_tags_fini((neu_req_write_tags_t *) &header[1]);
} else if (NEU_REQ_WRITE_GTAGS == header->type) {
neu_req_write_gtags_fini((neu_req_write_gtags_t *) &header[1]);
}
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
if (neu_otel_control_is_started() && trace) {
neu_otel_scope_set_status_code2(scope, NEU_OTEL_STATUS_ERROR,
NEU_ERR_NODE_NOT_EXIST);
}
} else {
forward_msg(manager, header, header->receiver);
re_flag = true;
}
if (neu_otel_control_is_started() && trace) {
neu_otel_scope_set_span_end_time(scope, neu_time_ns());
if (!re_flag) {
neu_otel_trace_set_final(trace);
}
}
break;
}
case NEU_REQ_PRGFILE_PROCESS:
case NEU_REQ_PRGFILE_UPLOAD:
case NEU_REQ_SCAN_TAGS:
case NEU_REQ_TEST_READ_TAG:
case NEU_REQ_GET_NODE_STATE: {
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_RESP_NODE_RENAME: {
neu_resp_node_rename_t *resp = (neu_resp_node_rename_t *) &header[1];
if (0 == resp->error) {
neu_manager_update_node_name(manager, resp->node, resp->new_name);
manager_storage_update_node(manager, resp->node, resp->new_name);
if (neu_node_manager_is_driver(manager->node_manager,
resp->new_name)) {
UT_array *apps = neu_subscribe_manager_find_by_driver(
manager->subscribe_manager, resp->new_name);
// notify app node about driver renaming
utarray_foreach(apps, neu_app_subscribe_t *, app)
{
header->type = NEU_REQ_UPDATE_NODE;
forward_msg_copy(manager, header, app->app_name);
}
utarray_free(apps);
}
}
neu_resp_error_t e = { .error = resp->error };
header->type = NEU_RESP_ERROR;
reply(manager, header, &e);
break;
}
case NEU_RESP_UPDATE_DRIVER_GROUP: {
neu_resp_update_group_t *resp = (neu_resp_update_group_t *) &header[1];
if (0 == resp->error) {
neu_manager_update_group_name(manager, resp->driver, resp->group,
resp->new_name);
UT_array *apps = neu_subscribe_manager_find(
manager->subscribe_manager, resp->driver, resp->new_name);
if (NULL != apps) {
// notify app node about group renaming
utarray_foreach(apps, neu_app_subscribe_t *, app)
{
header->type = NEU_REQ_UPDATE_GROUP;
forward_msg_copy(manager, header, app->app_name);
}
utarray_free(apps);
}
}
neu_resp_error_t e = { .error = resp->error };
header->type = NEU_RESP_ERROR;
reply(manager, header, &e);
break;
}
case NEU_REQ_UPDATE_GROUP: {
neu_resp_error_t e = { 0 };
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
e.error = NEU_ERR_NODE_NOT_EXIST;
} else if (!neu_node_manager_is_driver(manager->node_manager,
header->receiver)) {
e.error = NEU_ERR_GROUP_NOT_ALLOW;
} else {
header->type = NEU_REQ_UPDATE_DRIVER_GROUP;
forward_msg(manager, header, header->receiver);
}
if (e.error) {
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
}
break;
}
case NEU_REQ_DEL_GROUP: {
neu_req_del_group_t *cmd = (neu_req_del_group_t *) &header[1];
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
UT_array *apps = neu_subscribe_manager_find(
manager->subscribe_manager, cmd->driver, cmd->group);
neu_subscribe_manager_remove(manager->subscribe_manager,
cmd->driver, cmd->group);
if (NULL != apps) {
utarray_foreach(apps, neu_app_subscribe_t *, app)
{
forward_msg_copy(manager, header, app->app_name);
}
utarray_free(apps);
}
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_REQ_DEL_TAG: {
neu_req_del_tag_t *cmd = (neu_req_del_tag_t *) &header[1];
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
for (int i = 0; i < cmd->n_tag; i++) {
free(cmd->tags[i]);
}
free(cmd->tags);
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
UT_array *apps = neu_subscribe_manager_find(
manager->subscribe_manager, cmd->driver, cmd->group);
if (NULL != apps) {
utarray_foreach(apps, neu_app_subscribe_t *, app)
{
neu_msg_t *msg_copy = neu_msg_copy((neu_msg_t *) header);
neu_reqresp_head_t *header_copy =
neu_msg_get_header(msg_copy);
neu_req_del_tag_t *cmd_copy =
(neu_req_del_tag_t *) &header_copy[1];
neu_req_del_tag_copy(cmd_copy, cmd);
forward_msg(manager, header_copy, app->app_name);
}
utarray_free(apps);
}
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_REQ_UPDATE_TAG:
case NEU_REQ_ADD_TAG: {
neu_req_add_tag_t *cmd = (neu_req_add_tag_t *) &header[1];
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
for (int i = 0; i < cmd->n_tag; i++) {
neu_tag_fini(&cmd->tags[i]);
}
free(cmd->tags);
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_REQ_RENAME_TAG: {
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_REQ_ADD_GTAG: {
neu_req_add_gtag_t *cmd = (neu_req_add_gtag_t *) &header[1];
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
for (int i = 0; i < cmd->n_group; i++) {
for (int j = 0; j < cmd->groups[i].n_tag; j++) {
neu_tag_fini(&cmd->groups[i].tags[j]);
}
free(cmd->groups[i].tags);
}
free(cmd->groups);
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_REQ_IMPORT_TAGS: {
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_REQ_NODE_SETTING:
case NEU_REQ_NODE_SETTING_EVENT: {
neu_req_node_setting_t *cmd = (neu_req_node_setting_t *) &header[1];
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
free(cmd->setting);
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_RESP_ADD_TAG:
case NEU_RESP_ADD_GTAG:
case NEU_RESP_IMPORT_TAGS:
case NEU_RESP_UPDATE_TAG:
case NEU_RESP_GET_TAG:
case NEU_RESP_GET_GROUP:
case NEU_RESP_GET_NODE_SETTING:
case NEU_RESP_ERROR:
case NEU_RESP_DRIVER_ACTION:
case NEU_RESP_DRIVER_DIRECTORY:
case NEU_RESP_FUP_OPEN:
case NEU_RESP_FDOWN_OPEN:
case NEU_REQ_FDOWN_DATA:
case NEU_RESP_FUP_DATA:
case NEU_RESP_READ_GROUP:
case NEU_RESP_READ_GROUP_PAGINATE:
case NEU_RESP_TEST_READ_TAG:
case NEU_RESP_PRGFILE_PROCESS:
case NEU_RESP_SCAN_TAGS:
case NEU_RESP_WRITE_TAGS:
case NEU_RESP_SERVER_CERT_INFO:
case NEU_RESP_CLIENT_CERT_INFO:
case NEU_RESP_SERVER_CERT_EXPORT:
case NEU_RESP_SERVER_SECURITY_POLICY_STATUS:
case NEU_RESP_SERVER_AUTH_SWITCH_STATUS:
case NEU_RESP_SERVER_AUTH_USER_INFO:
case NEU_RESP_RENAME_TAG:
forward_msg(manager, header, header->receiver);
break;
case NEU_RESP_GET_NODE_STATE: {
neu_resp_get_node_state_t *resp =
(neu_resp_get_node_state_t *) &header[1];
neu_adapter_t *adapter_node =
neu_node_manager_find(manager->node_manager, header->sender);
resp->sub_group_count = neu_subscribe_manager_group_count(
manager->subscribe_manager, header->sender);
resp->is_driver =
(adapter_node->module->type == NEU_NA_TYPE_DRIVER) ? true : false;
resp->core_level = manager->log_level;
forward_msg(manager, header, header->receiver);
break;
}
case NEU_REQ_ADD_DRIVERS: {
neu_req_driver_array_t *cmd = (neu_req_driver_array_t *) &header[1];
neu_resp_error_t e = { 0 };
e.error = neu_manager_add_drivers(manager, cmd);
if (NEU_ERR_SUCCESS == e.error) {
for (uint16_t i = 0; i < cmd->n_driver; ++i) {
neu_req_driver_t *driver = &cmd->drivers[i];
manager_storage_add_node(manager, driver->node, driver->tags);
adapter_storage_setting(driver->node, driver->setting);
for (uint16_t j = 0; j < driver->n_group; j++) {
adapter_storage_add_group(driver->node,
driver->groups[j].group,
driver->groups[j].interval, NULL);
adapter_storage_add_tags(
driver->node, driver->groups[j].group,
driver->groups[j].tags, driver->groups[j].n_tag);
}
}
}
neu_req_driver_array_fini(cmd);
header->type = NEU_RESP_ERROR;
snprintf(header->receiver, sizeof(header->receiver), "%s",
header->sender);
reply(manager, header, &e);
break;
}
case NEU_REQ_UPDATE_LOG_LEVEL: {
neu_req_update_log_level_t *cmd =
(neu_req_update_log_level_t *) &header[1];
if (cmd->core) {
manager->log_level = cmd->log_level;
nlog_level_change(manager->log_level);
}
if (strlen(cmd->node) > 0) {
if (neu_node_manager_find(manager->node_manager,
header->receiver) == NULL) {
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
forward_msg(manager, header, header->receiver);
}
} else {
if (cmd->core) {
neu_resp_error_t e = { .error = NEU_ERR_SUCCESS };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
} else {
neu_resp_error_t e = { .error = NEU_ERR_PARAM_IS_WRONG };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
}
}
break;
}
case NEU_REQ_UPDATE_GLOBAL_LOG_LEVEL: {
neu_req_update_global_log_level_t *cmd =
(neu_req_update_global_log_level_t *) &header[1];
nlog_info("Setting global log level to %d for core and all nodes",
cmd->log_level);
manager->log_level = cmd->log_level;
nlog_level_change(manager->log_level);
UT_array *nodes = neu_node_manager_get_all(manager->node_manager);
if (nodes != NULL) {
neu_resp_node_info_t *node_info = NULL;
while ((node_info = (neu_resp_node_info_t *) utarray_next(
nodes, node_info)) != NULL) {
neu_reqresp_head_t node_header = { 0 };
neu_req_update_node_log_level_t node_cmd = { 0 };
node_header.type = NEU_REQ_UPDATE_NODE_LOG_LEVEL;
node_header.ctx = NULL;
node_header.otel_trace_type = header->otel_trace_type;
node_header.monitor = false;
snprintf(node_header.sender, sizeof(node_header.sender), "%s",
"manager");
snprintf(node_header.receiver, sizeof(node_header.receiver),
"%s", node_info->node);
node_cmd.log_level = cmd->log_level;
neu_msg_t *node_msg = neu_msg_new(NEU_REQ_UPDATE_NODE_LOG_LEVEL,
&node_header, &node_cmd);
if (node_msg != NULL) {
struct sockaddr_un addr = neu_node_manager_get_addr(
manager->node_manager, node_info->node);
int ret =
neu_send_msg_to(manager->server_fd, &addr, node_msg);
if (ret != 0) {
nlog_warn("Failed to send global log level update to "
"node %s, ret: %d",
node_info->node, ret);
neu_msg_free(node_msg);
} else {
nlog_debug("Sent global log level update to node %s",
node_info->node);
}
}
}
utarray_free(nodes);
}
neu_resp_error_t e = { .error = NEU_ERR_SUCCESS };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
break;
}
case NEU_REQ_ADD_NODE_EVENT:
case NEU_REQ_DEL_NODE_EVENT:
case NEU_REQ_NODE_CTL_EVENT:
case NEU_REQ_ADD_GROUP_EVENT:
case NEU_REQ_DEL_GROUP_EVENT:
case NEU_REQ_UPDATE_GROUP_EVENT:
case NEU_REQ_ADD_TAG_EVENT:
case NEU_REQ_DEL_TAG_EVENT:
case NEU_REQ_UPDATE_TAG_EVENT:
case NEU_REQ_RENAME_TAG_EVENT:
case NEU_REQ_ADD_GTAG_EVENT:
case NEU_REQ_ADD_PLUGIN_EVENT:
case NEU_REQ_DEL_PLUGIN_EVENT:
case NEU_REQ_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UNSUBSCRIBE_GROUP_EVENT:
case NEU_REQ_SUBSCRIBE_GROUPS_EVENT: {
if (neu_node_manager_find(manager->node_manager, header->receiver)) {
forward_msg(manager, header, header->receiver);
}
break;
}
default:
nlog_warn("unknown msg type: %d", header->type);
assert(false);
break;
}
return 0;
}
inline static void forward_msg_copy(neu_manager_t * manager,
neu_reqresp_head_t *header,
const char * node)
{
neu_msg_t *msg = neu_msg_copy((neu_msg_t *) header);
forward_msg(manager, neu_msg_get_header(msg), node);
}
static void start_static_adapter(neu_manager_t *manager, const char *name)
{
neu_adapter_t * adapter = NULL;
neu_plugin_instance_t instance = { 0 };
neu_adapter_info_t adapter_info = {
.name = name,
};
neu_plugin_manager_load_static(manager->plugin_manager, name, &instance);
adapter_info.handle = instance.handle;
adapter_info.module = instance.module;
adapter = neu_adapter_create(&adapter_info, true);
neu_node_manager_add_static(manager->node_manager, adapter);
neu_adapter_init(adapter, false);
neu_adapter_start(adapter);
}
static void start_single_adapter(neu_manager_t *manager, const char *name,
const char *plugin_name, bool display)
{
neu_adapter_t * adapter = NULL;
neu_plugin_instance_t instance = { 0 };
neu_adapter_info_t adapter_info = {
.name = name,
};
if (0 !=
neu_plugin_manager_create_instance(manager->plugin_manager, plugin_name,
&instance)) {
return;
}
adapter_info.handle = instance.handle;
adapter_info.module = instance.module;
adapter = neu_adapter_create(&adapter_info, true);
neu_node_manager_add_single(manager->node_manager, adapter, display);
if (display) {
manager_storage_add_node(manager, name, "");
}
neu_adapter_init(adapter, false);
neu_adapter_start_single(adapter);
}
inline static void reply(neu_manager_t *manager, neu_reqresp_head_t *header,
void *data)
{
neu_msg_gen(header, data);
struct sockaddr_un addr =
neu_node_manager_get_addr(manager->node_manager, header->receiver);
neu_reqresp_type_e t = header->type;
void * ctx = header->ctx;
char receiver[NEU_NODE_NAME_LEN] = { 0 };
strncpy(receiver, header->receiver, sizeof(receiver));
neu_msg_t *msg = (neu_msg_t *) header;
int ret = neu_send_msg_to(manager->server_fd, &addr, msg);
if (0 == ret) {
nlog_notice("reply %s to %s(%s) %p", neu_reqresp_type_string(t),
receiver, &addr.sun_path[1], ctx);
} else {
nlog_warn("reply %s to %s, error: %d", neu_reqresp_type_string(t),
receiver, ret);
neu_msg_free(msg);
}
}
static int update_timestamp(void *usr_data)
{
(void) usr_data;
global_timestamp = neu_time_ms();
return 0;
}
static char *file_save_tmp(const char *data, const char *suffix)
{
int d_len = 0;
char *file = (char *) neu_decode64(&d_len, data);
if (file == NULL) {
nlog_warn("library so file decode64 ret is NULL");
return NULL;
}
if (d_len == 0) {
nlog_warn("library so file decode64 len is 0");
free(file);
return NULL;
}
char *tmp_path = neu_persister_save_file_tmp(file, d_len, suffix);
if (tmp_path == NULL) {
free(file);
return NULL;
}
free(file);
return tmp_path;
}
static int copy_file(const char *src, const char *dst)
{
FILE * source, *destination;
char buffer[1024];
size_t bytes_read;
source = fopen(src, "rb");
if (source == NULL) {
nlog_error("failed to open source file!");
return -1;
}
destination = fopen(dst, "wb");
if (destination == NULL) {
nlog_error("failed to open destination file!");
fclose(source);
return -1;
}
while ((bytes_read = fread(buffer, 1, sizeof(buffer), source)) > 0) {
if (fwrite(buffer, 1, bytes_read, destination) != bytes_read) {
nlog_error("failed to write to destination file!");
fclose(source);
fclose(destination);
return -1;
}
}
if (ferror(source)) {
nlog_error("error reading source file");
fclose(source);
fclose(destination);
return -1;
}
fclose(source);
fclose(destination);
return 0;
}
static bool mv_tmp_library_file(neu_plugin_kind_e kind, const char *tmp_path,
const char *library)
{
char file_name[128] = { 0 };
char path_name[128] = { 0 };
if (kind == NEU_PLUGIN_KIND_CUSTOM) {
snprintf(file_name, sizeof(file_name), "%s/custom/%s", g_plugin_dir,
library);
snprintf(path_name, sizeof(path_name), "%s/custom", g_plugin_dir);
} else if (kind == NEU_PLUGIN_KIND_SYSTEM) {
snprintf(file_name, sizeof(file_name), "%s/system/%s", g_plugin_dir,
library);
snprintf(path_name, sizeof(path_name), "%s/system", g_plugin_dir);
} else {
return false;
}
struct stat st;
if (stat(path_name, &st) == -1) {
if (mkdir(path_name, 0700) == -1) {
nlog_error("%s mkdir fail", path_name);
return false;
}
}
if (copy_file(tmp_path, file_name) != 0) {
nlog_error("%s copy_file %s fail!", tmp_path, file_name);
return false;
} else {
return true;
}
return false;
}
static bool mv_tmp_schema_file(neu_plugin_kind_e kind, const char *tmp_path,
const char *schema)
{
char file_name[128] = { 0 };
char path_name[128] = { 0 };
if (kind == NEU_PLUGIN_KIND_CUSTOM) {
snprintf(file_name, sizeof(file_name), "%s/custom/schema/%s.json",
g_plugin_dir, schema);
snprintf(path_name, sizeof(path_name), "%s/custom/schema",
g_plugin_dir);
} else if (kind == NEU_PLUGIN_KIND_SYSTEM) {
snprintf(file_name, sizeof(file_name), "%s/system/schema/%s.json",
g_plugin_dir, schema);
snprintf(path_name, sizeof(path_name), "%s/system/schema",
g_plugin_dir);
} else {
return false;
}
struct stat st;
if (stat(path_name, &st) == -1) {
if (mkdir(path_name, 0700) == -1) {
nlog_error("%s mkdir fail", path_name);
return false;
}
}
if (copy_file(tmp_path, file_name) != 0) {
nlog_error("%s copy_file %s fail!", tmp_path, file_name);
return false;
} else {
return true;
}
return false;
}
struct notify_monitor_ctx {
neu_manager_t * manager;
neu_reqresp_type_e event;
void * data;
};
inline static void notify_monitor(neu_manager_t * manager,
neu_reqresp_type_e event, void *data)
{
struct notify_monitor_ctx ctx = {
.manager = manager,
.event = event,
.data = data,
};
// monitor not ready, ignore
neu_node_manager_t *mgr = manager->node_manager;
struct sockaddr_un addr = neu_node_manager_get_addr(mgr, "monitor");
if (0 == addr.sun_path[1]) {
return;
}
// message header
neu_msg_t *msg = neu_msg_new(ctx.event, NULL, ctx.data);
if (NULL == msg) {
return;
}
neu_reqresp_head_t *header = neu_msg_get_header(msg);
snprintf(header->sender, sizeof(header->sender), "%s", "manager");
snprintf(header->receiver, sizeof(header->receiver), "%s", "monitor");
int ret = neu_send_msg_to(manager->server_fd, &addr, msg);
if (0 != ret) {
nlog_warn("notify %s of %s, error: %s(%d)", header->receiver,
neu_reqresp_type_string(header->type), strerror(errno),
errno);
neu_msg_free(msg);
}
return;
}