diff --git a/include/neuron/errcodes.h b/include/neuron/errcodes.h index f22deb1b..0cb88336 100644 --- a/include/neuron/errcodes.h +++ b/include/neuron/errcodes.h @@ -98,6 +98,7 @@ typedef enum { NEU_ERR_LIBRARY_MODULE_VERSION_NOT_MATCH = 2314, NEU_ERR_LIBRARY_NAME_NOT_CONFORM = 2315, NEU_ERR_LIBRARY_CLIB_NOT_MATCH = 2316, + NEU_ERR_LIBRARY_UPDATE_FAIL = 2317, NEU_ERR_LICENSE_NOT_FOUND = 2400, NEU_ERR_LICENSE_INVALID = 2401, diff --git a/src/core/manager.c b/src/core/manager.c index 0178e202..21bb034e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -615,7 +615,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) free(so_tmp_path); free(schema_tmp_path); header->type = NEU_RESP_ERROR; - e.error = NEU_ERR_LIBRARY_ADD_FAIL; + e.error = NEU_ERR_LIBRARY_UPDATE_FAIL; strcpy(header->receiver, header->sender); reply(manager, header, &e); break; @@ -628,7 +628,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) free(so_tmp_path); free(schema_tmp_path); header->type = NEU_RESP_ERROR; - e.error = NEU_ERR_LIBRARY_ADD_FAIL; + e.error = NEU_ERR_LIBRARY_UPDATE_FAIL; strcpy(header->receiver, header->sender); reply(manager, header, &e); break; @@ -641,7 +641,21 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) free(so_tmp_path); free(schema_tmp_path); header->type = NEU_RESP_ERROR; - e.error = NEU_ERR_LIBRARY_ADD_FAIL; + e.error = NEU_ERR_LIBRARY_UPDATE_FAIL; + strcpy(header->receiver, 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; strcpy(header->receiver, header->sender); reply(manager, header, &e); break; diff --git a/src/core/plugin_manager.c b/src/core/plugin_manager.c index 06ffd161..f27cbb27 100644 --- a/src/core/plugin_manager.c +++ b/src/core/plugin_manager.c @@ -98,7 +98,7 @@ int neu_plugin_manager_add(neu_plugin_manager_t *mgr, snprintf(lib_path, sizeof(lib_path) - 1, "%s/%s", lib_paths[i], plugin_lib_name); - handle = dlopen(lib_path, RTLD_NOW | RTLD_NODELETE); + handle = dlopen(lib_path, RTLD_NOW); if (handle == NULL) { nlog_warn("failed to open library %s, error: %s", lib_path, @@ -173,6 +173,78 @@ int neu_plugin_manager_add(neu_plugin_manager_t *mgr, return NEU_ERR_SUCCESS; } +int neu_plugin_manager_update(neu_plugin_manager_t *mgr, + const char * plugin_lib_name) +{ + char lib_path[256] = { 0 }; + void * handle = NULL; + void * module = NULL; + neu_plugin_module_t *pm = NULL; + plugin_entity_t * plugin = NULL; + char lib_paths[3][64] = { 0 }; + snprintf(lib_paths[0], sizeof(lib_paths[0]), "%s", g_plugin_dir); + snprintf(lib_paths[1], sizeof(lib_paths[1]), "%s/system", g_plugin_dir); + snprintf(lib_paths[2], sizeof(lib_paths[2]), "%s/custom", g_plugin_dir); + + assert(strlen(plugin_lib_name) <= NEU_PLUGIN_LIBRARY_LEN); + + for (size_t i = 0; i < sizeof(lib_paths) / sizeof(lib_paths[0]); i++) { + + snprintf(lib_path, sizeof(lib_path) - 1, "%s/%s", lib_paths[i], + plugin_lib_name); + + handle = dlopen(lib_path, RTLD_NOW); + + if (handle == NULL) { + nlog_warn("failed to open library %s, error: %s", lib_path, + dlerror()); + } else { + break; + } + } + + if (handle == NULL) { + return NEU_ERR_LIBRARY_FAILED_TO_OPEN; + } + + module = dlsym(handle, "neu_plugin_module"); + if (module == NULL) { + dlclose(handle); + nlog_warn("failed to find neu_plugin_module symbol in %s", lib_path); + return NEU_ERR_LIBRARY_MODULE_INVALID; + } + + pm = (neu_plugin_module_t *) module; + + HASH_FIND_STR(mgr->plugins, pm->module_name, plugin); + if (plugin == NULL) { + dlclose(handle); + return NEU_ERR_LIBRARY_MODULE_NOT_EXISTS; + } + + plugin->version = pm->version; + plugin->display = pm->display; + plugin->type = pm->type; + plugin->kind = pm->kind; + free(plugin->schema); + free(plugin->description); + free(plugin->description_zh); + plugin->schema = strdup(pm->schema); + plugin->description = strdup(pm->module_descr); + plugin->description_zh = strdup(pm->module_descr_zh); + plugin->single = pm->single; + if (plugin->single) { + free(plugin->single_name); + plugin->single_name = strdup(pm->single_name); + } + + nlog_notice("update plugin, name: %s, library: %s, kind: %d, type: %d", + plugin->name, plugin->lib_name, plugin->kind, plugin->type); + + dlclose(handle); + return NEU_ERR_SUCCESS; +} + int neu_plugin_manager_del(neu_plugin_manager_t *mgr, const char *plugin_name) { plugin_entity_t *plugin = NULL; @@ -322,7 +394,7 @@ int neu_plugin_manager_create_instance(neu_plugin_manager_t * mgr, snprintf(lib_path, sizeof(lib_path) - 1, "%s/%s", lib_paths[i], plugin->lib_name); - instance->handle = dlopen(lib_path, RTLD_NOW | RTLD_NODELETE); + instance->handle = dlopen(lib_path, RTLD_NOW); if (instance->handle == NULL) { continue; @@ -387,7 +459,7 @@ bool neu_plugin_manager_create_instance_by_path(neu_plugin_manager_t *mgr, (void) mgr; - instance->handle = dlopen(plugin_path, RTLD_NOW | RTLD_NODELETE); + instance->handle = dlopen(plugin_path, RTLD_NOW); if (instance->handle == NULL) { const char *dl_err = dlerror(); diff --git a/src/core/plugin_manager.h b/src/core/plugin_manager.h index 5388c5a4..efac57a3 100644 --- a/src/core/plugin_manager.h +++ b/src/core/plugin_manager.h @@ -71,4 +71,7 @@ bool neu_plugin_manager_create_instance_by_path(neu_plugin_manager_t *mgr, bool neu_plugin_manager_remove_library(neu_plugin_manager_t *mgr, const char * library); +int neu_plugin_manager_update(neu_plugin_manager_t *mgr, + const char * plugin_lib_name); + #endif \ No newline at end of file diff --git a/tests/ft/plugin/test_plugin.py b/tests/ft/plugin/test_plugin.py index ea46b85b..47312ac5 100644 --- a/tests/ft/plugin/test_plugin.py +++ b/tests/ft/plugin/test_plugin.py @@ -228,6 +228,24 @@ class TestPlugin: assert 400 == response.status_code assert NEU_ERR_BODY_IS_WRONG == response.json().get("error") + @description(given="incorrect configuration", when="update plugin", then="success") + def test_09_update_plugin_success0(self): + test_data = TestPlugin.test_data + plugin_data = {} + plugin_data['library'] = test_data['library_c1'] + plugin_data['so_file'] = test_data['so_file_c1_2'] + plugin_data['schema_file'] = test_data['schema_file'] + + response = api.updata_plugin( + library_name=plugin_data['library'], so_file=plugin_data['so_file'], schema_file=plugin_data['schema_file']) + assert 200 == response.status_code + assert NEU_ERR_SUCCESS == response.json().get("error") + response = api.get_plugins() + assert 200 == response.status_code + for plugin in response.json().get("plugins"): + if plugin['name'] == 'c1': + assert plugin['version'] == '2.7.99' + @description(given="incorrect configuration", when="update plugin", then="fail") def test_10_update_plugin_fail3(self): test_data = TestPlugin.test_data diff --git a/tests/plugins/c1/c1_2.c b/tests/plugins/c1/c1_2.c index d465c7dc..a349bcea 100644 --- a/tests/plugins/c1/c1_2.c +++ b/tests/plugins/c1/c1_2.c @@ -63,7 +63,7 @@ static const neu_plugin_intf_funs_t plugin_intf_funs = { }; const neu_plugin_module_t neu_plugin_module = { - .version = NEURON_PLUGIN_VER_1_0, + .version = NEU_VERSION(2, 7, 99), .schema = "c1", .module_name = "c1", .module_descr = "c1 v2",