From 090cfe6c513293072848f5fb05cccb45e3a34b92 Mon Sep 17 00:00:00 2001 From: fly_1997 Date: Sat, 11 May 2024 10:11:51 +0800 Subject: [PATCH] update version to v1.0.1 (cherry picked from commit 9932a6119a22204327f04de7341a8ce4d4a20464) --- 0001-fix-remove-plugin-bug-and-refactor.patch | 1080 ----------- ...nd-replace-raw-poniters-with-smart-p.patch | 1599 ----------------- ...-description-extract-class-and-fix-b.patch | 1034 ----------- ...e-error-and-check-plugin-list-config.patch | 200 --- ...-file-permission-and-fix-service-fil.patch | 322 ---- ...rror-and-args-parsing-error-printing.patch | 252 --- oeAware-manager-v1.0.0.tar.gz | Bin 23676 -> 0 bytes oeAware-manager-v1.0.1.tar.gz | Bin 0 -> 26719 bytes oeAware-manager.spec | 17 +- 9 files changed, 7 insertions(+), 4497 deletions(-) delete mode 100644 0001-fix-remove-plugin-bug-and-refactor.patch delete mode 100644 0002-add-error-code-and-replace-raw-poniters-with-smart-p.patch delete mode 100644 0003-add-client-error-description-extract-class-and-fix-b.patch delete mode 100644 0004-fix-auto-enable-error-and-check-plugin-list-config.patch delete mode 100644 0005-modify-logs-sock-file-permission-and-fix-service-fil.patch delete mode 100644 0006-fix-load-error-and-args-parsing-error-printing.patch delete mode 100644 oeAware-manager-v1.0.0.tar.gz create mode 100644 oeAware-manager-v1.0.1.tar.gz diff --git a/0001-fix-remove-plugin-bug-and-refactor.patch b/0001-fix-remove-plugin-bug-and-refactor.patch deleted file mode 100644 index 1f15f19..0000000 --- a/0001-fix-remove-plugin-bug-and-refactor.patch +++ /dev/null @@ -1,1080 +0,0 @@ -From 47fb3c3a0097675ebc9ee2cdc20806638cb57b4d Mon Sep 17 00:00:00 2001 -From: fly_1997 -Date: Thu, 25 Apr 2024 10:31:05 +0800 -Subject: [PATCH 1/4] fix remove plugin bug and refactor - ---- - src/client/client.cpp | 33 +++++---- - src/client/client.h | 8 +-- - src/client/cmd_handler.h | 3 +- - src/plugin_mgr/dep_handler.cpp | 52 ++++++-------- - src/plugin_mgr/dep_handler.h | 15 ++-- - src/plugin_mgr/instance_run_handler.cpp | 77 +++++++++++---------- - src/plugin_mgr/instance_run_handler.h | 45 +++++------- - src/plugin_mgr/memory_store.h | 67 ++++++++++++++++++ - src/plugin_mgr/message_manager.cpp | 2 +- - src/plugin_mgr/message_manager.h | 9 ++- - src/plugin_mgr/plugin.cpp | 24 +++---- - src/plugin_mgr/plugin.h | 21 ++---- - src/plugin_mgr/plugin_manager.cpp | 92 ++++++++++++------------- - src/plugin_mgr/plugin_manager.h | 21 +++--- - 14 files changed, 253 insertions(+), 216 deletions(-) - create mode 100644 src/plugin_mgr/memory_store.h - -diff --git a/src/client/client.cpp b/src/client/client.cpp -index 2377c4b..72fb6a2 100644 ---- a/src/client/client.cpp -+++ b/src/client/client.cpp -@@ -11,6 +11,21 @@ - ******************************************************************************/ - #include "client.h" - -+const std::string Client::OPT_STRING = "Qqd:t:l:r:e:"; -+const struct option Client::long_options[] = { -+ {"help", no_argument, NULL, 'h'}, -+ {"load", required_argument, NULL, 'l'}, -+ {"type", required_argument, NULL, 't'}, -+ {"remove", required_argument, NULL, 'r'}, -+ {"query", required_argument, NULL, 'q'}, -+ {"query-dep", required_argument, NULL, 'Q'}, -+ {"enable", required_argument, NULL, 'e'}, -+ {"disable", required_argument, NULL, 'd'}, -+ {"list", no_argument, NULL, 'L'}, -+ {"download", required_argument, NULL, 'D'}, -+ {0, 0, 0, 0}, -+}; -+ - static void print_error(const Msg &msg) { - for (int i = 0; i < msg.payload_size(); ++i) { - printf("%s\n", msg.payload(i).c_str()); -@@ -40,20 +55,6 @@ void Client::run_cmd(int cmd) { - this->cmd_handler->res_handler(res); - } - --const std::string Client::OPT_STRING = "Qqd:t:l:r:e:"; --const struct option Client::long_options[] = { -- {"help", no_argument, NULL, 'h'}, -- {"load", required_argument, NULL, 'l'}, -- {"type", required_argument, NULL, 't'}, -- {"remove", required_argument, NULL, 'r'}, -- {"query", required_argument, NULL, 'q'}, -- {"query-dep", required_argument, NULL, 'Q'}, -- {"enable", required_argument, NULL, 'e'}, -- {"disable", required_argument, NULL, 'd'}, -- {"list", no_argument, NULL, 'L'}, -- {"download", required_argument, NULL, 'D'}, -- {0, 0, 0, 0}, --}; - int Client::arg_parse(int argc, char *argv[]) { - int cmd = -1; - int opt; -@@ -95,10 +96,12 @@ int Client::arg_parse(int argc, char *argv[]) { - } - return cmd; - } -+ - void Client::arg_error(const std::string &msg) { - std::cerr << "oeawarectl: " << msg << "\n"; - exit(EXIT_FAILURE); - } -+ - void Client::close() { - tcp_socket.clear(); --} -\ No newline at end of file -+} -diff --git a/src/client/client.h b/src/client/client.h -index 0c2b053..9528f13 100644 ---- a/src/client/client.h -+++ b/src/client/client.h -@@ -31,9 +31,9 @@ private: - - TcpSocket tcp_socket; - CmdHandler *cmd_handler; -- const static std::string OPT_STRING; -- const static int MAX_OPT_SIZE = 11; -- const static struct option long_options[MAX_OPT_SIZE]; -+ static const std::string OPT_STRING; -+ static const int MAX_OPT_SIZE = 20; -+ static const struct option long_options[MAX_OPT_SIZE]; - }; - --#endif // !CLIENT_H -\ No newline at end of file -+#endif // !CLIENT_H -diff --git a/src/client/cmd_handler.h b/src/client/cmd_handler.h -index 0056430..4afae4c 100644 ---- a/src/client/cmd_handler.h -+++ b/src/client/cmd_handler.h -@@ -21,7 +21,6 @@ static std::string arg; - - class CmdHandler { - public: -- CmdHandler(){} - virtual void handler(Msg &msg) = 0; - virtual void res_handler(Msg &msg) = 0; - }; -@@ -80,4 +79,4 @@ void set_type(char* _type); - void set_arg(char* _arg); - void print_help(); - --#endif // !CLIENT_CMD_HANDLER_H -\ No newline at end of file -+#endif // !CLIENT_CMD_HANDLER_H -diff --git a/src/plugin_mgr/dep_handler.cpp b/src/plugin_mgr/dep_handler.cpp -index f2e9ba3..9a6ddc5 100644 ---- a/src/plugin_mgr/dep_handler.cpp -+++ b/src/plugin_mgr/dep_handler.cpp -@@ -14,28 +14,22 @@ - #include - - void DepHandler::add_arc_node(Node* node, const std::vector &dep_nodes) { -- ArcNode *arc_head = new ArcNode(); -- node->head = arc_head; -+ ArcNode *arc_head = node->head; - node->cnt = dep_nodes.size(); - int real_cnt = 0; - bool state = true; -- for (auto val : dep_nodes) { -+ for (auto name : dep_nodes) { - ArcNode *tmp = new ArcNode(); -- tmp->val = val; -- tmp->node_name = node->val; -- tmp->next = arc_head->next; -- if (arc_head->next != nullptr) { -- arc_head->next->pre = tmp; -- } -- -- tmp->pre = arc_head; -+ tmp->arc_name = name; -+ tmp->node_name = node->name; -+ tmp->next = arc_head->next; - arc_head->next = tmp; - -- if (nodes.count(val)) { -- arc_nodes[val][tmp] = true; -+ if (nodes.count(name)) { -+ arc_nodes[name][tmp] = true; - real_cnt++; - } else { -- arc_nodes[val][tmp] = false; -+ arc_nodes[name][tmp] = false; - state = false; - } - } -@@ -46,15 +40,14 @@ void DepHandler::add_arc_node(Node* node, const std::vector &dep_no - - void DepHandler::add_node(std::string name, std::vector dep_nodes) { - Node *cur_node = add_new_node(name); -- change_arc_nodes(name, true); -- add_arc_node(cur_node, dep_nodes); - this->nodes[name] = cur_node; -+ add_arc_node(cur_node, dep_nodes); -+ change_arc_nodes(name, true); - } - - void DepHandler::del_node(std::string name) { - del_node_and_arc_nodes(get_node(name)); - this->nodes.erase(name); -- change_arc_nodes(name, false); - } - - -@@ -65,8 +58,9 @@ Node* DepHandler::get_node(std::string name) { - - Node* DepHandler::add_new_node(std::string name) { - Node *cur_node = new Node(name); -+ cur_node->head = new ArcNode(); -+ - tail->next = cur_node; -- cur_node->pre = tail; - tail = cur_node; - return cur_node; - } -@@ -74,18 +68,15 @@ Node* DepHandler::add_new_node(std::string name) { - - - void DepHandler::del_node_and_arc_nodes(Node *node) { -- Node *pre = node->pre; - Node *next = node->next; -- pre->next = next; -- if (next != nullptr) -- next->pre = pre; - ArcNode *arc = node->head; - while(arc) { - ArcNode *tmp = arc->next; - if (arc != node->head){ -- arc_nodes[node->val].erase(arc); -- if (arc_nodes[node->val].empty()) { -- arc_nodes.erase(node->val); -+ std::string name = arc->arc_name; -+ arc_nodes[name].erase(arc); -+ if (arc_nodes[name].empty()) { -+ arc_nodes.erase(name); - } - } - delete arc; -@@ -95,6 +86,7 @@ void DepHandler::del_node_and_arc_nodes(Node *node) { - delete node; - } - void DepHandler::change_arc_nodes(std::string name, bool state) { -+ if (!nodes[name]->state || !arc_nodes.count(name)) return; - std::unordered_map &mp = arc_nodes[name]; - for (auto &vec : mp) { - vec.second = state; -@@ -127,7 +119,7 @@ void DepHandler::query_node_top(std::string name, std::vectornext != nullptr) { -- query.emplace_back(std::vector{name, p->next->val}); -+ query.emplace_back(std::vector{name, p->next->arc_name}); - p = p->next; - } - } -@@ -137,8 +129,8 @@ void DepHandler::query_node(std::string name, std::vector{name}); - for (auto cur = p->head->next; cur != nullptr; cur = cur->next) { -- query.emplace_back(std::vector{name, cur->val}); -- query_node(cur->val, query); -+ query.emplace_back(std::vector{name, cur->arc_name}); -+ query_node(cur->arc_name, query); - } - } - -@@ -149,9 +141,9 @@ std::vector DepHandler::get_pre_dependencies(std::string name) { - while (!q.empty()) { - auto &node = q.front(); - q.pop(); -- res.emplace_back(node->val); -+ res.emplace_back(node->name); - for (auto arc_node = node->head->next; arc_node != nullptr; arc_node = arc_node->next) { -- q.push(nodes[arc_node->val]); -+ q.push(nodes[arc_node->arc_name]); - } - } - return res; -diff --git a/src/plugin_mgr/dep_handler.h b/src/plugin_mgr/dep_handler.h -index a18f439..8ff91e2 100644 ---- a/src/plugin_mgr/dep_handler.h -+++ b/src/plugin_mgr/dep_handler.h -@@ -19,23 +19,21 @@ - - struct ArcNode { - ArcNode *next; -- ArcNode *pre; -- std::string val; -+ std::string arc_name; - std::string node_name; -- ArcNode() : next(nullptr), pre(nullptr) {} -+ ArcNode() : next(nullptr) {} - }; - - // a instance node - struct Node { - Node *next; -- Node *pre; - ArcNode *head; -- std::string val; -+ std::string name; - int cnt; - int real_cnt; - bool state; // dependency closed-loop -- Node() : next(nullptr), pre(nullptr), head(nullptr), state(true), cnt(0), real_cnt(0) {} -- Node(std::string val): val(val), next(nullptr), pre(nullptr), head(nullptr), state(true), cnt(0), real_cnt(0) {} -+ Node() : next(nullptr), head(nullptr), state(true), cnt(0), real_cnt(0) {} -+ Node(std::string name): name(name), next(nullptr), head(nullptr), state(true), cnt(0), real_cnt(0) {} - }; - - class DepHandler { -@@ -55,6 +53,9 @@ public: - void query_node(std::string name, std::vector> &query); - // query all instance dependencies - void query_all_top(std::vector> &query); -+ bool have_dep(const std::string &name) { -+ return arc_nodes.count(name); -+ } - bool is_empty() const { - return nodes.empty(); - } -diff --git a/src/plugin_mgr/instance_run_handler.cpp b/src/plugin_mgr/instance_run_handler.cpp -index a7f8b49..162079e 100644 ---- a/src/plugin_mgr/instance_run_handler.cpp -+++ b/src/plugin_mgr/instance_run_handler.cpp -@@ -13,7 +13,7 @@ - #include - #include - --void* get_ring_buf(Instance *instance) { -+static void* get_ring_buf(Instance *instance) { - if (instance == nullptr) { - return nullptr; - } -@@ -32,19 +32,19 @@ static void reflash_ring_buf(Instance *instance) { - ((CollectorInstance*)instance)->get_interface()->reflash_ring_buf(); - } - --static void run_aware(Instance *instance, std::vector &deps, std::unordered_map *all_instance) { -+void InstanceRunHandler::run_aware(Instance *instance, std::vector &deps) { - void *a[MAX_DEPENDENCIES_SIZE]; - for (int i = 0; i < deps.size(); ++i) { -- Instance *ins = (*all_instance)[deps[i]]; -+ Instance *ins = memory_store->get_instance(deps[i]); - a[i] = get_ring_buf(ins); - } - ((ScenarioInstance*)instance)->get_interface()->aware(a, (int)deps.size()); - } - --static void run_tune(Instance *instance, std::vector &deps, std::unordered_map *all_instance) { -+void InstanceRunHandler::run_tune(Instance *instance, std::vector &deps) { - void *a[MAX_DEPENDENCIES_SIZE]; - for (int i = 0; i < deps.size(); ++i) { -- Instance *ins = (*all_instance)[deps[i]]; -+ Instance *ins = memory_store->get_instance(deps[i]); - a[i] = get_ring_buf(ins); - } - ((TuneInstance*)instance)->get_interface()->tune(a, (int)deps.size()); -@@ -67,6 +67,7 @@ void InstanceRunHandler::insert_instance(Instance *instance) { - } - INFO("[PluginManager] " << instance->get_name() << " instance insert into running queue."); - } -+ - void InstanceRunHandler::delete_instance(Instance *instance) { - switch (instance->get_type()) { - case PluginType::COLLECTOR: -@@ -85,7 +86,6 @@ void InstanceRunHandler::delete_instance(Instance *instance) { - INFO("[PluginManager] " << instance->get_name() << " instance delete from running queue."); - } - -- - void InstanceRunHandler::handle_instance() { - InstanceRunMessage msg; - while(this->recv_queue_try_pop(msg)){ -@@ -100,6 +100,7 @@ void InstanceRunHandler::handle_instance() { - } - } - } -+ - template - static std::vector get_deps(Instance *instance) { - std::string deps = ((T*)instance)->get_interface()->get_dep(); -@@ -127,12 +128,12 @@ void InstanceRunHandler::adjust_collector_queue(const std::vector & - } - if (ok) continue; - if (flag) { -- if (find(m_dep) && !collector.count(m_dep)) { -- this->insert_instance((*this->all_instance)[m_dep]); -+ if (is_instance_exist(m_dep) && !collector.count(m_dep)) { -+ this->insert_instance(memory_store->get_instance(m_dep)); - } - } else { -- if (find(m_dep) && collector.count(m_dep)) { -- this->delete_instance((*this->all_instance)[m_dep]); -+ if (is_instance_exist(m_dep) && collector.count(m_dep)) { -+ this->delete_instance(memory_store->get_instance(m_dep)); - } - } - } -@@ -143,26 +144,35 @@ void InstanceRunHandler::check_scenario_dependency(const std::vectorget_interface()->get_cycle(); -- if (time % t != 0) return; -- reflash_ring_buf(instance); -+void InstanceRunHandler::schedule_collector(uint64_t time) { -+ for (auto &p : collector) { -+ Instance *instance = p.second; -+ int t = ((CollectorInstance*)instance)->get_interface()->get_cycle(); -+ if (time % t != 0) return; -+ reflash_ring_buf(instance); -+ } - } - --static void schedule_scenario(Instance *instance, unsigned long long time, InstanceRunHandler *instance_run_handler) { -- int t = ((ScenarioInstance*)instance)->get_interface()->get_cycle(); -- if (time % t != 0) return; -- std::vector origin_deps = get_deps(instance); -- run_aware(instance, origin_deps, instance_run_handler->get_all_instance()); -- std::vector cur_deps = get_deps(instance); -- instance_run_handler->check_scenario_dependency(origin_deps, cur_deps); -+void InstanceRunHandler::schedule_scenario(uint64_t time) { -+ for (auto &p : scenario) { -+ Instance *instance = p.second; -+ int t = ((ScenarioInstance*)instance)->get_interface()->get_cycle(); -+ if (time % t != 0) return; -+ std::vector origin_deps = get_deps(instance); -+ run_aware(instance, origin_deps); -+ std::vector cur_deps = get_deps(instance); -+ check_scenario_dependency(origin_deps, cur_deps); -+ } - } - --static void schedule_tune(Instance *instance, unsigned long long time, InstanceRunHandler *instance_run_handler) { -- int t = ((TuneInstance*)instance)->get_interface()->get_cycle(); -- if (time % t != 0) return; -- std::vector deps = get_deps(instance); -- run_tune(instance, deps, instance_run_handler->get_all_instance()); -+void InstanceRunHandler::schedule_tune(uint64_t time) { -+ for (auto &p : tune) { -+ Instance *instance = p.second; -+ int t = ((TuneInstance*)instance)->get_interface()->get_cycle(); -+ if (time % t != 0) return; -+ std::vector deps = get_deps(instance); -+ run_tune(instance, deps); -+ } - } - - void start(InstanceRunHandler *instance_run_handler) { -@@ -170,16 +180,9 @@ void start(InstanceRunHandler *instance_run_handler) { - INFO("[PluginManager] instance schedule started!"); - while(true) { - instance_run_handler->handle_instance(); -- for (auto &p : instance_run_handler->get_collector()) { -- schedule_collector(p.second, time); -- } -- for (auto &p : instance_run_handler->get_scenario()) { -- schedule_scenario(p.second, time, instance_run_handler); -- } -- -- for (auto &p : instance_run_handler->get_tune()) { -- schedule_tune(p.second, time, instance_run_handler); -- } -+ instance_run_handler->schedule_collector(time); -+ instance_run_handler->schedule_scenario(time); -+ instance_run_handler->schedule_tune(time); - - usleep(instance_run_handler->get_cycle() * 1000); - time += instance_run_handler->get_cycle(); -@@ -189,4 +192,4 @@ void start(InstanceRunHandler *instance_run_handler) { - void InstanceRunHandler::run() { - std::thread t(start, this); - t.detach(); --} -\ No newline at end of file -+} -diff --git a/src/plugin_mgr/instance_run_handler.h b/src/plugin_mgr/instance_run_handler.h -index 4730ce8..c9a8dfc 100644 ---- a/src/plugin_mgr/instance_run_handler.h -+++ b/src/plugin_mgr/instance_run_handler.h -@@ -15,13 +15,12 @@ - #include "safe_queue.h" - #include "plugin.h" - #include "logger.h" -+#include "memory_store.h" - #include - #include - #include - #include - --const int DEFAULT_CYCLE_SIZE = 10; --const int MAX_DEPENDENCIES_SIZE = 20; - enum class RunType { - ENABLED, - DISABLED, -@@ -32,9 +31,6 @@ class InstanceRunMessage { - public: - InstanceRunMessage() {} - InstanceRunMessage(RunType type, Instance *instance) : type(type), instance(instance) {} -- void init() { -- -- } - RunType get_type() { - return type; - } -@@ -51,11 +47,12 @@ class InstanceRunHandler { - public: - InstanceRunHandler() : cycle(DEFAULT_CYCLE_SIZE) {} - void run(); -+ void schedule_collector(uint64_t time); -+ void schedule_scenario(uint64_t time); -+ void schedule_tune(uint64_t time); - void handle_instance(); -- void delete_instance(Instance *instance); -- void insert_instance(Instance *instance); -- void set_all_instance(std::unordered_map *all_instance) { -- this->all_instance = all_instance; -+ void set_memory_store(MemoryStore *memory_store) { -+ this->memory_store = memory_store; - } - void set_cycle(int cycle) { - this->cycle = cycle; -@@ -63,20 +60,8 @@ public: - int get_cycle() { - return cycle; - } -- bool find(std::string name) { -- return (*this->all_instance).count(name); -- } -- std::unordered_map get_collector() { -- return this->collector; -- } -- std::unordered_map get_scenario() { -- return this->scenario; -- } -- std::unordered_map get_tune() { -- return this->tune; -- } -- std::unordered_map* get_all_instance() { -- return this->all_instance; -+ bool is_instance_exist(const std::string &name) { -+ return memory_store->is_instance_exist(name); - } - void recv_queue_push(InstanceRunMessage &msg) { - this->recv_queue.push(msg); -@@ -87,16 +72,22 @@ public: - bool recv_queue_try_pop(InstanceRunMessage &msg) { - return this->recv_queue.try_pop(msg); - } -- void check_scenario_dependency(const std::vector &deps, const std::vector &m_deps); - private: -+ void run_aware(Instance *instance, std::vector &deps); -+ void run_tune(Instance *instance, std::vector &deps); -+ void delete_instance(Instance *instance); -+ void insert_instance(Instance *instance); - void adjust_collector_queue(const std::vector &deps, const std::vector &m_deps, bool flag); -- -+ void check_scenario_dependency(const std::vector &deps, const std::vector &m_deps); -+ - std::unordered_map collector; - std::unordered_map scenario; - std::unordered_map tune; - SafeQueue recv_queue; -- std::unordered_map *all_instance; -+ MemoryStore *memory_store; - int cycle; -+ static const int DEFAULT_CYCLE_SIZE = 10; -+ static const int MAX_DEPENDENCIES_SIZE = 20; - }; - --#endif // !PLUGIN_MGR_INSTANCE_RUN_HANDLER_H -\ No newline at end of file -+#endif // !PLUGIN_MGR_INSTANCE_RUN_HANDLER_H -diff --git a/src/plugin_mgr/memory_store.h b/src/plugin_mgr/memory_store.h -new file mode 100644 -index 0000000..190fcdd ---- /dev/null -+++ b/src/plugin_mgr/memory_store.h -@@ -0,0 +1,67 @@ -+/****************************************************************************** -+ * Copyright (c) 2024 Huawei Technologies Co., Ltd. -+ * oeAware is licensed under Mulan PSL v2. -+ * You can use this software according to the terms and conditions of the Mulan PSL v2. -+ * You may obtain a copy of Mulan PSL v2 at: -+ * http://license.coscl.org.cn/MulanPSL2 -+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -+ * See the Mulan PSL v2 for more details. -+ ******************************************************************************/ -+#ifndef PLUGIN_MGR_MEMORY_STORE_H -+#define PLUGIN_MGR_MEMORY_STORE_H -+#include "plugin.h" -+#include "logger.h" -+#include -+ -+//OeAware memory storage, which is used to store plugins and instances in the memory. -+class MemoryStore { -+public: -+ void add_plugin(const std::string &name, Plugin *plugin) { -+ this->plugins.insert(std::make_pair(name, plugin)); -+ } -+ void add_instance(const std::string &name, Instance *instance) { -+ this->instances.insert(std::make_pair(name, instance)); -+ } -+ Plugin* get_plugin(const std::string &name) const { -+ return this->plugins.at(name); -+ } -+ Instance* get_instance(const std::string &name) const { -+ return this->instances.at(name); -+ } -+ void delete_plugin(const std::string &name) { -+ Plugin *plugin = plugins.at(name); -+ this->plugins.erase(name); -+ delete plugin; -+ } -+ void delete_instance(const std::string &name) { -+ Instance *instance = instances.at(name); -+ this->instances.erase(name); -+ } -+ bool is_plugin_exist(const std::string &name) const { -+ return this->plugins.count(name); -+ } -+ bool is_instance_exist(const std::string &name) const { -+ return this->instances.count(name); -+ } -+ std::vector get_all_plugins() { -+ std::vector res; -+ for (auto &p : plugins) { -+ res.emplace_back(p.second); -+ } -+ return res; -+ } -+ std::vector get_all_instances() { -+ std::vector res; -+ for (auto &p : instances) { -+ res.emplace_back(p.second); -+ } -+ return res; -+ } -+private: -+ std::unordered_map plugins; -+ std::unordered_map instances; -+}; -+ -+#endif // !PLUGIN_MGR_MEMORY_STORE_H -diff --git a/src/plugin_mgr/message_manager.cpp b/src/plugin_mgr/message_manager.cpp -index 92f467f..296c682 100644 ---- a/src/plugin_mgr/message_manager.cpp -+++ b/src/plugin_mgr/message_manager.cpp -@@ -80,7 +80,7 @@ void TcpSocket::serve_accept(SafeQueue *handler_msg, SafeQueue - for (int i = 0; i < num; ++i) { - int cur_fd = evs[i].data.fd; - if (cur_fd == sock) { -- conn = accept(cur_fd, NULL, NULL); -+ int conn = accept(cur_fd, NULL, NULL); - struct epoll_event ev; - ev.events = EPOLLIN; - ev.data.fd = conn; -diff --git a/src/plugin_mgr/message_manager.h b/src/plugin_mgr/message_manager.h -index d900c6f..d1faad3 100644 ---- a/src/plugin_mgr/message_manager.h -+++ b/src/plugin_mgr/message_manager.h -@@ -68,15 +68,14 @@ private: - - class TcpSocket { - public: -- TcpSocket() : conn(-1) {} -- int domain_listen(const char *name); -+ TcpSocket() {} - bool init(); - void serve_accept(SafeQueue *handler_msg, SafeQueue *res_msg); -+private: -+ int domain_listen(const char *name); -+ - int sock; -- struct sockaddr_in addr; -- int conn; - int epfd; -- struct epoll_event ev; - }; - - class MessageManager { -diff --git a/src/plugin_mgr/plugin.cpp b/src/plugin_mgr/plugin.cpp -index 091e73b..1a2db0d 100644 ---- a/src/plugin_mgr/plugin.cpp -+++ b/src/plugin_mgr/plugin.cpp -@@ -11,6 +11,11 @@ - ******************************************************************************/ - #include "plugin.h" - -+const std::string Instance::PLUGIN_ENABLED = "running"; -+const std::string Instance::PLUGIN_DISABLED = "close"; -+const std::string Instance::PLUGIN_STATE_ON = "available"; -+const std::string Instance::PLUGIN_STATE_OFF = "unavailable"; -+ - int Plugin::load(const std::string dl_path) { - void *handler = dlopen(dl_path.c_str(), RTLD_LAZY); - if (handler == nullptr) { -@@ -20,17 +25,8 @@ int Plugin::load(const std::string dl_path) { - return 0; - } - --std::string plugin_type_to_string(PluginType type) { -- switch (type) { -- case PluginType::COLLECTOR: { -- return COLLECTOR_TEXT; -- } -- case PluginType::SCENARIO: { -- return SCENARIO_TEXT; -- } -- case PluginType::TUNE: { -- return TUNE_TEXT; -- } -- } -- return ""; --} -\ No newline at end of file -+std::string Instance::get_info() const { -+ std::string state_text = this->state ? PLUGIN_STATE_ON : PLUGIN_STATE_OFF; -+ std::string run_text = this->enabled ? PLUGIN_ENABLED : PLUGIN_DISABLED; -+ return name + "(" + state_text + ", " + run_text + ")"; -+} -diff --git a/src/plugin_mgr/plugin.h b/src/plugin_mgr/plugin.h -index 892cb74..11b4748 100644 ---- a/src/plugin_mgr/plugin.h -+++ b/src/plugin_mgr/plugin.h -@@ -16,15 +16,6 @@ - #include - #include - --const std::string PLUGIN_ENABLED = "running"; --const std::string PLUGIN_DISABLED = "close"; --const std::string PLUGIN_STATE_ON = "available"; --const std::string PLUGIN_STATE_OFF = "unavailable"; -- --const std::string COLLECTOR_TEXT = "collector"; --const std::string SCENARIO_TEXT = "scenario"; --const std::string TUNE_TEXT = "tune"; -- - enum class PluginType { - COLLECTOR, - SCENARIO, -@@ -67,17 +58,17 @@ public: - bool get_enabled() const { - return this->enabled; - } -- std::string get_info() const { -- std::string state_text = this->state ? PLUGIN_STATE_ON : PLUGIN_STATE_OFF; -- std::string run_text = this->enabled ? PLUGIN_ENABLED : PLUGIN_DISABLED; -- return name + "(" + state_text + ", " + run_text + ")"; -- } -+ std::string get_info() const; - private: - std::string name; - std::string plugin_name; - PluginType type; - bool state; - bool enabled; -+ const static std::string PLUGIN_ENABLED; -+ const static std::string PLUGIN_DISABLED; -+ const static std::string PLUGIN_STATE_ON; -+ const static std::string PLUGIN_STATE_OFF; - }; - - class CollectorInstance : public Instance { -@@ -163,4 +154,4 @@ private: - std::string name; - }; - --#endif -\ No newline at end of file -+#endif -diff --git a/src/plugin_mgr/plugin_manager.cpp b/src/plugin_mgr/plugin_manager.cpp -index ec9b85e..47f9451 100644 ---- a/src/plugin_mgr/plugin_manager.cpp -+++ b/src/plugin_mgr/plugin_manager.cpp -@@ -16,15 +16,11 @@ - #include - #include - -+const std::string PluginManager::COLLECTOR_TEXT = "collector"; -+const std::string PluginManager::SCENARIO_TEXT = "scenario"; -+const std::string PluginManager::TUNE_TEXT = "tune"; - const static int ST_MODE_MASK = 0777; - --bool PluginManager::check(char **deps, int len) { -- for (int i = 0; i < len; ++i) { -- if (!is_instance_exist(deps[i])) return false; -- } -- return true; --} -- - void PluginManager::init(Config *config) { - plugin_types[COLLECTOR_TEXT] = PluginType::COLLECTOR; - plugin_types[SCENARIO_TEXT] = PluginType::SCENARIO; -@@ -32,24 +28,29 @@ void PluginManager::init(Config *config) { - this->config = config; - } - --bool PluginManager::remove(const std::string name) { -- if (!plugins.count(name)) return false; -- Plugin *plugin = plugins[name]; -+bool PluginManager::remove(const std::string &name) { -+ if (!memory_store.is_plugin_exist(name)) return false; -+ Plugin *plugin = memory_store.get_plugin(name); -+ std::vector instance_names; - for (int i = 0; i < plugin->get_instance_len(); ++i) { - Instance *instance = plugin->get_instance(i); - std::string iname = instance->get_name(); -- instances.erase(iname); -+ if (dep_handler->have_dep(iname)) { -+ return false; -+ } -+ instance_names.emplace_back(iname); -+ } -+ for(auto &iname : instance_names) { -+ memory_store.delete_instance(iname); - dep_handler->del_node(iname); -- INFO("[PluginManager] instance : " << instance->get_name()); - } -- delete plugin; -- plugins.erase(name); -+ memory_store.delete_plugin(name); - update_instance_state(); - return true; - } - bool PluginManager::query_all_plugins(Message &res) { -- for (auto &t : plugins) { -- Plugin *p = t.second; -+ std::vector all_plugins = memory_store.get_all_plugins(); -+ for (auto &p : all_plugins) { - res.add_payload(p->get_name()); - for (int i = 0; i < p->get_instance_len(); ++i) { - std::string info = p->get_instance(i)->get_info(); -@@ -60,11 +61,11 @@ bool PluginManager::query_all_plugins(Message &res) { - } - - bool PluginManager::query_plugin(std::string name, Message &res) { -- if (!plugins.count(name)) { -+ if (!memory_store.is_plugin_exist(name)) { - res.add_payload("no such plugin!"); - return true; - } -- Plugin *plugin = plugins[name]; -+ Plugin *plugin = memory_store.get_plugin(name); - res.add_payload(name); - for (int i = 0; i < plugin->get_instance_len(); ++i) { - std::string info = plugin->get_instance(i)->get_info(); -@@ -106,10 +107,6 @@ std::vector get_dep(T *interface) { - template - void PluginManager::save_instance(Plugin *plugin, T *interface_list, int len) { - if (interface_list == nullptr) return; -- std::unordered_map tmp_interfaces; -- for (int i = 0; i < len; ++i) { -- tmp_interfaces[interface_list[i].get_name()] = true; -- } - for (int i = 0; i < len; ++i) { - T *interface = interface_list + i; - Instance *instance = new U(); -@@ -127,7 +124,7 @@ void PluginManager::save_instance(Plugin *plugin, T *interface_list, int len) { - instance->set_state(dep_handler->get_node_state(name)); - ((U*)instance)->set_interface(interface); - DEBUG("[PluginManager] Instance: " << name.c_str()); -- this->instances[name] = instance; -+ memory_store.add_instance(name, instance); - plugin->add_instance(instance); - } - } -@@ -163,17 +160,18 @@ bool PluginManager::load_instance(Plugin *plugin) { - } - - void PluginManager::update_instance_state() { -- for (auto &v : instances) { -- if (dep_handler->get_node_state(v.first)) { -- v.second->set_state(true); -+ std::vector all_instances = memory_store.get_all_instances(); -+ for (auto &instance : all_instances) { -+ if (dep_handler->get_node_state(instance->get_name())) { -+ instance->set_state(true); - } else { -- v.second->set_state(false); -+ instance->set_state(false); - } - } - } - - bool PluginManager::load_plugin(const std::string name, PluginType type) { -- if (plugins.count(name)) { -+ if (memory_store.is_plugin_exist(name)) { - WARN("[PluginManager] " << name << " already loaded!"); - return false; - } -@@ -188,21 +186,21 @@ bool PluginManager::load_plugin(const std::string name, PluginType type) { - delete plugin; - return false; - } -- plugins[name] = plugin; -+ memory_store.add_plugin(name, plugin); - return true; - } - --std::string generate_dot(std::unordered_map instances, const std::vector> &query) { -+std::string generate_dot(MemoryStore &memory_store, const std::vector> &query) { - std::string res; - res += "digraph G {\n"; - std::unordered_map> sub_graph; - for (auto &vec : query) { -- Instance *instance = instances[vec[0]]; -+ Instance *instance = memory_store.get_instance(vec[0]); - sub_graph[instance->get_plugin_name()].emplace_back(vec[0]); - if (vec.size() == 1) { - continue; - } -- instance = instances[vec[1]]; -+ instance = memory_store.get_instance(vec[1]); - sub_graph[instance->get_plugin_name()].emplace_back(vec[1]); - res += vec[0] + "->" + vec[1] + ";"; - } -@@ -229,7 +227,7 @@ bool PluginManager::query_top(std::string name, Message &res) { - res.add_payload("Instance not available!"); - return false; - } -- std::string dot_text = generate_dot(instances, query); -+ std::string dot_text = generate_dot(memory_store, query); - res.add_payload(dot_text); - return true; - } -@@ -242,17 +240,17 @@ bool PluginManager::query_all_tops(Message &res) { - res.add_payload("No instance available!"); - return false; - } -- std::string dot_text = generate_dot(instances, query); -+ std::string dot_text = generate_dot(memory_store, query); - res.add_payload(dot_text); - return true; - } - - bool PluginManager::instance_enabled(std::string name) { -- if (!instances.count(name)) { -+ if (!memory_store.is_instance_exist(name)) { - WARN("[PluginManager] " << name << " instance can't load!"); - return false; - } -- Instance *instance = instances[name]; -+ Instance *instance = memory_store.get_instance(name); - if (!instance->get_state()) { - WARN("[PluginManager] " << name << " instance is unavailable, lacking dependencies!"); - return false; -@@ -263,7 +261,7 @@ bool PluginManager::instance_enabled(std::string name) { - } - std::vector pre_dependencies = dep_handler->get_pre_dependencies(name); - for (int i = pre_dependencies.size() - 1; i >= 0; --i) { -- instance = instances[pre_dependencies[i]]; -+ instance = memory_store.get_instance(pre_dependencies[i]); - if (instance->get_enabled()) { - continue; - } -@@ -275,11 +273,11 @@ bool PluginManager::instance_enabled(std::string name) { - } - - bool PluginManager::instance_disabled(std::string name) { -- if (!instances.count(name)) { -+ if (!memory_store.is_instance_exist(name)) { - WARN("[PluginManager] " << name << " instance can't load!"); - return false; - } -- Instance *instance = instances[name]; -+ Instance *instance = memory_store.get_instance(name); - if (!instance->get_state()) { - WARN("[PluginManager] " << name << " instance is unavailable, lacking dependencies!"); - return false; -@@ -341,11 +339,11 @@ void PluginManager::pre_enable() { - EnableItem item = config->get_enable_list(i); - if (item.get_enabled()) { - std::string name = item.get_name(); -- if (!plugins.count(name)) { -+ if (!memory_store.is_plugin_exist(name)) { - WARN("[PluginManager] plugin " << name << " cannot be enabled, because it does not exist."); - continue; - } -- Plugin *plugin = plugins[name]; -+ Plugin *plugin = memory_store.get_plugin(name); - for (int j = 0; j < plugin->get_instance_len(); ++j) { - instance_enabled(plugin->get_instance(i)->get_name()); - } -@@ -380,7 +378,7 @@ static bool check_load_msg(Message &msg, std::unordered_mapget_type()) { - case PluginType::COLLECTOR: { - CollectorInterface *collector_interface = ((CollectorInstance*)instance)->get_interface(); -@@ -397,7 +395,7 @@ void* PluginManager::get_data_buffer(std::string name) { - } - - void PluginManager::instance_dep_check(std::string name, Message &res) { -- Plugin *plugin = plugins[name]; -+ Plugin *plugin = memory_store.get_plugin(name); - for (int i = 0; i < plugin->get_instance_len(); ++i) { - std::string instance_name = plugin->get_instance(i)->get_name(); - std::vector> query; -@@ -405,7 +403,7 @@ void PluginManager::instance_dep_check(std::string name, Message &res) { - std::vector lack; - for (auto &item : query) { - if (item.size() < 2) continue; -- if (!instances.count(item[1])) { -+ if (!memory_store.is_instance_exist(item[1])) { - lack.emplace_back(item[1]); - } - } -@@ -437,7 +435,7 @@ static bool file_exist(const std::string &file_name) { - } - - int PluginManager::run() { -- instance_run_handler->set_all_instance(&instances); -+ instance_run_handler->set_memory_store(&memory_store); - instance_run_handler->run(); - while (true) { - Message msg; -@@ -483,7 +481,7 @@ int PluginManager::run() { - res.add_payload(name + " removed!"); - INFO("[PluginManager] " << name << " removed!"); - } else { -- res.add_payload(name + " does not exist!"); -+ res.add_payload(name + " remove failed!"); - } - break; - } -@@ -562,4 +560,4 @@ int PluginManager::run() { - res_msg->push(res); - } - return 0; --} -\ No newline at end of file -+} -diff --git a/src/plugin_mgr/plugin_manager.h b/src/plugin_mgr/plugin_manager.h -index 415e5ea..f648931 100644 ---- a/src/plugin_mgr/plugin_manager.h -+++ b/src/plugin_mgr/plugin_manager.h -@@ -13,11 +13,10 @@ - #define PLUGIN_MGR_PLUGIN_MANAGER_H - - #include "instance_run_handler.h" --#include "plugin.h" - #include "config.h" -+#include "memory_store.h" - #include "dep_handler.h" - #include "message_manager.h" --#include "logger.h" - #include - #include - #include -@@ -39,7 +38,6 @@ public: - void* get_data_buffer(std::string name); - private: - void pre_load_plugin(PluginType type); -- bool check(char **deps, int len); - bool query_all_plugins(Message &res); - bool query_plugin(std::string name, Message &res); - bool query_top(std::string name, Message &res); -@@ -54,24 +52,23 @@ private: - bool load_instance(Plugin *plugin); - bool load_plugin(const std::string path, PluginType type); - void batch_load(); -- bool remove(const std::string name); -+ bool remove(const std::string &name); - void batch_remove(); - void add_list(Message &msg); -- bool is_instance_exist(std::string name) { -- return this->instances.find(name) != this->instances.end(); -- } - void update_instance_state(); - private: - InstanceRunHandler *instance_run_handler; - Config *config; - SafeQueue *handler_msg; - SafeQueue *res_msg; -- std::unordered_map plugins; -- std::unordered_map instances; -- DepHandler *dep_handler; -- std::unordered_map plugin_types; -+ MemoryStore memory_store; -+ DepHandler *dep_handler; -+ std::unordered_map plugin_types; -+ static const std::string COLLECTOR_TEXT; -+ static const std::string SCENARIO_TEXT; -+ static const std::string TUNE_TEXT; - }; - - bool check_permission(std::string path, int mode); - --#endif -\ No newline at end of file -+#endif --- -2.33.0 - diff --git a/0002-add-error-code-and-replace-raw-poniters-with-smart-p.patch b/0002-add-error-code-and-replace-raw-poniters-with-smart-p.patch deleted file mode 100644 index b2e7b26..0000000 --- a/0002-add-error-code-and-replace-raw-poniters-with-smart-p.patch +++ /dev/null @@ -1,1599 +0,0 @@ -From 97949b2f4a1e894493c21f813f067d099f39176c Mon Sep 17 00:00:00 2001 -From: fly_1997 -Date: Sun, 28 Apr 2024 10:09:30 +0800 -Subject: [PATCH 2/4] add error code and replace raw poniters with smart - pointers - ---- - oeAware.service | 2 +- - src/common/message_protocol.h | 15 +- - src/plugin_mgr/CMakeLists.txt | 4 +- - src/plugin_mgr/config.cpp | 10 +- - src/plugin_mgr/dep_handler.cpp | 43 ++- - src/plugin_mgr/dep_handler.h | 25 +- - src/plugin_mgr/error_code.cpp | 29 ++ - src/plugin_mgr/error_code.h | 33 ++ - src/plugin_mgr/instance_run_handler.cpp | 65 ++-- - src/plugin_mgr/instance_run_handler.h | 30 +- - src/plugin_mgr/main.cpp | 21 +- - src/plugin_mgr/memory_store.h | 24 +- - src/plugin_mgr/message_manager.cpp | 1 - - src/plugin_mgr/message_manager.h | 9 +- - src/plugin_mgr/plugin.h | 16 +- - src/plugin_mgr/plugin_manager.cpp | 389 ++++++++++++++---------- - src/plugin_mgr/plugin_manager.h | 55 ++-- - 17 files changed, 443 insertions(+), 328 deletions(-) - create mode 100644 src/plugin_mgr/error_code.cpp - create mode 100644 src/plugin_mgr/error_code.h - -diff --git a/oeAware.service b/oeAware.service -index 9260492..3ab4b69 100644 ---- a/oeAware.service -+++ b/oeAware.service -@@ -4,7 +4,7 @@ After=network.target - - [Service] - Type=simple --ExecStart=/usr/bin/oeAware /etc/oeAware/config.yaml -+ExecStart=/usr/bin/oeaware /etc/oeAware/config.yaml - ExecStop=kill -9 $MAINPID - Restart=on-failure - RestartSec=1 -diff --git a/src/common/message_protocol.h b/src/common/message_protocol.h -index 1226e0b..3771298 100644 ---- a/src/common/message_protocol.h -+++ b/src/common/message_protocol.h -@@ -24,7 +24,6 @@ const int MAX_RECV_BUFF_SIZE = 16384; - const int MAX_EVENT_SIZE = 1024; - const int PROTOCOL_LENGTH_SIZE = sizeof(size_t); - const int HEADER_LENGTH_SIZE = sizeof(size_t); -- - const int HEADER_STATE_OK = 0; - const int HEADER_STATE_FAILED = 1; - -@@ -39,7 +38,8 @@ enum class Opt { - QUERY_ALL_TOP, - LIST, - DOWNLOAD, -- RESPONSE, -+ RESPONSE_OK, -+ RESPONSE_ERROR, - SHUTDOWN, - }; - -@@ -70,6 +70,9 @@ class Msg { - void set_opt(Opt opt) { - this->_opt = opt; - } -+ Opt get_opt() const { -+ return this->_opt; -+ } - private: - Opt _opt; - std::vector _payload; -@@ -80,17 +83,17 @@ private: - friend class boost::serialization::access; - template - void serialize(Archive &ar, const unsigned int version) { -- ar & state_code; -+ ar & code; - } - public: - void set_state_code(int code) { -- this->state_code = code; -+ this->code = code; - } - int get_state_code() { -- return this->state_code; -+ return this->code; - } - private: -- int state_code; -+ int code; - }; - - class MessageProtocol { -diff --git a/src/plugin_mgr/CMakeLists.txt b/src/plugin_mgr/CMakeLists.txt -index 09fa80a..a32c800 100644 ---- a/src/plugin_mgr/CMakeLists.txt -+++ b/src/plugin_mgr/CMakeLists.txt -@@ -12,7 +12,7 @@ include_directories(/usr/include) - include_directories(../common) - link_directories(/usr/lib64) - --add_executable (oeAware -+add_executable (oeaware - ${SOURCE} - ) --target_link_libraries(oeAware common) -+target_link_libraries(oeaware common) -diff --git a/src/plugin_mgr/config.cpp b/src/plugin_mgr/config.cpp -index bd87937..b997b8f 100644 ---- a/src/plugin_mgr/config.cpp -+++ b/src/plugin_mgr/config.cpp -@@ -52,14 +52,14 @@ bool Config::load(const std::string path) { - YAML::Node enable_list = node["enable_list"]; - if (enable_list.IsSequence()) { - for (int i = 0; i < enable_list.size(); ++i) { -- YAML::Node instances = enable_list[i]["instances"]; -+ YAML::Node plugin = enable_list[i]["name"]; - std::string name = enable_list[i]["name"].as(); - EnableItem enable_item(name); -- if (instances.IsNull()) { -+ if (plugin.IsScalar()) { - enable_item.set_enabled(true); -- } else if (instances.IsSequence()) { -- for (int j = 0; j < instances.size(); ++j) { -- std::string i_name = instances[j]["name"].as(); -+ } else if (plugin.IsSequence()) { -+ for (int j = 0; j < plugin.size(); ++j) { -+ std::string i_name = plugin[j].as(); - enable_item.add_instance(i_name); - } - } else { -diff --git a/src/plugin_mgr/dep_handler.cpp b/src/plugin_mgr/dep_handler.cpp -index 9a6ddc5..eff333c 100644 ---- a/src/plugin_mgr/dep_handler.cpp -+++ b/src/plugin_mgr/dep_handler.cpp -@@ -13,13 +13,13 @@ - #include - #include - --void DepHandler::add_arc_node(Node* node, const std::vector &dep_nodes) { -- ArcNode *arc_head = node->head; -+void DepHandler::add_arc_node(std::shared_ptr node, const std::vector &dep_nodes) { -+ std::shared_ptr arc_head = node->head; - node->cnt = dep_nodes.size(); - int real_cnt = 0; - bool state = true; - for (auto name : dep_nodes) { -- ArcNode *tmp = new ArcNode(); -+ std::shared_ptr tmp = std::make_shared(); - tmp->arc_name = name; - tmp->node_name = node->name; - tmp->next = arc_head->next; -@@ -39,7 +39,7 @@ void DepHandler::add_arc_node(Node* node, const std::vector &dep_no - - - void DepHandler::add_node(std::string name, std::vector dep_nodes) { -- Node *cur_node = add_new_node(name); -+ std::shared_ptr cur_node = add_new_node(name); - this->nodes[name] = cur_node; - add_arc_node(cur_node, dep_nodes); - change_arc_nodes(name, true); -@@ -51,27 +51,24 @@ void DepHandler::del_node(std::string name) { - } - - --Node* DepHandler::get_node(std::string name) { -+std::shared_ptr DepHandler::get_node(std::string name) { - return this->nodes[name]; - } - - --Node* DepHandler::add_new_node(std::string name) { -- Node *cur_node = new Node(name); -- cur_node->head = new ArcNode(); -- -+std::shared_ptr DepHandler::add_new_node(std::string name) { -+ std::shared_ptr cur_node = std::make_shared(name); -+ cur_node->head = std::make_shared(); - tail->next = cur_node; - tail = cur_node; - return cur_node; - } - -- -- --void DepHandler::del_node_and_arc_nodes(Node *node) { -- Node *next = node->next; -- ArcNode *arc = node->head; -+void DepHandler::del_node_and_arc_nodes(std::shared_ptr node) { -+ std::shared_ptr next = node->next; -+ std::shared_ptr arc = node->head; - while(arc) { -- ArcNode *tmp = arc->next; -+ std::shared_ptr tmp = arc->next; - if (arc != node->head){ - std::string name = arc->arc_name; - arc_nodes[name].erase(arc); -@@ -79,19 +76,16 @@ void DepHandler::del_node_and_arc_nodes(Node *node) { - arc_nodes.erase(name); - } - } -- delete arc; -- arc = tmp; -- -+ arc = tmp; - } -- delete node; - } - void DepHandler::change_arc_nodes(std::string name, bool state) { - if (!nodes[name]->state || !arc_nodes.count(name)) return; -- std::unordered_map &mp = arc_nodes[name]; -+ std::unordered_map, bool> &mp = arc_nodes[name]; - for (auto &vec : mp) { - vec.second = state; - if (nodes.count(vec.first->node_name)) { -- Node *tmp = nodes[vec.first->node_name]; -+ std::shared_ptr tmp = nodes[vec.first->node_name]; - if (state) { - tmp->real_cnt++; - if (tmp->real_cnt == tmp->cnt) { -@@ -101,6 +95,7 @@ void DepHandler::change_arc_nodes(std::string name, bool state) { - tmp->real_cnt--; - tmp->state = false; - } -+ change_arc_nodes(vec.first->node_name, state); - } - } - } -@@ -113,7 +108,7 @@ void DepHandler::query_all_top(std::vector> &query) { - } - - void DepHandler::query_node_top(std::string name, std::vector> &query) { -- ArcNode *p = nodes[name]->head; -+ std::shared_ptr p = nodes[name]->head; - if (p->next == nullptr) { - query.emplace_back(std::vector{name}); - return; -@@ -126,7 +121,7 @@ void DepHandler::query_node_top(std::string name, std::vector> &query) { - if (!nodes.count(name)) return; -- Node *p = nodes[name]; -+ std::shared_ptr p = nodes[name]; - query.emplace_back(std::vector{name}); - for (auto cur = p->head->next; cur != nullptr; cur = cur->next) { - query.emplace_back(std::vector{name, cur->arc_name}); -@@ -136,7 +131,7 @@ void DepHandler::query_node(std::string name, std::vector DepHandler::get_pre_dependencies(std::string name) { - std::vector res; -- std::queue q; -+ std::queue> q; - q.push(nodes[name]); - while (!q.empty()) { - auto &node = q.front(); -diff --git a/src/plugin_mgr/dep_handler.h b/src/plugin_mgr/dep_handler.h -index 8ff91e2..cc8570a 100644 ---- a/src/plugin_mgr/dep_handler.h -+++ b/src/plugin_mgr/dep_handler.h -@@ -16,9 +16,10 @@ - #include - #include - #include -+#include - - struct ArcNode { -- ArcNode *next; -+ std::shared_ptr next; - std::string arc_name; - std::string node_name; - ArcNode() : next(nullptr) {} -@@ -26,8 +27,8 @@ struct ArcNode { - - // a instance node - struct Node { -- Node *next; -- ArcNode *head; -+ std::shared_ptr next; -+ std::shared_ptr head; - std::string name; - int cnt; - int real_cnt; -@@ -39,10 +40,10 @@ struct Node { - class DepHandler { - public: - DepHandler() { -- this->head = new Node(); -+ this->head = std::make_shared(); - this->tail = head; - } -- Node* get_node(std::string name); -+ std::shared_ptr get_node(std::string name); - bool get_node_state(std::string name) { - return this->nodes[name]->state; - } -@@ -64,15 +65,15 @@ public: - } - private: - void query_node_top(std::string name, std::vector> &query); -- void add_arc_node(Node* node, const std::vector &dep_nodes); -+ void add_arc_node(std::shared_ptr node, const std::vector &dep_nodes); - void change_arc_nodes(std::string name, bool state); -- void del_node_and_arc_nodes(Node *node); -- Node* add_new_node(std::string name); -+ void del_node_and_arc_nodes(std::shared_ptr node); -+ std::shared_ptr add_new_node(std::string name); - -- std::unordered_map> arc_nodes; -- std::unordered_map nodes; -- Node * head; -- Node *tail; -+ std::unordered_map, bool>> arc_nodes; -+ std::unordered_map> nodes; -+ std::shared_ptr head; -+ std::shared_ptr tail; - }; - - #endif // !PLUGIN_MGR_DEP_HANDLER_H -diff --git a/src/plugin_mgr/error_code.cpp b/src/plugin_mgr/error_code.cpp -new file mode 100644 -index 0000000..252e4c2 ---- /dev/null -+++ b/src/plugin_mgr/error_code.cpp -@@ -0,0 +1,29 @@ -+#include "error_code.h" -+ -+const std::unordered_map ErrorText::error_codes = { -+ {ErrorCode::ENABLE_INSTANCE_NOT_LOAD, "instance is not loaded"}, -+ {ErrorCode::ENABLE_INSTANCE_UNAVAILABLE, "instance is unavailable"}, -+ {ErrorCode::ENABLE_INSTANCE_ALREADY_ENABLED, "instance is already enabled"}, -+ {ErrorCode::DISABLE_INSTANCE_NOT_LOAD, "instance is not loaded"}, -+ {ErrorCode::DISABLE_INSTANCE_UNAVAILABLE, "instance is unavailable"}, -+ {ErrorCode::DISABLE_INSTANCE_ALREADY_DISABLED, "instance is already disabled"}, -+ {ErrorCode::REMOVE_PLUGIN_NOT_EXIST, "plugin does not exist"}, -+ {ErrorCode::REMOVE_INSTANCE_IS_RUNNING, "instance is running"}, -+ {ErrorCode::REMOVE_INSTANCE_HAVE_DEP, "instance with pre-dependency"}, -+ {ErrorCode::LOAD_PLUGIN_FILE_NOT_EXIST, "plugin file does not exist"}, -+ {ErrorCode::LOAD_PLUGIN_FILE_PERMISSION_DEFINED, "plugin file permission defined"}, -+ {ErrorCode::LOAD_PLUGIN_EXIST, "plugin already loaded"}, -+ {ErrorCode::LOAD_PLUGIN_DLOPEN_FAILED, "plugin dlopen failed"}, -+ {ErrorCode::LOAD_PLUGIN_DLSYM_FAILED, "plugin dlsym failed"}, -+ {ErrorCode::QUERY_PLUGIN_NOT_EXIST, "plugin does not exist"}, -+ {ErrorCode::QUERY_DEP_NOT_EXIST, "instance does not exist"}, -+ {ErrorCode::DOWNLOAD_NOT_FOUND, "unable to find a match"}, -+}; -+std::string ErrorText::get_error_text(ErrorCode code) { -+ auto it = ErrorText::error_codes.find(code); -+ if (it != ErrorText::error_codes.end()) { -+ return it->second; -+ } else { -+ return "unknown error."; -+ } -+} -\ No newline at end of file -diff --git a/src/plugin_mgr/error_code.h b/src/plugin_mgr/error_code.h -new file mode 100644 -index 0000000..f58d5ed ---- /dev/null -+++ b/src/plugin_mgr/error_code.h -@@ -0,0 +1,33 @@ -+#ifndef PLUGIN_MGR_ERROR_CODE_H -+#define PLUGIN_MGR_ERROR_CODE_H -+#include -+#include -+ -+enum class ErrorCode { -+ ENABLE_INSTANCE_NOT_LOAD, -+ ENABLE_INSTANCE_UNAVAILABLE, -+ ENABLE_INSTANCE_ALREADY_ENABLED, -+ DISABLE_INSTANCE_NOT_LOAD, -+ DISABLE_INSTANCE_UNAVAILABLE, -+ DISABLE_INSTANCE_ALREADY_DISABLED, -+ REMOVE_PLUGIN_NOT_EXIST, -+ REMOVE_INSTANCE_IS_RUNNING, -+ REMOVE_INSTANCE_HAVE_DEP, -+ LOAD_PLUGIN_FILE_NOT_EXIST, -+ LOAD_PLUGIN_FILE_PERMISSION_DEFINED, -+ LOAD_PLUGIN_EXIST, -+ LOAD_PLUGIN_DLOPEN_FAILED, -+ LOAD_PLUGIN_DLSYM_FAILED, -+ QUERY_PLUGIN_NOT_EXIST, -+ QUERY_DEP_NOT_EXIST, -+ DOWNLOAD_NOT_FOUND, -+ OK, -+}; -+ -+class ErrorText { -+public: -+ static std::string get_error_text(ErrorCode code); -+ static const std::unordered_map error_codes; -+}; -+ -+#endif // !PLUGIN_MGR_ERROR_CODE_H -\ No newline at end of file -diff --git a/src/plugin_mgr/instance_run_handler.cpp b/src/plugin_mgr/instance_run_handler.cpp -index 162079e..862e806 100644 ---- a/src/plugin_mgr/instance_run_handler.cpp -+++ b/src/plugin_mgr/instance_run_handler.cpp -@@ -13,74 +13,74 @@ - #include - #include - --static void* get_ring_buf(Instance *instance) { -+static void* get_ring_buf(std::shared_ptr instance) { - if (instance == nullptr) { - return nullptr; - } - switch (instance->get_type()) { - case PluginType::COLLECTOR: -- return ((CollectorInstance*)instance)->get_interface()->get_ring_buf(); -+ return (std::dynamic_pointer_cast(instance))->get_interface()->get_ring_buf(); - case PluginType::SCENARIO: -- return ((ScenarioInstance*)instance)->get_interface()->get_ring_buf(); -+ return (std::dynamic_pointer_cast(instance))->get_interface()->get_ring_buf(); - case PluginType::TUNE: - break; - } - return nullptr; - } - --static void reflash_ring_buf(Instance *instance) { -- ((CollectorInstance*)instance)->get_interface()->reflash_ring_buf(); -+static void reflash_ring_buf(std::shared_ptr instance) { -+ (std::dynamic_pointer_cast(instance))->get_interface()->reflash_ring_buf(); - } - --void InstanceRunHandler::run_aware(Instance *instance, std::vector &deps) { -+void InstanceRunHandler::run_aware(std::shared_ptr instance, std::vector &deps) { - void *a[MAX_DEPENDENCIES_SIZE]; - for (int i = 0; i < deps.size(); ++i) { -- Instance *ins = memory_store->get_instance(deps[i]); -+ std::shared_ptr ins = memory_store.get_instance(deps[i]); - a[i] = get_ring_buf(ins); - } -- ((ScenarioInstance*)instance)->get_interface()->aware(a, (int)deps.size()); -+ (std::dynamic_pointer_cast(instance))->get_interface()->aware(a, (int)deps.size()); - } - --void InstanceRunHandler::run_tune(Instance *instance, std::vector &deps) { -+void InstanceRunHandler::run_tune(std::shared_ptr instance, std::vector &deps) { - void *a[MAX_DEPENDENCIES_SIZE]; - for (int i = 0; i < deps.size(); ++i) { -- Instance *ins = memory_store->get_instance(deps[i]); -+ std::shared_ptr ins = memory_store.get_instance(deps[i]); - a[i] = get_ring_buf(ins); - } -- ((TuneInstance*)instance)->get_interface()->tune(a, (int)deps.size()); -+ (std::dynamic_pointer_cast(instance))->get_interface()->tune(a, (int)deps.size()); - } - --void InstanceRunHandler::insert_instance(Instance *instance) { -+void InstanceRunHandler::insert_instance(std::shared_ptr instance) { - switch (instance->get_type()) { - case PluginType::COLLECTOR: - collector[instance->get_name()] = instance; -- ((CollectorInstance*)instance)->get_interface()->enable(); -+ (std::dynamic_pointer_cast(instance))->get_interface()->enable(); - break; - case PluginType::SCENARIO: - scenario[instance->get_name()] = instance; -- ((ScenarioInstance*)instance)->get_interface()->enable(); -+ (std::dynamic_pointer_cast(instance))->get_interface()->enable(); - break; - case PluginType::TUNE: - tune[instance->get_name()] = instance; -- ((TuneInstance*)instance)->get_interface()->enable(); -+ (std::dynamic_pointer_cast(instance))->get_interface()->enable(); - break; - } - INFO("[PluginManager] " << instance->get_name() << " instance insert into running queue."); - } - --void InstanceRunHandler::delete_instance(Instance *instance) { -+void InstanceRunHandler::delete_instance(std::shared_ptr instance) { - switch (instance->get_type()) { - case PluginType::COLLECTOR: - collector.erase(instance->get_name()); -- ((CollectorInstance*)instance)->get_interface()->disable(); -+ (std::dynamic_pointer_cast(instance))->get_interface()->disable(); - break; - case PluginType::SCENARIO: - scenario.erase(instance->get_name()); -- ((ScenarioInstance*)instance)->get_interface()->disable(); -+ (std::dynamic_pointer_cast(instance))->get_interface()->disable(); - break; - case PluginType::TUNE: - tune.erase(instance->get_name()); -- ((TuneInstance*)instance)->get_interface()->disable(); -+ (std::dynamic_pointer_cast(instance))->get_interface()->disable(); - break; - } - INFO("[PluginManager] " << instance->get_name() << " instance delete from running queue."); -@@ -89,21 +89,22 @@ void InstanceRunHandler::delete_instance(Instance *instance) { - void InstanceRunHandler::handle_instance() { - InstanceRunMessage msg; - while(this->recv_queue_try_pop(msg)){ -- Instance *instance = msg.get_instance(); -+ std::shared_ptr instance = msg.get_instance(); - switch (msg.get_type()){ - case RunType::ENABLED: -- insert_instance(instance); -+ insert_instance(std::move(instance)); - break; - case RunType::DISABLED: -- delete_instance(instance); -+ delete_instance(std::move(instance)); - break; - } - } - } - - template --static std::vector get_deps(Instance *instance) { -- std::string deps = ((T*)instance)->get_interface()->get_dep(); -+static std::vector get_deps(std::shared_ptr instance) { -+ std::shared_ptr t_instance = std::dynamic_pointer_cast(instance); -+ std::string deps = (t_instance)->get_interface()->get_dep(); - std::string dep = ""; - std::vector vec; - for (int i = 0; i < deps.length(); ++i) { -@@ -129,11 +130,11 @@ void InstanceRunHandler::adjust_collector_queue(const std::vector & - if (ok) continue; - if (flag) { - if (is_instance_exist(m_dep) && !collector.count(m_dep)) { -- this->insert_instance(memory_store->get_instance(m_dep)); -+ this->insert_instance(memory_store.get_instance(m_dep)); - } - } else { - if (is_instance_exist(m_dep) && collector.count(m_dep)) { -- this->delete_instance(memory_store->get_instance(m_dep)); -+ this->delete_instance(memory_store.get_instance(m_dep)); - } - } - } -@@ -146,8 +147,8 @@ void InstanceRunHandler::check_scenario_dependency(const std::vectorget_interface()->get_cycle(); -+ std::shared_ptr instance = p.second; -+ int t = (std::dynamic_pointer_cast(instance))->get_interface()->get_cycle(); - if (time % t != 0) return; - reflash_ring_buf(instance); - } -@@ -155,8 +156,8 @@ void InstanceRunHandler::schedule_collector(uint64_t time) { - - void InstanceRunHandler::schedule_scenario(uint64_t time) { - for (auto &p : scenario) { -- Instance *instance = p.second; -- int t = ((ScenarioInstance*)instance)->get_interface()->get_cycle(); -+ std::shared_ptr instance = p.second; -+ int t = (std::dynamic_pointer_cast(instance))->get_interface()->get_cycle(); - if (time % t != 0) return; - std::vector origin_deps = get_deps(instance); - run_aware(instance, origin_deps); -@@ -167,8 +168,8 @@ void InstanceRunHandler::schedule_scenario(uint64_t time) { - - void InstanceRunHandler::schedule_tune(uint64_t time) { - for (auto &p : tune) { -- Instance *instance = p.second; -- int t = ((TuneInstance*)instance)->get_interface()->get_cycle(); -+ std::shared_ptr instance = p.second; -+ int t = (std::dynamic_pointer_cast(instance))->get_interface()->get_cycle(); - if (time % t != 0) return; - std::vector deps = get_deps(instance); - run_tune(instance, deps); -diff --git a/src/plugin_mgr/instance_run_handler.h b/src/plugin_mgr/instance_run_handler.h -index c9a8dfc..83f9f4a 100644 ---- a/src/plugin_mgr/instance_run_handler.h -+++ b/src/plugin_mgr/instance_run_handler.h -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - - enum class RunType { - ENABLED, -@@ -30,30 +31,27 @@ enum class RunType { - class InstanceRunMessage { - public: - InstanceRunMessage() {} -- InstanceRunMessage(RunType type, Instance *instance) : type(type), instance(instance) {} -+ InstanceRunMessage(RunType type, std::shared_ptr instance) : type(type), instance(instance) {} - RunType get_type() { - return type; - } -- Instance* get_instance() { -+ std::shared_ptr get_instance() { - return instance; - } - private: - RunType type; -- Instance *instance; -+ std::shared_ptr instance; - }; - - // A handler to schedule plugin instance - class InstanceRunHandler { - public: -- InstanceRunHandler() : cycle(DEFAULT_CYCLE_SIZE) {} -+ InstanceRunHandler(MemoryStore &memory_store) : memory_store(memory_store), cycle(DEFAULT_CYCLE_SIZE) {} - void run(); - void schedule_collector(uint64_t time); - void schedule_scenario(uint64_t time); - void schedule_tune(uint64_t time); - void handle_instance(); -- void set_memory_store(MemoryStore *memory_store) { -- this->memory_store = memory_store; -- } - void set_cycle(int cycle) { - this->cycle = cycle; - } -@@ -61,7 +59,7 @@ public: - return cycle; - } - bool is_instance_exist(const std::string &name) { -- return memory_store->is_instance_exist(name); -+ return memory_store.is_instance_exist(name); - } - void recv_queue_push(InstanceRunMessage &msg) { - this->recv_queue.push(msg); -@@ -73,18 +71,18 @@ public: - return this->recv_queue.try_pop(msg); - } - private: -- void run_aware(Instance *instance, std::vector &deps); -- void run_tune(Instance *instance, std::vector &deps); -- void delete_instance(Instance *instance); -- void insert_instance(Instance *instance); -+ void run_aware(std::shared_ptr instance, std::vector &deps); -+ void run_tune(std::shared_ptr instance, std::vector &deps); -+ void delete_instance(std::shared_ptr instance); -+ void insert_instance(std::shared_ptr instance); - void adjust_collector_queue(const std::vector &deps, const std::vector &m_deps, bool flag); - void check_scenario_dependency(const std::vector &deps, const std::vector &m_deps); - -- std::unordered_map collector; -- std::unordered_map scenario; -- std::unordered_map tune; -+ std::unordered_map> collector; -+ std::unordered_map> scenario; -+ std::unordered_map> tune; - SafeQueue recv_queue; -- MemoryStore *memory_store; -+ MemoryStore &memory_store; - int cycle; - static const int DEFAULT_CYCLE_SIZE = 10; - static const int MAX_DEPENDENCIES_SIZE = 20; -diff --git a/src/plugin_mgr/main.cpp b/src/plugin_mgr/main.cpp -index 8ec0577..92f48bb 100644 ---- a/src/plugin_mgr/main.cpp -+++ b/src/plugin_mgr/main.cpp -@@ -13,10 +13,25 @@ - - Logger logger; - -+void print_help() { -+ printf("Usage: ./oeaware [path]\n" -+ " ./oeaware --help\n" -+ "Examples:\n" -+ " ./oeaware /etc/oeAware/config.yaml\n"); -+} -+ - int main(int argc, char **argv) { - Config config; - if (argc < 2) { -- ERROR("System need config arg!"); -+ ERROR("System need a argument!"); -+ exit(EXIT_FAILURE); -+ } -+ if (std::string(argv[1]) == "--help") { -+ print_help(); -+ exit(EXIT_SUCCESS); -+ } -+ if (!file_exist(argv[1])) { -+ ERROR("Config file " << argv[1] << " does not exist!"); - exit(EXIT_FAILURE); - } - std::string config_path(argv[1]); -@@ -36,8 +51,8 @@ int main(int argc, char **argv) { - message_manager.init(&config); - message_manager.run(); - INFO("[PluginManager] Start plugin manager!"); -- PluginManager plugin_manager(&handler_msg, &res_msg); -- plugin_manager.init(&config); -+ PluginManager plugin_manager(config, handler_msg, res_msg); -+ plugin_manager.init(); - plugin_manager.pre_load(); - plugin_manager.run(); - return 0; -diff --git a/src/plugin_mgr/memory_store.h b/src/plugin_mgr/memory_store.h -index 190fcdd..ac3ff98 100644 ---- a/src/plugin_mgr/memory_store.h -+++ b/src/plugin_mgr/memory_store.h -@@ -14,29 +14,27 @@ - #include "plugin.h" - #include "logger.h" - #include -+#include - - //OeAware memory storage, which is used to store plugins and instances in the memory. - class MemoryStore { - public: -- void add_plugin(const std::string &name, Plugin *plugin) { -+ void add_plugin(const std::string &name, std::shared_ptr plugin) { - this->plugins.insert(std::make_pair(name, plugin)); - } -- void add_instance(const std::string &name, Instance *instance) { -+ void add_instance(const std::string &name, std::shared_ptr instance) { - this->instances.insert(std::make_pair(name, instance)); - } -- Plugin* get_plugin(const std::string &name) const { -+ std::shared_ptr get_plugin(const std::string &name) const { - return this->plugins.at(name); - } -- Instance* get_instance(const std::string &name) const { -+ std::shared_ptr get_instance(const std::string &name) const { - return this->instances.at(name); - } - void delete_plugin(const std::string &name) { -- Plugin *plugin = plugins.at(name); - this->plugins.erase(name); -- delete plugin; - } - void delete_instance(const std::string &name) { -- Instance *instance = instances.at(name); - this->instances.erase(name); - } - bool is_plugin_exist(const std::string &name) const { -@@ -45,23 +43,23 @@ public: - bool is_instance_exist(const std::string &name) const { - return this->instances.count(name); - } -- std::vector get_all_plugins() { -- std::vector res; -+ std::vector> get_all_plugins() { -+ std::vector> res; - for (auto &p : plugins) { - res.emplace_back(p.second); - } - return res; - } -- std::vector get_all_instances() { -- std::vector res; -+ std::vector> get_all_instances() { -+ std::vector> res; - for (auto &p : instances) { - res.emplace_back(p.second); - } - return res; - } - private: -- std::unordered_map plugins; -- std::unordered_map instances; -+ std::unordered_map> plugins; -+ std::unordered_map> instances; - }; - - #endif // !PLUGIN_MGR_MEMORY_STORE_H -diff --git a/src/plugin_mgr/message_manager.cpp b/src/plugin_mgr/message_manager.cpp -index 296c682..e2fd3b6 100644 ---- a/src/plugin_mgr/message_manager.cpp -+++ b/src/plugin_mgr/message_manager.cpp -@@ -68,7 +68,6 @@ static void recv_msg(Msg &msg, MessageHeader &header, SafeQueue *res_ms - for (int i = 0; i < res.get_payload_len(); ++i) { - msg.add_payload(res.get_payload(i)); - } -- header.set_state_code(res.get_state_code()); - } - - void TcpSocket::serve_accept(SafeQueue *handler_msg, SafeQueue *res_msg){ -diff --git a/src/plugin_mgr/message_manager.h b/src/plugin_mgr/message_manager.h -index d1faad3..4cd7311 100644 ---- a/src/plugin_mgr/message_manager.h -+++ b/src/plugin_mgr/message_manager.h -@@ -28,7 +28,7 @@ enum class MessageType { - - class Message { - public: -- Message() : type(MessageType::EXTERNAL), state_code(HEADER_STATE_OK) {} -+ Message() : type(MessageType::EXTERNAL) {} - Message(Opt opt) : opt(opt) {} - Message(Opt opt, MessageType type) : opt(opt), type(type) {} - Message(Opt opt, std::vector payload) : opt(opt), payload(payload) {} -@@ -53,16 +53,9 @@ public: - int get_payload_len() const { - return this->payload.size(); - } -- void set_state_code(int code) { -- this->state_code = code; -- } -- int get_state_code() const { -- return this->state_code; -- } - private: - Opt opt; - MessageType type; -- int state_code; - std::vector payload; - }; - -diff --git a/src/plugin_mgr/plugin.h b/src/plugin_mgr/plugin.h -index 11b4748..69837af 100644 ---- a/src/plugin_mgr/plugin.h -+++ b/src/plugin_mgr/plugin.h -@@ -14,6 +14,7 @@ - #include "interface.h" - #include - #include -+#include - #include - - enum class PluginType { -@@ -122,11 +123,8 @@ private: - class Plugin { - public: - Plugin(std::string name, PluginType type) : name(name), type(type), handler(nullptr) { } -- ~Plugin() { -- for (int i = 0; i < instances.size(); ++i) { -- delete instances[i]; -- } -- dlclose(this->handler); -+ ~Plugin() { -+ dlclose(handler); - } - int load(const std::string dl_path); - std::string get_name() const { -@@ -135,21 +133,21 @@ public: - PluginType get_type() const { - return this->type; - } -- void add_instance(Instance *ins) { -+ void add_instance(std::shared_ptr ins) { - instances.emplace_back(ins); - } -- Instance* get_instance(int i) const { -+ std::shared_ptr get_instance(int i) const { - return instances[i]; - } - size_t get_instance_len() const { - return instances.size(); - } -- void * get_handler() const { -+ void* get_handler() const { - return handler; - } - private: - void *handler; -- std::vector instances; -+ std::vector> instances; - PluginType type; - std::string name; - }; -diff --git a/src/plugin_mgr/plugin_manager.cpp b/src/plugin_mgr/plugin_manager.cpp -index 47f9451..e7e32bf 100644 ---- a/src/plugin_mgr/plugin_manager.cpp -+++ b/src/plugin_mgr/plugin_manager.cpp -@@ -21,61 +21,64 @@ const std::string PluginManager::SCENARIO_TEXT = "scenario"; - const std::string PluginManager::TUNE_TEXT = "tune"; - const static int ST_MODE_MASK = 0777; - --void PluginManager::init(Config *config) { -+void PluginManager::init() { - plugin_types[COLLECTOR_TEXT] = PluginType::COLLECTOR; - plugin_types[SCENARIO_TEXT] = PluginType::SCENARIO; - plugin_types[TUNE_TEXT] = PluginType::TUNE; -- this->config = config; - } - --bool PluginManager::remove(const std::string &name) { -- if (!memory_store.is_plugin_exist(name)) return false; -- Plugin *plugin = memory_store.get_plugin(name); -+ErrorCode PluginManager::remove(const std::string &name) { -+ if (!memory_store.is_plugin_exist(name)) { -+ return ErrorCode::REMOVE_PLUGIN_NOT_EXIST; -+ } -+ std::shared_ptr plugin = memory_store.get_plugin(name); - std::vector instance_names; - for (int i = 0; i < plugin->get_instance_len(); ++i) { -- Instance *instance = plugin->get_instance(i); -+ std::shared_ptr instance = plugin->get_instance(i); - std::string iname = instance->get_name(); -- if (dep_handler->have_dep(iname)) { -- return false; -+ if (instance->get_enabled()) { -+ return ErrorCode::REMOVE_INSTANCE_IS_RUNNING; -+ } -+ if (dep_handler.have_dep(iname)) { -+ return ErrorCode::REMOVE_INSTANCE_HAVE_DEP; - } - instance_names.emplace_back(iname); - } - for(auto &iname : instance_names) { - memory_store.delete_instance(iname); -- dep_handler->del_node(iname); -+ dep_handler.del_node(iname); - } - memory_store.delete_plugin(name); - update_instance_state(); -- return true; -+ return ErrorCode::OK; - } --bool PluginManager::query_all_plugins(Message &res) { -- std::vector all_plugins = memory_store.get_all_plugins(); -+ErrorCode PluginManager::query_all_plugins(std::string &res) { -+ std::vector> all_plugins = memory_store.get_all_plugins(); - for (auto &p : all_plugins) { -- res.add_payload(p->get_name()); -+ res += p->get_name() + "\n"; - for (int i = 0; i < p->get_instance_len(); ++i) { - std::string info = p->get_instance(i)->get_info(); -- res.add_payload(" " + info); -+ res += "\t" + info + "\n"; - } - } -- return 1; -+ return ErrorCode::OK; - } - --bool PluginManager::query_plugin(std::string name, Message &res) { -+ErrorCode PluginManager::query_plugin(const std::string &name, std::string &res) { - if (!memory_store.is_plugin_exist(name)) { -- res.add_payload("no such plugin!"); -- return true; -+ return ErrorCode::QUERY_PLUGIN_NOT_EXIST; - } -- Plugin *plugin = memory_store.get_plugin(name); -- res.add_payload(name); -+ std::shared_ptr plugin = memory_store.get_plugin(name); -+ res += name + "\n"; - for (int i = 0; i < plugin->get_instance_len(); ++i) { - std::string info = plugin->get_instance(i)->get_info(); -- res.add_payload(" " + info); -+ res += "\t" + info + "\n"; - } -- return true; -+ return ErrorCode::OK; - } - - template --int PluginManager::load_dl_instance(Plugin *plugin, T **interface_list) { -+int PluginManager::load_dl_instance(std::shared_ptr plugin, T **interface_list) { - int (*get_instance)(T**) = (int(*)(T**))dlsym(plugin->get_handler(), "get_instance"); - if (get_instance == nullptr) { - ERROR("[PluginManager] dlsym error!\n"); -@@ -105,11 +108,11 @@ std::vector get_dep(T *interface) { - } - - template --void PluginManager::save_instance(Plugin *plugin, T *interface_list, int len) { -+void PluginManager::save_instance(std::shared_ptr plugin, T *interface_list, int len) { - if (interface_list == nullptr) return; - for (int i = 0; i < len; ++i) { - T *interface = interface_list + i; -- Instance *instance = new U(); -+ std::shared_ptr instance = std::make_shared(); - std::string name = interface->get_name(); - instance->set_name(name); - instance->set_plugin_name(plugin->get_name()); -@@ -117,19 +120,19 @@ void PluginManager::save_instance(Plugin *plugin, T *interface_list, int len) { - instance->set_enabled(false); - if (plugin->get_type() == PluginType::COLLECTOR) { - DEBUG("[PluginManager] add node"); -- dep_handler->add_node(name); -+ dep_handler.add_node(name); - } else { -- dep_handler->add_node(name, get_dep(interface)); -+ dep_handler.add_node(name, get_dep(interface)); - } -- instance->set_state(dep_handler->get_node_state(name)); -- ((U*)instance)->set_interface(interface); -+ instance->set_state(dep_handler.get_node_state(name)); -+ (std::dynamic_pointer_cast(instance))->set_interface(interface); - DEBUG("[PluginManager] Instance: " << name.c_str()); - memory_store.add_instance(name, instance); - plugin->add_instance(instance); - } - } - --bool PluginManager::load_instance(Plugin *plugin) { -+bool PluginManager::load_instance(std::shared_ptr plugin) { - int len = 0; - DEBUG("plugin: " << plugin->get_name()); - switch (plugin->get_type()) { -@@ -160,9 +163,9 @@ bool PluginManager::load_instance(Plugin *plugin) { - } - - void PluginManager::update_instance_state() { -- std::vector all_instances = memory_store.get_all_instances(); -+ std::vector> all_instances = memory_store.get_all_instances(); - for (auto &instance : all_instances) { -- if (dep_handler->get_node_state(instance->get_name())) { -+ if (dep_handler.get_node_state(instance->get_name())) { - instance->set_state(true); - } else { - instance->set_state(false); -@@ -170,24 +173,28 @@ void PluginManager::update_instance_state() { - } - } - --bool PluginManager::load_plugin(const std::string name, PluginType type) { -+ErrorCode PluginManager::load_plugin(const std::string name, PluginType type) { -+ std::string plugin_path = get_path(type) + "/" + name; -+ if (!file_exist(plugin_path)) { -+ return ErrorCode::LOAD_PLUGIN_FILE_NOT_EXIST; -+ } -+ if (!check_permission(plugin_path, S_IRUSR | S_IRGRP)) { -+ return ErrorCode::LOAD_PLUGIN_FILE_PERMISSION_DEFINED; -+ } - if (memory_store.is_plugin_exist(name)) { -- WARN("[PluginManager] " << name << " already loaded!"); -- return false; -+ return ErrorCode::LOAD_PLUGIN_EXIST; - } - const std::string dl_path = get_path(type) + '/' + name; -- Plugin *plugin = new Plugin(name, type); -+ std::shared_ptr plugin = std::make_shared(name, type); - int error = plugin->load(dl_path); - if (error) { -- WARN("[PluginManager] " << name << " load error!"); -- return false; -+ return ErrorCode::LOAD_PLUGIN_DLOPEN_FAILED; - } - if (!this->load_instance(plugin)) { -- delete plugin; -- return false; -+ return ErrorCode::LOAD_PLUGIN_DLSYM_FAILED; - } - memory_store.add_plugin(name, plugin); -- return true; -+ return ErrorCode::OK; - } - - std::string generate_dot(MemoryStore &memory_store, const std::vector> &query) { -@@ -195,7 +202,7 @@ std::string generate_dot(MemoryStore &memory_store, const std::vector> sub_graph; - for (auto &vec : query) { -- Instance *instance = memory_store.get_instance(vec[0]); -+ std::shared_ptr instance = memory_store.get_instance(vec[0]); - sub_graph[instance->get_plugin_name()].emplace_back(vec[0]); - if (vec.size() == 1) { - continue; -@@ -219,47 +226,37 @@ std::string generate_dot(MemoryStore &memory_store, const std::vector> query; -- dep_handler->query_node(name, query); -- if (query.empty()) { -- res.add_payload("Instance not available!"); -- return false; -- } -- std::string dot_text = generate_dot(memory_store, query); -- res.add_payload(dot_text); -- return true; -+ dep_handler.query_node(name, query); -+ res = generate_dot(memory_store, query); -+ return ErrorCode::OK; - } - --bool PluginManager::query_all_tops(Message &res) { -+ErrorCode PluginManager::query_all_tops(std::string &res) { - std::vector> query; -- dep_handler->query_all_top(query); -+ dep_handler.query_all_top(query); - DEBUG("[PluginManager] query size:" << query.size()); -- if (query.empty()) { -- res.add_payload("No instance available!"); -- return false; -- } -- std::string dot_text = generate_dot(memory_store, query); -- res.add_payload(dot_text); -- return true; -+ res = generate_dot(memory_store, query); -+ return ErrorCode::OK; - } - --bool PluginManager::instance_enabled(std::string name) { -+ErrorCode PluginManager::instance_enabled(std::string name) { - if (!memory_store.is_instance_exist(name)) { -- WARN("[PluginManager] " << name << " instance can't load!"); -- return false; -+ return ErrorCode::ENABLE_INSTANCE_NOT_LOAD; - } -- Instance *instance = memory_store.get_instance(name); -+ std::shared_ptr instance = memory_store.get_instance(name); - if (!instance->get_state()) { -- WARN("[PluginManager] " << name << " instance is unavailable, lacking dependencies!"); -- return false; -+ return ErrorCode::ENABLE_INSTANCE_UNAVAILABLE; - } - if (instance->get_enabled()) { -- WARN("[PluginManager] " << name << " instance was enabled!"); -- return false; -+ return ErrorCode::ENABLE_INSTANCE_ALREADY_ENABLED; - } -- std::vector pre_dependencies = dep_handler->get_pre_dependencies(name); -+ std::vector pre_dependencies = dep_handler.get_pre_dependencies(name); - for (int i = pre_dependencies.size() - 1; i >= 0; --i) { - instance = memory_store.get_instance(pre_dependencies[i]); - if (instance->get_enabled()) { -@@ -267,29 +264,25 @@ bool PluginManager::instance_enabled(std::string name) { - } - instance->set_enabled(true); - instance_run_handler->recv_queue_push(InstanceRunMessage(RunType::ENABLED, instance)); -- INFO("[PluginManager] " << name << " instance enabled!"); -+ DEBUG("[PluginManager] " << instance->get_name() << " instance enabled."); - } -- return true; -+ return ErrorCode::OK; - } - --bool PluginManager::instance_disabled(std::string name) { -+ErrorCode PluginManager::instance_disabled(std::string name) { - if (!memory_store.is_instance_exist(name)) { -- WARN("[PluginManager] " << name << " instance can't load!"); -- return false; -+ return ErrorCode::DISABLE_INSTANCE_NOT_LOAD; - } -- Instance *instance = memory_store.get_instance(name); -+ std::shared_ptr instance = memory_store.get_instance(name); - if (!instance->get_state()) { -- WARN("[PluginManager] " << name << " instance is unavailable, lacking dependencies!"); -- return false; -+ return ErrorCode::DISABLE_INSTANCE_UNAVAILABLE; - } - if (!instance->get_enabled()) { -- WARN("[PluginManager] " << name << " instance was disabled!"); -- return false; -+ return ErrorCode::DISABLE_INSTANCE_ALREADY_DISABLED; - } - instance->set_enabled(false); - instance_run_handler->recv_queue_push(InstanceRunMessage(RunType::DISABLED, instance)); -- INFO("[PluginManager] " << name << " instance disabled!"); -- return true; -+ return ErrorCode::OK; - } - - static bool end_with(const std::string &s, const std::string &ending) { -@@ -320,30 +313,46 @@ static std::string get_plugin_in_dir(const std::string &path) { - return res; - } - --void PluginManager::add_list(Message &res) { -- std::string list_text; -- list_text += "Download Packages:\n"; -- for (int i = 0; i < config->get_plugin_list_size(); ++i) { -- PluginInfo info = config->get_plugin_list(i); -- list_text += info.get_name() + "\n"; -+ErrorCode PluginManager::add_list(std::string &res) { -+ res += "Download Packages:\n"; -+ for (int i = 0; i < config.get_plugin_list_size(); ++i) { -+ PluginInfo info = config.get_plugin_list(i); -+ res += info.get_name() + "\n"; - } -- list_text += "Installed Plugins:\n"; -- list_text += get_plugin_in_dir(DEFAULT_COLLECTOR_PATH); -- list_text += get_plugin_in_dir(DEFAULT_SCENARIO_PATH); -- list_text += get_plugin_in_dir(DEFAULT_TUNE_PATH); -- res.add_payload(list_text); -+ res += "Installed Plugins:\n"; -+ res += get_plugin_in_dir(DEFAULT_COLLECTOR_PATH); -+ res += get_plugin_in_dir(DEFAULT_SCENARIO_PATH); -+ res += get_plugin_in_dir(DEFAULT_TUNE_PATH); -+ return ErrorCode::OK; -+} -+ -+ErrorCode PluginManager::download(const std::string &name, std::string &res) { -+ std::string url; -+ std::string type; -+ for (int i = 0; i < config.get_plugin_list_size(); ++i) { -+ PluginInfo info = config.get_plugin_list(i); -+ if (info.get_name() == name) { -+ url = info.get_url(); -+ break; -+ } -+ } -+ if (url.empty()) { -+ return ErrorCode::DOWNLOAD_NOT_FOUND; -+ } -+ res += url; -+ return ErrorCode::OK; - } - - void PluginManager::pre_enable() { -- for (int i = 0; i < config->get_enable_list_size(); ++i) { -- EnableItem item = config->get_enable_list(i); -+ for (int i = 0; i < config.get_enable_list_size(); ++i) { -+ EnableItem item = config.get_enable_list(i); - if (item.get_enabled()) { - std::string name = item.get_name(); - if (!memory_store.is_plugin_exist(name)) { - WARN("[PluginManager] plugin " << name << " cannot be enabled, because it does not exist."); - continue; - } -- Plugin *plugin = memory_store.get_plugin(name); -+ std::shared_ptr plugin = memory_store.get_plugin(name); - for (int j = 0; j < plugin->get_instance_len(); ++j) { - instance_enabled(plugin->get_instance(i)->get_name()); - } -@@ -373,19 +382,15 @@ void PluginManager::pre_load() { - pre_enable(); - } - --static bool check_load_msg(Message &msg, std::unordered_map &plugin_types) { -- return msg.get_payload_len() == 2 && plugin_types.count(msg.get_payload(1)); --} -- - void* PluginManager::get_data_buffer(std::string name) { -- Instance *instance = memory_store.get_instance(name); -+ std::shared_ptr instance = memory_store.get_instance(name); - switch (instance->get_type()) { - case PluginType::COLLECTOR: { -- CollectorInterface *collector_interface = ((CollectorInstance*)instance)->get_interface(); -+ CollectorInterface *collector_interface = (std::dynamic_pointer_cast(instance))->get_interface(); - return collector_interface->get_ring_buf(); - } - case PluginType::SCENARIO: { -- ScenarioInterface *scenario_interface = ((ScenarioInstance*)instance)->get_interface(); -+ ScenarioInterface *scenario_interface = (std::dynamic_pointer_cast(instance))->get_interface(); - return scenario_interface->get_ring_buf(); - } - default: -@@ -394,12 +399,13 @@ void* PluginManager::get_data_buffer(std::string name) { - return nullptr; - } - --void PluginManager::instance_dep_check(std::string name, Message &res) { -- Plugin *plugin = memory_store.get_plugin(name); -+std::string PluginManager::instance_dep_check(const std::string &name) { -+ std::shared_ptr plugin = memory_store.get_plugin(name); -+ std::string res; - for (int i = 0; i < plugin->get_instance_len(); ++i) { - std::string instance_name = plugin->get_instance(i)->get_name(); - std::vector> query; -- dep_handler->query_node(instance_name, query); -+ dep_handler.query_node(instance_name, query); - std::vector lack; - for (auto &item : query) { - if (item.size() < 2) continue; -@@ -408,13 +414,13 @@ void PluginManager::instance_dep_check(std::string name, Message &res) { - } - } - if (!lack.empty()) { -- std::string info = instance_name + " needed the following dependencies:"; -- for (auto &dep : lack) { -- info += "\n " + dep; -+ for (int i = 0; i < lack.size(); ++i) { -+ res += "\t" + lack[i]; -+ if (i != lack.size() - 1) res += '\n'; - } -- res.add_payload(info); - } - } -+ return res; - } - - // Check the file permission. The file owner is root. -@@ -429,76 +435,110 @@ bool check_permission(std::string path, int mode) { - return true; - } - --static bool file_exist(const std::string &file_name) { -+bool file_exist(const std::string &file_name) { - std::ifstream file(file_name); - return file.good(); - } - - int PluginManager::run() { -- instance_run_handler->set_memory_store(&memory_store); - instance_run_handler->run(); - while (true) { - Message msg; - Message res; -- res.set_opt(Opt::RESPONSE); -- this->handler_msg->wait_and_pop(msg); -+ this->handler_msg.wait_and_pop(msg); - if (msg.get_opt() == Opt::SHUTDOWN) break; - switch (msg.get_opt()) { - case Opt::LOAD: { -- if (!check_load_msg(msg, plugin_types)) { -- WARN("[PluginManager] args error!"); -- res.add_payload("args error!"); -- break; -- } - std::string plugin_name = msg.get_payload(0); - PluginType type = plugin_types[msg.get_payload(1)]; -- std::string plugin_path = get_path(type) + "/" + plugin_name; - if (!end_with(plugin_name, ".so")) break; -- if (!file_exist(plugin_path)) { -- WARN("[PluginManager] plugin " << plugin_name << " does not exist!"); -- res.add_payload("plugin does not exist!"); -- break; -- } -- if (!check_permission(plugin_path, S_IRUSR | S_IRGRP)) { -- WARN("[PluginManager] plugin " << plugin_name << " does not have the execute permission!"); -- res.add_payload("does not have the execute permission!"); -- break; -- } -- if(this->load_plugin(plugin_name, type)) { -- INFO("[PluginManager] plugin " << plugin_name << " loaded."); -- res.add_payload("plugin load succeed!"); -- instance_dep_check(plugin_name, res); -- DEBUG("[PluginManager] instance dependency checked!"); -+ ErrorCode ret_code = load_plugin(plugin_name, type); -+ if(ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] " << plugin_name << "plugin loaded."); -+ res.set_opt(Opt::RESPONSE_OK); -+ std::string lack_dep = instance_dep_check(plugin_name); -+ if (!lack_dep.empty()) { -+ INFO("[PluginManager] " << plugin_name << " requires the following dependencies:\n" << lack_dep); -+ res.add_payload(lack_dep); -+ } - } else { -- INFO("[PluginManager] plugin " << plugin_name << " load error!"); -- res.add_payload("plugin load failed!"); -+ WARN("[PluginManager] " << plugin_name << " " << ErrorText::get_error_text(ret_code) << "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); - } - break; - } - case Opt::REMOVE: { - std::string name = msg.get_payload(0); -- if (remove(name)) { -- res.add_payload(name + " removed!"); -- INFO("[PluginManager] " << name << " removed!"); -+ ErrorCode ret_code = remove(name); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] " << name << " plugin removed."); -+ res.set_opt(Opt::RESPONSE_OK); - } else { -- res.add_payload(name + " remove failed!"); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); -+ INFO("[PluginManager] " << name << " " << ErrorText::get_error_text(ret_code) + "."); - } - break; - } - case Opt::QUERY_ALL: { -- query_all_plugins(res); -+ std::string res_text; -+ ErrorCode ret_code = query_all_plugins(res_text); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] query all plugins information."); -+ res.set_opt(Opt::RESPONSE_OK); -+ res.add_payload(res_text); -+ } else { -+ WARN("[PluginManager] query all plugins failed, because " << ErrorText::get_error_text(ret_code) + "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); -+ } - break; - } - case Opt::QUERY: { -- query_plugin(msg.get_payload(0), res); -+ std::string res_text; -+ std::string name = msg.get_payload(0); -+ ErrorCode ret_code = query_plugin(name, res_text); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] " << name << " plugin query successfully."); -+ res.set_opt(Opt::RESPONSE_OK); -+ res.add_payload(res_text); -+ } else { -+ WARN("[PluginManager] " << name << " " << ErrorText::get_error_text(ret_code) + "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); -+ } - break; - } - case Opt::QUERY_TOP: { -- query_top(msg.get_payload(0), res); -+ std::string res_text; -+ std::string name = msg.get_payload(0); -+ ErrorCode ret_code = query_top(name , res_text); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] query " << name << " instance dependencies."); -+ res.set_opt(Opt::RESPONSE_OK); -+ res.add_payload(res_text); -+ } else { -+ WARN("[PluginManager] query "<< name << " instance dependencies failed, because " -+ << ErrorText::get_error_text(ret_code) << "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); -+ } - break; - } - case Opt::QUERY_ALL_TOP: { -- query_all_tops(res); -+ std::string res_text; -+ ErrorCode ret_code = query_all_tops(res_text); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] query all instances dependencies."); -+ res.set_opt(Opt::RESPONSE_OK); -+ res.add_payload(res_text); -+ } else { -+ WARN("[PluginManager] query all instances dependencies failed. because " -+ << ErrorText::get_error_text(ret_code) << "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); -+ } - break; - } - case Opt::ENABLED: { -@@ -508,10 +548,15 @@ int PluginManager::run() { - break; - } - std::string instance_name = msg.get_payload(0); -- if (instance_enabled(instance_name)) { -- res.add_payload("instance enabled!"); -+ ErrorCode ret_code = instance_enabled(instance_name); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] " << instance_name << " enabled successful."); -+ res.set_opt(Opt::RESPONSE_OK); - } else { -- res.add_payload("instance enabled failed!"); -+ WARN("[PluginManager] " << instance_name << " enabled failed. because " -+ << ErrorText::get_error_text(ret_code) + "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); - } - break; - } -@@ -522,42 +567,50 @@ int PluginManager::run() { - break; - } - std::string instance_name = msg.get_payload(0); -- if (instance_disabled(instance_name)) { -- res.add_payload("instance disabled!"); -+ ErrorCode ret_code = instance_disabled(instance_name); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] " << instance_name << " disabled successful."); -+ res.set_opt(Opt::RESPONSE_OK); - } else { -- res.add_payload("instance disabled failed!"); -+ WARN("[PluginManager] " << instance_name << " " << ErrorText::get_error_text(ret_code) << "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); - } - break; - } - case Opt::LIST: { -- add_list(res); -+ std::string res_text; -+ ErrorCode ret_code = add_list(res_text); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] query plugin_list."); -+ res.set_opt(Opt::RESPONSE_OK); -+ res.add_payload(res_text); -+ } else { -+ WARN("[PluginManager] query plugin_list failed, because " << ErrorText::get_error_text(ret_code) << "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); -+ } - break; - } - case Opt::DOWNLOAD: { -+ std::string res_text; - std::string name = msg.get_payload(0); -- std::string url = ""; -- std::string type = ""; -- for (int i = 0; i < config->get_plugin_list_size(); ++i) { -- PluginInfo info = config->get_plugin_list(i); -- if (info.get_name() == name) { -- url = info.get_url(); -- break; -- } -- } -- if (url.empty()) { -- WARN("[PluginManager] unable to find a match: " << name); -- res.set_state_code(HEADER_STATE_FAILED); -- res.add_payload("unable to find a match: " + name); -- break; -+ ErrorCode ret_code = download(name, res_text); -+ if (ret_code == ErrorCode::OK) { -+ INFO("[PluginManager] download " << name << " from " << res_text << "."); -+ res.set_opt(Opt::RESPONSE_OK); -+ res.add_payload(res_text); -+ } else { -+ WARN("[PluginManager] download " << name << " failed, because " << ErrorText::get_error_text(ret_code) + "."); -+ res.set_opt(Opt::RESPONSE_ERROR); -+ res.add_payload(ErrorText::get_error_text(ret_code)); - } -- res.add_payload(url); -- INFO("[PluginManager] download " << name << " from " << url << "."); - } - default: - break; - } - if (msg.get_type() == MessageType::EXTERNAL) -- res_msg->push(res); -+ res_msg.push(res); - } - return 0; - } -diff --git a/src/plugin_mgr/plugin_manager.h b/src/plugin_mgr/plugin_manager.h -index f648931..8d240cc 100644 ---- a/src/plugin_mgr/plugin_manager.h -+++ b/src/plugin_mgr/plugin_manager.h -@@ -17,6 +17,7 @@ - #include "memory_store.h" - #include "dep_handler.h" - #include "message_manager.h" -+#include "error_code.h" - #include - #include - #include -@@ -24,45 +25,43 @@ - - class PluginManager { - public: -- PluginManager(SafeQueue *handler_msg, SafeQueue *res_msg) { -- this->handler_msg = handler_msg; -- this->res_msg = res_msg; -- dep_handler = new DepHandler(); -- instance_run_handler = new InstanceRunHandler(); -- } -- ~PluginManager() { } -+ PluginManager(Config &config, SafeQueue &handler_msg, SafeQueue &res_msg) : -+ config(config), handler_msg(handler_msg), res_msg(res_msg) { -+ instance_run_handler.reset(new InstanceRunHandler(memory_store)); -+ } - int run(); - void pre_load(); - void pre_enable(); -- void init(Config *config); -+ void init(); - void* get_data_buffer(std::string name); - private: - void pre_load_plugin(PluginType type); -- bool query_all_plugins(Message &res); -- bool query_plugin(std::string name, Message &res); -- bool query_top(std::string name, Message &res); -- bool query_all_tops(Message &res); -- bool instance_enabled(std::string name); -- bool instance_disabled(std::string name); -- void instance_dep_check(std::string name, Message &res); -+ ErrorCode load_plugin(const std::string path, PluginType type); -+ ErrorCode remove(const std::string &name); -+ ErrorCode query_all_plugins(std::string &res); -+ ErrorCode query_plugin(const std::string &name, std::string &res); -+ ErrorCode query_top(const std::string &name, std::string &res); -+ ErrorCode query_all_tops(std::string &res); -+ ErrorCode instance_enabled(std::string name); -+ ErrorCode instance_disabled(std::string name); -+ ErrorCode add_list(std::string &res); -+ ErrorCode download(const std::string &name, std::string &res); -+ std::string instance_dep_check(const std::string &name); - template -- int load_dl_instance(Plugin *plugin, T **interface_list); -+ int load_dl_instance(std::shared_ptr plugin, T **interface_list); - template -- void save_instance(Plugin *plugin, T *interface_list, int len); -- bool load_instance(Plugin *plugin); -- bool load_plugin(const std::string path, PluginType type); -+ void save_instance(std::shared_ptr plugin, T *interface_list, int len); -+ bool load_instance(std::shared_ptr plugin); - void batch_load(); -- bool remove(const std::string &name); - void batch_remove(); -- void add_list(Message &msg); - void update_instance_state(); - private: -- InstanceRunHandler *instance_run_handler; -- Config *config; -- SafeQueue *handler_msg; -- SafeQueue *res_msg; -+ std::unique_ptr instance_run_handler; -+ Config &config; -+ SafeQueue &handler_msg; -+ SafeQueue &res_msg; - MemoryStore memory_store; -- DepHandler *dep_handler; -+ DepHandler dep_handler; - std::unordered_map plugin_types; - static const std::string COLLECTOR_TEXT; - static const std::string SCENARIO_TEXT; -@@ -70,5 +69,5 @@ private: - }; - - bool check_permission(std::string path, int mode); -- --#endif -+bool file_exist(const std::string &file_name); -+#endif --- -2.33.0 - diff --git a/0003-add-client-error-description-extract-class-and-fix-b.patch b/0003-add-client-error-description-extract-class-and-fix-b.patch deleted file mode 100644 index a8187b8..0000000 --- a/0003-add-client-error-description-extract-class-and-fix-b.patch +++ /dev/null @@ -1,1034 +0,0 @@ -From 72ec3921622e81b1faf0adda88cb40aa63bb4504 Mon Sep 17 00:00:00 2001 -From: fly_1997 -Date: Sun, 28 Apr 2024 20:13:37 +0800 -Subject: [PATCH 3/4] add client error description, extract class, and fix bugs - ---- - oeAware.service => oeaware.service | 0 - src/client/arg_parse.cpp | 104 ++++++++++++++++++ - src/client/arg_parse.h | 37 +++++++ - src/client/client.cpp | 92 +++------------- - src/client/client.h | 15 ++- - src/client/cmd_handler.cpp | 165 ++++++++++++++++------------- - src/client/cmd_handler.h | 38 +++---- - src/client/main.cpp | 10 +- - src/common/utils.cpp | 38 ++++--- - src/plugin_mgr/config.cpp | 29 ++++- - src/plugin_mgr/config.h | 27 ++++- - src/plugin_mgr/error_code.cpp | 1 + - src/plugin_mgr/error_code.h | 1 + - src/plugin_mgr/plugin_manager.cpp | 33 +++--- - src/plugin_mgr/plugin_manager.h | 4 +- - 15 files changed, 363 insertions(+), 231 deletions(-) - rename oeAware.service => oeaware.service (100%) - create mode 100644 src/client/arg_parse.cpp - create mode 100644 src/client/arg_parse.h - -diff --git a/oeAware.service b/oeaware.service -similarity index 100% -rename from oeAware.service -rename to oeaware.service -diff --git a/src/client/arg_parse.cpp b/src/client/arg_parse.cpp -new file mode 100644 -index 0000000..cbf0b8e ---- /dev/null -+++ b/src/client/arg_parse.cpp -@@ -0,0 +1,104 @@ -+/****************************************************************************** -+ * Copyright (c) 2024 Huawei Technologies Co., Ltd. -+ * oeAware is licensed under Mulan PSL v2. -+ * You can use this software according to the terms and conditions of the Mulan PSL v2. -+ * You may obtain a copy of Mulan PSL v2 at: -+ * http://license.coscl.org.cn/MulanPSL2 -+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -+ * See the Mulan PSL v2 for more details. -+ ******************************************************************************/ -+#include "arg_parse.h" -+#include -+#include -+ -+const std::string ArgParse::OPT_STRING = "Qqd:t:l:r:e:"; -+const struct option ArgParse::long_options[] = { -+ {"help", no_argument, NULL, 'h'}, -+ {"load", required_argument, NULL, 'l'}, -+ {"type", required_argument, NULL, 't'}, -+ {"remove", required_argument, NULL, 'r'}, -+ {"query", required_argument, NULL, 'q'}, -+ {"query-dep", required_argument, NULL, 'Q'}, -+ {"enable", required_argument, NULL, 'e'}, -+ {"disable", required_argument, NULL, 'd'}, -+ {"list", no_argument, NULL, 'L'}, -+ {"install", required_argument, NULL, 'i'}, -+ {0, 0, 0, 0}, -+}; -+ -+void ArgParse::arg_error(const std::string &msg) { -+ std::cerr << "oeawarectl: " << msg << "\n"; -+ exit(EXIT_FAILURE); -+} -+ -+void ArgParse::set_type(char *_type) { -+ type = _type; -+} -+ -+void ArgParse::set_arg(char *_arg) { -+ arg = std::string(_arg); -+} -+ -+void ArgParse::print_help() { -+ std::cout << "oeawarectl [options]...\n" -+ " options\n" -+ " -l|--load [plugin] load plugin and need plugin type.\n" -+ " -t|--type [plugin_type] assign plugin type. there are three types:\n" -+ " collector: collection plugin.\n" -+ " scenario: awareness plugin.\n" -+ " tune: tune plugin.\n" -+ " -r|--remove [plugin] remove plugin from system.\n" -+ " -e|--enable [instance] enable the plugin instance.\n" -+ " -d|--disable [instance] disable the plugin instance.\n" -+ " -q query all plugins information.\n" -+ " --query [plugin] query the plugin information.\n" -+ " -Q query all instances dependencies.\n" -+ " --query-dep [instance] query the instance dependency.\n" -+ " --list the list of supported plugins.\n" -+ " --install [plugin] install plugin from the list.\n" -+ " --help show this help message.\n"; -+} -+ -+int ArgParse::init(int argc, char *argv[]) { -+ int cmd = -1; -+ int opt; -+ bool help = false; -+ opterr = 0; -+ while((opt = getopt_long(argc, argv, OPT_STRING.c_str(), long_options, nullptr)) != -1) { -+ std::string full_opt; -+ switch (opt) { -+ case 't': -+ set_type(optarg); -+ break; -+ case 'h': -+ help = true; -+ break; -+ case '?': -+ arg_error("unknown option. See --help."); -+ return -1; -+ default: { -+ if (opt == 'l' || opt == 'r' || opt == 'q' || opt == 'Q' || opt == 'e' || opt == 'd' || opt == 'L' || opt == 'i') { -+ if (cmd != -1) { -+ arg_error("invalid option. See --help.\n"); -+ return -1; -+ } -+ cmd = opt; -+ if (optarg) { -+ set_arg(optarg); -+ } -+ } -+ } -+ -+ } -+ } -+ if (help) { -+ print_help(); -+ exit(EXIT_SUCCESS); -+ } -+ if (cmd < 0) { -+ arg_error("no option."); -+ } -+ return cmd; -+} -diff --git a/src/client/arg_parse.h b/src/client/arg_parse.h -new file mode 100644 -index 0000000..8535e9c ---- /dev/null -+++ b/src/client/arg_parse.h -@@ -0,0 +1,37 @@ -+/****************************************************************************** -+ * Copyright (c) 2024 Huawei Technologies Co., Ltd. -+ * oeAware is licensed under Mulan PSL v2. -+ * You can use this software according to the terms and conditions of the Mulan PSL v2. -+ * You may obtain a copy of Mulan PSL v2 at: -+ * http://license.coscl.org.cn/MulanPSL2 -+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -+ * See the Mulan PSL v2 for more details. -+ ******************************************************************************/ -+#ifndef CLIENT_ARG_PARSE_H -+#define CLIENT_ARG_PARSE_H -+#include -+ -+class ArgParse { -+public: -+ static void arg_error(const std::string &msg); -+ static void print_help(); -+ int init(int argc, char *argv[]); -+ void set_type(char* _type); -+ void set_arg(char* _arg); -+ std::string get_type() const { -+ return this->type; -+ } -+ std::string get_arg() const { -+ return this->arg; -+ } -+private: -+ std::string arg; -+ std::string type; -+ static const std::string OPT_STRING; -+ static const int MAX_OPT_SIZE = 20; -+ static const struct option long_options[MAX_OPT_SIZE]; -+}; -+ -+#endif // !CLIENT_ARG_PARSE_H -diff --git a/src/client/client.cpp b/src/client/client.cpp -index 72fb6a2..39a0072 100644 ---- a/src/client/client.cpp -+++ b/src/client/client.cpp -@@ -11,97 +11,39 @@ - ******************************************************************************/ - #include "client.h" - --const std::string Client::OPT_STRING = "Qqd:t:l:r:e:"; --const struct option Client::long_options[] = { -- {"help", no_argument, NULL, 'h'}, -- {"load", required_argument, NULL, 'l'}, -- {"type", required_argument, NULL, 't'}, -- {"remove", required_argument, NULL, 'r'}, -- {"query", required_argument, NULL, 'q'}, -- {"query-dep", required_argument, NULL, 'Q'}, -- {"enable", required_argument, NULL, 'e'}, -- {"disable", required_argument, NULL, 'd'}, -- {"list", no_argument, NULL, 'L'}, -- {"download", required_argument, NULL, 'D'}, -- {0, 0, 0, 0}, --}; -- --static void print_error(const Msg &msg) { -- for (int i = 0; i < msg.payload_size(); ++i) { -- printf("%s\n", msg.payload(i).c_str()); -- } -+void Client::cmd_groups_init() { -+ cmd_handler_groups.insert(std::make_pair('l', new LoadHandler())); -+ cmd_handler_groups.insert(std::make_pair('q', new QueryHandler())); -+ cmd_handler_groups.insert(std::make_pair('r', new RemoveHandler())); -+ cmd_handler_groups.insert(std::make_pair('Q', new QueryTopHandler())); -+ cmd_handler_groups.insert(std::make_pair('e', new EnabledHandler())); -+ cmd_handler_groups.insert(std::make_pair('d', new DisabledHandler())); -+ cmd_handler_groups.insert(std::make_pair('L', new ListHandler())); -+ cmd_handler_groups.insert(std::make_pair('i', new InstallHandler(arg_parse.get_arg()))); - } -- --bool Client::init() { -+bool Client::init(int argc, char *argv[]) { -+ if ((cmd = arg_parse.init(argc, argv)) < 0) { -+ return false; -+ } -+ cmd_groups_init(); - return this->tcp_socket.init(); - } - --void Client::run_cmd(int cmd) { -+void Client::run_cmd() { - Msg msg; - Msg res; - MessageHeader header; -- this->cmd_handler = get_cmd_handler(cmd); -- this->cmd_handler->handler(msg); -+ this->cmd_handler = cmd_handler_groups[cmd]; -+ this->cmd_handler->handler(arg_parse, msg); - if(!this->tcp_socket.send_msg(msg)) { - return; - } - if (!this->tcp_socket.recv_msg(res, header)) { - return; - } -- if (header.get_state_code() == HEADER_STATE_FAILED) { -- print_error(res); -- return; -- } - this->cmd_handler->res_handler(res); - } - --int Client::arg_parse(int argc, char *argv[]) { -- int cmd = -1; -- int opt; -- bool help = false; -- opterr = 0; -- while((opt = getopt_long(argc, argv, OPT_STRING.c_str(), long_options, nullptr)) != -1) { -- std::string full_opt; -- switch (opt) { -- case 't': -- set_type(optarg); -- break; -- case 'h': -- help = true; -- break; -- case '?': -- arg_error("unknown option. See --help."); -- return -1; -- default: { -- if (opt == 'l' || opt == 'r' || opt == 'q' || opt == 'Q' || opt == 'e' || opt == 'd' || opt == 'L' || opt == 'D') { -- if (cmd != -1) { -- arg_error("invalid option. See --help.\n"); -- return -1; -- } -- cmd = opt; -- if (optarg) { -- set_arg(optarg); -- } -- } -- } -- -- } -- } -- if (help) { -- print_help(); -- exit(EXIT_SUCCESS); -- } -- if (cmd < 0) { -- arg_error("no option."); -- } -- return cmd; --} -- --void Client::arg_error(const std::string &msg) { -- std::cerr << "oeawarectl: " << msg << "\n"; -- exit(EXIT_FAILURE); --} -- - void Client::close() { - tcp_socket.clear(); - } -diff --git a/src/client/client.h b/src/client/client.h -index 9528f13..9e60251 100644 ---- a/src/client/client.h -+++ b/src/client/client.h -@@ -13,7 +13,7 @@ - #define CLIENT_H - #include "tcp_socket.h" - #include "cmd_handler.h" --#include -+#include - - class Client { - public: -@@ -22,18 +22,17 @@ public: - if (cmd_handler) - delete cmd_handler; - } -- bool init(); -- void run_cmd(int cmd); -+ bool init(int argc, char *argv[]); -+ void run_cmd(); - void close(); -- int arg_parse(int argc, char *argv[]); - private: -- void arg_error(const std::string &msg); -+ void cmd_groups_init(); - -+ int cmd; - TcpSocket tcp_socket; -+ ArgParse arg_parse; - CmdHandler *cmd_handler; -- static const std::string OPT_STRING; -- static const int MAX_OPT_SIZE = 20; -- static const struct option long_options[MAX_OPT_SIZE]; -+ std::unordered_map cmd_handler_groups; - }; - - #endif // !CLIENT_H -diff --git a/src/client/cmd_handler.cpp b/src/client/cmd_handler.cpp -index 8cdf8d2..1f2b8a5 100644 ---- a/src/client/cmd_handler.cpp -+++ b/src/client/cmd_handler.cpp -@@ -13,42 +13,13 @@ - #include "utils.h" - #include - --CmdHandler* get_cmd_handler(int cmd) { -- switch (cmd) { -- case 'l': -- return new LoadHandler(); -- case 'q': -- return new QueryHandler(); -- case 'r': -- return new RemoveHandler(); -- case 'Q': -- return new QueryTopHandler(); -- case 'e': -- return new EnabledHandler(); -- case 'd': -- return new DisabledHandler(); -- case 'L': -- return new ListHandler(); -- case 'D': -- return new DownloadHandler(); -- default: -- return nullptr; -- } -- return nullptr; --} -- --void set_type(char *_type) { -- type = _type; --} -+std::unordered_set LoadHandler::types = {"collector", "scenario", "tune"}; - --void set_arg(char *_arg) { -- arg = std::string(_arg); --} -- --void LoadHandler::handler(Msg &msg) { -- if (type.empty()) { -- printf("plugin type needed!\n"); -- exit(EXIT_FAILURE); -+void LoadHandler::handler(const ArgParse &arg_parse, Msg &msg) { -+ std::string arg = arg_parse.get_arg(); -+ std::string type = arg_parse.get_type(); -+ if (arg.empty() || type.empty() || !types.count(type)) { -+ ArgParse::arg_error("args error."); - } - msg.add_payload(arg); - msg.add_payload(type); -@@ -56,12 +27,24 @@ void LoadHandler::handler(Msg &msg) { - } - - void LoadHandler::res_handler(Msg &msg) { -- for (int i = 0; i < msg.payload_size(); ++i) { -- printf("%s\n", msg.payload(i).c_str()); -+ if (msg.get_opt() == Opt::RESPONSE_OK) { -+ std::cout << "Plugin loaded successfully."; -+ if (msg.payload_size()) { -+ std::cout << "But plugin requires the following dependencies to run.\n"; -+ for (int i = 0; i < msg.payload_size(); ++i) { -+ std::cout << msg.payload(i) << '\n'; -+ } -+ } else { -+ std::cout << '\n'; -+ } -+ } else { -+ std::cout << "Plugin loaded failed, because "<< msg.payload(0) << ".\n"; - } -+ - } - --void QueryHandler::handler(Msg &msg) { -+void QueryHandler::handler(const ArgParse &arg_parse, Msg &msg) { -+ std::string arg = arg_parse.get_arg(); - if (arg.empty()) { - msg.set_opt(Opt::QUERY_ALL); - } else { -@@ -70,37 +53,57 @@ void QueryHandler::handler(Msg &msg) { - } - } - -+void QueryHandler::print_format() { -+ std::cout << "format:\n" -+ "[plugin]\n" -+ "\t[instance]([dependency status], [running status])\n" -+ "dependency status: available means satisfying dependency, otherwise unavailable.\n" -+ "running status: running means that instance is running, otherwise close.\n"; -+} -+ - void QueryHandler::res_handler(Msg &msg) { -- int len = msg.payload_size(); -- if (len == 0) { -- printf("no plugins loaded!\n"); -+ if (msg.get_opt() == Opt::RESPONSE_ERROR) { -+ std::cout << "Plugin query failed, because " << msg.payload(0).c_str() <<".\n"; - return; -- } -+ } -+ int len = msg.payload_size(); -+ std::cout << "Show plugins and instances status.\n"; -+ std::cout << "------------------------------------------------------------\n"; - for (int i = 0; i < len; ++i) { -- printf("%s\n", msg.payload(i).c_str()); -+ std::cout << msg.payload(i).c_str(); - } -+ std::cout << "------------------------------------------------------------\n"; -+ print_format(); - } - --void RemoveHandler::handler(Msg &msg) { -+void RemoveHandler::handler(const ArgParse &arg_parse, Msg &msg) { -+ std::string arg = arg_parse.get_arg(); - msg.add_payload(arg); - msg.set_opt(Opt::REMOVE); - } - - void RemoveHandler::res_handler(Msg &msg) { -- printf("%s\n", msg.payload(0).c_str()); -+ if (msg.get_opt() == Opt::RESPONSE_OK) { -+ std::cout << "plugin remove successful.\n"; -+ } else { -+ std::cout << "plugin remove failed, because " << msg.payload(0) << ".\n"; -+ } - } - - void generate_png_from_dot(const std::string &dot_file, const std::string &png_file) { - std::string command = "dot -Tpng " + dot_file + " -o " + png_file; - std::system(command.c_str()); - } -+ - void write_to_file(const std::string &file_name, const std::string &text) { - std::ofstream out(file_name); - if (!out.is_open()) return; - out << text; - out.close(); - } --void QueryTopHandler::handler(Msg &msg) { -+ -+void QueryTopHandler::handler(const ArgParse &arg_parse, Msg &msg) { -+ std::string arg = arg_parse.get_arg(); - if (arg.empty()) { - msg.set_opt(Opt::QUERY_ALL_TOP); - } else { -@@ -110,70 +113,80 @@ void QueryTopHandler::handler(Msg &msg) { - } - - void QueryTopHandler::res_handler(Msg &msg) { -- std::string text; -- for(int i = 0; i < msg.payload_size(); ++i) { -- text += msg.payload(i).c_str(); -+ if (msg.get_opt() == Opt::RESPONSE_ERROR) { -+ std::cout << "Query instance dependencies failed, because "<< msg.payload(0) << ".\n"; -+ return; - } -+ std::string text = msg.payload(0); - write_to_file("dep.dot", text); - generate_png_from_dot("dep.dot", "dep.png"); -+ std::cout << "Generate dependencies graph dep.png.\n"; - } - --void EnabledHandler::handler(Msg &msg) { -+void EnabledHandler::handler(const ArgParse &arg_parse, Msg &msg) { -+ std::string arg = arg_parse.get_arg(); - msg.add_payload(arg); - msg.set_opt(Opt::ENABLED); - } - - void EnabledHandler::res_handler(Msg &msg) { -- printf("%s\n", msg.payload(0).c_str()); -+ if (msg.get_opt() == Opt::RESPONSE_OK) { -+ std::cout << "instance enabled.\n"; -+ } else { -+ std::cout << "instance enabled failed, because "<< msg.payload(0) << ".\n"; -+ } - } - --void DisabledHandler::handler(Msg &msg) { -+void DisabledHandler::handler(const ArgParse &arg_parse, Msg &msg) { -+ std::string arg = arg_parse.get_arg(); - msg.add_payload(arg); - msg.set_opt(Opt::DISABLED); - } - - void DisabledHandler::res_handler(Msg &msg) { -- printf("%s\n", msg.payload(0).c_str()); -+ if (msg.get_opt() == Opt::RESPONSE_OK) { -+ std::cout << "instance disabled.\n"; -+ } else { -+ std::cout << "instance disabled failed, because "<< msg.payload(0) << ".\n"; -+ } - } - --void ListHandler::handler(Msg &msg) { -+void ListHandler::handler(const ArgParse &arg_parse, Msg &msg) { - msg.set_opt(Opt::LIST); - } - - void ListHandler::res_handler(Msg &msg) { -+ if (msg.get_opt() == Opt::RESPONSE_ERROR) { -+ std::cerr << "query list failed, because "<< msg.payload(0) << ".\n"; -+ return; -+ } -+ std::cout << "plugin list as follows.\n"; -+ std::cout << "------------------------------------------------------------\n"; - for (int i = 0; i < msg.payload_size(); ++i) { -- printf("%s", msg.payload(i).c_str()); -+ std::cout << msg.payload(i); - } -+ std::cout << "------------------------------------------------------------\n"; - } - --void DownloadHandler::handler(Msg &msg) { -+void InstallHandler::handler(const ArgParse &arg_parse, Msg &msg) { -+ std::string arg = arg_parse.get_arg(); - msg.set_opt(Opt::DOWNLOAD); - msg.add_payload(arg); - } - --void DownloadHandler::res_handler(Msg &msg) { -- std::string path = arg; -+void InstallHandler::res_handler(Msg &msg) { -+ if (msg.get_opt() == Opt::RESPONSE_ERROR) { -+ std::cout << "download failed, because " << msg.payload(0) <<": " << this->arg.c_str() << '\n'; -+ return; -+ } -+ std::string path = this->arg; - std::string url = msg.payload(0); -- download(url, path); -+ if (!download(url, path)) { -+ std::cout << "download failed, please check url or your network.\n"; -+ return; -+ } - std::string command = "rpm -ivh " + path; - std::string rm = "rm -f " + path; - system(command.c_str()); - system(rm.c_str()); - } -- --void print_help() { -- printf("oeAware-client [options]...\n" -- " options\n" -- " -l|--load [plugin] load plugin and need plugin type.\n" -- " -t|--type [plugin_type] assign plugin type.\n" -- " -r|--remove [plugin] remove plugin from system.\n" -- " -e|--enable [instance] enable the plugin instance.\n" -- " -d|--disable [instance] disable the plugin instance.\n" -- " -q query all plugins information.\n" -- " --query [plugin] query the plugin information.\n" -- " -Q query all instances dependencies.\n" -- " --query-dep [instance] query the instance dependency.\n" -- " --list the list of supported plugins.\n" -- " --download [plugin] download plugin from the list.\n" -- ); --} -\ No newline at end of file -diff --git a/src/client/cmd_handler.h b/src/client/cmd_handler.h -index 4afae4c..ab21944 100644 ---- a/src/client/cmd_handler.h -+++ b/src/client/cmd_handler.h -@@ -11,72 +11,72 @@ - ******************************************************************************/ - #ifndef CLIENT_CMD_HANDLER_H - #define CLIENT_CMD_HANDLER_H -- - #include "message_protocol.h" -+#include "arg_parse.h" -+#include - #include - #include - --static std::string type; --static std::string arg; -- - class CmdHandler { - public: -- virtual void handler(Msg &msg) = 0; -+ virtual void handler(const ArgParse &arg_parse, Msg &msg) = 0; - virtual void res_handler(Msg &msg) = 0; -+private: - }; - - class LoadHandler : public CmdHandler { - public: -- void handler(Msg &msg) override; -+ void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; -+private: -+ static std::unordered_set types; - }; - - class QueryHandler : public CmdHandler { - public: -- void handler(Msg &msg) override; -+ void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; -+ void print_format(); - }; - - class RemoveHandler : public CmdHandler { - public: -- void handler(Msg &msg) override; -+ void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; - }; - - - class QueryTopHandler : public CmdHandler { - public: -- void handler(Msg &msg) override; -+ void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; - }; - - class EnabledHandler : public CmdHandler { - public: -- void handler(Msg &msg) override; -+ void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; - }; - - class DisabledHandler : public CmdHandler { - public: -- void handler(Msg &msg) override; -+ void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; - }; - - class ListHandler : public CmdHandler { - public: -- void handler(Msg &msg) override; -+ void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; - }; - --class DownloadHandler : public CmdHandler { -+class InstallHandler : public CmdHandler { - public: -- void handler(Msg &msg) override; -+ InstallHandler(const std::string &arg) : arg(arg) { } -+ void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; -+private: -+ std::string arg; - }; - --CmdHandler* get_cmd_handler(int cmd); --void set_type(char* _type); --void set_arg(char* _arg); --void print_help(); -- - #endif // !CLIENT_CMD_HANDLER_H -diff --git a/src/client/main.cpp b/src/client/main.cpp -index 89aa268..62b7ca5 100644 ---- a/src/client/main.cpp -+++ b/src/client/main.cpp -@@ -12,15 +12,11 @@ - #include "client.h" - - int main(int argc, char *argv[]) { -- int cmd; - Client client; -- if ((cmd = client.arg_parse(argc, argv)) < 0) { -+ if (!client.init(argc, argv)) { - exit(EXIT_FAILURE); - } -- if (!client.init()) { -- exit(EXIT_FAILURE); -- } -- client.run_cmd(cmd); -+ client.run_cmd(); - client.close(); - return 0; --} -\ No newline at end of file -+} -diff --git a/src/common/utils.cpp b/src/common/utils.cpp -index 8830c50..9435a5b 100644 ---- a/src/common/utils.cpp -+++ b/src/common/utils.cpp -@@ -12,33 +12,39 @@ - #include "utils.h" - #include - --static size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) { -- size_t written = fwrite(ptr, size, nmemb, (FILE*)stream); -- return written; -+static size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *file) { -+ return fwrite(ptr, size, nmemb, file); - } - -+// set curl options -+static void curl_set_opt(CURL *curl, const std::string &url, FILE *file) { -+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); -+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); -+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); -+ -+} -+// Downloads file from the specified url to the path. - bool download(const std::string &url, const std::string &path) { - CURL *curl = nullptr; - CURLcode res; -+ bool ok = true; - curl_global_init(CURL_GLOBAL_DEFAULT); - curl = curl_easy_init(); - if (curl) { -- FILE *fp = fopen(path.c_str(), "wb"); -- if (fp == nullptr) { -+ FILE *file = fopen(path.c_str(), "wb"); -+ if (file == nullptr) { - return false; - } -- curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); -- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); -- curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); -+ curl_set_opt(curl, url, file); - res = curl_easy_perform(curl); -- curl_easy_cleanup(curl); -- fclose(fp); -- if (res == CURLE_OK) { -- return true; -- } else { -- return false; -- } -+ fclose(file); -+ if (res != CURLE_OK) { -+ ok = false; -+ } -+ } else { -+ ok = false; - } - curl_global_cleanup(); -- return false; -+ curl_easy_cleanup(curl); -+ return ok; - } -\ No newline at end of file -diff --git a/src/plugin_mgr/config.cpp b/src/plugin_mgr/config.cpp -index b997b8f..1de5a34 100644 ---- a/src/plugin_mgr/config.cpp -+++ b/src/plugin_mgr/config.cpp -@@ -14,10 +14,20 @@ - #include - #include - --void create_dir(std::string path) { -- if (access(path.c_str(), F_OK) == -1) { -- mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IROTH); -- } -+bool create_dir(const std::string &path) { -+ size_t pos = 0; -+ do { -+ pos = path.find_first_of("/", pos + 1); -+ std::string sub_path = path.substr(0, pos); -+ struct stat buffer; -+ if (stat(sub_path.c_str(), &buffer) == 0) { -+ continue; -+ } -+ if (mkdir(sub_path.c_str(), S_IRWXU | S_IRWXG) != 0) { -+ return false; -+ } -+ } while (pos != std::string::npos); -+ return true; - } - - bool Config::load(const std::string path) { -@@ -42,7 +52,16 @@ bool Config::load(const std::string path) { - std::string name = plugin_list[i]["name"].as(); - std::string description = plugin_list[i]["description"].as(); - std::string url = plugin_list[i]["url"].as(); -- this->plugin_list.emplace_back(PluginInfo(name, description, url)); -+ PluginInfo info(name, description, url); -+ if (name.empty()) { -+ std::cerr << "Warn: " << name << " url is empty.\n"; -+ continue; -+ } -+ if (this->plugin_list.count(name)) { -+ std::cerr << "Warn: duplicate " << name << " in plugin_list.\n"; -+ continue; -+ } -+ this->plugin_list.insert(std::make_pair(name, info)); - } - } else { - std::cerr << "Error: 'plugin_list' is not a sequence" << '\n'; -diff --git a/src/plugin_mgr/config.h b/src/plugin_mgr/config.h -index 2592fbe..16c7871 100644 ---- a/src/plugin_mgr/config.h -+++ b/src/plugin_mgr/config.h -@@ -14,6 +14,7 @@ - - #include "plugin.h" - #include -+#include - #include - #include - -@@ -31,12 +32,24 @@ public: - std::string get_url() const { - return this->url; - } -+ bool operator ==(const PluginInfo &other) const { -+ return name == other.get_name(); -+ } - private: - std::string name; - std::string description; - std::string url; - }; - -+namespace std { -+ template <> -+ struct hash { -+ size_t operator ()(const PluginInfo &obj) const { -+ return hash()(obj.get_name()); -+ } -+ }; -+} -+ - class EnableItem { - public: - EnableItem(std::string name) : name(name) { } -@@ -79,12 +92,18 @@ public: - std::string get_log_path() const { - return this->log_path; - } -- PluginInfo get_plugin_list(int i) const { -- return this->plugin_list[i]; -+ PluginInfo get_plugin_info(const std::string &name) const { -+ return this->plugin_list.at(name); -+ } -+ std::unordered_map get_plugin_list() const { -+ return this->plugin_list; - } - size_t get_plugin_list_size() const { - return this->plugin_list.size(); - } -+ bool is_plugin_info_exist(const std::string &name) { -+ return this->plugin_list.count(name); -+ } - EnableItem get_enable_list(int i) const { - return this->enable_list[i]; - } -@@ -96,11 +115,11 @@ private: - int schedule_cycle; - std::string log_path; - std::string log_type; -- std::vector plugin_list; -+ std::unordered_map plugin_list; - std::vector enable_list; - }; - - std::string get_path(PluginType type); --void create_dir(std::string path); -+bool create_dir(const std::string &path); - - #endif -\ No newline at end of file -diff --git a/src/plugin_mgr/error_code.cpp b/src/plugin_mgr/error_code.cpp -index 252e4c2..6e09cb0 100644 ---- a/src/plugin_mgr/error_code.cpp -+++ b/src/plugin_mgr/error_code.cpp -@@ -11,6 +11,7 @@ const std::unordered_map ErrorText::error_codes = { - {ErrorCode::REMOVE_INSTANCE_IS_RUNNING, "instance is running"}, - {ErrorCode::REMOVE_INSTANCE_HAVE_DEP, "instance with pre-dependency"}, - {ErrorCode::LOAD_PLUGIN_FILE_NOT_EXIST, "plugin file does not exist"}, -+ {ErrorCode::LOAD_PLUGIN_FILE_IS_NOT_SO, "file is not a plugin file"}, - {ErrorCode::LOAD_PLUGIN_FILE_PERMISSION_DEFINED, "plugin file permission defined"}, - {ErrorCode::LOAD_PLUGIN_EXIST, "plugin already loaded"}, - {ErrorCode::LOAD_PLUGIN_DLOPEN_FAILED, "plugin dlopen failed"}, -diff --git a/src/plugin_mgr/error_code.h b/src/plugin_mgr/error_code.h -index f58d5ed..7c06054 100644 ---- a/src/plugin_mgr/error_code.h -+++ b/src/plugin_mgr/error_code.h -@@ -15,6 +15,7 @@ enum class ErrorCode { - REMOVE_INSTANCE_HAVE_DEP, - LOAD_PLUGIN_FILE_NOT_EXIST, - LOAD_PLUGIN_FILE_PERMISSION_DEFINED, -+ LOAD_PLUGIN_FILE_IS_NOT_SO, - LOAD_PLUGIN_EXIST, - LOAD_PLUGIN_DLOPEN_FAILED, - LOAD_PLUGIN_DLSYM_FAILED, -diff --git a/src/plugin_mgr/plugin_manager.cpp b/src/plugin_mgr/plugin_manager.cpp -index e7e32bf..c9981ef 100644 ---- a/src/plugin_mgr/plugin_manager.cpp -+++ b/src/plugin_mgr/plugin_manager.cpp -@@ -173,11 +173,14 @@ void PluginManager::update_instance_state() { - } - } - --ErrorCode PluginManager::load_plugin(const std::string name, PluginType type) { -+ErrorCode PluginManager::load_plugin(const std::string &name, PluginType type) { - std::string plugin_path = get_path(type) + "/" + name; - if (!file_exist(plugin_path)) { - return ErrorCode::LOAD_PLUGIN_FILE_NOT_EXIST; - } -+ if (!end_with(name, ".so")) { -+ return ErrorCode::LOAD_PLUGIN_FILE_IS_NOT_SO; -+ } - if (!check_permission(plugin_path, S_IRUSR | S_IRGRP)) { - return ErrorCode::LOAD_PLUGIN_FILE_PERMISSION_DEFINED; - } -@@ -285,7 +288,7 @@ ErrorCode PluginManager::instance_disabled(std::string name) { - return ErrorCode::OK; - } - --static bool end_with(const std::string &s, const std::string &ending) { -+bool PluginManager::end_with(const std::string &s, const std::string &ending) { - if (s.length() >= ending.length()) { - return (s.compare(s.length() - ending.length(), ending.length(), ending) == 0); - } else { -@@ -293,7 +296,7 @@ static bool end_with(const std::string &s, const std::string &ending) { - } - } - --static std::string get_plugin_in_dir(const std::string &path) { -+std::string PluginManager::get_plugin_in_dir(const std::string &path) { - std::string res; - struct stat s = {}; - lstat(path.c_str(), &s); -@@ -314,10 +317,10 @@ static std::string get_plugin_in_dir(const std::string &path) { - } - - ErrorCode PluginManager::add_list(std::string &res) { -- res += "Download Packages:\n"; -- for (int i = 0; i < config.get_plugin_list_size(); ++i) { -- PluginInfo info = config.get_plugin_list(i); -- res += info.get_name() + "\n"; -+ auto plugin_list = config.get_plugin_list(); -+ res += "Supported Packages:\n"; -+ for (auto &p : plugin_list) { -+ res += p.first + "\n"; - } - res += "Installed Plugins:\n"; - res += get_plugin_in_dir(DEFAULT_COLLECTOR_PATH); -@@ -326,20 +329,11 @@ ErrorCode PluginManager::add_list(std::string &res) { - return ErrorCode::OK; - } - --ErrorCode PluginManager::download(const std::string &name, std::string &res) { -- std::string url; -- std::string type; -- for (int i = 0; i < config.get_plugin_list_size(); ++i) { -- PluginInfo info = config.get_plugin_list(i); -- if (info.get_name() == name) { -- url = info.get_url(); -- break; -- } -- } -- if (url.empty()) { -+ErrorCode PluginManager::download(const std::string &name, std::string &res) { -+ if (!config.is_plugin_info_exist(name)) { - return ErrorCode::DOWNLOAD_NOT_FOUND; - } -- res += url; -+ res += config.get_plugin_info(name).get_url(); - return ErrorCode::OK; - } - -@@ -451,7 +445,6 @@ int PluginManager::run() { - case Opt::LOAD: { - std::string plugin_name = msg.get_payload(0); - PluginType type = plugin_types[msg.get_payload(1)]; -- if (!end_with(plugin_name, ".so")) break; - ErrorCode ret_code = load_plugin(plugin_name, type); - if(ret_code == ErrorCode::OK) { - INFO("[PluginManager] " << plugin_name << "plugin loaded."); -diff --git a/src/plugin_mgr/plugin_manager.h b/src/plugin_mgr/plugin_manager.h -index 8d240cc..709d42e 100644 ---- a/src/plugin_mgr/plugin_manager.h -+++ b/src/plugin_mgr/plugin_manager.h -@@ -36,7 +36,7 @@ public: - void* get_data_buffer(std::string name); - private: - void pre_load_plugin(PluginType type); -- ErrorCode load_plugin(const std::string path, PluginType type); -+ ErrorCode load_plugin(const std::string &path, PluginType type); - ErrorCode remove(const std::string &name); - ErrorCode query_all_plugins(std::string &res); - ErrorCode query_plugin(const std::string &name, std::string &res); -@@ -55,6 +55,8 @@ private: - void batch_load(); - void batch_remove(); - void update_instance_state(); -+ bool end_with(const std::string &s, const std::string &ending); -+ std::string get_plugin_in_dir(const std::string &path); - private: - std::unique_ptr instance_run_handler; - Config &config; --- -2.33.0 - diff --git a/0004-fix-auto-enable-error-and-check-plugin-list-config.patch b/0004-fix-auto-enable-error-and-check-plugin-list-config.patch deleted file mode 100644 index fa22264..0000000 --- a/0004-fix-auto-enable-error-and-check-plugin-list-config.patch +++ /dev/null @@ -1,200 +0,0 @@ -From 7ff05329ac299727fc2be5d7f1a92a4e3b0bdd43 Mon Sep 17 00:00:00 2001 -From: fly_1997 -Date: Mon, 29 Apr 2024 17:31:44 +0800 -Subject: [PATCH 4/4] fix auto enable error and check plugin list config - ---- - oeaware.service | 2 +- - src/client/arg_parse.cpp | 7 ++++--- - src/common/utils.cpp | 34 ++++++++++++++++++------------- - src/plugin_mgr/config.cpp | 21 ++++++++++++++----- - src/plugin_mgr/config.h | 3 +++ - src/plugin_mgr/plugin_manager.cpp | 11 +++++++++- - 6 files changed, 54 insertions(+), 24 deletions(-) - -diff --git a/oeaware.service b/oeaware.service -index 3ab4b69..b321530 100644 ---- a/oeaware.service -+++ b/oeaware.service -@@ -5,7 +5,7 @@ After=network.target - [Service] - Type=simple - ExecStart=/usr/bin/oeaware /etc/oeAware/config.yaml --ExecStop=kill -9 $MAINPID -+ExecStop=kill $MAINPID && sleep 5 && kill -9 $MAINPID - Restart=on-failure - RestartSec=1 - RemainAfterExit=yes -diff --git a/src/client/arg_parse.cpp b/src/client/arg_parse.cpp -index cbf0b8e..70fcd4a 100644 ---- a/src/client/arg_parse.cpp -+++ b/src/client/arg_parse.cpp -@@ -30,6 +30,7 @@ const struct option ArgParse::long_options[] = { - - void ArgParse::arg_error(const std::string &msg) { - std::cerr << "oeawarectl: " << msg << "\n"; -+ print_help(); - exit(EXIT_FAILURE); - } - -@@ -42,7 +43,7 @@ void ArgParse::set_arg(char *_arg) { - } - - void ArgParse::print_help() { -- std::cout << "oeawarectl [options]...\n" -+ std::cout << "usage: oeawarectl [options]...\n" - " options\n" - " -l|--load [plugin] load plugin and need plugin type.\n" - " -t|--type [plugin_type] assign plugin type. there are three types:\n" -@@ -76,12 +77,12 @@ int ArgParse::init(int argc, char *argv[]) { - help = true; - break; - case '?': -- arg_error("unknown option. See --help."); -+ arg_error("unknown option."); - return -1; - default: { - if (opt == 'l' || opt == 'r' || opt == 'q' || opt == 'Q' || opt == 'e' || opt == 'd' || opt == 'L' || opt == 'i') { - if (cmd != -1) { -- arg_error("invalid option. See --help.\n"); -+ arg_error("invalid option."); - return -1; - } - cmd = opt; -diff --git a/src/common/utils.cpp b/src/common/utils.cpp -index 9435a5b..f2c277d 100644 ---- a/src/common/utils.cpp -+++ b/src/common/utils.cpp -@@ -23,28 +23,34 @@ static void curl_set_opt(CURL *curl, const std::string &url, FILE *file) { - curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); - - } -+static bool curl_handle(CURL *curl, const std::string &url, const std::string &path) { -+ FILE *file = fopen(path.c_str(), "wb"); -+ if (file == nullptr) { -+ return false; -+ } -+ curl_set_opt(curl, url, file); -+ CURLcode res = curl_easy_perform(curl); -+ long http_code = 0; -+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); -+ fclose(file); -+ if (res == CURLE_OK && http_code >= 200 && http_code < 300) { -+ return true; -+ } -+ return false; -+} -+ - // Downloads file from the specified url to the path. - bool download(const std::string &url, const std::string &path) { - CURL *curl = nullptr; -- CURLcode res; -- bool ok = true; -+ bool ret = true; - curl_global_init(CURL_GLOBAL_DEFAULT); - curl = curl_easy_init(); - if (curl) { -- FILE *file = fopen(path.c_str(), "wb"); -- if (file == nullptr) { -- return false; -- } -- curl_set_opt(curl, url, file); -- res = curl_easy_perform(curl); -- fclose(file); -- if (res != CURLE_OK) { -- ok = false; -- } -+ if (!curl_handle(curl, url, path)) ret = false; - } else { -- ok = false; -+ ret = false; - } - curl_global_cleanup(); - curl_easy_cleanup(curl); -- return ok; -+ return ret; - } -\ No newline at end of file -diff --git a/src/plugin_mgr/config.cpp b/src/plugin_mgr/config.cpp -index 1de5a34..3c76e8e 100644 ---- a/src/plugin_mgr/config.cpp -+++ b/src/plugin_mgr/config.cpp -@@ -30,6 +30,18 @@ bool create_dir(const std::string &path) { - return true; - } - -+bool check_plugin_list(YAML::Node plugin_list_item) { -+ if (plugin_list_item["name"].IsNull()) { -+ std::cerr << "Warn: null name in plugin_list.\n"; -+ return false; -+ } -+ if (plugin_list_item["url"].IsNull()) { -+ std::cerr << "Warn: null url in plugin_list.\n"; -+ return false; -+ } -+ return true; -+} -+ - bool Config::load(const std::string path) { - YAML::Node node; - struct stat buffer; -@@ -49,16 +61,15 @@ bool Config::load(const std::string path) { - YAML::Node plugin_list = node["plugin_list"]; - if (plugin_list.IsSequence()) { - for (int i = 0; i < plugin_list.size(); ++i) { -+ if (!check_plugin_list(plugin_list[i])){ -+ continue; -+ } - std::string name = plugin_list[i]["name"].as(); - std::string description = plugin_list[i]["description"].as(); - std::string url = plugin_list[i]["url"].as(); - PluginInfo info(name, description, url); -- if (name.empty()) { -- std::cerr << "Warn: " << name << " url is empty.\n"; -- continue; -- } - if (this->plugin_list.count(name)) { -- std::cerr << "Warn: duplicate " << name << " in plugin_list.\n"; -+ std::cerr << "Warn: duplicate \"" << name << "\" in plugin_list.\n"; - continue; - } - this->plugin_list.insert(std::make_pair(name, info)); -diff --git a/src/plugin_mgr/config.h b/src/plugin_mgr/config.h -index 16c7871..5ab7672 100644 ---- a/src/plugin_mgr/config.h -+++ b/src/plugin_mgr/config.h -@@ -65,6 +65,9 @@ public: - size_t get_instance_size() const { - return this->instance.size(); - } -+ std::string get_instance_name(int i) { -+ return this->instance[i]; -+ } - std::string get_name() const { - return this->name; - } -diff --git a/src/plugin_mgr/plugin_manager.cpp b/src/plugin_mgr/plugin_manager.cpp -index c9981ef..0826a60 100644 ---- a/src/plugin_mgr/plugin_manager.cpp -+++ b/src/plugin_mgr/plugin_manager.cpp -@@ -348,7 +348,16 @@ void PluginManager::pre_enable() { - } - std::shared_ptr plugin = memory_store.get_plugin(name); - for (int j = 0; j < plugin->get_instance_len(); ++j) { -- instance_enabled(plugin->get_instance(i)->get_name()); -+ instance_enabled(plugin->get_instance(j)->get_name()); -+ } -+ } else { -+ for (int j = 0; j < item.get_instance_size(); ++j) { -+ std::string name = item.get_instance_name(j); -+ if (!memory_store.is_instance_exist(name)) { -+ WARN("[PluginManager] instance " << name << " cannot be enabled, because it does not exist."); -+ continue; -+ } -+ instance_enabled(name); - } - } - } --- -2.33.0 - diff --git a/0005-modify-logs-sock-file-permission-and-fix-service-fil.patch b/0005-modify-logs-sock-file-permission-and-fix-service-fil.patch deleted file mode 100644 index 40500a5..0000000 --- a/0005-modify-logs-sock-file-permission-and-fix-service-fil.patch +++ /dev/null @@ -1,322 +0,0 @@ -From 906d417f7a370b6b9f60069bae41ee6d00d7537e Mon Sep 17 00:00:00 2001 -From: fly_1997 -Date: Tue, 7 May 2024 18:02:15 +0800 -Subject: [PATCH] modify logs, sock file permission and fix service file, - repetition of dependencies - ---- - config.yaml | 11 ++++----- - oeaware.service | 2 +- - src/client/cmd_handler.cpp | 22 +++++++++++++----- - src/client/cmd_handler.h | 2 ++ - src/plugin_mgr/dep_handler.cpp | 36 +++++++++++++++++++++--------- - src/plugin_mgr/dep_handler.h | 8 +++---- - src/plugin_mgr/error_code.cpp | 2 +- - src/plugin_mgr/message_manager.cpp | 3 +++ - src/plugin_mgr/plugin.h | 6 +++-- - src/plugin_mgr/plugin_manager.cpp | 15 ++++++++----- - 10 files changed, 73 insertions(+), 34 deletions(-) - -diff --git a/config.yaml b/config.yaml -index ef0b44b..99d01d7 100644 ---- a/config.yaml -+++ b/config.yaml -@@ -1,8 +1,9 @@ - log_path: /var/log/oeAware --log_level: 1 -+log_level: 2 - enable_list: -- - name: aaa.so -+ - plugin_list: -- - name: test -- description: hello world -- url: https://gitee.com/openeuler/oeAware-manager -\ No newline at end of file -+ - name: numafast -+ description: numafast is a userspace tool designed for Kunpeng Chips that aims to improve -+ system performance by reducing cross-NUMA memory access. -+ url: https://repo.oepkgs.net/openeuler/rpm/openEuler-22.03-LTS-SP1/extras/aarch64/Packages/n/numafast-v1.0.0-2.aarch64.rpm -\ No newline at end of file -diff --git a/oeaware.service b/oeaware.service -index b321530..be13c4b 100644 ---- a/oeaware.service -+++ b/oeaware.service -@@ -5,7 +5,7 @@ After=network.target - [Service] - Type=simple - ExecStart=/usr/bin/oeaware /etc/oeAware/config.yaml --ExecStop=kill $MAINPID && sleep 5 && kill -9 $MAINPID -+ExecStop=kill $MAINPID - Restart=on-failure - RestartSec=1 - RemainAfterExit=yes -diff --git a/src/client/cmd_handler.cpp b/src/client/cmd_handler.cpp -index 1f2b8a5..4fec95b 100644 ---- a/src/client/cmd_handler.cpp -+++ b/src/client/cmd_handler.cpp -@@ -15,12 +15,22 @@ - - std::unordered_set LoadHandler::types = {"collector", "scenario", "tune"}; - -+void LoadHandler::check(const std::string &arg, const std::string &type) { -+ if (arg.empty()) { -+ ArgParse::arg_error("plugin name empty."); -+ } -+ if (type.empty()) { -+ ArgParse::arg_error("type empty."); -+ } -+ if (!types.count(type)) { -+ ArgParse::arg_error("this type is not supported."); -+ } -+} -+ - void LoadHandler::handler(const ArgParse &arg_parse, Msg &msg) { - std::string arg = arg_parse.get_arg(); - std::string type = arg_parse.get_type(); -- if (arg.empty() || type.empty() || !types.count(type)) { -- ArgParse::arg_error("args error."); -- } -+ check(arg, type); - msg.add_payload(arg); - msg.add_payload(type); - msg.set_opt(Opt::LOAD); -@@ -84,7 +94,7 @@ void RemoveHandler::handler(const ArgParse &arg_parse, Msg &msg) { - - void RemoveHandler::res_handler(Msg &msg) { - if (msg.get_opt() == Opt::RESPONSE_OK) { -- std::cout << "plugin remove successful.\n"; -+ std::cout << "plugin remove successfully.\n"; - } else { - std::cout << "plugin remove failed, because " << msg.payload(0) << ".\n"; - } -@@ -131,7 +141,7 @@ void EnabledHandler::handler(const ArgParse &arg_parse, Msg &msg) { - - void EnabledHandler::res_handler(Msg &msg) { - if (msg.get_opt() == Opt::RESPONSE_OK) { -- std::cout << "instance enabled.\n"; -+ std::cout << "instance enabled successfully.\n"; - } else { - std::cout << "instance enabled failed, because "<< msg.payload(0) << ".\n"; - } -@@ -145,7 +155,7 @@ void DisabledHandler::handler(const ArgParse &arg_parse, Msg &msg) { - - void DisabledHandler::res_handler(Msg &msg) { - if (msg.get_opt() == Opt::RESPONSE_OK) { -- std::cout << "instance disabled.\n"; -+ std::cout << "instance disabled successfully.\n"; - } else { - std::cout << "instance disabled failed, because "<< msg.payload(0) << ".\n"; - } -diff --git a/src/client/cmd_handler.h b/src/client/cmd_handler.h -index ab21944..1b6f1c1 100644 ---- a/src/client/cmd_handler.h -+++ b/src/client/cmd_handler.h -@@ -29,6 +29,7 @@ public: - void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; - private: -+ void check(const std::string &arg, const std::string &type); - static std::unordered_set types; - }; - -@@ -36,6 +37,7 @@ class QueryHandler : public CmdHandler { - public: - void handler(const ArgParse &arg_parse, Msg &msg) override; - void res_handler(Msg &msg) override; -+private: - void print_format(); - }; - -diff --git a/src/plugin_mgr/dep_handler.cpp b/src/plugin_mgr/dep_handler.cpp -index eff333c..652fdce 100644 ---- a/src/plugin_mgr/dep_handler.cpp -+++ b/src/plugin_mgr/dep_handler.cpp -@@ -11,6 +11,7 @@ - ******************************************************************************/ - #include "dep_handler.h" - #include -+#include - #include - - void DepHandler::add_arc_node(std::shared_ptr node, const std::vector &dep_nodes) { -@@ -38,14 +39,14 @@ void DepHandler::add_arc_node(std::shared_ptr node, const std::vector dep_nodes) { -+void DepHandler::add_node(const std::string &name, std::vector dep_nodes) { - std::shared_ptr cur_node = add_new_node(name); - this->nodes[name] = cur_node; - add_arc_node(cur_node, dep_nodes); - change_arc_nodes(name, true); - } - --void DepHandler::del_node(std::string name) { -+void DepHandler::del_node(const std::string &name) { - del_node_and_arc_nodes(get_node(name)); - this->nodes.erase(name); - } -@@ -119,26 +120,41 @@ void DepHandler::query_node_top(std::string name, std::vector> &query) { -+void DepHandler::query_node(const std::string &name, std::vector> &query) { - if (!nodes.count(name)) return; -- std::shared_ptr p = nodes[name]; -- query.emplace_back(std::vector{name}); -- for (auto cur = p->head->next; cur != nullptr; cur = cur->next) { -- query.emplace_back(std::vector{name, cur->arc_name}); -- query_node(cur->arc_name, query); -+ std::queue q; -+ std::unordered_set vis; -+ vis.insert(name); -+ q.push(name); -+ while (!q.empty()) { -+ auto node = nodes[q.front()]; -+ q.pop(); -+ query.emplace_back(std::vector{node->name}); -+ for (auto cur = node->head->next; cur != nullptr; cur = cur->next) { -+ query.emplace_back(std::vector{node->name, cur->arc_name}); -+ if (!vis.count(cur->arc_name)) { -+ vis.insert(cur->arc_name); -+ q.push(cur->arc_name); -+ } -+ } - } - } - --std::vector DepHandler::get_pre_dependencies(std::string name) { -+std::vector DepHandler::get_pre_dependencies(const std::string &name) { - std::vector res; - std::queue> q; -+ std::unordered_set vis; -+ vis.insert(name); - q.push(nodes[name]); - while (!q.empty()) { - auto &node = q.front(); - q.pop(); - res.emplace_back(node->name); - for (auto arc_node = node->head->next; arc_node != nullptr; arc_node = arc_node->next) { -- q.push(nodes[arc_node->arc_name]); -+ if (!vis.count(arc_node->arc_name)) { -+ vis.insert(arc_node->arc_name); -+ q.push(nodes[arc_node->arc_name]); -+ } - } - } - return res; -diff --git a/src/plugin_mgr/dep_handler.h b/src/plugin_mgr/dep_handler.h -index cc8570a..76abf49 100644 ---- a/src/plugin_mgr/dep_handler.h -+++ b/src/plugin_mgr/dep_handler.h -@@ -47,11 +47,11 @@ public: - bool get_node_state(std::string name) { - return this->nodes[name]->state; - } -- void add_node(std::string name, std::vector dep_nodes = {}); -- void del_node(std::string name); -- std::vector get_pre_dependencies(std::string name); -+ void add_node(const std::string &name, std::vector dep_nodes = {}); -+ void del_node(const std::string &name); -+ std::vector get_pre_dependencies(const std::string &name); - // query instance dependency -- void query_node(std::string name, std::vector> &query); -+ void query_node(const std::string &name, std::vector> &query); - // query all instance dependencies - void query_all_top(std::vector> &query); - bool have_dep(const std::string &name) { -diff --git a/src/plugin_mgr/error_code.cpp b/src/plugin_mgr/error_code.cpp -index 6e09cb0..30cc4f8 100644 ---- a/src/plugin_mgr/error_code.cpp -+++ b/src/plugin_mgr/error_code.cpp -@@ -12,7 +12,7 @@ const std::unordered_map ErrorText::error_codes = { - {ErrorCode::REMOVE_INSTANCE_HAVE_DEP, "instance with pre-dependency"}, - {ErrorCode::LOAD_PLUGIN_FILE_NOT_EXIST, "plugin file does not exist"}, - {ErrorCode::LOAD_PLUGIN_FILE_IS_NOT_SO, "file is not a plugin file"}, -- {ErrorCode::LOAD_PLUGIN_FILE_PERMISSION_DEFINED, "plugin file permission defined"}, -+ {ErrorCode::LOAD_PLUGIN_FILE_PERMISSION_DEFINED, "plugin file permission is not the specified permission"}, - {ErrorCode::LOAD_PLUGIN_EXIST, "plugin already loaded"}, - {ErrorCode::LOAD_PLUGIN_DLOPEN_FAILED, "plugin dlopen failed"}, - {ErrorCode::LOAD_PLUGIN_DLSYM_FAILED, "plugin dlsym failed"}, -diff --git a/src/plugin_mgr/message_manager.cpp b/src/plugin_mgr/message_manager.cpp -index e2fd3b6..f081f20 100644 ---- a/src/plugin_mgr/message_manager.cpp -+++ b/src/plugin_mgr/message_manager.cpp -@@ -25,6 +25,9 @@ int TcpSocket::domain_listen(const char *name) { - ERROR("[MessageManager] bind error!"); - return -1; - } -+ if (chmod(name, S_IRWXU | S_IRGRP | S_IXGRP) == -1) { -+ ERROR("[MessageManager] " << name << " chmod error!"); -+ } - if (listen(sock, 20) < 0) { - ERROR("[MessageManager] listen error!"); - return -1; -diff --git a/src/plugin_mgr/plugin.h b/src/plugin_mgr/plugin.h -index 69837af..a2a1815 100644 ---- a/src/plugin_mgr/plugin.h -+++ b/src/plugin_mgr/plugin.h -@@ -123,8 +123,10 @@ private: - class Plugin { - public: - Plugin(std::string name, PluginType type) : name(name), type(type), handler(nullptr) { } -- ~Plugin() { -- dlclose(handler); -+ ~Plugin() { -+ if (handler != nullptr) { -+ dlclose(handler); -+ } - } - int load(const std::string dl_path); - std::string get_name() const { -diff --git a/src/plugin_mgr/plugin_manager.cpp b/src/plugin_mgr/plugin_manager.cpp -index 0826a60..5ef395c 100644 ---- a/src/plugin_mgr/plugin_manager.cpp -+++ b/src/plugin_mgr/plugin_manager.cpp -@@ -13,6 +13,7 @@ - #include "default_path.h" - #include "utils.h" - #include -+#include - #include - #include - -@@ -203,15 +204,15 @@ ErrorCode PluginManager::load_plugin(const std::string &name, PluginType type) { - std::string generate_dot(MemoryStore &memory_store, const std::vector> &query) { - std::string res; - res += "digraph G {\n"; -- std::unordered_map> sub_graph; -+ std::unordered_map> sub_graph; - for (auto &vec : query) { - std::shared_ptr instance = memory_store.get_instance(vec[0]); -- sub_graph[instance->get_plugin_name()].emplace_back(vec[0]); -+ sub_graph[instance->get_plugin_name()].insert(vec[0]); - if (vec.size() == 1) { - continue; - } - instance = memory_store.get_instance(vec[1]); -- sub_graph[instance->get_plugin_name()].emplace_back(vec[1]); -+ sub_graph[instance->get_plugin_name()].insert(vec[1]); - res += vec[0] + "->" + vec[1] + ";"; - } - int id = 0; -@@ -371,8 +372,12 @@ void PluginManager::pre_load_plugin(PluginType type) { - while ((entry = readdir(dir)) != nullptr) { - std::string name = entry->d_name; - if (end_with(name, ".so")) { -- Message msg; -- load_plugin(name, type); -+ auto ret = load_plugin(name, type); -+ if (ret != ErrorCode::OK) { -+ WARN("[PluginManager] " << name << " plugin preload failed, because " << ErrorText::get_error_text(ret) << "."); -+ } else { -+ INFO("[PluginManager] " << name << " plugin loaded."); -+ } - } - } - closedir(dir); --- -2.33.0 - diff --git a/0006-fix-load-error-and-args-parsing-error-printing.patch b/0006-fix-load-error-and-args-parsing-error-printing.patch deleted file mode 100644 index 827aed8..0000000 --- a/0006-fix-load-error-and-args-parsing-error-printing.patch +++ /dev/null @@ -1,252 +0,0 @@ -From c35c26e51d93b0eb5b0aecdf08c338178079e02a Mon Sep 17 00:00:00 2001 -From: fly_1997 -Date: Fri, 10 May 2024 12:01:08 +0800 -Subject: [PATCH] fix load error and args parsing error printing - ---- - src/client/arg_parse.cpp | 28 +++++++++++++++++++++++++--- - src/client/arg_parse.h | 3 +++ - src/client/cmd_handler.cpp | 28 +++++++++++----------------- - src/plugin_mgr/config.cpp | 11 +++++------ - src/plugin_mgr/config.h | 2 +- - src/plugin_mgr/dep_handler.cpp | 2 +- - src/plugin_mgr/plugin_manager.cpp | 2 +- - 7 files changed, 47 insertions(+), 29 deletions(-) - -diff --git a/src/client/arg_parse.cpp b/src/client/arg_parse.cpp -index 70fcd4a..805f5a7 100644 ---- a/src/client/arg_parse.cpp -+++ b/src/client/arg_parse.cpp -@@ -62,10 +62,23 @@ void ArgParse::print_help() { - " --help show this help message.\n"; - } - -+void ArgParse::init_opts() { -+ opts.insert('l'); -+ opts.insert('r'); -+ opts.insert('q'); -+ opts.insert('Q'); -+ opts.insert('e'); -+ opts.insert('d'); -+ opts.insert('L'); -+ opts.insert('i'); -+ opts.insert('t'); -+} -+ - int ArgParse::init(int argc, char *argv[]) { - int cmd = -1; - int opt; - bool help = false; -+ init_opts(); - opterr = 0; - while((opt = getopt_long(argc, argv, OPT_STRING.c_str(), long_options, nullptr)) != -1) { - std::string full_opt; -@@ -76,9 +89,15 @@ int ArgParse::init(int argc, char *argv[]) { - case 'h': - help = true; - break; -- case '?': -- arg_error("unknown option."); -- return -1; -+ case '?': { -+ std::string err; -+ err += optopt; -+ if (!opts.count(optopt)) { -+ arg_error("unknown option '-" + err + "'."); -+ } else{ -+ arg_error("option -" + err + " requires an argument."); -+ } -+ } - default: { - if (opt == 'l' || opt == 'r' || opt == 'q' || opt == 'Q' || opt == 'e' || opt == 'd' || opt == 'L' || opt == 'i') { - if (cmd != -1) { -@@ -94,6 +113,9 @@ int ArgParse::init(int argc, char *argv[]) { - - } - } -+ if (cmd == 'l' && type.empty()) { -+ arg_error("option '-t' is required."); -+ } - if (help) { - print_help(); - exit(EXIT_SUCCESS); -diff --git a/src/client/arg_parse.h b/src/client/arg_parse.h -index 8535e9c..682f0e5 100644 ---- a/src/client/arg_parse.h -+++ b/src/client/arg_parse.h -@@ -12,12 +12,14 @@ - #ifndef CLIENT_ARG_PARSE_H - #define CLIENT_ARG_PARSE_H - #include -+#include - - class ArgParse { - public: - static void arg_error(const std::string &msg); - static void print_help(); - int init(int argc, char *argv[]); -+ void init_opts(); - void set_type(char* _type); - void set_arg(char* _arg); - std::string get_type() const { -@@ -29,6 +31,7 @@ public: - private: - std::string arg; - std::string type; -+ std::unordered_set opts; - static const std::string OPT_STRING; - static const int MAX_OPT_SIZE = 20; - static const struct option long_options[MAX_OPT_SIZE]; -diff --git a/src/client/cmd_handler.cpp b/src/client/cmd_handler.cpp -index 4fec95b..b410968 100644 ---- a/src/client/cmd_handler.cpp -+++ b/src/client/cmd_handler.cpp -@@ -16,14 +16,8 @@ - std::unordered_set LoadHandler::types = {"collector", "scenario", "tune"}; - - void LoadHandler::check(const std::string &arg, const std::string &type) { -- if (arg.empty()) { -- ArgParse::arg_error("plugin name empty."); -- } -- if (type.empty()) { -- ArgParse::arg_error("type empty."); -- } - if (!types.count(type)) { -- ArgParse::arg_error("this type is not supported."); -+ ArgParse::arg_error("type '" + type + "' is not supported."); - } - } - -@@ -94,9 +88,9 @@ void RemoveHandler::handler(const ArgParse &arg_parse, Msg &msg) { - - void RemoveHandler::res_handler(Msg &msg) { - if (msg.get_opt() == Opt::RESPONSE_OK) { -- std::cout << "plugin remove successfully.\n"; -+ std::cout << "Plugin remove successfully.\n"; - } else { -- std::cout << "plugin remove failed, because " << msg.payload(0) << ".\n"; -+ std::cout << "Plugin remove failed, because " << msg.payload(0) << ".\n"; - } - } - -@@ -141,9 +135,9 @@ void EnabledHandler::handler(const ArgParse &arg_parse, Msg &msg) { - - void EnabledHandler::res_handler(Msg &msg) { - if (msg.get_opt() == Opt::RESPONSE_OK) { -- std::cout << "instance enabled successfully.\n"; -+ std::cout << "Instance enabled successfully.\n"; - } else { -- std::cout << "instance enabled failed, because "<< msg.payload(0) << ".\n"; -+ std::cout << "Instance enabled failed, because "<< msg.payload(0) << ".\n"; - } - } - -@@ -155,9 +149,9 @@ void DisabledHandler::handler(const ArgParse &arg_parse, Msg &msg) { - - void DisabledHandler::res_handler(Msg &msg) { - if (msg.get_opt() == Opt::RESPONSE_OK) { -- std::cout << "instance disabled successfully.\n"; -+ std::cout << "Instance disabled successfully.\n"; - } else { -- std::cout << "instance disabled failed, because "<< msg.payload(0) << ".\n"; -+ std::cout << "Instance disabled failed, because "<< msg.payload(0) << ".\n"; - } - } - -@@ -167,10 +161,10 @@ void ListHandler::handler(const ArgParse &arg_parse, Msg &msg) { - - void ListHandler::res_handler(Msg &msg) { - if (msg.get_opt() == Opt::RESPONSE_ERROR) { -- std::cerr << "query list failed, because "<< msg.payload(0) << ".\n"; -+ std::cerr << "Query list failed, because "<< msg.payload(0) << ".\n"; - return; - } -- std::cout << "plugin list as follows.\n"; -+ std::cout << "Plugin list as follows.\n"; - std::cout << "------------------------------------------------------------\n"; - for (int i = 0; i < msg.payload_size(); ++i) { - std::cout << msg.payload(i); -@@ -186,13 +180,13 @@ void InstallHandler::handler(const ArgParse &arg_parse, Msg &msg) { - - void InstallHandler::res_handler(Msg &msg) { - if (msg.get_opt() == Opt::RESPONSE_ERROR) { -- std::cout << "download failed, because " << msg.payload(0) <<": " << this->arg.c_str() << '\n'; -+ std::cout << "Download failed, because " << msg.payload(0) <<": " << this->arg.c_str() << '\n'; - return; - } - std::string path = this->arg; - std::string url = msg.payload(0); - if (!download(url, path)) { -- std::cout << "download failed, please check url or your network.\n"; -+ std::cout << "Download failed, please check url or your network.\n"; - return; - } - std::string command = "rpm -ivh " + path; -diff --git a/src/plugin_mgr/config.cpp b/src/plugin_mgr/config.cpp -index 3c76e8e..f50399b 100644 ---- a/src/plugin_mgr/config.cpp -+++ b/src/plugin_mgr/config.cpp -@@ -84,16 +84,15 @@ bool Config::load(const std::string path) { - for (int i = 0; i < enable_list.size(); ++i) { - YAML::Node plugin = enable_list[i]["name"]; - std::string name = enable_list[i]["name"].as(); -+ YAML::Node instances = enable_list[i]["instances"]; - EnableItem enable_item(name); -- if (plugin.IsScalar()) { -+ if (instances.IsNull()) { - enable_item.set_enabled(true); -- } else if (plugin.IsSequence()) { -- for (int j = 0; j < plugin.size(); ++j) { -- std::string i_name = plugin[j].as(); -+ } else { -+ for (int j = 0; j < instances.size(); ++j) { -+ std::string i_name = instances[j].as(); - enable_item.add_instance(i_name); - } -- } else { -- continue; - } - this->enable_list.emplace_back(enable_item); - } -diff --git a/src/plugin_mgr/config.h b/src/plugin_mgr/config.h -index 5ab7672..6d0ee4d 100644 ---- a/src/plugin_mgr/config.h -+++ b/src/plugin_mgr/config.h -@@ -52,7 +52,7 @@ namespace std { - - class EnableItem { - public: -- EnableItem(std::string name) : name(name) { } -+ EnableItem(std::string name) : name(name), enabled(false) { } - void set_enabled(bool enabled) { - this->enabled = enabled; - } -diff --git a/src/plugin_mgr/dep_handler.cpp b/src/plugin_mgr/dep_handler.cpp -index 652fdce..816056d 100644 ---- a/src/plugin_mgr/dep_handler.cpp -+++ b/src/plugin_mgr/dep_handler.cpp -@@ -132,7 +132,7 @@ void DepHandler::query_node(const std::string &name, std::vector{node->name}); - for (auto cur = node->head->next; cur != nullptr; cur = cur->next) { - query.emplace_back(std::vector{node->name, cur->arc_name}); -- if (!vis.count(cur->arc_name)) { -+ if (!vis.count(cur->arc_name) && nodes.count(cur->arc_name)) { - vis.insert(cur->arc_name); - q.push(cur->arc_name); - } -diff --git a/src/plugin_mgr/plugin_manager.cpp b/src/plugin_mgr/plugin_manager.cpp -index 5ef395c..77acc40 100644 ---- a/src/plugin_mgr/plugin_manager.cpp -+++ b/src/plugin_mgr/plugin_manager.cpp -@@ -461,7 +461,7 @@ int PluginManager::run() { - PluginType type = plugin_types[msg.get_payload(1)]; - ErrorCode ret_code = load_plugin(plugin_name, type); - if(ret_code == ErrorCode::OK) { -- INFO("[PluginManager] " << plugin_name << "plugin loaded."); -+ INFO("[PluginManager] " << plugin_name << " plugin loaded."); - res.set_opt(Opt::RESPONSE_OK); - std::string lack_dep = instance_dep_check(plugin_name); - if (!lack_dep.empty()) { --- -2.33.0 - diff --git a/oeAware-manager-v1.0.0.tar.gz b/oeAware-manager-v1.0.0.tar.gz deleted file mode 100644 index 61c539617401a22902121c786e1929be31fda96e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23676 zcmV)cK&ZbTiwFP!000001MEEOQxjRfeooc?52tqTR!LP15MDcO`5{7(+zWx5ppNCW ztR^{uzIM8EyE`cN6FTw|5FAl)z!@1um>C6J9S0K7|7AAa37_U)xWC^y{mKJzXIy9Y zj$PK+eICE}^W-=g;mXB9Nf{8Ni$hdMQuWCDe;VLvZEaU)qwvflpFRbl@++MAIk1Pa2vV5{c%vAocy)G=F^F-=ombWkIFK(t<1uQuWwy zW1u0>Q2$RmTHY%a2Ry%X|35(g?LERJ+AV6j7SOM}mG5_W zc>HfZQ2)WEs`%g5+|+dBg9!0=uKz?D6n!x*%3?a3zNpgw$%-mX9z7F|#Us5@(i8{= z>wLb9s{A)i=tnE81!ja~@}ia8AXxnYENdQ?4T%LOb@CDEJ#Qq zq$7a+Ys=>M@EqX(-I4ZiG#-9GINt96!C+f!Tc!WEv^BPU^#2d=kXnzqyl#wb85?`% zgV&{vZDVe;w0YG}icg;gi&K+-@cqGe(4wDqXY6H!tqL{-8;qTojpp(s8PfI4@%nm6 zOi)>)frO$Zq=2Fh1`=|8PgWA-zIb;Kp>z1x){V`bA4iuyJgJXJBToguAg=%0jRnB)R_a&KkZH-^e5K} z+tcQQ74zw9_$=n0m=C`CY4;0@qJ{u5HohqAOj+OXc*!#tH_e%e;=*$re7RDb*}%as zubY$e0E}ZZme;G115U)YK5gXYjL&C^OWVfS3-j)Tx$+3c_m{?v`N_YJUMt7yAh59( z^7+E{s54a>9fR3Jv4XrnCgy|B%oleGZyuO89>ZW^Z`rtgwKhr)mt!@y#^194P~4@7 zZ;RJo6>>Rq@-D6c2)UfG@nvD}Hms>cUop)oFz4nAxyPI`fM_n~K;UQ$W1x{`5M$}; z!hsMgra43~6mE94NnV*LZ0F3oJEhT?()uVYHgB$Ri$u#~@4!uA`zBCej6FBzXPj|| zKHT-}vGMpij_@ssE@xs`;)za|i;?hg=<|-`MzlSdfN+R^ z$S8e(eShK>+y1JMzY8!6`5%AJwo>H}cg)$1 zYQb@l7e;-WeE(9zu-N@_fB^1@nO$gp^G z3t|Eq=+?OTVAY&n1sjD=$4M$_08!_@;|A>=2YqrxWsC12gtDZOzYXCN+!ce>n=uSH zyI&Mue_y<@iIIvC4CaPpKe=i?zs9Y`m>DxcJ3Rl`z;Qh@B_w8M%$WbKVwMYvV?>!e zxn_R3j8*~MU0dgbRRo<1XEv6%FaT{mFH0=knYW)=tl1cWJPi7KEH2L7Dt-S0X9u`L z2ilw}ZR~;}S-i~6!U!rf_t==5vS+89NWu3O^DlAl%8YSi9i0!N66ggMFo`+hLLw*c zzr_)%Q@7VPAo8PF=H`KBP6?91Snv{1*qJu(trqi>=CiL|$87?~z4y?#Gj2YdsPx)e zaeEe%#Oo!mGA&C4jolfCOl8c^7T31WX&6v=F_&kJ8!PZ`yt&6@w&pD3yByqTFMH#_ z4d#XXO6k=Ls56=!pT*UWw#>zwP&NQWw8J-J`zv|wkKC7C)|#QhV4(~=2b{qZjhrC3 zyv}uQeEWGJKMh6!cI}lktTA)*Rxz>nHMlGj?WQ@khC*c{`xCR~-7Su(W|VZ8;=~&B zx6nuzUV+@WFstQ^j81LBAezR`E2ssEckY)F#_X2|cdw|qU9g-D(eV+NmMfAL5Q%33 zz5eAR5J9Dcyr_5qP{U!C*E#tRCeX>ZpKw_M+~Q-bLiY2E@PZk2dJH%~AGYOfel})| ze-Bjv@K>1?ChuA`(9|fzG8jbQUgunT$o2g$UX3QQdj~XwKEohX#0YctE93EVbLtHc z$z|c_kRiHLT$?p+eg*Hw=5A@?C2RzejIVMKi}@^+QpW4);`}&lL3Pc(0P=tsbLn;I z>+g(wuC%d%LHXHZT+Gn1QgO5N*&ZY_5DT#c-x?sL&1X;vy~P3ZtH5Mw`Z-jz#@q}p zUs;D-!HBlTQGCl!jj(u_Ok;A3M|G}J2E>NMe_52$N+DP5=ZwtPa>ab|X*jnon0SRIjW==g(0=y+F>(LYfjKMH0^JkRm0idV%dZ zA6HU3p1qJLth+!&jaZ#=l4NCAMp#cwpeZK9!2sKHPRWu4jAb=S^dZ=x*)W7eLQ#{V zJV%D7J6o=72l9Qo$BcE(^j+!K!W`$O%}dN|7Yx zGPCd+rhS~a@wXvBI%rCi*^E1kIH+x&SGo!aM7s#0e9^fJDhJex@?(Lt^stBbzwN zDd#^?*h^e16Tq^8GKG6 z2)GA6r&Iw@!d^F7Sv!={a+!N0NoDmcVB~@PvdD9fOcPYo z1XTolqMTB}@i?GLf*~F$GG+EOfbNwZ5M{xe*UA< zYm0>EN-#?zWHLZ1KojJV3cIbQ!_OlrtmL7?OE#xQl)-3{RIAz=AdwU^Kwx+T^SvkD z^1udUc)}c$p9YZz-OQn07Y8}EqZ|>B^$AtcG_FXl!K@4}!@pU{>29oZYObM{FOff);s5@4nSp;Z)+$po= z6cnbpqqe3xD)8$r*gnO7KIv3y`6!f;-IW&aB7lJoNLvg7S3)`xoTf-lU<=tHZF9Sf42+@v5 zA>hxxT7YO$St%uQ%SK?<6tB2I{8nTl%>nmVtixMV#wdOyczI{DXLm53xL+o7kt;7v zlVUc_T@}d3zm=?B=2I+6G2??h8hAm1Sqi-ZDVUc)pwKk154?lHAx~&osC;V#SW1W) zk(ZE&$?d1A3P+W)j>}1Je#^c*g14(`<||kW=&-^OmzT?cdurCTeVQMgS7WX`(qJkr|?op1pf3BoN`*YpWUqm5L&dCgwH@P zM&eze?ryftK?qCXPkV3Qxme^>S3l|M?d||bC&SRxg-&*dv8OxNdz!avu(2c56FL=+ zd%8e>tu~M?jl{z3&;TMeQTrp_7jBP)x;fHlJp7-hfiN7f00ZBVIQEvEvEClU93!XW zVGhIYAOSv(l}Qm6;CHnk{m6b#sJ|b$>gqiUBT!eyNqY!Dbl^5Sg`(5LA;8RA@#!?h+%CPK?o3fEfT{F0pXq z?sLMBpSXD*(lJ$aPOWn~g~@>>P%=UV)y{P(QH9i<$qq=KVy0{(uVmN|J500r1y+QL zrkOWffAy5-qDb0R%F-)KnG8gdl$|G9^$-?fSV%CC(Eduid8AkLs*r8TgVXL@T&toS zf_UN*xYl32^oS&+>w;AcI?}T%T~NKMWK@w+EJJQ&XA#;6kamSwmCFEDGBU~;5VBUn z%1_8(z&UFA-JVB&Jd%93BT47}*8%tcV&PCnPdEV8Wjgtb@0cBO|F^NFEm(Q~ueGJM z@#Fo!5AghnR9Jw|_a}Hr2h|d)m_ax7MKELV&WrHdyCkJTj9>?W?6?4Tf`>w*#SexB zgeXIc?MH{#vof_dY5@zr6Kq0iVhH;E1a|2@XH@Wvg5kQf@ZAyU`JjUm_)sI5^c8q~ zLHni2esPzp{LET=hvnXOkT36KoDN}KpHVasBR<=0<(E$Q??u>82B5}H3^91^N*ao6 zo)i*FlKPt6^?g}LtTE_%AS?SUq^E#g4haRpuzI6wj0(v#{jZCke)=i6BuZV&X4uIK z^eri>vWC5;5k;^e%&(b-c^`EnO#)l?l55FUc0709f^f|O;gR!sz_&h*s+ zH8`B9^R?Ju@OKUgQwHa;2312;%G82`<8{7PFFhG0!w%llG(7-?9jOJ5y&c1NqSeuS z_oKA=(p{boC);VoFx%RGs+}K#edz!Of7#m;zV*$Oe_mJN(`=(wqx?#< zF}mx8gm)DeH;egQyzIG&H}8yzTy2~!71H8Y!q~NS)QvecZH&+SymVoK-MYH};A^}B zGxZG+RoEWIoBROz!K(56PVsThmdfrI#;wKuM>qE;Ch$tj!#N=D11FXP;y?6gDRD3` zBBZ5X9%Byu_kXQb@xKiQKgRzL@IWNEm=W}$olY1)o;{@DAQuvRWY%;3?hH9h6!jEPp zs@7N7=&voZ|5wie{%;KjtlxWn8IHsJzp1sg%KuxNKl=ZNc+Q`eMg4-$)9#a&_!KOoAsDUo`r zC+rVzezEo_nG=`ry!qHC8)IuIP7@~@;Ug`GGNUhi zMbuA>P-ySZTZaP|d}rD3nkPq2q_dJP9)mVowaEXqrT*J_4)gyEP5fdUhxmW6vHJi2 z(gv>|{r>|zQI@FrV<&#=mn$|5<^XPnm)H2RMqfOeP7CS?`|9SiO>4I z!2fP{ z_#eRnXZFg<0{qKhdwls_5dQ|td%^M`Sbg(qm6v#7I)PC8!_#k=4fE{g>9^=Jni$8&1)T_Ovfs!;6^BriIe4 z$G=ia+5cfu-CG^7AI|Cj>D9*Tm!#xzfgPr#$L1lT; zxn@FSuN^EW)6Q1=`SZ24VEH0g{(HZ+{AXtR+0T*JkKO%m?8)-*iE5XUp z>G5u(x*%-TRbDSn!j%=}W31mBelhY;@zC#me!U^wlM%b!kcdE**--GG-*}BTPEIvg z;A(>iD`U7PEv$;jn}VDl-JNr%{Q1xSSz(8q+t!gY|6jj+Wv~D1t8dmz|6dQ0UM$^f zS_qab!?PRn+jt5L5L zj3>R}G>Rva(IjL&pG<>~$wja@NG__uH(cI<%8&sCyep0>wq3v7Rhrz;$&4u!ETvhZX!jM{?^63zaVXrN(?jJo(Kvri9=@<5ih;a1>qR~QnIN>e2@jLl>Lk1L=u?wX0`rh{K;`G( zJDbzZ{^n#e-mKJBF|b<rCiaLw9;fE_jDcED?@>*SeVMB%gz~u-A2?OZ1`bo?`vwSw@ zaV5mxUoU(8I1JfmzA~^sA{cWauNbPV1$y+#g|8OSfyvl2>-Wb~n6XcQ9y-zJbm%g$ zNRf!SUwhN`WdH=wLXg@mw(YY)x9Ldf37hUPTA>u9kj!0~K2PG-m%0btr3anh5}SYV z9GL#gg9-YMFDaGT@C!Ti48?q2;THSL%TU)!#Y3^!BxGO8)QP*TS%11|@dgsCf7owZ zFpY!1{tD!;iSg@q)!^e6cy=-;YfBu#V9El%?iWbW(X*{w7cU`(F?z~VZC|# zHmK+$^kz_jFANehScmh9byHx!K0R(!ovPdYQ4%Z3iU<(xe%zX%H1(s;S^ui3@cIAp z_I2c(|JOG>=l_>)%J)AHk;?ObdH#QV=l?Dn8r@)*HTJL>eOUO94!HY@$p@t&Ae+Hu zg=!A;xy{IU%f;Q5%WZaY>$j3bY%*+b;SZI$e8)esEeDKE^r=}ÿIU;d8*)Z47s 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�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 c4PDJ_7i0aAzZ|~dR+DLXp_h6* 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 v1.0.0 +Requires: oeAware-scenario >= v1.0.0 Requires: graphviz %description @@ -54,6 +48,9 @@ install -D -p -m 0644 oeaware.service %{buildroot}%{_unitdir}/oeaware.service %attr(0644, root, root) %{_unitdir}/oeaware.service %changelog +* Sat May 11 2024 fly_1997 -v1.0.1-1 +- update version to v1.0.1 + * Wed May 8 2024 fly_1997 -v1.0.0-5 - fix systemd service uninstallation issue - fix load error and args parsing error printing