modify master service

This commit is contained in:
Zheng shuxin 2017-06-27 17:11:04 +08:00
parent f8cb1566ca
commit f973f28492
17 changed files with 740 additions and 232 deletions

View File

@ -1,8 +1,3 @@
POST /?cmd=list HTTP/1.0
Content-Length: 25
{ cmd: 'list', data: {}}
POST /?cmd=list HTTP/1.0
Content-Length: 25
Connection: keep-alive
@ -10,20 +5,25 @@ Connection: keep-alive
{ cmd: 'list', data: {}}
POST /?cmd=stat HTTP/1.0
Content-Length: 49
Content-Length: 72
Connection: keep-alive
{ cmd: 'stat', data: [{'name':'8084','type':4}]}
{ cmd: 'stat', data: [{'path':'/opt/soft/master/conf/service/web.cf'}]}
POST /?cmd=stop HTTP/1.0
Content-Length: 49
Content-Length: 72
Connection: keep-alive
{ cmd: 'stop', data: [{'name':'8084','type':4}]}
{ cmd: 'stop', data: [{'path':'/opt/soft/master/conf/service/web.cf'}]}
POST /?cmd=start HTTP/1.0
Content-Length: 64
Content-Length: 73
Connection: keep-alive
{ cmd: 'start', data: ['/opt/soft/master/conf/service/web.cf']}
{ cmd: 'start', data: [{'path':'/opt/soft/master/conf/service/web.cf'}]}
POST /?cmd=reload HTTP/1.0
Content-Length: 74
Connection: keep-alive
{ cmd: 'reload', data: [{'path':'/opt/soft/master/conf/service/web.cf'}]}

View File

