diff --git a/include/dap_chain_plugins.h b/include/dap_chain_plugins.h index 54837f3136d38c8e224b8c8a68352b526c65de54..2f2b3d6ec477c87e10f19fe6a4f1172170fe4bae 100644 --- a/include/dap_chain_plugins.h +++ b/include/dap_chain_plugins.h @@ -1,3 +1,27 @@ +/* +* Authors: +* Alexey V. Stratulat <alexey.stratulat@demlabs.net> +* DeM Labs Inc. https://demlabs.net +* DeM Labs Open source community https://gitlab.demlabs.net/cellframe/libdap-plugins-python +* Copyright (c) 2017-2020 +* All rights reserved. + +This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) 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 3 of the License, or + (at your option) any later version. + + DAP 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 any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + #ifndef _DAP_CHAIN_PLUGINS_ #define _DAP_CHAIN_PLUGINS_ #include <Python.h> @@ -7,22 +31,21 @@ #include "dap_chain_plugins_manifest.h" #include "dap_chain_plugins_list.h" #include "python-cellframe.h" +#include "dap_chain_plugins_command.h" #ifdef __cplusplus extern "C"{ #endif -#undef LOG_TAG -#define LOG_TAG "dap_chain_plugins" - -static PyObject *sys_path; +static PyObject *s_sys_path; -const char *plugins_root_path; +const char *s_plugins_root_path; int dap_chain_plugins_init(); void dap_chain_plugins_deinit(); void dap_chain_plugins_loading(); -void dap_chain_plugins_load_plugin(const char *dir_path, const char *name); +void dap_chain_plugins_load_plugin(const char *a_dir_path, const char *a_name); +int dap_chain_plugins_reload_plugin(const char * a_name_plugin); #ifdef __cplusplus } diff --git a/include/dap_chain_plugins_command.h b/include/dap_chain_plugins_command.h new file mode 100644 index 0000000000000000000000000000000000000000..145870df0e03ce4de4ea72c242a5844e6a0061a6 --- /dev/null +++ b/include/dap_chain_plugins_command.h @@ -0,0 +1,41 @@ +/* +* Authors: +* Alexey V. Stratulat <alexey.stratulat@demlabs.net> +* DeM Labs Inc. https://demlabs.net +* DeM Labs Open source community https://gitlab.demlabs.net/cellframe/libdap-plugins-python +* Copyright (c) 2017-2020 +* All rights reserved. + +This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) 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 3 of the License, or + (at your option) any later version. + + DAP 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 any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#pragma once + +#define _DAP_CHAIN_PLUGINS_COMMAND_ +#include "dap_chain_node_cli.h" +#include "dap_chain_node_cli_cmd.h" +#include "dap_chain_plugins_manifest.h" +#include "dap_chain_plugins.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void dap_chain_plugins_command_create(void); +int dap_chain_plugins_command_handler(int a_argc, char **a_argv, void *a_arg_func, char **a_str_reply); + +#ifdef __cplusplus +} +#endif diff --git a/include/dap_chain_plugins_list.h b/include/dap_chain_plugins_list.h index 7eec9695ed9afaf09efee441b6c1110854d14831..c11169320ef7a9ef4e0d8ae296e91629cb9678b3 100644 --- a/include/dap_chain_plugins_list.h +++ b/include/dap_chain_plugins_list.h @@ -1,9 +1,32 @@ +/* +* Authors: +* Alexey V. Stratulat <alexey.stratulat@demlabs.net> +* DeM Labs Inc. https://demlabs.net +* DeM Labs Open source community https://gitlab.demlabs.net/cellframe/libdap-plugins-python +* Copyright (c) 2017-2020 +* All rights reserved. + +This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) 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 3 of the License, or + (at your option) any later version. + + DAP 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 any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + #ifndef _DAP_CHAIN_PLUGINS_LIST_ #define _DAP_CHAIN_PLUGINS_LIST_ #include "Python.h" #include "stdbool.h" -//#include "dap_list.h" #include "dap_common.h" #include "dap_strfuncs.h" #include "utlist.h" @@ -13,25 +36,23 @@ extern "C" { #endif -#undef LOG_TAG -#define LOG_TAG "dap_chain_plugins_list" - typedef struct dap_chain_list_plugin_module{ char *name; PyObject *obj_module; struct dap_chain_list_plugin_module *next; }dap_chain_plugin_list_module_t; -static dap_chain_plugin_list_module_t* m_dap_chain_plugins_module_list; +static dap_chain_plugin_list_module_t* s_dap_chain_plugins_module_list; void dap_chain_plugins_list_init(); dap_chain_plugin_list_module_t* dap_chain_plugins_list_get(); -bool dap_chain_plugins_list_check_load_plugins(dap_chain_plugins_list_char_t *list); +bool dap_chain_plugins_list_check_load_plugins(dap_chain_plugins_list_char_t *a_list); -void dap_chain_plugins_list_add(PyObject *module, const char *name); -void dap_chain_plugins_list_name_del(const char *name); +void dap_chain_plugins_list_add(PyObject *a_module, const char *a_name); +void dap_chain_plugins_list_name_del(const char *a_name); +int dap_chain_plugins_list_name_cmp(dap_chain_plugin_list_module_t *a_element, const char *a_name); #ifdef __cplusplus extern "C" { diff --git a/include/dap_chain_plugins_manifest.h b/include/dap_chain_plugins_manifest.h index 107a6c213b2ecc8f8af68f0491fde61fdbf1c657..f9aea69a14bbb02945451d0fa3494742caccc3fe 100644 --- a/include/dap_chain_plugins_manifest.h +++ b/include/dap_chain_plugins_manifest.h @@ -1,3 +1,27 @@ +/* +* Authors: +* Alexey V. Stratulat <alexey.stratulat@demlabs.net> +* DeM Labs Inc. https://demlabs.net +* DeM Labs Open source community https://gitlab.demlabs.net/cellframe/libdap-plugins-python +* Copyright (c) 2017-2020 +* All rights reserved. + +This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) 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 3 of the License, or + (at your option) any later version. + + DAP 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 any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + #ifndef _DAP_CHAIN_PLUGINS_MANIFEST_ #define _DAP_CHAIN_PLUGINS_MANIFEST_ #include "dap_common.h" @@ -11,14 +35,14 @@ extern "C"{ #endif -#undef LOG_TAG -#define LOG_TAG "dap_chain_plugins_manifest" typedef struct dap_chain_plugins_list_char{ char *value; struct dap_chain_plugins_list_char *next; }dap_chain_plugins_list_char_t; +void dap_chain_plugins_list_char_delete_all(dap_chain_plugins_list_char_t *a_list); + typedef struct dap_list_manifest{ char *name; char *version; @@ -28,18 +52,28 @@ typedef struct dap_list_manifest{ struct dap_list_manifest *next; }dap_chain_plugins_list_manifest_t; -dap_chain_plugins_list_manifest_t* manifests; +dap_chain_plugins_list_manifest_t* s_manifests; + +int dap_chain_plugins_manifest_name_cmp(dap_chain_plugins_list_manifest_t *a_man, const char *a_name); -dap_chain_plugins_list_manifest_t *dap_chain_plugins_manifest_new(const char *name, const char *version, const dap_chain_plugins_list_char_t *dep, const char *author, - const char *description); +dap_chain_plugins_list_manifest_t *dap_chain_plugins_manifest_new(const char *a_name, const char *a_version, + const dap_chain_plugins_list_char_t *a_dep, + const char *a_author, + const char *a_description); void dap_chain_plugins_manifest_list_create(); -dap_chain_plugins_list_manifest_t* dap_chain_plugins_manifests_get_list(); +dap_chain_plugins_list_manifest_t* dap_chain_plugins_manifests_get_list(void); +dap_chain_plugins_list_manifest_t *dap_chain_plugins_manifest_list_get_name(const char *a_name); + +char* dap_chain_plugins_manifests_get_list_dependencyes(dap_chain_plugins_list_manifest_t *a_element); + +dap_chain_plugins_list_manifest_t* dap_chain_plugins_add_manifest_from_file(const char *a_file_path); -dap_chain_plugins_list_manifest_t* dap_chain_plugins_add_manifest_from_file(const char *file_path); +bool dap_chain_plugins_manifest_list_add_from_file(const char *a_path_file); -bool dap_chain_plugins_manifest_list_add_from_file(const char *path_file); +bool dap_chain_plugins_manifest_list_delete_name(const char *a_name); +void dap_chain_plugins_manifest_list_delete_all(void); #ifdef __cplusplus } diff --git a/src/dap_chain_plugins.c b/src/dap_chain_plugins.c index e3ed1e3e49944ee491c88fb61cca10d904716e9d..916627bb7cc3389375fa9cd4d0fb3b96b0100cf0 100644 --- a/src/dap_chain_plugins.c +++ b/src/dap_chain_plugins.c @@ -1,35 +1,43 @@ #include "dap_chain_plugins.h" -int dap_chain_plugins_init(dap_config_t *config){ - if(dap_config_get_item_bool_default(config, "plugins", "py_load", false)){ - plugins_root_path = dap_config_get_item_str_default(config, "plugins", "py_path", - "/opt/cellframe-node/var/plugins/"); - log_it(L_INFO, "Start initialize python plugins. Path plugins %s", plugins_root_path); - if (!dap_dir_test(plugins_root_path)){ - log_it(L_ERROR, "The directory %s was not found.", plugins_root_path); +#undef LOG_TAG +#define LOG_TAG "dap_chain_plugins" + +int dap_chain_plugins_init(dap_config_t *a_config){ + log_it(L_ERROR, "Z1"); + if(dap_config_get_item_bool_default(a_config, "plugins", "py_load", false)){ + const char *l_defaule_path_plugins = dap_strjoin(NULL, "/opt/", dap_get_appname(), "/var/plugins/", NULL); + const char *l_plugins_root_path = dap_config_get_item_str_default(a_config, "plugins", "py_path", + l_defaule_path_plugins); + s_plugins_root_path = dap_strjoin(NULL, l_plugins_root_path, "/", NULL); + log_it(L_INFO, "Start initialize python plugins. Path plugins %s", s_plugins_root_path); + if (!dap_dir_test(s_plugins_root_path)){ + log_it(L_ERROR, "The directory %s was not found.", s_plugins_root_path); return -1; } PyImport_AppendInittab("CellFrame", PyInit_libCellFrame); Py_Initialize(); - PyObject *sys_module = PyImport_ImportModule("sys"); - sys_path = PyObject_GetAttrString(sys_module, "path"); + PyObject *l_sys_module = PyImport_ImportModule("sys"); + s_sys_path = PyObject_GetAttrString(l_sys_module, "path"); //Get list files - dap_list_name_directories_t *list_plugins_name = dap_get_subs(plugins_root_path); - dap_list_name_directories_t *element; + dap_list_name_directories_t *l_list_plugins_name = dap_get_subs(s_plugins_root_path); + dap_list_name_directories_t *l_element; //Loading manifest and start module log_it(L_NOTICE, "Registration manifests"); dap_chain_plugins_manifest_list_create(); dap_chain_plugins_list_init(); - char *name_file = NULL; - LL_FOREACH(list_plugins_name, element){ - log_it(L_NOTICE, "Registration %s manifest", element->name_directory); - name_file = dap_strjoin("",plugins_root_path, element->name_directory, "/manifest.json", NULL); - if (!dap_chain_plugins_manifest_list_add_from_file(name_file)){ - log_it(L_ERROR, "Registration %s manifest fail", element->name_directory); + char *l_name_file = NULL; + log_it(L_ERROR, "Z2"); + LL_FOREACH(l_list_plugins_name, l_element){ + log_it(L_NOTICE, "Registration %s manifest", l_element->name_directory); + l_name_file = dap_strjoin("",l_plugins_root_path, "/", l_element->name_directory, "/manifest.json", NULL); + if (!dap_chain_plugins_manifest_list_add_from_file(l_name_file)){ + log_it(L_ERROR, "Registration %s manifest fail", l_element->name_directory); } - DAP_FREE(name_file); + DAP_FREE(l_name_file); } dap_chain_plugins_loading(); + dap_chain_plugins_command_create(); }else{ log_it(L_NOTICE, "Permission to initialize python plugins has not been obtained."); return -2; @@ -40,103 +48,147 @@ int dap_chain_plugins_init(dap_config_t *config){ void dap_chain_plugins_loading(){ log_it(L_NOTICE, "Loading plugins"); dap_chain_plugins_list_manifest_t *l_manifests = dap_chain_plugins_manifests_get_list(); - dap_chain_plugins_list_manifest_t *man = NULL; - dap_chain_plugins_list_manifest_t *treshold = NULL; - dap_chain_plugins_list_manifest_t *tmp = NULL; - LL_FOREACH_SAFE(l_manifests, man, tmp){ - if (man->name == NULL){ + dap_chain_plugins_list_manifest_t *l_man = NULL; + dap_chain_plugins_list_manifest_t *l_treshold = NULL; + dap_chain_plugins_list_manifest_t *l_tmp = NULL; + if (l_manifests == NULL) + return; + LL_FOREACH_SAFE(l_manifests, l_man, l_tmp){ + if (l_man->name == NULL){ log_it(L_ERROR, "Can loading plugin, file not found"); break; } - log_it(L_NOTICE, "Check dependencys for plugin %s", man->name); - if (man->dependencys != NULL){ + log_it(L_NOTICE, "Check dependencys for plugin %s", l_man->name); + if (l_man->dependencys != NULL){ log_it(L_NOTICE, "Plugin have dependencys"); - if (!dap_chain_plugins_list_check_load_plugins(man->dependencys)){ - log_it(L_NOTICE, "Plugin %s add treshold", man->name); - LL_APPEND(treshold, man); + if (!dap_chain_plugins_list_check_load_plugins(l_man->dependencys)){ + log_it(L_NOTICE, "Plugin %s add treshold", l_man->name); + LL_APPEND(l_treshold, l_man); }else{ - dap_chain_plugins_load_plugin(dap_strjoin("", plugins_root_path, man->name, "/", NULL), man->name); + dap_chain_plugins_load_plugin(dap_strjoin("", s_plugins_root_path, l_man->name, "/", NULL), l_man->name); } }else{ - dap_chain_plugins_load_plugin(dap_strjoin("", plugins_root_path, man->name, "/", NULL), man->name); + dap_chain_plugins_load_plugin(dap_strjoin("", s_plugins_root_path, l_man->name, "/", NULL), l_man->name); } } - int c_processed = 0; - int step_processed = 0; - int len; - LL_COUNT(treshold, man, len); + int l_c_processed = 0; + int l_step_processed = 0; + int l_len; + LL_COUNT(l_treshold, l_man, l_len); do{ - LL_FOREACH_SAFE(treshold, man, tmp){ - if (dap_chain_plugins_list_check_load_plugins(man->dependencys)){ - log_it(L_NOTICE, "For plugin %s loading all dependecys", man->name); - dap_chain_plugins_load_plugin(dap_strjoin("", plugins_root_path, man->name, "/", NULL), man->name); - LL_DELETE(treshold, man); - c_processed++; - step_processed = 0; + LL_FOREACH_SAFE(l_treshold, l_man, l_tmp){ + if (dap_chain_plugins_list_check_load_plugins(l_man->dependencys)){ + log_it(L_NOTICE, "For plugin %s loading all dependecys", l_man->name); + dap_chain_plugins_load_plugin(dap_strjoin("", s_plugins_root_path, l_man->name, "/", NULL), l_man->name); + LL_DELETE(l_treshold, l_man); + l_c_processed++; + l_step_processed = 0; } } - step_processed++; - }while(c_processed < len && step_processed <= 2); + l_step_processed++; + }while(l_c_processed < l_len && l_step_processed <= 2); //Check loading all treshold - LL_COUNT(treshold, man, len); - if (len > 0){ + LL_COUNT(l_treshold, l_man, l_len); + if (l_len > 0){ log_it(L_WARNING, "I can't loading some plugins from list treshold"); - LL_FOREACH(treshold, man){ - log_it(L_ERROR, "The plugin %s does not load with a dependency resolution error.", man->name); + LL_FOREACH(l_treshold, l_man){ + log_it(L_ERROR, "The plugin %s does not load with a dependency resolution error.", l_man->name); } } } -void dap_chain_plugins_load_plugin(const char *dir_path, const char *name){ - log_it(L_NOTICE, "Loading %s plugin directory %s", name, dir_path); +void dap_chain_plugins_load_plugin(const char *a_dir_path, const char *a_name){ + log_it(L_NOTICE, "Loading %s plugin directory %s", a_name, a_dir_path); PyErr_Clear(); - PyObject *obj_dir_path = PyUnicode_FromString(dir_path); - PyList_Append(sys_path, obj_dir_path); - Py_XDECREF(obj_dir_path); - PyObject *module = PyImport_ImportModule(name); - PyObject *func_init = PyObject_GetAttrString(module, "init"); - PyObject *func_deinit = PyObject_GetAttrString(module, "deinit"); - PyObject *res_int = NULL; + PyObject *l_obj_dir_path = PyUnicode_FromString(a_dir_path); + PyList_Append(s_sys_path, l_obj_dir_path); + Py_XDECREF(l_obj_dir_path); + PyObject *l_module = PyImport_ImportModule(a_name); + PyObject *l_func_init = PyObject_GetAttrString(l_module, "init"); + PyObject *l_func_deinit = PyObject_GetAttrString(l_module, "deinit"); + PyObject *l_res_int = NULL; PyErr_Clear(); - if (func_init != NULL && PyCallable_Check(func_init)){ - res_int = PyEval_CallObject(func_init, NULL); - if (res_int && PyLong_Check(res_int)){ - if (_PyLong_AsInt(res_int) == 0){ - dap_chain_plugins_list_add(module, name); + if (l_func_init != NULL && PyCallable_Check(l_func_init)){ + l_res_int = PyEval_CallObject(l_func_init, NULL); + if (l_res_int && PyLong_Check(l_res_int)){ + if (_PyLong_AsInt(l_res_int) == 0){ + dap_chain_plugins_list_add(l_module, a_name); } else { PyErr_Print(); - log_it(L_ERROR, "Code error %i at initialization %s plugin", _PyLong_AsInt(res_int), name); + log_it(L_ERROR, "Code error %i at initialization %s plugin", _PyLong_AsInt(l_res_int), a_name); } } else { - log_it(L_ERROR, "Function initialization %s plugin don't reterned integer value", name); + log_it(L_ERROR, "Function initialization %s plugin don't reterned integer value", a_name); } - Py_XDECREF(res_int); + Py_XDECREF(l_res_int); }else { - log_it(L_ERROR, "For plugins %s don't found function init", name); + log_it(L_ERROR, "For plugins %s don't found function init", a_name); } - if (func_deinit == NULL || !PyCallable_Check(func_deinit)){ - log_it(L_WARNING, "For plugins %s don't found function deinit", name); + if (l_func_deinit == NULL || !PyCallable_Check(l_func_deinit)){ + log_it(L_WARNING, "For plugins %s don't found function deinit", a_name); } } void dap_chain_plugins_deinit(){ log_it(L_NOTICE, "Deinit python plugins"); - dap_chain_plugin_list_module_t *plugins = dap_chain_plugins_list_get(); - dap_chain_plugin_list_module_t *plugin; - dap_chain_plugin_list_module_t *tmp; - PyObject *res_int = NULL; - LL_FOREACH_SAFE(plugins, plugin, tmp){ - PyObject *func_deinit = PyObject_GetAttrString(plugin->obj_module, "deinit"); - if (func_deinit != NULL || PyCallable_Check(func_deinit)){ - res_int = PyEval_CallObject(func_deinit, NULL); + dap_chain_plugin_list_module_t *l_plugins = dap_chain_plugins_list_get(); + dap_chain_plugin_list_module_t *l_plugin; + dap_chain_plugin_list_module_t *l_tmp; + PyObject *l_res_int = NULL; + LL_FOREACH_SAFE(l_plugins, l_plugin, l_tmp){ + PyObject *l_func_deinit = PyObject_GetAttrString(l_plugin->obj_module, "deinit"); + if (l_func_deinit != NULL || PyCallable_Check(l_func_deinit)){ + l_res_int = PyEval_CallObject(l_func_deinit, NULL); } else { - log_it(L_WARNING, "For plugin %s can't callable function deinit", plugin->name); + log_it(L_WARNING, "For plugin %s can't callable function deinit", l_plugin->name); } - DAP_FREE(plugin->name); - Py_XDECREF(plugin->obj_module); - LL_DELETE(plugins, plugin); + DAP_FREE(l_plugin->name); + Py_XDECREF(l_plugin->obj_module); + LL_DELETE(l_plugins, l_plugin); } + dap_chain_plugins_manifest_list_delete_all(); Py_Finalize(); } +int dap_chain_plugins_reload_plugin(const char * a_name_plugin){ + log_it(L_NOTICE, "Reload plugin %s", a_name_plugin); + dap_chain_plugin_list_module_t *l_plugins = dap_chain_plugins_list_get(); + dap_chain_plugin_list_module_t *l_plugin = NULL; + LL_SEARCH(l_plugins, l_plugin, a_name_plugin, dap_chain_plugins_list_name_cmp); + if (l_plugin == NULL) + return -4; + PyObject *l_func_deinit = PyObject_GetAttrString(l_plugin->obj_module, "deinit"); + if (l_func_deinit != NULL || PyCallable_Check(l_func_deinit)){ + PyEval_CallObject(l_func_deinit, NULL); + } else { + log_it(L_WARNING, "For plugin %s can't callable function deinit", l_plugin->name); + } + DAP_FREE(l_plugin->name); + Py_XDECREF(l_plugin->obj_module); + LL_DELETE(l_plugins, l_plugin); + dap_chain_plugins_manifest_list_delete_name(a_name_plugin); + //Loading plugin + char *l_path_plugin = dap_strjoin(NULL, s_plugins_root_path, a_name_plugin, NULL); + char *l_name_file_manifest = dap_strjoin("",s_plugins_root_path, a_name_plugin, "/manifest.json", NULL); + if (!dap_chain_plugins_manifest_list_add_from_file(l_name_file_manifest)){ + log_it(L_ERROR, "Registration %s manifest fail", l_path_plugin); + return -3; + } + DAP_FREE(l_name_file_manifest); + dap_chain_plugins_list_manifest_t *l_manifest = dap_chain_plugins_manifest_list_get_name(a_name_plugin); + if (l_manifest->dependencys != NULL){ + if (!dap_chain_plugins_list_check_load_plugins(l_manifest->dependencys)){ + log_it(L_NOTICE, "%s plugin has unresolved dependencys, restart all plagins", l_manifest->name); + return -2; + }else{ + dap_chain_plugins_load_plugin(dap_strjoin("", s_plugins_root_path, l_manifest->name, "/", NULL), l_manifest->name); + return 0; + } + }else{ + dap_chain_plugins_load_plugin(dap_strjoin("", s_plugins_root_path, l_manifest->name, "/", NULL), l_manifest->name); + return 0; + } + + return -1; +} diff --git a/src/dap_chain_plugins_command.c b/src/dap_chain_plugins_command.c new file mode 100644 index 0000000000000000000000000000000000000000..0aa95c629feee3ad1c6081fbb137663fa53e01c4 --- /dev/null +++ b/src/dap_chain_plugins_command.c @@ -0,0 +1,105 @@ +#include "dap_chain_plugins_command.h" + +static bool s_l_restart_plugins = false; + +#undef LOG_TAG +#define LOG_TAG "dap_chain_plugins_command" + +void dap_chain_plugins_command_create(void){ + if (!s_l_restart_plugins){ + dap_chain_node_cli_cmd_item_create("plugins", dap_chain_plugins_command_handler, NULL, + "Commands for working with plugins.", + "plugins list \t- show list plugins \n" + "plugins show --name <name_plugin> \t-show information for plugin \n" + "plugins restart \t-Restart all plugins \n" + "plugins reload --name <name_plugin> \t-Restart plugin \n\n"); + s_l_restart_plugins = true; + } +} +int dap_chain_plugins_command_handler(int a_argc, char **a_argv, void *a_arg_func, char **a_str_reply){ + (void)a_arg_func; + log_it(L_NOTICE, "Handler cmd"); + enum { + CMD_NONE, CMD_LIST, CMD_SHOW_NAME, CMD_RESTART, CMD_RELOAD_NAME + }; + int l_arg_index = 1; + int l_cmd_name = CMD_NONE; + const char *l_name_plugin = NULL; + dap_chain_plugins_list_manifest_t *l_element = NULL; + if (dap_chain_node_cli_find_option_val(a_argv,l_arg_index, a_argc, "list", NULL)) + l_cmd_name = CMD_LIST; + if (dap_chain_node_cli_find_option_val(a_argv,l_arg_index, a_argc, "show", NULL)) + l_cmd_name = CMD_SHOW_NAME; + if (dap_chain_node_cli_find_option_val(a_argv,l_arg_index, a_argc, "restart", NULL)) + l_cmd_name = CMD_RESTART; + if (dap_chain_node_cli_find_option_val(a_argv,l_arg_index, a_argc, "reload", NULL)) + l_cmd_name = CMD_RELOAD_NAME; + char *l_str = NULL; + switch (l_cmd_name) { + case CMD_LIST: + l_str = dap_strdup("|\tName plugin\t|\tVersion\t|\tAuthor(s)\t|\n"); + LL_FOREACH(dap_chain_plugins_manifests_get_list(), l_element){ + l_str = dap_strjoin(NULL, + l_str, "|\t",l_element->name, "\t|\t", l_element->version, "\t|\t", l_element->author, "\t|\n", NULL); + + } + dap_chain_node_cli_set_reply_text(a_str_reply, l_str); + break; + case CMD_SHOW_NAME: + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "--name", &l_name_plugin); + log_it(L_NOTICE, "name plugin: %s", l_name_plugin); + LL_SEARCH(dap_chain_plugins_manifests_get_list(), l_element, l_name_plugin, dap_chain_plugins_manifest_name_cmp); + if (l_element != NULL){ + char *l_dep = dap_chain_plugins_manifests_get_list_dependencyes(l_element); + if (l_dep != NULL){ + dap_chain_node_cli_set_reply_text(a_str_reply, " Name: %s\n Version: %s\n Author: %s\n" + " Description: %s\n Dependencys: %s \n\n", + l_element->name, l_element->version, l_element->author, + l_element->description, l_dep); + DAP_FREE(l_dep); + } else { + dap_chain_node_cli_set_reply_text(a_str_reply, " Name: %s\n Version: %s\n Author: %s\n" + " Description: %s\n\n", + l_element->name, l_element->version, l_element->author, l_element->description); + } + } else { + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't searching plugin with name %s", l_name_plugin); + } + break; + case CMD_RESTART: + log_it(L_NOTICE, "Start procedure restart python plugins module"); + dap_chain_plugins_deinit(); + dap_chain_plugins_init(g_config); + log_it(L_NOTICE, "Done procedure restart python plugins module"); + dap_chain_node_cli_set_reply_text(a_str_reply, "Done procedure restart python plugins module."); + break; + case CMD_RELOAD_NAME: + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "--name", &l_name_plugin); + int l_result = dap_chain_plugins_reload_plugin(l_name_plugin); + switch (l_result) { + case 0: + dap_chain_node_cli_set_reply_text(a_str_reply, "Restarting the plugin %s completed successfully.", l_name_plugin); + break; + case -2: + dap_chain_node_cli_set_reply_text(a_str_reply, + "%s plugin has unresolved dependencys, restart all plagins", + l_name_plugin); + break; + case -3: + dap_chain_node_cli_set_reply_text(a_str_reply, "Registration %s manifest for %s plugin fail", l_name_plugin); + break; + case -4: + dap_chain_node_cli_set_reply_text(a_str_reply, "A plugin named %s will not find", l_name_plugin); + break; + default: + dap_chain_node_cli_set_reply_text(a_str_reply, "An unforeseen error has occurred."); + break; + } + break; + default: + dap_chain_node_cli_set_reply_text(a_str_reply, "Not validation parameters"); + break; + + } + return 0; +} diff --git a/src/dap_chain_plugins_list.c b/src/dap_chain_plugins_list.c index cac4d70334b147c176f2ea24d351118ebc9fb448..c6e81eec508c1c39feb454809dd5da015b80e470 100644 --- a/src/dap_chain_plugins_list.c +++ b/src/dap_chain_plugins_list.c @@ -1,57 +1,64 @@ #include "dap_chain_plugins_list.h" +#undef LOG_TAG +#define LOG_TAG "dap_chain_plugins_list" + void dap_chain_plugins_list_init(){ - m_dap_chain_plugins_module_list = NULL; + s_dap_chain_plugins_module_list = NULL; } -void dap_chain_plugins_list_add(PyObject *module, const char *name){ +void dap_chain_plugins_list_add(PyObject *a_module, const char *a_name){ dap_chain_plugin_list_module_t *elemnet = (dap_chain_plugin_list_module_t*)DAP_NEW(dap_chain_plugin_list_module_t); - elemnet->name = dap_strdup(name); - elemnet->obj_module = module; - LL_APPEND(m_dap_chain_plugins_module_list, elemnet); + elemnet->name = dap_strdup(a_name); + elemnet->obj_module = a_module; + LL_APPEND(s_dap_chain_plugins_module_list, elemnet); } dap_chain_plugin_list_module_t* dap_chain_plugins_list_get(){ - return m_dap_chain_plugins_module_list; + return s_dap_chain_plugins_module_list; } int dap_chain_plugins_list_cmp(dap_chain_plugin_list_module_t *e1, dap_chain_plugin_list_module_t *e2){ return strcmp(e1->name, e2->name); } -bool dap_chain_plugins_list_check_load_plugins(dap_chain_plugins_list_char_t *list){ - dap_chain_plugins_list_char_t *value_from_list = NULL; - dap_chain_plugin_list_module_t *element_from_list_module; - dap_chain_plugin_list_module_t *element_lnk = (dap_chain_plugin_list_module_t*)DAP_NEW( +bool dap_chain_plugins_list_check_load_plugins(dap_chain_plugins_list_char_t *a_list){ + dap_chain_plugins_list_char_t *l_value_from_list = NULL; + dap_chain_plugin_list_module_t *l_element_from_list_module; + dap_chain_plugin_list_module_t *l_element_lnk = (dap_chain_plugin_list_module_t*)DAP_NEW( dap_chain_plugin_list_module_t); int lenght; - LL_COUNT(m_dap_chain_plugins_module_list, element_from_list_module, lenght); + LL_COUNT(s_dap_chain_plugins_module_list, l_element_from_list_module, lenght); if (lenght == 0) return false; - LL_FOREACH(list, value_from_list){ - element_lnk->name = value_from_list->value; - LL_SEARCH(m_dap_chain_plugins_module_list, element_from_list_module, element_lnk, dap_chain_plugins_list_cmp); - if (!element_from_list_module) + LL_FOREACH(a_list, l_value_from_list){ + l_element_lnk->name = l_value_from_list->value; + LL_SEARCH(s_dap_chain_plugins_module_list, l_element_from_list_module, l_element_lnk, dap_chain_plugins_list_cmp); + if (!l_element_from_list_module) return false; } return true; } -void dap_chain_plugins_list_name_del(const char *name){ - dap_chain_plugin_list_module_t *plugin; - dap_chain_plugin_list_module_t *tmp; +void dap_chain_plugins_list_name_del(const char *a_name){ + dap_chain_plugin_list_module_t *l_plugin; + dap_chain_plugin_list_module_t *l_tmp; bool plugin_searcging = false; - LL_FOREACH_SAFE(m_dap_chain_plugins_module_list, plugin, tmp){ - if (strcmp(plugin->name, name) == 0){ - DAP_FREE(plugin->name); - Py_XDECREF(plugin->obj_module); - LL_DELETE(m_dap_chain_plugins_module_list, plugin); + LL_FOREACH_SAFE(s_dap_chain_plugins_module_list, l_plugin, l_tmp){ + if (strcmp(l_plugin->name, a_name) == 0){ + DAP_FREE(l_plugin->name); + Py_XDECREF(l_plugin->obj_module); + LL_DELETE(s_dap_chain_plugins_module_list, l_plugin); plugin_searcging = true; } } if (!plugin_searcging){ - log_it(L_WARNING, "Can't searching plugins %s for delete", name); + log_it(L_WARNING, "Can't searching plugins %s for delete", a_name); } } +int dap_chain_plugins_list_name_cmp(dap_chain_plugin_list_module_t *a_element, const char *a_name){ + return strcmp(a_element->name, a_name); +} + diff --git a/src/dap_chain_plugins_manifest.c b/src/dap_chain_plugins_manifest.c index 4a202f98279d01c0b5e6206d72ed755e221c6754..3a896ccabcf3d02ee55f70f48f9ba93e32c08b11 100644 --- a/src/dap_chain_plugins_manifest.c +++ b/src/dap_chain_plugins_manifest.c @@ -1,37 +1,55 @@ #include "dap_chain_plugins_manifest.h" -dap_chain_plugins_list_manifest_t *dap_chain_plugins_manifest_new(const char *name, const char *version, const dap_chain_plugins_list_char_t *dep, const char *author, - const char *description){ - dap_chain_plugins_list_manifest_t *man = (dap_chain_plugins_list_manifest_t*)DAP_NEW(dap_chain_plugins_list_manifest_t); - man->name = dap_strdup(name); - man->author = dap_strdup(author); - man->version = dap_strdup(version); - man->description = dap_strdup(description); - man->dependencys = NULL; +#undef LOG_TAG +#define LOG_TAG "dap_chain_plugins_manifest" + +void dap_chain_plugins_list_char_delete_all(dap_chain_plugins_list_char_t *a_list){ + dap_chain_plugins_list_char_t *l_element; + dap_chain_plugins_list_char_t *l_tmp; + LL_FOREACH_SAFE(a_list, l_element, l_tmp){ + DAP_FREE(l_element->value); + LL_DELETE(a_list, l_element); + } +} + +dap_chain_plugins_list_manifest_t *dap_chain_plugins_manifest_new(const char *a_name, const char *a_version, + const dap_chain_plugins_list_char_t *a_dep, + const char *a_author, + const char *a_description){ + dap_chain_plugins_list_manifest_t *l_man = (dap_chain_plugins_list_manifest_t*)DAP_NEW(dap_chain_plugins_list_manifest_t); + l_man->name = dap_strdup(a_name); + l_man->author = dap_strdup(a_author); + l_man->version = dap_strdup(a_version); + l_man->description = dap_strdup(a_description); + l_man->dependencys = NULL; //copy informantion from dep to man->dependencys - int len_dep; - dap_chain_plugins_list_char_t *char_t; - LL_COUNT((dap_chain_plugins_list_char_t*)dep, char_t, len_dep); - LL_FOREACH((dap_chain_plugins_list_char_t*)dep, char_t){ - LL_APPEND(man->dependencys, char_t); + int l_len_dep; + dap_chain_plugins_list_char_t *l_char_t; + LL_COUNT((dap_chain_plugins_list_char_t*)a_dep, l_char_t, l_len_dep); + LL_FOREACH((dap_chain_plugins_list_char_t*)a_dep, l_char_t){ + LL_APPEND(l_man->dependencys, l_char_t); } - man->dependencys = (dap_chain_plugins_list_char_t*)dep; - return man; + l_man->dependencys = (dap_chain_plugins_list_char_t*)a_dep; + return l_man; } -static dap_chain_plugins_list_char_t* JSON_array_to_dap_list_char(json_object *j_obj){ - dap_chain_plugins_list_char_t *list = NULL; - dap_chain_plugins_list_char_t *element = NULL; - for (int i = 0; i < json_object_array_length(j_obj); i++){ - element = (dap_chain_plugins_list_char_t*)DAP_NEW(dap_chain_plugins_list_char_t); - element->value = dap_strdup(json_object_get_string(json_object_array_get_idx(j_obj, i))); - LL_APPEND(list, element); +static dap_chain_plugins_list_char_t* JSON_array_to_dap_list_char(json_object *a_j_obj){ + dap_chain_plugins_list_char_t *l_list = NULL; + dap_chain_plugins_list_char_t *l_element = NULL; + for (int i = 0; i < json_object_array_length(a_j_obj); i++){ + l_element = (dap_chain_plugins_list_char_t*)DAP_NEW(dap_chain_plugins_list_char_t); + l_element->value = dap_strdup(json_object_get_string(json_object_array_get_idx(a_j_obj, i))); + LL_APPEND(l_list, l_element); } - return list; + return l_list; } void dap_chain_plugins_manifest_list_create(){ - manifests = NULL; + s_manifests = NULL; +} + +int dap_chain_plugins_manifest_name_cmp(dap_chain_plugins_list_manifest_t *man, const char *name){ + return dap_strcmp(man->name, name); } dap_chain_plugins_list_manifest_t* dap_chain_plugins_add_manifest_from_file(const char *file_path){ @@ -68,17 +86,68 @@ dap_chain_plugins_list_manifest_t* dap_chain_plugins_add_manifest_from_file(cons } void dap_chain_plugins_manifest_list_add_manifest(dap_chain_plugins_list_manifest_t *man){ - LL_APPEND(manifests, man); + LL_APPEND(s_manifests, man); } dap_chain_plugins_list_manifest_t* dap_chain_plugins_manifests_get_list(){ - return manifests; + return s_manifests; +} + +dap_chain_plugins_list_manifest_t *dap_chain_plugins_manifest_list_get_name(const char *a_name){ + dap_chain_plugins_list_manifest_t *l_element; + LL_SEARCH(s_manifests, l_element, a_name, dap_chain_plugins_manifest_name_cmp); + return l_element; +} + +char* dap_chain_plugins_manifests_get_list_dependencyes(dap_chain_plugins_list_manifest_t *a_element){ + if (a_element->dependencys == NULL) { + return NULL; + } else { + char *l_result = ""; + dap_chain_plugins_list_char_t *l_el; + int l_max_count_list = 0; + LL_COUNT(a_element->dependencys, l_el, l_max_count_list); + int l_count_list = 1; + LL_FOREACH(a_element->dependencys, l_el){ + if (l_count_list != l_max_count_list) + l_result = dap_strjoin(NULL, l_result, l_el->value, ", ", NULL); + else + l_result = dap_strjoin(NULL, l_result, l_el->value, NULL); + } + return l_result; + } } -bool dap_chain_plugins_manifest_list_add_from_file(const char *file_path){ - dap_chain_plugins_list_manifest_t *manifest = dap_chain_plugins_add_manifest_from_file(file_path); - if (manifest == NULL) +bool dap_chain_plugins_manifest_list_add_from_file(const char *a_file_path){ + dap_chain_plugins_list_manifest_t *l_manifest = dap_chain_plugins_add_manifest_from_file(a_file_path); + if (l_manifest == NULL) return false; - dap_chain_plugins_manifest_list_add_manifest(manifest); + dap_chain_plugins_manifest_list_add_manifest(l_manifest); return true; } + +bool dap_chain_plugins_manifest_list_delete_name(const char *a_name){ + dap_chain_plugins_list_manifest_t *l_element; + LL_SEARCH(s_manifests, l_element, a_name, dap_chain_plugins_manifest_name_cmp); + if (l_element == NULL) + return false; + DAP_FREE(l_element->name); + DAP_FREE(l_element->version); + DAP_FREE(l_element->author); + DAP_FREE(l_element->description); + dap_chain_plugins_list_char_delete_all(l_element->dependencys); + LL_DELETE(s_manifests, l_element); + return true; +} +void dap_chain_plugins_manifest_list_delete_all(void){ + dap_chain_plugins_list_manifest_t *l_element; + dap_chain_plugins_list_manifest_t *tmp; + LL_FOREACH_SAFE(s_manifests, l_element, tmp){ + DAP_FREE(l_element->name); + DAP_FREE(l_element->version); + DAP_FREE(l_element->author); + DAP_FREE(l_element->description); + dap_chain_plugins_list_char_delete_all(l_element->dependencys); + LL_DELETE(s_manifests, l_element); + } +}