提交 f0a62f3b authored 作者: blu's avatar blu

refactor communitation archtecture to use evdamon only

上级 bce9f55b
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
"files.associations": { "files.associations": {
"chrono": "cpp", "chrono": "cpp",
"optional": "cpp", "optional": "cpp",
"string": "cpp" "string": "cpp",
"set": "cpp"
}, },
"C_Cpp.errorSquiggles": "Disabled" "C_Cpp.errorSquiggles": "Disabled"
} }
\ No newline at end of file
...@@ -391,22 +391,22 @@ togo_end: ...@@ -391,22 +391,22 @@ togo_end:
spdlog::error("failed to save new generated sn"); spdlog::error("failed to save new generated sn");
exit(1); exit(1);
}else{ }else{
// replace sn // // replace sn
size_t idx = 0; // size_t idx = 0;
for(auto &j:_sn_tmpl) { // for(auto &j:_sn_tmpl) {
idx = 0; // idx = 0;
while(true) { // while(true) {
idx = _config_default_tmpl.find(j, idx); // idx = _config_default_tmpl.find(j, idx);
if(idx == string::npos) break; // if(idx == string::npos) break;
_config_default_tmpl.replace(idx, j.size(), sn); // _config_default_tmpl.replace(idx, j.size(), sn);
idx+=sn.size(); // idx+=sn.size();
} // }
} // }
// replace camera addr, user, password, cloud-addr // // replace camera addr, user, password, cloud-addr
spdlog::debug("new config: {}", _config_default_tmpl); // spdlog::debug("new config: {}", _config_default_tmpl);
json j = json::parse(_config_default_tmpl); // json j = json::parse(_config_default_tmpl);
return setLocalConfig(j); // return setLocalConfig(j);
} }
} }
...@@ -418,26 +418,6 @@ togo_end: ...@@ -418,26 +418,6 @@ togo_end:
return setValue(info, LVDB_KEY_SN, fileName, _validateSn); return setValue(info, LVDB_KEY_SN, fileName, _validateSn);
}; };
// int setSn(json &info) {
// std::ifstream i("file.json");
// json j;
// i >> j;
// // write prettified JSON to another file
// std::ofstream o("pretty.json");
// o << std::setw(4) << j << std::endl;
// return -1;
// }
// int getSn(json &info) {
// fstream file;
// file.open(LVDB_KEY_SN, ios::out|ios);
// if(snfile.e)
// json j;
// i >> j;
// // write prettified JSON to another file
// std::ofstream o("pretty.json");
// o << std::setw(4) << j << std::endl;
// }
// config // config
int _validateConfig(const json &config) { int _validateConfig(const json &config) {
if(config.count("data") == 0|| config["data"].size() == 0) { if(config.count("data") == 0|| config["data"].size() == 0) {
......
...@@ -6,6 +6,7 @@ update: 2019/09/02 ...@@ -6,6 +6,7 @@ update: 2019/09/02
*/ */
#include <chrono> #include <chrono>
#include <set>
#include "inc/tinythread.hpp" #include "inc/tinythread.hpp"
#include "inc/httplib.h" #include "inc/httplib.h"
#include "inc/database.h" #include "inc/database.h"
...@@ -20,63 +21,85 @@ using namespace nlohmann; ...@@ -20,63 +21,85 @@ using namespace nlohmann;
// //
class HttpSrv{ class HttpSrv {
#define KEY_CONFIG_MAP "configmap" #define KEY_CONFIG_MAP "configmap"
private: private:
Server svr; Server svr;
// sn:module -> sn_of_evmgr // sn:module -> sn_of_evmgr
json configMap; json configMap;
json config(json &newConfig){ json config(json &newConfig)
{
json ret; json ret;
int iret; int iret;
json oldConfigMap = this->configMap; json oldConfigMap = this->configMap;
ret["code"] = 0; ret["code"] = 0;
ret["msg"] = "ok"; ret["msg"] = "ok";
ret["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); ret["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
spdlog::info(newConfig.dump()); spdlog::info(newConfig.dump());
try{ try {
if(newConfig.count("data") == 0 || newConfig["data"].size() == 0) { if(newConfig.count("data") == 0 || newConfig["data"].size() == 0) {
ret["code"] = 1; ret["code"] = 1;
ret["msg"] = "evcloudsvc invalid config body received: " + newConfig.dump(4); ret["msg"] = "evcloudsvc invalid config body received: " + newConfig.dump(4);
spdlog::error(ret["msg"].get<string>()); spdlog::error(ret["msg"].get<string>());
}else{ }
else {
json &data = newConfig["data"]; json &data = newConfig["data"];
for(auto &[k, v]: data.items()) { for(auto &[k, v]: data.items()) {
// TODO: confirm overwrite, take snapshot
if(this->configMap.count(k) != 0) {
spdlog::warn("evcloudsvc TODO: key {} already exist, take snapshot for safety", k);
}
// this is one evmgr // this is one evmgr
if(v.count("sn") == 0||v["sn"] != k) { if(v.count("sn") == 0||v["sn"] != k) {
ret["code"] = 2; ret["code"] = 2;
ret["msg"] = "evcloudsvc invalid value for key " + k; ret["msg"] = "evcloudsvc invalid value for key " + k;
spdlog::error(ret["msg"].get<string>()); spdlog::error(ret["msg"].get<string>());
break; break;
}else{ }
else {
// find all modules // find all modules
if(v.count("ipcs") == 0||v["ipcs"].size() == 0) { if(v.count("ipcs") == 0||v["ipcs"].size() == 0) {
spdlog::error("invalid ipcs in config body"); spdlog::error("invalid ipcs in config body");
ret["code"] = 3; ret["code"] = 3;
break; break;
}else{ }
else {
json &ipcs = v["ipcs"]; json &ipcs = v["ipcs"];
for(auto &ipc : ipcs) { for(auto &ipc : ipcs) {
if(ipc.count("modules") == 0||ipc["modules"].size() == 0) { if(ipc.count("modules") == 0||ipc["modules"].size() == 0) {
spdlog::error("invalid modules in ipcs config body"); spdlog::error("invalid modules in ipcs config body");
ret["code"] = 4; ret["code"] = 4;
break; break;
}else{ }
else {
json &modules = ipc["modules"]; json &modules = ipc["modules"];
for(auto &[mn, ma]: modules.items()) { for(auto &[mn, ma]: modules.items()) {
for(auto &m:ma) { for(auto &m:ma) {
if(m.count("sn") != 0 && m["sn"].size() != 0){ if(m.count("sn") != 0 && m["sn"].size() != 0) {
string modKey; string modKey;
string sn = m["sn"];
//ml //ml
if(mn == "evml" && m.count("type") != 0 && m["type"].size() != 0) { if(mn == "evml" && m.count("type") != 0 && m["type"].size() != 0) {
modKey = m["sn"].get<string>() +":evml:" + m["type"].get<string>(); modKey = sn +":evml:" + m["type"].get<string>();
}else{
modKey = m["sn"].get<string>() + ":" + mn;
} }
else {
modKey = sn + ":" + mn;
}
// modules
if(this->configMap["sn2mods"].count(sn) == 0) {
this->configMap["sn2mods"][sn] = json();
}
this->configMap["sn2mods"][sn].push_back(modKey);
// modkey -> sn_of_evmgr // modkey -> sn_of_evmgr
this->configMap[modKey] = k; this->configMap["mod2mgr"][modKey] = k;
}else{ }
else {
string msg = "evcloudsvc invalid config: " + data.dump(4);; string msg = "evcloudsvc invalid config: " + data.dump(4);;
ret["code"] = -1; ret["code"] = -1;
ret["msg"] = msg; ret["msg"] = msg;
...@@ -91,16 +114,18 @@ class HttpSrv{ ...@@ -91,16 +114,18 @@ class HttpSrv{
} }
} // for ipc } // for ipc
} }
} }
if(ret["code"] != 0) { if(ret["code"] != 0) {
break; break;
} }
} }
// update evmgr config // update evmgr config
json evmgrData; json evmgrData;
evmgrData["data"] = data; evmgrData["data"] = data;
this->configMap[k] = k;
//save //save
iret = LVDB::setLocalConfig(evmgrData, k); iret = LVDB::setLocalConfig(evmgrData, k);
if(iret < 0) { if(iret < 0) {
...@@ -115,128 +140,143 @@ class HttpSrv{ ...@@ -115,128 +140,143 @@ class HttpSrv{
if(ret["code"] == 0) { if(ret["code"] == 0) {
iret = LVDB::setValue(this->configMap, KEY_CONFIG_MAP); iret = LVDB::setValue(this->configMap, KEY_CONFIG_MAP);
if(iret >= 0) { if(iret >= 0) {
}else{ }
else {
ret["code"] = iret; ret["code"] = iret;
ret["msg"] = "failed to save configmap"; ret["msg"] = "failed to save configmap";
} }
}else{ }
else {
this->configMap = oldConfigMap; this->configMap = oldConfigMap;
} }
ret["data"] = newConfig["data"]; ret["data"] = newConfig["data"];
} }
}catch(exception &e) { }
catch(exception &e) {
ret.clear(); ret.clear();
ret["code"] = -1; ret["code"] = -1;
ret["msg"] = e.what(); ret["msg"] = e.what();
} }
return ret; return ret;
} }
protected: protected:
public: public:
void run(){ void run()
{
// load configmap // load configmap
json cnfm; json cnfm;
LVDB::getValue(cnfm, KEY_CONFIG_MAP); int ret = LVDB::getValue(cnfm, KEY_CONFIG_MAP);
if(cnfm.size() != 0){ if(ret < 0 || cnfm.size() == 0) {
this->configMap["sn2mods"] = json();
this->configMap["mod2mgr"] = json();
int iret = LVDB::setValue(this->configMap, KEY_CONFIG_MAP);
if(iret >= 0) {
}
else {
spdlog::error("evcloudsvc failed to save configmap");
exit(1);
}
}
else {
this->configMap = cnfm; this->configMap = cnfm;
} }
svr.Post("/register", [this](const Request& req, Response& res){ // svr.Post("/register", [this](const Request& req, Response& res){
json ret; // json ret;
try{ // try{
string sn = req.get_param_value("sn"); // string sn = req.get_param_value("sn");
string module = req.get_param_value("module"); // string module = req.get_param_value("module");
bool force = (req.get_param_value("force") == "true") ? true: false; // bool force = (req.get_param_value("force") == "true") ? true: false;
if(sn.empty()||module.empty()){ // if(sn.empty()||module.empty()){
throw StrException("no para sn/module"); // throw StrException("no para sn/module");
} // }
auto cfg = json::parse(req.body); // auto cfg = json::parse(req.body);
string key, modname; // string key, modname;
if(module == "evmgr") { // if(module == "evmgr") {
key = sn; // key = sn;
// trigger exception // // trigger exception
(void)cfg.at("data").at(key); // (void)cfg.at("data").at(key);
}else { // }else {
if(modname == "evml") { // if(modname == "evml") {
string // string
modname = "evml:" + module.substr(4, module.size()); // modname = "evml:" + module.substr(4, module.size());
}else{
modname = module;
}
modname = sn + ":" + modname;
if(this->configMap.count(modname) == 0){
spdlog::info("evcloudsvc no such edge module registred: {}, create new entry", key);
ret = this->config(cfg);
if(ret["code"] == 0) {
}else{
spdlog::error("failed to config: {}", ret.dump(4));
}
}else{
key = configMap[modname];
}
}
if(!key.empty()){
// TODO: calc md5
spdlog::info("evcloudsvc key: {}", key);
int r;
ret["code"] = 0;
ret["msg"] = "diff";
json data;
r = LVDB::getLocalConfig(data, key);
if(r < 0||force) {
spdlog::error("failed to get localconfig or force to updaste. create new");
ret = this->config(cfg);
}else{
json diff = json::diff(cfg, data);
spdlog::info("evcloudsvc diff: {}", diff.dump(4));
ret["data"] = diff;
}
}
}catch(exception &e) {
ret.clear();
ret["code"] = -1;
ret["msg"] = e.what();
}
res.set_content(ret.dump(), "text/json"); // }else{
// modname = module;
}); // }
// modname = sn + ":" + modname;
// if(this->configMap.count(modname) == 0){
// spdlog::info("evcloudsvc no such edge module registred: {}, create new entry", key);
// ret = this->config(cfg);
// if(ret["code"] == 0) {
// }else{
// spdlog::error("failed to config: {}", ret.dump(4));
// }
// }else{
// key = configMap[modname];
// }
// }
// if(!key.empty()){
// // TODO: calc md5
// spdlog::info("evcloudsvc key: {}", key);
// int r;
// ret["code"] = 0;
// ret["msg"] = "diff";
// json data;
// r = LVDB::getLocalConfig(data, key);
// if(r < 0||force) {
// spdlog::error("failed to get localconfig or force to updaste. create new");
// ret = this->config(cfg);
// }else{
// json diff = json::diff(cfg, data);
// spdlog::info("evcloudsvc diff: {}", diff.dump(4));
// ret["data"] = diff;
// }
// }
// }catch(exception &e) {
// ret.clear();
// ret["code"] = -1;
// ret["msg"] = e.what();
// }
// res.set_content(ret.dump(), "text/json");
svr.Get("/config", [this](const Request& req, Response& res){ // });
svr.Get("/config", [this](const Request& req, Response& res) {
json ret; json ret;
ret["code"] = 0; ret["code"] = 0;
ret["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); ret["time"] = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
ret["msg"] = "ok"; ret["msg"] = "ok";
string sn = req.get_param_value("sn"); string sn = req.get_param_value("sn");
string module = req.get_param_value("module"); string module = req.get_param_value("module");
if(sn.empty() || module.empty() || module.size()< 4){ try {
ret["code"] = 1; if(!sn.empty() && !module.empty() && module.size()> 4) {
ret["msg"] = "evcloud bad req: no sn/module param"; spdlog::info("evcloudsvc get module config with sn {}, module {}", sn, module);
spdlog::error(ret["msg"].get<string>());
}else{
try{
string modname = module.substr(0,4); string modname = module.substr(0,4);
string key; string key;
if(module == "evmgr") { if(module == "evmgr") {
key = sn; key = sn;
}else { }
else {
if(modname == "evml") { if(modname == "evml") {
modname = "evml:" + module.substr(4, module.size()); modname = "evml:" + module.substr(4, module.size());
}else{ }
else {
modname = module; modname = module;
} }
key = this->configMap.at(sn + ":" + modname); key = this->configMap["mod2mgr"].at(sn + ":" + modname);
spdlog::debug("key: ", key); spdlog::debug("key: ", key);
} }
if(!key.empty()) { if(!key.empty()) {
json config; json config;
int iret = LVDB::getLocalConfig(config, key); int iret = LVDB::getLocalConfig(config, key);
...@@ -244,31 +284,80 @@ class HttpSrv{ ...@@ -244,31 +284,80 @@ class HttpSrv{
ret["code"] = 1; ret["code"] = 1;
ret["msg"] = "evcloud failed to get config with key: " + key ; ret["msg"] = "evcloud failed to get config with key: " + key ;
spdlog::error(ret["msg"].get<string>()); spdlog::error(ret["msg"].get<string>());
}else{ }
else {
ret["data"] = config["data"]; ret["data"] = config["data"];
ret["lastupdated"] = config["lastupdated"]; ret["lastupdated"] = config["lastupdated"];
} }
}else{ }
else {
ret["code"] = 1; ret["code"] = 1;
ret["msg"] = "no config for sn " + sn + ", module " + module; ret["msg"] = "no config for sn " + sn + ", module " + module;
} }
}catch(exception &e){
ret["code"] = -1; }
ret["msg"] = string("evcloudsvc exception: ") + e.what(); else if(!sn.empty() && module.empty()) {
spdlog::error(ret["msg"].get<string>()); spdlog::info("evcloudsvc get config for sn {}", sn);
if(this->configMap["sn2mods"].count(sn) != 0) {
auto mods = this->configMap["sn2mods"][sn];
set<string> s;
for(const string & elem : mods) {
s.insert(this->configMap["mod2mgr"][elem].get<string>());
spdlog::info("evcloudsvc {}->{}", elem, this->configMap["mod2mgr"][elem].get<string>());
}
json data;
for(auto &key : s) {
json cfg;
int iret = LVDB::getLocalConfig(cfg, key);
if(iret < 0) {
ret["code"] = 1;
ret["msg"] = "evcloud failed to get config with key: " + key ;
spdlog::error(ret["msg"].get<string>());
}
else {
for(auto &[k,v]: cfg["data"].items()) {
if(data.count(k) != 0) {
json diff = json::diff(data[k], v);
if(diff.size() != 0) {
string msg = "evcloudsvc inconsistent configuration for k,v, newv: " + k + ",\n" + data[k].dump(4) + "new v:\n" + v.dump(4);
ret["code"] = 3;
ret["msg"] = msg;
break;
}
}
else {
data[k] = v;
}
} // for each mgr
if(ret["code"] != 0) {
break;
}
}
} // for keys of mgr
ret["data"] = data;
}
} }
} }
catch(exception &e) {
ret["code"] = -1;
ret["msg"] = string("evcloudsvc exception: ") + e.what();
spdlog::error(ret["msg"].get<string>());
}
res.set_content(ret.dump(), "text/json"); res.set_content(ret.dump(), "text/json");
}); });
svr.Post("/config", [this](const Request& req, Response& res){ svr.Post("/config", [this](const Request& req, Response& res) {
json ret; json ret;
string msg; string msg;
try{ try {
json cfg = json::parse(req.body); json cfg = json::parse(req.body);
ret = this->config(cfg); ret = this->config(cfg);
}catch (exception &e) { }
catch (exception &e) {
msg = string("evcloudsvc exception on POST /config: ") + e.what(); msg = string("evcloudsvc exception on POST /config: ") + e.what();
ret["msg"] = msg; ret["msg"] = msg;
ret["code"]= -1; ret["code"]= -1;
...@@ -276,25 +365,26 @@ class HttpSrv{ ...@@ -276,25 +365,26 @@ class HttpSrv{
res.set_content(ret.dump(), "text/json"); res.set_content(ret.dump(), "text/json");
}); });
svr.Post("/reset", [](const Request& req, Response& res){ svr.Post("/reset", [](const Request& req, Response& res) {
}); });
svr.Get("/keys", [](const Request& req, Response& res){ svr.Get("/keys", [](const Request& req, Response& res) {
string fileName = req.get_param_value("filename"); string fileName = req.get_param_value("filename");
auto v = LVDB::getKeys(fileName); auto v = LVDB::getKeys(fileName);
json ret = v; json ret = v;
res.set_content(ret.dump(), "text/json"); res.set_content(ret.dump(), "text/json");
}); });
svr.Get("/value", [](const Request& req, Response& res){ svr.Get("/value", [](const Request& req, Response& res) {
string key = req.get_param_value("key"); string key = req.get_param_value("key");
string filename = req.get_param_value("filename"); string filename = req.get_param_value("filename");
json j; json j;
int ret = LVDB::getValue(j, key, filename); int ret = LVDB::getValue(j, key, filename);
if(ret < 0) { if(ret < 0) {
j["code"] = 1; j["code"] = 1;
}else{ }
else {
j["code"] = 0; j["code"] = 0;
} }
res.set_content(j.dump(), "text/json"); res.set_content(j.dump(), "text/json");
...@@ -303,13 +393,15 @@ class HttpSrv{ ...@@ -303,13 +393,15 @@ class HttpSrv{
svr.listen("0.0.0.0", 8089); svr.listen("0.0.0.0", 8089);
} }
HttpSrv(){ HttpSrv()
{
}; };
~HttpSrv(){}; ~HttpSrv() {};
}; };
int main() { int main()
{
HttpSrv srv; HttpSrv srv;
srv.run(); srv.run();
} }
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论