@ -136,6 +136,288 @@ namespace acl
}
acl::json_node& gson(acl::json &$json, const reload_req_data_t &$obj)
{
acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.path))
$node.add_null("path");
else
$node.add_text("path", acl::get_value($obj.path));
return $node;
}
acl::json_node& gson(acl::json &$json, const reload_req_data_t *$obj)
{
return gson ($json, *$obj);
}
acl::string gson(const reload_req_data_t &$obj)
{
acl::json $json;
acl::json_node &$node = acl::gson ($json, $obj);
return $node.to_string ();
}
std::pair<bool,std::string> gson(acl::json_node &$node, reload_req_data_t &$obj)
{
acl::json_node *path = $node["path"];
std::pair<bool, std::string> $result;
if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [reload_req_data_t.path] failed:{"+$result.second+"}");
return std::make_pair(true,"");
}
std::pair<bool,std::string> gson(acl::json_node &$node, reload_req_data_t *$obj)
{
return gson($node, *$obj);
}
std::pair<bool,std::string> gson(const acl::string &$str, reload_req_data_t &$obj)
{
acl::json _json;
_json.update($str.c_str());
if (!_json.finish())
{
return std::make_pair(false, "json not finish error");
}
return gson(_json.get_root(), $obj);
}
acl::json_node& gson(acl::json &$json, const reload_req_t &$obj)
{
acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.cmd))
$node.add_null("cmd");
else
$node.add_text("cmd", acl::get_value($obj.cmd));
if (check_nullptr($obj.data))
$node.add_null("data");
else
$node.add_child("data", acl::gson($json, $obj.data));
return $node;
}
acl::json_node& gson(acl::json &$json, const reload_req_t *$obj)
{
return gson ($json, *$obj);
}
acl::string gson(const reload_req_t &$obj)
{
acl::json $json;
acl::json_node &$node = acl::gson ($json, $obj);
return $node.to_string ();
}
std::pair<bool,std::string> gson(acl::json_node &$node, reload_req_t &$obj)
{
acl::json_node *cmd = $node["cmd"];
acl::json_node *data = $node["data"];
std::pair<bool, std::string> $result;
if(!cmd ||!($result = gson(*cmd, &$obj.cmd), $result.first))
return std::make_pair(false, "required [reload_req_t.cmd] failed:{"+$result.second+"}");
if(!data ||!data->get_obj()||!($result = gson(*data->get_obj(), &$obj.data), $result.first))
return std::make_pair(false, "required [reload_req_t.data] failed:{"+$result.second+"}");
return std::make_pair(true,"");
}
std::pair<bool,std::string> gson(acl::json_node &$node, reload_req_t *$obj)
{
return gson($node, *$obj);
}
std::pair<bool,std::string> gson(const acl::string &$str, reload_req_t &$obj)
{
acl::json _json;
_json.update($str.c_str());
if (!_json.finish())
{
return std::make_pair(false, "json not finish error");
}
return gson(_json.get_root(), $obj);
}
acl::json_node& gson(acl::json &$json, const reload_res_data_t &$obj)
{
acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.status))
$node.add_null("status");
else
$node.add_number("status", acl::get_value($obj.status));
if (check_nullptr($obj.proc_count))
$node.add_null("proc_count");
else
$node.add_number("proc_count", acl::get_value($obj.proc_count));
if (check_nullptr($obj.proc_signaled))
$node.add_null("proc_signaled");
else
$node.add_number("proc_signaled", acl::get_value($obj.proc_signaled));
if (check_nullptr($obj.path))
$node.add_null("path");
else
$node.add_text("path", acl::get_value($obj.path));
return $node;
}
acl::json_node& gson(acl::json &$json, const reload_res_data_t *$obj)
{
return gson ($json, *$obj);
}
acl::string gson(const reload_res_data_t &$obj)
{
acl::json $json;
acl::json_node &$node = acl::gson ($json, $obj);
return $node.to_string ();
}
std::pair<bool,std::string> gson(acl::json_node &$node, reload_res_data_t &$obj)
{
acl::json_node *status = $node["status"];
acl::json_node *proc_count = $node["proc_count"];
acl::json_node *proc_signaled = $node["proc_signaled"];
acl::json_node *path = $node["path"];
std::pair<bool, std::string> $result;
if(!status ||!($result = gson(*status, &$obj.status), $result.first))
return std::make_pair(false, "required [reload_res_data_t.status] failed:{"+$result.second+"}");
if(!proc_count ||!($result = gson(*proc_count, &$obj.proc_count), $result.first))
return std::make_pair(false, "required [reload_res_data_t.proc_count] failed:{"+$result.second+"}");
if(!proc_signaled ||!($result = gson(*proc_signaled, &$obj.proc_signaled), $result.first))
return std::make_pair(false, "required [reload_res_data_t.proc_signaled] failed:{"+$result.second+"}");
if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [reload_res_data_t.path] failed:{"+$result.second+"}");
return std::make_pair(true,"");
}
std::pair<bool,std::string> gson(acl::json_node &$node, reload_res_data_t *$obj)
{
return gson($node, *$obj);
}
std::pair<bool,std::string> gson(const acl::string &$str, reload_res_data_t &$obj)
{
acl::json _json;
_json.update($str.c_str());
if (!_json.finish())
{
return std::make_pair(false, "json not finish error");
}
return gson(_json.get_root(), $obj);
}
acl::json_node& gson(acl::json &$json, const reload_res_t &$obj)
{
acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.status))
$node.add_null("status");
else
$node.add_number("status", acl::get_value($obj.status));
if (check_nullptr($obj.msg))
$node.add_null("msg");
else
$node.add_text("msg", acl::get_value($obj.msg));
if (check_nullptr($obj.data))
$node.add_null("data");
else
$node.add_child("data", acl::gson($json, $obj.data));
return $node;
}
acl::json_node& gson(acl::json &$json, const reload_res_t *$obj)
{
return gson ($json, *$obj);
}
acl::string gson(const reload_res_t &$obj)
{
acl::json $json;
acl::json_node &$node = acl::gson ($json, $obj);
return $node.to_string ();
}
std::pair<bool,std::string> gson(acl::json_node &$node, reload_res_t &$obj)
{
acl::json_node *status = $node["status"];
acl::json_node *msg = $node["msg"];
acl::json_node *data = $node["data"];
std::pair<bool, std::string> $result;
if(!status ||!($result = gson(*status, &$obj.status), $result.first))
return std::make_pair(false, "required [reload_res_t.status] failed:{"+$result.second+"}");
if(!msg ||!($result = gson(*msg, &$obj.msg), $result.first))
return std::make_pair(false, "required [reload_res_t.msg] failed:{"+$result.second+"}");
if(!data ||!data->get_obj()||!($result = gson(*data->get_obj(), &$obj.data), $result.first))
return std::make_pair(false, "required [reload_res_t.data] failed:{"+$result.second+"}");
return std::make_pair(true,"");
}
std::pair<bool,std::string> gson(acl::json_node &$node, reload_res_t *$obj)
{
return gson($node, *$obj);
}
std::pair<bool,std::string> gson(const acl::string &$str, reload_res_t &$obj)
{
acl::json _json;
_json.update($str.c_str());
if (!_json.finish())
{
return std::make_pair(false, "json not finish error");
}
return gson(_json.get_root(), $obj);
}
acl::json_node& gson(acl::json &$json, const req_t &$obj)
{
acl::json_node &$node = $json.create_node();
@ -433,6 +715,63 @@ namespace acl
}
acl::json_node& gson(acl::json &$json, const start_req_data_t &$obj)
{
acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.path))
$node.add_null("path");
else
$node.add_text("path", acl::get_value($obj.path));
return $node;
}
acl::json_node& gson(acl::json &$json, const start_req_data_t *$obj)
{
return gson ($json, *$obj);
}
acl::string gson(const start_req_data_t &$obj)
{
acl::json $json;
acl::json_node &$node = acl::gson ($json, $obj);
return $node.to_string ();
}
std::pair<bool,std::string> gson(acl::json_node &$node, start_req_data_t &$obj)
{
acl::json_node *path = $node["path"];
std::pair<bool, std::string> $result;
if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [start_req_data_t.path] failed:{"+$result.second+"}");
return std::make_pair(true,"");
}
std::pair<bool,std::string> gson(acl::json_node &$node, start_req_data_t *$obj)
{
return gson($node, *$obj);
}
std::pair<bool,std::string> gson(const acl::string &$str, start_req_data_t &$obj)
{
acl::json _json;
_json.update($str.c_str());
if (!_json.finish())
{
return std::make_pair(false, "json not finish error");
}
return gson(_json.get_root(), $obj);
}
acl::json_node& gson(acl::json &$json, const start_req_t &$obj)
{
acl::json_node &$node = $json.create_node();
@ -653,15 +992,10 @@ namespace acl
{
acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.name))
$node.add_null("name");
if (check_nullptr($obj.path))
$node.add_null("path");
else
$node.add_text("name", acl::get_value($obj.name));
if (check_nullptr($obj.type))
$node.add_null("type");
else
$node.add_number("type", acl::get_value($obj.type));
$node.add_text("path", acl::get_value($obj.path));
return $node;
@ -683,15 +1017,11 @@ namespace acl
std::pair<bool,std::string> gson(acl::json_node &$node, stat_req_data_t &$obj)
{
acl::json_node *name = $node["name"];
acl::json_node *type = $node["type"];
acl::json_node *path = $node["path"];
std::pair<bool, std::string> $result;
if(!name ||!($result = gson(*name, &$obj.name), $result.first))
return std::make_pair(false, "required [stat_req_data_t.name] failed:{"+$result.second+"}");
if(!type ||!($result = gson(*type, &$obj.type), $result.first))
return std::make_pair(false, "required [stat_req_data_t.type] failed:{"+$result.second+"}");
if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [stat_req_data_t.path] failed:{"+$result.second+"}");
return std::make_pair(true,"");
}
@ -860,15 +1190,10 @@ namespace acl
{
acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.name))
$node.add_null("name");
if (check_nullptr($obj.path))
$node.add_null("path");
else
$node.add_text("name", acl::get_value($obj.name));
if (check_nullptr($obj.type))
$node.add_null("type");
else
$node.add_number("type", acl::get_value($obj.type));
$node.add_text("path", acl::get_value($obj.path));
return $node;
@ -890,15 +1215,11 @@ namespace acl
std::pair<bool,std::string> gson(acl::json_node &$node, stop_req_data_t &$obj)
{
acl::json_node *name = $node["name"];
acl::json_node *type = $node["type"];
acl::json_node *path = $node["path"];
std::pair<bool, std::string> $result;
if(!name ||!($result = gson(*name, &$obj.name), $result.first))
return std::make_pair(false, "required [stop_req_data_t.name] failed:{"+$result.second+"}");
if(!type ||!($result = gson(*type, &$obj.type), $result.first))
return std::make_pair(false, "required [stop_req_data_t.type] failed:{"+$result.second+"}");
if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [stop_req_data_t.path] failed:{"+$result.second+"}");
return std::make_pair(true,"");
}
@ -997,10 +1318,10 @@ namespace acl
else
$node.add_number("status", acl::get_value($obj.status));
if (check_nullptr($obj.name))
$node.add_null("name");
if (check_nullptr($obj.path))
$node.add_null("path");
else
$node.add_text("name", acl::get_value($obj.name));
$node.add_text("path", acl::get_value($obj.path));
return $node;
@ -1023,14 +1344,14 @@ namespace acl
std::pair<bool,std::string> gson(acl::json_node &$node, stop_res_data_t &$obj)
{
acl::json_node *status = $node["status"];
acl::json_node *name = $node["name"];
acl::json_node *path = $node["path"];
std::pair<bool, std::string> $result;
if(!status ||!($result = gson(*status, &$obj.status), $result.first))
return std::make_pair(false, "required [stop_res_data_t.status] failed:{"+$result.second+"}");
if(!name ||!($result = gson(*name, &$obj.name), $result.first))
return std::make_pair(false, "required [stop_res_data_t.name] failed:{"+$result.second+"}");
if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [stop_res_data_t.path] failed:{"+$result.second+"}");
return std::make_pair(true,"");
}

