diff --git a/docs/json-persistence/json_adapter.json b/docs/json-persistence/json_adapter.json index af8dc7e0..8b7dc16f 100644 --- a/docs/json-persistence/json_adapter.json +++ b/docs/json-persistence/json_adapter.json @@ -2,18 +2,21 @@ "node_req": { "nodes": [ { + "id": 1, "state": 1, "type": 1, "name": "sample-driver-adapter", "plugin_name": "sample-drv-plugin" }, { + "id": 2, "state": 2, "type": 5, "name": "sample-app-adapter", "plugin_name": "sample-app-plugin" }, { + "id": 3, "state": 3, "type": 3, "name": "mqtt-adapter", @@ -24,18 +27,21 @@ "node_resp": { "nodes": [ { + "id": 1, "state": 1, "type": 1, "name": "sample-driver-adapter", "plugin_name": "sample-drv-plugin" }, { + "id": 2, "state": 2, "type": 5, "name": "sample-app-adapter", "plugin_name": "sample-app-plugin" }, { + "id": 3, "state": 3, "type": 3, "name": "mqtt-adapter", diff --git a/src/adapter/adapter.c b/src/adapter/adapter.c index a61432e6..16062a05 100644 --- a/src/adapter/adapter.c +++ b/src/adapter/adapter.c @@ -443,11 +443,22 @@ static int persister_singleton_load_subscriptions(neu_adapter_t *adapter, return rv; } +static int persist_adapter_info_cmp(const void *a, const void *b) +{ + return ((neu_persist_adapter_info_t *) a)->id - + ((neu_persist_adapter_info_t *) b)->id; +} + static int persister_singleton_load_data(neu_adapter_t *adapter) { vector_t * adapter_infos = NULL; neu_persister_t *persister = persister_singleton_get(); + // declaration for neu_manager_update_node_id since it is not exposed + int neu_manager_update_node_id(neu_manager_t * manager, + neu_node_id_t node_id, + neu_node_id_t new_node_id); + log_info("%s start persistence loading", adapter->name); int rv = persister_singleton_load_plugins(adapter); @@ -461,6 +472,10 @@ static int persister_singleton_load_data(neu_adapter_t *adapter) goto error_load_adapters; } + // sort by adapter id + qsort(adapter_infos->data, adapter_infos->size, + sizeof(neu_persist_adapter_info_t), persist_adapter_info_cmp); + VECTOR_FOR_EACH(adapter_infos, iter) { neu_persist_adapter_info_t *adapter_info = iterator_get(&iter); @@ -480,6 +495,13 @@ static int persister_singleton_load_data(neu_adapter_t *adapter) goto error_add_adapters; } + if (node_id != adapter_info->id) { + // set to persisted adapter id + neu_manager_update_node_id(adapter->manager, node_id, + adapter_info->id); + node_id = adapter_info->id; + } + rv = persister_singleton_load_setting(adapter, adapter_info->name, node_id); if (0 != rv) { @@ -2058,6 +2080,18 @@ adapter_id_t neu_adapter_get_id(neu_adapter_t *adapter) return adapter->id; } +// NOTE: Do NOT expose this function in header files, use for persistence only! +adapter_id_t neu_adapter_set_id(neu_adapter_t *adapter, adapter_id_t id) +{ + if (adapter == NULL) { + return 0; + } + + adapter_id_t old = adapter->id; + adapter->id = id; + return old; +} + adapter_type_e neu_adapter_get_type(neu_adapter_t *adapter) { if (adapter == NULL) { diff --git a/src/core/neu_manager.c b/src/core/neu_manager.c index f70e0499..68b0cc73 100644 --- a/src/core/neu_manager.c +++ b/src/core/neu_manager.c @@ -1386,6 +1386,47 @@ int neu_manager_add_node(neu_manager_t *manager, neu_cmd_add_node_t *cmd, return rv; } +// NOTE: Do NOT expose this function in header files, use for persistence only! +int neu_manager_update_node_id(neu_manager_t *manager, neu_node_id_t node_id, + neu_node_id_t new_node_id) +{ + int rv = 0; + adapter_id_t adapter_id; + adapter_id_t new_adapter_id; + adapter_reg_entity_t *reg_entity; + + // declaration for neu_adapter_set_id since it is not exposed + adapter_id_t neu_adapter_set_id(neu_adapter_t * adapter, adapter_id_t id); + + if (0 == new_node_id) { + return NEU_ERR_EINVAL; + } + + adapter_id = neu_manager_adapter_id_from_node_id(manager, node_id); + new_adapter_id = neu_manager_adapter_id_from_node_id(manager, new_node_id); + + nng_mtx_lock(manager->adapters_mtx); + reg_entity = find_reg_adapter_by_id(&manager->reg_adapters, new_adapter_id); + if (NULL != reg_entity) { + rv = NEU_ERR_NODE_EXIST; + } else { + reg_entity = find_reg_adapter_by_id(&manager->reg_adapters, adapter_id); + if (reg_entity != NULL) { + reg_entity->adapter_id = new_adapter_id; + neu_adapter_set_id(reg_entity->adapter, new_adapter_id); + if (new_adapter_id >= manager->new_adapter_id) { + // update new available adapter id + manager->new_adapter_id = new_adapter_id + 1; + } + } else { + rv = NEU_ERR_NODE_NOT_EXIST; + } + } + nng_mtx_unlock(manager->adapters_mtx); + + return rv; +} + int neu_manager_del_node(neu_manager_t *manager, neu_node_id_t node_id) { int rv = 0; @@ -2107,6 +2148,8 @@ int neu_manager_get_persist_adapter_infos(neu_manager_t *manager, } neu_persist_adapter_info_t adapter_info = {}; + adapter_info.id = + neu_manager_adapter_id_to_node_id(manager, reg_entity->adapter_id); adapter_info.type = neu_adapter_get_type(reg_entity->adapter); adapter_info.state = neu_adapter_get_state(reg_entity->adapter).running; adapter_info.name = strdup(adapter_name); diff --git a/src/persist/json/persist_json_adapter.c b/src/persist/json/persist_json_adapter.c index 5cc8fcc4..0ab9886a 100644 --- a/src/persist/json/persist_json_adapter.c +++ b/src/persist/json/persist_json_adapter.c @@ -1,6 +1,6 @@ /** * NEURON IIoT System for Industry 4.0 - * Copyright (C) 2020-2021 EMQ Technologies Co., Ltd All rights reserved. + * 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 @@ -56,6 +56,11 @@ int neu_json_encode_node_resp(void *json_object, void *param) .name = "name", .t = NEU_JSON_STR, .v.val_str = p_node->name, + }, + { + .name = "id", + .t = NEU_JSON_INT, + .v.val_int = p_node->id, } }; node_array = neu_json_encode_array(node_array, node_elems, NEU_JSON_ELEM_SIZE(node_elems)); @@ -75,21 +80,11 @@ int neu_json_encode_node_resp(void *json_object, void *param) int neu_json_decode_node_req(char *buf, neu_json_node_req_t **result) { - int ret = 0; - void * json_obj = NULL; - neu_json_node_req_t *req = calloc(1, sizeof(neu_json_node_req_t)); - if (req == NULL) { - return -1; - } + int ret = 0; + neu_json_node_req_t *req = calloc(1, sizeof(neu_json_node_req_t)); - json_obj = neu_json_decode_new(buf); - - req->n_node = neu_json_decode_array_size_by_json(json_obj, "nodes"); - if (req->n_node < 0) { - goto decode_fail; - } - - req->nodes = calloc(req->n_node, sizeof(neu_json_node_req_node_t)); + req->n_node = neu_json_decode_array_size(buf, "nodes"); + req->nodes = calloc(req->n_node, sizeof(neu_json_node_req_node_t)); neu_json_node_req_node_t *p_node = req->nodes; for (int i = 0; i < req->n_node; i++) { neu_json_elem_t node_elems[] = { { @@ -107,9 +102,13 @@ int neu_json_decode_node_req(char *buf, neu_json_node_req_t **result) { .name = "name", .t = NEU_JSON_STR, + }, + { + .name = "id", + .t = NEU_JSON_INT, } }; - ret = neu_json_decode_array_by_json( - json_obj, "nodes", i, NEU_JSON_ELEM_SIZE(node_elems), node_elems); + ret = neu_json_decode_array(buf, "nodes", i, + NEU_JSON_ELEM_SIZE(node_elems), node_elems); if (ret != 0) { goto decode_fail; } @@ -118,11 +117,12 @@ int neu_json_decode_node_req(char *buf, neu_json_node_req_t **result) p_node->state = node_elems[1].v.val_int; p_node->plugin_name = node_elems[2].v.val_str; p_node->name = node_elems[3].v.val_str; + p_node->id = node_elems[4].v.val_int; p_node++; } *result = req; - goto decode_exit; + return ret; decode_fail: if (req->nodes != NULL) { @@ -131,13 +131,7 @@ decode_fail: if (req != NULL) { free(req); } - ret = -1; - -decode_exit: - if (json_obj != NULL) { - neu_json_decode_free(json_obj); - } - return ret; + return -1; } void neu_json_decode_node_req_free(neu_json_node_req_t *req) diff --git a/src/persist/json/persist_json_adapter.h b/src/persist/json/persist_json_adapter.h index 1e731a0a..850447a8 100644 --- a/src/persist/json/persist_json_adapter.h +++ b/src/persist/json/persist_json_adapter.h @@ -1,6 +1,6 @@ /** * NEURON IIoT System for Industry 4.0 - * Copyright (C) 2020-2021 EMQ Technologies Co., Ltd All rights reserved. + * 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 @@ -32,6 +32,7 @@ extern "C" { #endif typedef struct { + int64_t id; char * name; int64_t type; char * plugin_name; @@ -46,6 +47,7 @@ typedef struct { int neu_json_encode_node_resp(void *json_object, void *param); typedef struct { + int64_t id; char * name; int64_t type; char * plugin_name; diff --git a/tests/json_persistence_test.cc b/tests/json_persistence_test.cc index d05b52a4..e0a9198c 100644 --- a/tests/json_persistence_test.cc +++ b/tests/json_persistence_test.cc @@ -13,13 +13,13 @@ TEST(JsonAdapter, AdapterPersistenceDecode) { char *buf = (char *) "{\"nodes\": " - "[{\"type\":1, \"state\": 1, \"name\": " + "[{\"id\":1, \"type\":1, \"state\": 1, \"name\": " "\"sample-driver-adapter\", \"plugin_name\": " "\"sample-drv-plugin\"}, " - "{\"type\":5, \"state\": 2, \"name\": " + "{\"id\":2, \"type\":5, \"state\": 2, \"name\": " "\"sample-app-adapter\", \"plugin_name\": " "\"sample-app-plugin\"}, " - "{\"type\": 3, \"state\": 3, \"name\": " + "{\"id\":3, \"type\": 3, \"state\": 3, \"name\": " "\"mqtt-adapter\", \"plugin_name\": \"mqtt-plugin\"}]}"; neu_json_node_req_t *req = NULL; @@ -160,11 +160,11 @@ TEST(JsonAdapterTest, AdapterPersistenceEncode) { char *buf = (char *) "{\"nodes\": [{\"type\": 1, \"state\": 1, \"plugin_name\": " - "\"sample-drv-plugin\", \"name\": \"sample-driver-adapter\"}, " - "{\"type\": 5, \"state\": 2, \"plugin_name\": " - "\"sample-app-plugin\", \"name\": \"sample-app-adapter\"}, " - "{\"type\": 3, \"state\": 3, \"plugin_name\": " - "\"mqtt-plugin\", \"name\": \"mqtt-adapter\"}]}"; + "\"sample-drv-plugin\", \"name\": \"sample-driver-adapter\", " + "\"id\": 1}, {\"type\": 5, \"state\": 2, \"plugin_name\": " + "\"sample-app-plugin\", \"name\": \"sample-app-adapter\", " + "\"id\": 2}, {\"type\": 3, \"state\": 3, \"plugin_name\": " + "\"mqtt-plugin\", \"name\": \"mqtt-adapter\", \"id\": 3}]}"; char *buf2 = (char *) "{\"nodes\": []}"; char *result = NULL; @@ -179,16 +179,19 @@ TEST(JsonAdapterTest, AdapterPersistenceEncode) resp.nodes = (neu_json_node_resp_node_t *) calloc( 3, sizeof(neu_json_node_resp_node_t)); + resp.nodes[0].id = 1; resp.nodes[0].state = 1; resp.nodes[0].type = 1; resp.nodes[0].name = strdup((char *) "sample-driver-adapter"); resp.nodes[0].plugin_name = strdup((char *) "sample-drv-plugin"); + resp.nodes[1].id = 2; resp.nodes[1].state = 2; resp.nodes[1].type = 5; resp.nodes[1].name = strdup((char *) "sample-app-adapter"); resp.nodes[1].plugin_name = strdup((char *) "sample-app-plugin"); + resp.nodes[2].id = 3; resp.nodes[2].state = 3; resp.nodes[2].type = 3; resp.nodes[2].name = strdup((char *) "mqtt-adapter"); diff --git a/tests/persistence_test.cc b/tests/persistence_test.cc index d3e77635..bd3b3197 100644 --- a/tests/persistence_test.cc +++ b/tests/persistence_test.cc @@ -10,11 +10,11 @@ TEST(PersistenceAdapterTest, Adapter) const char *adapters_fname = neu_persister_get_adapters_fname(persister); const char *plugins_fname = neu_persister_get_plugins_fname(persister); - neu_json_node_req_node_t node1 = { (char *) "sample-driver-adapter", 1, + neu_json_node_req_node_t node1 = { 1, (char *) "sample-driver-adapter", 1, (char *) "sample-drv-plugin", 1 }; - neu_json_node_req_node_t node2 = { (char *) "sample-app-adapter", 5, + neu_json_node_req_node_t node2 = { 2, (char *) "sample-app-adapter", 5, (char *) "sample-app-plugin", 2 }; - neu_json_node_req_node_t node3 = { (char *) "mqtt-adapter", 3, + neu_json_node_req_node_t node3 = { 3, (char *) "mqtt-adapter", 3, (char *) "mqtt-plugin", 3 }; neu_json_node_req_t *req =