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