View File

@ -16,6 +16,38 @@ namespace acl
std::pair<bool,std::string> gson(acl::json_node &$node, list_res_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, list_res_t &$obj);
//reload_req_data_t
acl::string gson(const reload_req_data_t &$obj);
acl::json_node& gson(acl::json &$json, const reload_req_data_t &$obj);
acl::json_node& gson(acl::json &$json, const reload_req_data_t *$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, reload_req_data_t &$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, reload_req_data_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, reload_req_data_t &$obj);
//reload_req_t
acl::string gson(const reload_req_t &$obj);
acl::json_node& gson(acl::json &$json, const reload_req_t &$obj);
acl::json_node& gson(acl::json &$json, const reload_req_t *$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, reload_req_t &$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, reload_req_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, reload_req_t &$obj);
//reload_res_data_t
acl::string gson(const reload_res_data_t &$obj);
acl::json_node& gson(acl::json &$json, const reload_res_data_t &$obj);
acl::json_node& gson(acl::json &$json, const reload_res_data_t *$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, reload_res_data_t &$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, reload_res_data_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, reload_res_data_t &$obj);
//reload_res_t
acl::string gson(const reload_res_t &$obj);
acl::json_node& gson(acl::json &$json, const reload_res_t &$obj);
acl::json_node& gson(acl::json &$json, const reload_res_t *$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, reload_res_t &$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, reload_res_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, reload_res_t &$obj);
//req_t
acl::string gson(const req_t &$obj);
acl::json_node& gson(acl::json &$json, const req_t &$obj);
@ -40,6 +72,14 @@ namespace acl
std::pair<bool,std::string> gson(acl::json_node &$node, serv_info_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, serv_info_t &$obj);
//start_req_data_t
acl::string gson(const start_req_data_t &$obj);
acl::json_node& gson(acl::json &$json, const start_req_data_t &$obj);
acl::json_node& gson(acl::json &$json, const start_req_data_t *$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, start_req_data_t &$obj);
std::pair<bool,std::string> gson(acl::json_node &$node, start_req_data_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, start_req_data_t &$obj);
//start_req_t
acl::string gson(const start_req_t &$obj);
acl::json_node& gson(acl::json &$json, const start_req_t &$obj);

View File

@ -49,8 +49,7 @@ struct list_res_t : res_t
struct stat_req_data_t
{
acl::string name;
int type;
acl::string path;
};
struct stat_req_t : req_t
@ -65,9 +64,15 @@ struct stat_res_t : res_t
//////////////////////////////////////////////////////////////////////////////
struct start_req_data_t
{
acl::string path;
};
struct start_req_t : req_t
{
std::vector<acl::string> data;
std::vector<start_req_data_t> data;
};
struct start_res_data_t
@ -87,8 +92,7 @@ struct start_res_t : res_t
struct stop_req_data_t
{
acl::string name;
int type;
acl::string path;
};
struct stop_req_t : req_t
@ -99,10 +103,35 @@ struct stop_req_t : req_t
struct stop_res_data_t
{
int status;
acl::string name;
acl::string path;
};
struct stop_res_t : res_t
{
std::vector<stop_res_data_t> data;
};
//////////////////////////////////////////////////////////////////////////////
struct reload_req_data_t
{
acl::string path;
};
struct reload_req_t : req_t
{
std::vector<reload_req_data_t> data;
};
struct reload_res_data_t
{
int status;
int proc_count;
int proc_signaled;
acl::string path;
};
struct reload_res_t : res_t
{
std::vector<reload_res_data_t> data;
};

View File

@ -49,8 +49,7 @@ struct list_res_t : res_t
struct stat_req_data_t
{
acl::string name;
int type;
acl::string path;
};
struct stat_req_t : req_t
@ -65,9 +64,15 @@ struct stat_res_t : res_t
//////////////////////////////////////////////////////////////////////////////
struct start_req_data_t
{
acl::string path;
};
struct start_req_t : req_t
{
std::vector<acl::string> data;
std::vector<start_req_data_t> data;
};
struct start_res_data_t
@ -87,8 +92,7 @@ struct start_res_t : res_t
struct stop_req_data_t
{
acl::string name;
int type;
acl::string path;
};
struct stop_req_t : req_t
@ -99,10 +103,35 @@ struct stop_req_t : req_t
struct stop_res_data_t
{
int status;
acl::string name;
acl::string path;
};
struct stop_res_t : res_t
{
std::vector<stop_res_data_t> data;
};
//////////////////////////////////////////////////////////////////////////////
struct reload_req_data_t
{
acl::string path;
};
struct reload_req_t : req_t
{
std::vector<reload_req_data_t> data;
};
struct reload_res_data_t
{
int status;
int proc_count;
int proc_signaled;
acl::string path;
};
struct reload_res_t : res_t
{
std::vector<reload_res_data_t> data;
};

View File

@ -199,6 +199,7 @@ int main(int argc, char **argv)
}
#endif
if (0)
acl_watchdog_start(watchdog); /* same as trigger servers */
acl_event_loop(acl_var_master_global_event);

View File

@ -20,14 +20,14 @@ bool service_start::run(const start_req_t& req, start_res_t& res)
const ACL_MASTER_SERV* serv;
size_t n = 0;
for (std::vector<acl::string>::const_iterator cit = req.data.begin();
cit != req.data.end(); ++cit)
for (std::vector<start_req_data_t>::const_iterator
cit = req.data.begin(); cit != req.data.end(); ++cit)
{
const char* name = (*cit).c_str();
if ((serv = acl_master_start(name)) == NULL)
const char* path = (*cit).path.c_str();
if ((serv = acl_master_start(path)) == NULL)
{
data.status = 500;
data.name = name;
data.path = path;
}
else
{

View File

@ -14,9 +14,9 @@
#include "master/master_api.h"
#include "service_stat.h"
bool service_stat::stat_one(const char* name, int type, serv_info_t& info)
bool service_stat::stat_one(const char* path, serv_info_t& info)
{
ACL_MASTER_SERV *serv = acl_master_lookup(name, type);
ACL_MASTER_SERV *serv = acl_master_lookup(path);
if (serv == NULL)
{
@ -35,9 +35,9 @@ bool service_stat::stat_one(const char* name, int type, serv_info_t& info)
info.listen_fd_count = serv->listen_fd_count;
if (serv->owner && *serv->owner)
info.owner = serv->owner;
info.owner = serv->owner;
if (serv->notify_addr && *serv->notify_addr)
info.notify_addr = serv->notify_addr;
info.notify_addr = serv->notify_addr;
if (serv->notify_recipients && *serv->notify_recipients)
info.notify_recipients = serv->notify_recipients;
@ -60,7 +60,7 @@ bool service_stat::run(const stat_req_t& req, stat_res_t& res)
cit = req.data.begin(); cit != req.data.end(); ++cit)
{
serv_info_t info;
if (stat_one((*cit).name.c_str(), (*cit).type, info))
if (stat_one((*cit).path.c_str(), info))
n++;
res.data.push_back(info);
}

View File

@ -25,5 +25,5 @@ public:
bool run(const stat_req_t& req, stat_res_t& res);
private:
bool stat_one(const char* name, int type, serv_info_t& info);
bool stat_one(const char* path, serv_info_t& info);
};

View File

@ -14,9 +14,9 @@
#include "master/master_api.h"
#include "service_stop.h"
bool service_stop::stop_one(const char* name, int type, stop_res_data_t& data)
bool service_stop::stop_one(const char* path, stop_res_data_t& data)
{
if (acl_master_stop(name, type) < 0)
if (acl_master_stop(path) < 0)
{
data.status = 404;
return false;
@ -34,9 +34,9 @@ bool service_stop::run(const stop_req_t& req, stop_res_t& res)
cit = req.data.begin(); cit != req.data.end(); ++cit)
{
stop_res_data_t data;
data.name = (*cit).name;
data.path = (*cit).path;
if (stop_one((*cit).name.c_str(), (*cit).type, data))
if (stop_one((*cit).path.c_str(), data))
n++;
res.data.push_back(data);
}
@ -50,7 +50,7 @@ bool service_stop::run(const stop_req_t& req, stop_res_t& res)
{
res.status = 500;
res.msg = "error";
logger_error("not all service have been started!, n=%d, %d",
logger_error("not all services were started!, n=%d, %d",
(int) n, (int) req.data.size());
}

View File

@ -25,5 +25,5 @@ public:
bool run(const stop_req_t& req, stop_res_t& res);
private:
bool stop_one(const char* name, int type, stop_res_data_t& data);
bool stop_one(const char* path, stop_res_data_t& data);
};

View File

@ -15,6 +15,7 @@
#include "action/service_stat.h"
#include "action/service_start.h"
#include "action/service_stop.h"
#include "action/service_reload.h"
#include "http_client.h"
http_client::http_client(acl::aio_socket_stream *client, int rw_timeout)
@ -75,6 +76,8 @@ int http_client::on_head(int status, void* ctx)
{
http_client* hc = (http_client*) ctx;
acl_aio_disable_readwrite(hc->conn_);
if (status != HTTP_CHAT_OK)
{
logger_error("invalid status=%d", status);
@ -121,7 +124,10 @@ int http_client::on_body(int status, char *data, int dlen, void *ctx)
hc->json_.update(data);
if (status == HTTP_CHAT_OK)
{
acl_aio_disable_readwrite(hc->conn_);
return hc->handle() ? 0 : -1;
}
return 0;
}
@ -169,6 +175,8 @@ bool http_client::handle(void)
ret = handle_start();
else if (EQ(cmd, "stop"))
ret = handle_stop();
else if (EQ(cmd, "reload"))
ret = handle_reload();
else {
logger_warn("invalid cmd=%s", cmd);
acl::string dummy;
@ -280,3 +288,23 @@ bool http_client::handle_start(void)
return true;
}
bool http_client::handle_reload(void)
{
reload_req_t req;
reload_res_t res;
if (deserialize<reload_req_t>(json_, req) == false)
{
res.status = 400;
res.msg = "invalid json";
reply<reload_res_t>(res.status, res);
return false;
}
service_reload service;
service.run(req, res);
reply<reload_res_t>(res.status, res);
return true;
}

View File

@ -38,6 +38,7 @@ private:
bool handle_stat(void);
bool handle_stop(void);
bool handle_start(void);
bool handle_reload(void);
void do_reply(int status, const acl::string& buf);

View File

@ -50,8 +50,8 @@ typedef struct ACL_MASTER_SERV {
#if 0
struct ACL_BINHASH *children; /* linkage */
#endif
ACL_RING children; /* linkage children */
struct ACL_MASTER_SERV *next; /* linkage */
ACL_RING children; /* linkage of children */
struct ACL_MASTER_SERV *next; /* linkage of serv */
} ACL_MASTER_SERV;
/*
@ -182,6 +182,10 @@ extern void acl_master_spawn(ACL_MASTER_SERV *);
extern void acl_master_reap_child(void);
extern void acl_master_delete_children(ACL_MASTER_SERV *);
extern void acl_master_delete_all_children(void);
extern void acl_master_signal_children(ACL_MASTER_SERV *serv, int signum,
int *nchildren, int *nsignaled);
extern void acl_master_sighup_children(ACL_MASTER_SERV *serv,
int *nchildren, int *nsignaled);
/*
* master_warning.c

View File

@ -22,24 +22,34 @@
#include "master.h"
#include "master_api.h"
#define STR_SAME !strcmp
#define SAME !strcmp
ACL_MASTER_SERV *acl_master_lookup(const char *name, int type)
ACL_MASTER_SERV *acl_master_lookup(const char *path)
{
return acl_master_ent_find(name, type);
}
ACL_MASTER_SERV *acl_master_start(const char *filepath)
{
ACL_MASTER_SERV *entry = acl_master_ent_load(filepath), *serv;
ACL_MASTER_SERV *entry = acl_master_ent_load(path), *serv;
if (entry == NULL) {
acl_msg_error("%s(%d), %s: load %s error %s", __FILE__,
__LINE__, __FUNCTION__, filepath, acl_last_serror());
__LINE__, __FUNCTION__, path, acl_last_serror());
return NULL;
}
serv = acl_master_lookup(entry->name, entry->type);
serv = acl_master_ent_find(entry->name, entry->type);
acl_master_ent_free(entry);
return serv;
}
ACL_MASTER_SERV *acl_master_start(const char *path)
{
ACL_MASTER_SERV *entry = acl_master_ent_load(path), *serv;
if (entry == NULL) {
acl_msg_error("%s(%d), %s: load %s error %s", __FILE__,
__LINE__, __FUNCTION__, path, acl_last_serror());
return NULL;
}
serv = acl_master_ent_find(entry->name, entry->type);
if (serv != NULL) {
acl_msg_error("%s(%d), %s: same service %s %d running",
__FILE__, __LINE__, __FUNCTION__,
@ -54,38 +64,52 @@ ACL_MASTER_SERV *acl_master_start(const char *filepath)
return entry;
}
ACL_MASTER_SERV *acl_master_restart(const char *filepath)
ACL_MASTER_SERV *acl_master_restart(const char *path)
{
ACL_MASTER_SERV *entry = acl_master_ent_load(filepath);
(void) acl_master_stop(path);
if (entry == NULL) {
acl_msg_error("%s(%d), %s: load %s error %s", __FILE__,
__LINE__, __FUNCTION__, filepath, acl_last_serror());
return NULL;
}
(void) acl_master_stop(entry->name, entry->type);
acl_master_ent_free(entry);
return acl_master_start(filepath);
return acl_master_start(path);
}
/* stop one service according the master_service name in configure */
int acl_master_stop(const char *name, int type)
int acl_master_stop(const char *path)
{
ACL_MASTER_SERV *serv, **servp;
ACL_MASTER_SERV *serv = acl_master_lookup(path);
ACL_MASTER_SERV *iter, **servp;
for (servp = &acl_var_master_head; (serv = *servp) != 0;) {
if (serv->type == type && STR_SAME(serv->name, name)) {
*servp = serv->next;
acl_master_service_stop(serv);
acl_master_ent_free(serv);
return 0;
}
if (serv == NULL) {
acl_msg_error("%s(%d), %s: no service, path %s",
__FILE__, __LINE__, __FUNCTION__, path);
return -1;
}
acl_msg_warn("%s(%d), %s: service - %s %d not found",
__FILE__, __LINE__, __FUNCTION__, name, type);
for (servp = &acl_var_master_head; (iter = *servp) != 0;) {
if (iter->type == serv->type && SAME(iter->name, serv->name)) {
*servp = iter->next;
acl_master_service_stop(iter);
acl_master_ent_free(iter);
return 0;
} else
servp = &iter->next;
}
acl_msg_warn("%s(%d), %s: not found service - %s %d, path %s",
__FILE__, __LINE__, __FUNCTION__, serv->name, serv->type, path);
return -1;
}
int acl_master_reload(const char *path, int *nchilden, int *nsignaled)
{
ACL_MASTER_SERV *serv = acl_master_lookup(path);
if (serv == NULL) {
acl_msg_error("%s(%d), %s: no service for path %s",
__FILE__, __LINE__, __FUNCTION__, path);
return -1;
}
acl_master_sighup_children(serv, nchilden, nsignaled);
return 0;
}

View File

@ -19,10 +19,11 @@ extern "C" {
#include "master.h"
ACL_MASTER_SERV *acl_master_lookup(const char *name, int type);
ACL_MASTER_SERV *acl_master_lookup(const char *path);
ACL_MASTER_SERV *acl_master_start(const char *path);
ACL_MASTER_SERV *acl_master_restart(const char *path);
int acl_master_stop(const char *name, int type);
int acl_master_stop(const char *path);
int acl_master_reload(const char *path, int *nchildren, int *nsignaled);
#ifdef __cplusplus

View File

@ -18,7 +18,7 @@
ACL_BINHASH *acl_var_master_child_table = NULL;
static void master_unthrottle(ACL_MASTER_SERV *serv);
void acl_master_spawn_init(void)
void acl_master_spawn_init(void)
{
if (acl_var_master_child_table == 0)
acl_var_master_child_table = acl_binhash_create(0, 0);
@ -43,7 +43,6 @@ static void master_unthrottle_wrapper(int type acl_unused,
static void master_unthrottle(ACL_MASTER_SERV *serv)
{
/*
* Enable process creation within this class.
* Disable the "unthrottle" timer just in case
@ -87,15 +86,89 @@ static void master_throttle(ACL_MASTER_SERV *serv)
/* acl_master_spawn - spawn off new child process if we can */
static unsigned master_generation = 0;
static ACL_VSTRING *env_gen = 0;
static void start_child(ACL_MASTER_SERV *serv)
{
const char *myname = "start_child";
ACL_MASTER_NV *nv;
int i, n;
/* MASTER_FLOW_READ_STREAM has been inited in master_vars.c */
if (acl_var_master_flow_pipe[0] <= ACL_MASTER_FLOW_READ)
acl_msg_fatal("%s: flow pipe read descriptor <= %d",
myname, ACL_MASTER_FLOW_READ);
if (dup2(acl_var_master_flow_pipe[0], ACL_MASTER_FLOW_READ) < 0)
acl_msg_fatal("%s: dup2: %s", myname, strerror(errno));
if (close(acl_var_master_flow_pipe[0]) < 0)
acl_msg_fatal("close %d: %s",
acl_var_master_flow_pipe[0], strerror(errno));
/* MASTER_FLOW_WRITE_STREAM has been inited in master_vars.c */
if (acl_var_master_flow_pipe[1] <= ACL_MASTER_FLOW_WRITE)
acl_msg_fatal("%s: flow pipe read descriptor <= %d",
myname, ACL_MASTER_FLOW_WRITE);
if (dup2(acl_var_master_flow_pipe[1], ACL_MASTER_FLOW_WRITE) < 0)
acl_msg_fatal("%s: dup2: %s", myname, strerror(errno));
if (close(acl_var_master_flow_pipe[1]) < 0)
acl_msg_fatal("close %d: %s",
acl_var_master_flow_pipe[1], strerror(errno));
/* status channel */
acl_vstream_close(serv->status_reader);
/* MASTER_STAT_STREAM has been inited in master_vars.c*/
if (serv->status_fd[1] <= ACL_MASTER_STATUS_FD)
acl_msg_fatal("%s: status file descriptor collision", myname);
if (dup2(serv->status_fd[1], ACL_MASTER_STATUS_FD) < 0)
acl_msg_fatal("%s: dup2 status_fd: %s", myname, strerror(errno));
close(serv->status_fd[1]);
for (n = 0; n < serv->listen_fd_count; n++) {
if (serv->listen_fds[n] <= ACL_MASTER_LISTEN_FD + n)
acl_msg_fatal("%s: listen fd collision", myname);
if (dup2(serv->listen_fds[n], ACL_MASTER_LISTEN_FD + n) < 0)
acl_msg_fatal("%s: dup2 listen_fd %d: %s",
myname, serv->listen_fds[n], strerror(errno));
(void) close(serv->listen_fds[n]);
acl_vstream_free(serv->listen_streams[n]);
}
acl_vstring_sprintf(env_gen, "%s=%o", ACL_MASTER_GEN_NAME,
master_generation);
if (putenv(acl_vstring_str(env_gen)) < 0)
acl_msg_fatal("%s: putenv: %s", myname, strerror(errno));
n = acl_array_size(serv->children_env);
for (i = 0; i < n; i++) {
nv = (ACL_MASTER_NV *)
acl_array_index(serv->children_env, i);
if (nv == NULL)
break;
setenv(nv->name, nv->value, 1);
}
/* begin to call the child process */
if (acl_msg_verbose)
acl_msg_info("%s: cmd = %s", myname, serv->path);
/* help programs written by golang to change runing privilege */
if (serv->owner && *serv->owner) {
acl_msg_info("%s: acl_chroot_uid %s", myname, serv->owner);
acl_chroot_uid(NULL, serv->owner);
}
execvp(serv->path, serv->args->argv);
acl_msg_fatal("%s: exec %s: %s", myname, serv->path, strerror(errno));
}
void acl_master_spawn(ACL_MASTER_SERV *serv)
{
const char *myname = "acl_master_spawn";
ACL_MASTER_PROC *proc;
ACL_MASTER_NV *nv;
ACL_MASTER_PID pid;
int n, i;
static unsigned master_generation = 0;
static ACL_VSTRING *env_gen = 0;
ACL_MASTER_PID pid;
if (env_gen == 0)
env_gen = acl_vstring_alloc(100);
@ -135,120 +208,42 @@ void acl_master_spawn(ACL_MASTER_SERV *serv)
switch (pid = fork()) {
/*
* Error. We're out of some essential resource.
* Best recourse is to try again later.
* Error. We're out of some essential resource. Best recourse is to
* try again later.
*/
case -1:
acl_msg_warn("%s: fork: %s -- throttling", myname, strerror(errno));
master_throttle(serv);
return;
break;
/*
* Child process. Redirect child stdin/stdout to
* the parent-child connection and run the requested
* command. Leave child stderr alone. Disable exit
* handlers: they should be executed by the parent only.
*/
/*
* Child process. Redirect child stdin/stdout to the parent-child
* connection and run the requested command. Leave child stderr alone.
* Disable exit handlers: they should be executed by the parent only.
*/
case 0: /* child process */
start_child(serv);
/* MASTER_FLOW_READ_STREAM has been inited in master_vars.c */
if (acl_var_master_flow_pipe[0] <= ACL_MASTER_FLOW_READ)
acl_msg_fatal("%s: flow pipe read descriptor <= %d",
myname, ACL_MASTER_FLOW_READ);
if (dup2(acl_var_master_flow_pipe[0], ACL_MASTER_FLOW_READ) < 0)
acl_msg_fatal("%s: dup2: %s", myname, strerror(errno));
if (close(acl_var_master_flow_pipe[0]) < 0)
acl_msg_fatal("close %d: %s",
acl_var_master_flow_pipe[0], strerror(errno));
/* MASTER_FLOW_WRITE_STREAM has been inited in master_vars.c */
if (acl_var_master_flow_pipe[1] <= ACL_MASTER_FLOW_WRITE)
acl_msg_fatal("%s: flow pipe read descriptor <= %d",
myname, ACL_MASTER_FLOW_WRITE);
if (dup2(acl_var_master_flow_pipe[1], ACL_MASTER_FLOW_WRITE) < 0)
acl_msg_fatal("%s: dup2: %s", myname, strerror(errno));
if (close(acl_var_master_flow_pipe[1]) < 0)
acl_msg_fatal("close %d: %s",
acl_var_master_flow_pipe[1], strerror(errno));
/* status channel */
acl_vstream_close(serv->status_reader);
/* MASTER_STAT_STREAM has been inited in master_vars.c*/
if (serv->status_fd[1] <= ACL_MASTER_STATUS_FD)
acl_msg_fatal("%s: status file descriptor collision",
myname);
if (dup2(serv->status_fd[1], ACL_MASTER_STATUS_FD) < 0)
acl_msg_fatal("%s: dup2 status_fd: %s",
myname, strerror(errno));
close(serv->status_fd[1]);
for (n = 0; n < serv->listen_fd_count; n++) {
if (serv->listen_fds[n] <= ACL_MASTER_LISTEN_FD + n)
acl_msg_fatal("%s(%d)->%s: "
"listen file descriptor collision",
__FILE__, __LINE__, myname);
if (dup2(serv->listen_fds[n], ACL_MASTER_LISTEN_FD + n) < 0)
acl_msg_fatal("%s: dup2 listen_fd %d: %s",
myname, serv->listen_fds[n], strerror(errno));
(void) close(serv->listen_fds[n]);
if (acl_msg_verbose)
acl_msg_info(">>>fd is: %d<<", ACL_MASTER_LISTEN_FD + n);
acl_vstream_free(serv->listen_streams[n]);
}
acl_vstring_sprintf(env_gen, "%s=%o",
ACL_MASTER_GEN_NAME, master_generation);
if (putenv(acl_vstring_str(env_gen)) < 0)
acl_msg_fatal("%s: putenv: %s", myname, strerror(errno));
n = acl_array_size(serv->children_env);
for (i = 0; i < n; i++) {
nv = (ACL_MASTER_NV *)
acl_array_index(serv->children_env, i);
if (nv == NULL)
break;
setenv(nv->name, nv->value, 1);
}
/* begin to call the child process */
if (acl_msg_verbose)
acl_msg_info("%s(%d)->%s: cmd = %s",
__FILE__, __LINE__, myname, serv->path);
/* help programs written by golang to change runing privilege */
if (serv->owner && *serv->owner) {
acl_msg_info("%s(%d)->%s: acl_chroot_uid %s",
__FILE__, __LINE__, myname, serv->owner);
acl_chroot_uid(NULL, serv->owner);
}
execvp(serv->path, serv->args->argv);
acl_msg_fatal("%s(%d)->%s: exec %s: %s", __FILE__, __LINE__,
myname, serv->path, strerror(errno));
exit(1);
/* NOTREACHED */
exit(1);
/*
* Parent. Fill in a process member data structure
* and set up links between child and process.
* Say this process has become available.
* If this service has a wakeup timer that is turned
* on only when the service is actually used,
* turn on the wakeup timer.
*/
/*
* Parent. Fill in a process member data structure and set up links
* between child and process. Say this process has become available.
* If this service has a wakeup timer that is turned on only when the
* service is actually used, turn on the wakeup timer.
*/
default: /* the parent process */
if (acl_msg_verbose)
acl_msg_info("spawn command %s; pid %d", serv->path, pid);
acl_msg_info("spawn cmd %s pid %d", serv->path, pid);
proc = (ACL_MASTER_PROC *) acl_mycalloc(1, sizeof(ACL_MASTER_PROC));
proc->serv = serv;
proc->pid = pid;
proc->gen = master_generation;
proc->use_count = 0;
proc->avail = 0;
acl_binhash_enter(acl_var_master_child_table, (char *) &pid,
sizeof(pid), (char *) proc);
acl_binhash_enter(acl_var_master_child_table,
(char *) &pid, sizeof(pid), (char *) proc);
acl_ring_prepend(&serv->children, &proc->me);
serv->total_proc++;
acl_master_avail_more(serv, proc);
@ -256,8 +251,7 @@ void acl_master_spawn(ACL_MASTER_SERV *serv)
serv->flags &= ~ACL_MASTER_FLAG_CONDWAKE;
acl_master_wakeup_init(serv);
if (acl_msg_verbose)
acl_msg_info("start conditional timer for %s",
serv->name);
acl_msg_info("start timer for %s", serv->name);
}
break;
@ -306,11 +300,11 @@ static void master_delete_child(ACL_MASTER_PROC *proc)
void acl_master_reap_child(void)
{
const char *myname = "acl_master_reap_child";
ACL_MASTER_SERV *serv;
ACL_MASTER_PROC *proc;
ACL_MASTER_PID pid;
ACL_MASTER_SERV *serv;
ACL_MASTER_PROC *proc;
ACL_MASTER_PID pid;
ACL_WAIT_STATUS_T status;
char buf[256];
char buf[256];
/*
* Pick up termination status of all dead children.
@ -321,11 +315,11 @@ void acl_master_reap_child(void)
*/
while ((pid = waitpid((pid_t) - 1, &status, WNOHANG)) > 0) {
if (acl_msg_verbose)
acl_msg_info("master_reap_child: pid %d", pid);
acl_msg_info("%s: pid %d", myname, pid);
if ((proc = (ACL_MASTER_PROC *)
acl_binhash_find(acl_var_master_child_table,
(char *) &pid, sizeof(pid))) == 0) {
proc = (ACL_MASTER_PROC *) acl_binhash_find(
acl_var_master_child_table, &pid, sizeof(pid));
if (proc == NULL) {
acl_msg_warn("master_reap: unknown pid: %d", pid);
continue;
}
@ -338,12 +332,14 @@ void acl_master_reap_child(void)
serv = proc->serv;
if (WIFEXITED(status)) {
acl_msg_warn("%s(%d), %s: process %s pid %d "
"exit status %d", __FILE__, __LINE__,
myname, serv->path, pid, WEXITSTATUS(status));
if (serv->notify_addr != NULL
&& serv->notify_recipients != NULL)
{
&& serv->notify_recipients != NULL) {
snprintf(buf, sizeof(buf), "exit status %d",
WEXITSTATUS(status));
master_warning(serv->notify_addr,
@ -353,12 +349,12 @@ void acl_master_reap_child(void)
}
if (WIFSIGNALED(status)) {
acl_msg_warn("%s(%d), %s: process %s pid %d killed"
" by signal %d", __FILE__, __LINE__, myname,
serv->path, pid, WTERMSIG(status));
if (serv->notify_addr != NULL
&& serv->notify_recipients != NULL)
{
if (serv->notify_addr && serv->notify_recipients) {
snprintf(buf, sizeof(buf), "killed by %d",
WTERMSIG(status));
master_warning(serv->notify_addr,
@ -419,3 +415,37 @@ void acl_master_delete_all_children(void)
acl_master_ent_free(serv);
}
}
void acl_master_signal_children(ACL_MASTER_SERV *serv, int signum,
int *nchildren, int *nsignaled)
{
const char *myname = "acl_master_signal_children";
ACL_RING_ITER iter;
ACL_MASTER_PROC *proc;
int n = 0;
acl_ring_foreach(iter, &serv->children) {
proc = acl_ring_to_appl(iter.ptr, ACL_MASTER_PROC, me);
acl_assert(proc);
if (kill(proc->pid, signum) < 0)
acl_msg_warn("%s: kill child %d, path %s error %s",
myname, proc->pid, serv->path, strerror(errno));
else
n++;
}
if (nchildren)
*nchildren = acl_ring_size(&serv->children);
if (nsignaled)
*nsignaled = n;
acl_msg_info("%s: service %s, path %s, signal %d, children %d,"
" signaled %d", myname, serv->name, serv->path,
signum, acl_ring_size(&serv->children), n);
}
void acl_master_sighup_children(ACL_MASTER_SERV *serv,
int *nchildren, int *nsignaled)
{
acl_master_signal_children(serv, SIGHUP, nchildren, nsignaled);
}