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 POST /?cmd=list HTTP/1.0
Content-Length: 25 Content-Length: 25
Connection: keep-alive Connection: keep-alive
@ -10,20 +5,25 @@ Connection: keep-alive
{ cmd: 'list', data: {}} { cmd: 'list', data: {}}
POST /?cmd=stat HTTP/1.0 POST /?cmd=stat HTTP/1.0
Content-Length: 49 Content-Length: 72
Connection: keep-alive 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 POST /?cmd=stop HTTP/1.0
Content-Length: 49 Content-Length: 72
Connection: keep-alive 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 POST /?cmd=start HTTP/1.0
Content-Length: 64 Content-Length: 73
Connection: keep-alive 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& gson(acl::json &$json, const req_t &$obj)
{ {
acl::json_node &$node = $json.create_node(); 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& gson(acl::json &$json, const start_req_t &$obj)
{ {
acl::json_node &$node = $json.create_node(); acl::json_node &$node = $json.create_node();
@ -653,15 +992,10 @@ namespace acl
{ {
acl::json_node &$node = $json.create_node(); acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.name)) if (check_nullptr($obj.path))
$node.add_null("name"); $node.add_null("path");
else else
$node.add_text("name", acl::get_value($obj.name)); $node.add_text("path", acl::get_value($obj.path));
if (check_nullptr($obj.type))
$node.add_null("type");
else
$node.add_number("type", acl::get_value($obj.type));
return $node; return $node;
@ -683,15 +1017,11 @@ namespace acl
std::pair<bool,std::string> gson(acl::json_node &$node, stat_req_data_t &$obj) std::pair<bool,std::string> gson(acl::json_node &$node, stat_req_data_t &$obj)
{ {
acl::json_node *name = $node["name"]; acl::json_node *path = $node["path"];
acl::json_node *type = $node["type"];
std::pair<bool, std::string> $result; std::pair<bool, std::string> $result;
if(!name ||!($result = gson(*name, &$obj.name), $result.first)) if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [stat_req_data_t.name] failed:{"+$result.second+"}"); return std::make_pair(false, "required [stat_req_data_t.path] 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+"}");
return std::make_pair(true,""); return std::make_pair(true,"");
} }
@ -860,15 +1190,10 @@ namespace acl
{ {
acl::json_node &$node = $json.create_node(); acl::json_node &$node = $json.create_node();
if (check_nullptr($obj.name)) if (check_nullptr($obj.path))
$node.add_null("name"); $node.add_null("path");
else else
$node.add_text("name", acl::get_value($obj.name)); $node.add_text("path", acl::get_value($obj.path));
if (check_nullptr($obj.type))
$node.add_null("type");
else
$node.add_number("type", acl::get_value($obj.type));
return $node; return $node;
@ -890,15 +1215,11 @@ namespace acl
std::pair<bool,std::string> gson(acl::json_node &$node, stop_req_data_t &$obj) std::pair<bool,std::string> gson(acl::json_node &$node, stop_req_data_t &$obj)
{ {
acl::json_node *name = $node["name"]; acl::json_node *path = $node["path"];
acl::json_node *type = $node["type"];
std::pair<bool, std::string> $result; std::pair<bool, std::string> $result;
if(!name ||!($result = gson(*name, &$obj.name), $result.first)) if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [stop_req_data_t.name] failed:{"+$result.second+"}"); return std::make_pair(false, "required [stop_req_data_t.path] 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+"}");
return std::make_pair(true,""); return std::make_pair(true,"");
} }
@ -997,10 +1318,10 @@ namespace acl
else else
$node.add_number("status", acl::get_value($obj.status)); $node.add_number("status", acl::get_value($obj.status));
if (check_nullptr($obj.name)) if (check_nullptr($obj.path))
$node.add_null("name"); $node.add_null("path");
else else
$node.add_text("name", acl::get_value($obj.name)); $node.add_text("path", acl::get_value($obj.path));
return $node; return $node;
@ -1023,14 +1344,14 @@ namespace acl
std::pair<bool,std::string> gson(acl::json_node &$node, stop_res_data_t &$obj) std::pair<bool,std::string> gson(acl::json_node &$node, stop_res_data_t &$obj)
{ {
acl::json_node *status = $node["status"]; acl::json_node *status = $node["status"];
acl::json_node *name = $node["name"]; acl::json_node *path = $node["path"];
std::pair<bool, std::string> $result; std::pair<bool, std::string> $result;
if(!status ||!($result = gson(*status, &$obj.status), $result.first)) if(!status ||!($result = gson(*status, &$obj.status), $result.first))
return std::make_pair(false, "required [stop_res_data_t.status] failed:{"+$result.second+"}"); return std::make_pair(false, "required [stop_res_data_t.status] failed:{"+$result.second+"}");
if(!name ||!($result = gson(*name, &$obj.name), $result.first)) if(!path ||!($result = gson(*path, &$obj.path), $result.first))
return std::make_pair(false, "required [stop_res_data_t.name] failed:{"+$result.second+"}"); return std::make_pair(false, "required [stop_res_data_t.path] failed:{"+$result.second+"}");
return std::make_pair(true,""); 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(acl::json_node &$node, list_res_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, 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 //req_t
acl::string gson(const req_t &$obj); acl::string gson(const req_t &$obj);
acl::json_node& gson(acl::json &$json, 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(acl::json_node &$node, serv_info_t *$obj);
std::pair<bool,std::string> gson(const acl::string &str, 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 //start_req_t
acl::string gson(const start_req_t &$obj); acl::string gson(const start_req_t &$obj);
acl::json_node& gson(acl::json &$json, 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 struct stat_req_data_t
{ {
acl::string name; acl::string path;
int type;
}; };
struct stat_req_t : req_t 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 struct start_req_t : req_t
{ {
std::vector<acl::string> data; std::vector<start_req_data_t> data;
}; };
struct start_res_data_t struct start_res_data_t
@ -87,8 +92,7 @@ struct start_res_t : res_t
struct stop_req_data_t struct stop_req_data_t
{ {
acl::string name; acl::string path;
int type;
}; };
struct stop_req_t : req_t struct stop_req_t : req_t
@ -99,10 +103,35 @@ struct stop_req_t : req_t
struct stop_res_data_t struct stop_res_data_t
{ {
int status; int status;
acl::string name; acl::string path;
}; };
struct stop_res_t : res_t struct stop_res_t : res_t
{ {
std::vector<stop_res_data_t> data; 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 struct stat_req_data_t
{ {
acl::string name; acl::string path;
int type;
}; };
struct stat_req_t : req_t 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 struct start_req_t : req_t
{ {
std::vector<acl::string> data; std::vector<start_req_data_t> data;
}; };
struct start_res_data_t struct start_res_data_t
@ -87,8 +92,7 @@ struct start_res_t : res_t
struct stop_req_data_t struct stop_req_data_t
{ {
acl::string name; acl::string path;
int type;
}; };
struct stop_req_t : req_t struct stop_req_t : req_t
@ -99,10 +103,35 @@ struct stop_req_t : req_t
struct stop_res_data_t struct stop_res_data_t
{ {
int status; int status;
acl::string name; acl::string path;
}; };
struct stop_res_t : res_t struct stop_res_t : res_t
{ {
std::vector<stop_res_data_t> data; 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 #endif
if (0)
acl_watchdog_start(watchdog); /* same as trigger servers */ acl_watchdog_start(watchdog); /* same as trigger servers */
acl_event_loop(acl_var_master_global_event); 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; const ACL_MASTER_SERV* serv;
size_t n = 0; size_t n = 0;
for (std::vector<acl::string>::const_iterator cit = req.data.begin(); for (std::vector<start_req_data_t>::const_iterator
cit != req.data.end(); ++cit) cit = req.data.begin(); cit != req.data.end(); ++cit)
{ {
const char* name = (*cit).c_str(); const char* path = (*cit).path.c_str();
if ((serv = acl_master_start(name)) == NULL) if ((serv = acl_master_start(path)) == NULL)
{ {
data.status = 500; data.status = 500;
data.name = name; data.path = path;
} }
else else
{ {

View File

@ -14,9 +14,9 @@
#include "master/master_api.h" #include "master/master_api.h"
#include "service_stat.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) 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; info.listen_fd_count = serv->listen_fd_count;
if (serv->owner && *serv->owner) if (serv->owner && *serv->owner)
info.owner = serv->owner; info.owner = serv->owner;
if (serv->notify_addr && *serv->notify_addr) 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) if (serv->notify_recipients && *serv->notify_recipients)
info.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) cit = req.data.begin(); cit != req.data.end(); ++cit)
{ {
serv_info_t info; serv_info_t info;
if (stat_one((*cit).name.c_str(), (*cit).type, info)) if (stat_one((*cit).path.c_str(), info))
n++; n++;
res.data.push_back(info); res.data.push_back(info);
} }

View File

@ -25,5 +25,5 @@ public:
bool run(const stat_req_t& req, stat_res_t& res); bool run(const stat_req_t& req, stat_res_t& res);
private: 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 "master/master_api.h"
#include "service_stop.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; data.status = 404;
return false; 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) cit = req.data.begin(); cit != req.data.end(); ++cit)
{ {
stop_res_data_t data; 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++; n++;
res.data.push_back(data); 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.status = 500;
res.msg = "error"; 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()); (int) n, (int) req.data.size());
} }

View File

@ -25,5 +25,5 @@ public:
bool run(const stop_req_t& req, stop_res_t& res); bool run(const stop_req_t& req, stop_res_t& res);
private: 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_stat.h"
#include "action/service_start.h" #include "action/service_start.h"
#include "action/service_stop.h" #include "action/service_stop.h"
#include "action/service_reload.h"
#include "http_client.h" #include "http_client.h"
http_client::http_client(acl::aio_socket_stream *client, int rw_timeout) 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; http_client* hc = (http_client*) ctx;
acl_aio_disable_readwrite(hc->conn_);
if (status != HTTP_CHAT_OK) if (status != HTTP_CHAT_OK)
{ {
logger_error("invalid status=%d", status); 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); hc->json_.update(data);
if (status == HTTP_CHAT_OK) if (status == HTTP_CHAT_OK)
{
acl_aio_disable_readwrite(hc->conn_);
return hc->handle() ? 0 : -1; return hc->handle() ? 0 : -1;
}
return 0; return 0;
} }
@ -169,6 +175,8 @@ bool http_client::handle(void)
ret = handle_start(); ret = handle_start();
else if (EQ(cmd, "stop")) else if (EQ(cmd, "stop"))
ret = handle_stop(); ret = handle_stop();
else if (EQ(cmd, "reload"))
ret = handle_reload();
else { else {
logger_warn("invalid cmd=%s", cmd); logger_warn("invalid cmd=%s", cmd);
acl::string dummy; acl::string dummy;
@ -280,3 +288,23 @@ bool http_client::handle_start(void)
return true; 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_stat(void);
bool handle_stop(void); bool handle_stop(void);
bool handle_start(void); bool handle_start(void);
bool handle_reload(void);
void do_reply(int status, const acl::string& buf); void do_reply(int status, const acl::string& buf);

View File

@ -50,8 +50,8 @@ typedef struct ACL_MASTER_SERV {
#if 0 #if 0
struct ACL_BINHASH *children; /* linkage */ struct ACL_BINHASH *children; /* linkage */
#endif #endif
ACL_RING children; /* linkage children */ ACL_RING children; /* linkage of children */
struct ACL_MASTER_SERV *next; /* linkage */ struct ACL_MASTER_SERV *next; /* linkage of serv */
} ACL_MASTER_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_reap_child(void);
extern void acl_master_delete_children(ACL_MASTER_SERV *); extern void acl_master_delete_children(ACL_MASTER_SERV *);
extern void acl_master_delete_all_children(void); 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 * master_warning.c

View File

@ -22,24 +22,34 @@
#include "master.h" #include "master.h"
#include "master_api.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 *entry = acl_master_ent_load(path), *serv;
}
ACL_MASTER_SERV *acl_master_start(const char *filepath)
{
ACL_MASTER_SERV *entry = acl_master_ent_load(filepath), *serv;
if (entry == NULL) { if (entry == NULL) {
acl_msg_error("%s(%d), %s: load %s error %s", __FILE__, 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; 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) { if (serv != NULL) {
acl_msg_error("%s(%d), %s: same service %s %d running", acl_msg_error("%s(%d), %s: same service %s %d running",
__FILE__, __LINE__, __FUNCTION__, __FILE__, __LINE__, __FUNCTION__,
@ -54,38 +64,52 @@ ACL_MASTER_SERV *acl_master_start(const char *filepath)
return entry; 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) { return acl_master_start(path);
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);
} }
/* stop one service according the master_service name in configure */ /* 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 == NULL) {
if (serv->type == type && STR_SAME(serv->name, name)) { acl_msg_error("%s(%d), %s: no service, path %s",
*servp = serv->next; __FILE__, __LINE__, __FUNCTION__, path);
acl_master_service_stop(serv); return -1;
acl_master_ent_free(serv);
return 0;
}
} }
acl_msg_warn("%s(%d), %s: service - %s %d not found", for (servp = &acl_var_master_head; (iter = *servp) != 0;) {
__FILE__, __LINE__, __FUNCTION__, name, type); 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; 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" #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_start(const char *path);
ACL_MASTER_SERV *acl_master_restart(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 #ifdef __cplusplus

View File

@ -18,7 +18,7 @@
ACL_BINHASH *acl_var_master_child_table = NULL; ACL_BINHASH *acl_var_master_child_table = NULL;
static void master_unthrottle(ACL_MASTER_SERV *serv); 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) if (acl_var_master_child_table == 0)
acl_var_master_child_table = acl_binhash_create(0, 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) static void master_unthrottle(ACL_MASTER_SERV *serv)
{ {
/* /*
* Enable process creation within this class. * Enable process creation within this class.
* Disable the "unthrottle" timer just in case * 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 */ /* 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) void acl_master_spawn(ACL_MASTER_SERV *serv)
{ {
const char *myname = "acl_master_spawn"; const char *myname = "acl_master_spawn";
ACL_MASTER_PROC *proc; ACL_MASTER_PROC *proc;
ACL_MASTER_NV *nv; ACL_MASTER_PID pid;
ACL_MASTER_PID pid;
int n, i;
static unsigned master_generation = 0;
static ACL_VSTRING *env_gen = 0;
if (env_gen == 0) if (env_gen == 0)
env_gen = acl_vstring_alloc(100); env_gen = acl_vstring_alloc(100);
@ -135,120 +208,42 @@ void acl_master_spawn(ACL_MASTER_SERV *serv)
switch (pid = fork()) { switch (pid = fork()) {
/* /*
* Error. We're out of some essential resource. * Error. We're out of some essential resource. Best recourse is to
* Best recourse is to try again later. * try again later.
*/ */
case -1: case -1:
acl_msg_warn("%s: fork: %s -- throttling", myname, strerror(errno)); acl_msg_warn("%s: fork: %s -- throttling", myname, strerror(errno));
master_throttle(serv); master_throttle(serv);
return; break;
/* /*
* Child process. Redirect child stdin/stdout to * Child process. Redirect child stdin/stdout to the parent-child
* the parent-child connection and run the requested * connection and run the requested command. Leave child stderr alone.
* command. Leave child stderr alone. Disable exit * Disable exit handlers: they should be executed by the parent only.
* handlers: they should be executed by the parent only. */
*/
case 0: /* child process */ 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 */ /* NOTREACHED */
exit(1);
/* /*
* Parent. Fill in a process member data structure * Parent. Fill in a process member data structure and set up links
* and set up links between child and process. * between child and process. Say this process has become available.
* Say this process has become available. * If this service has a wakeup timer that is turned on only when the
* If this service has a wakeup timer that is turned * service is actually used, turn on the wakeup timer.
* on only when the service is actually used, */
* turn on the wakeup timer.
*/
default: /* the parent process */ default: /* the parent process */
if (acl_msg_verbose) 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 = (ACL_MASTER_PROC *) acl_mycalloc(1, sizeof(ACL_MASTER_PROC));
proc->serv = serv; proc->serv = serv;
proc->pid = pid; proc->pid = pid;
proc->gen = master_generation; proc->gen = master_generation;
proc->use_count = 0; proc->use_count = 0;
proc->avail = 0; proc->avail = 0;
acl_binhash_enter(acl_var_master_child_table, (char *) &pid, acl_binhash_enter(acl_var_master_child_table,
sizeof(pid), (char *) proc); (char *) &pid, sizeof(pid), (char *) proc);
acl_ring_prepend(&serv->children, &proc->me); acl_ring_prepend(&serv->children, &proc->me);
serv->total_proc++; serv->total_proc++;
acl_master_avail_more(serv, 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; serv->flags &= ~ACL_MASTER_FLAG_CONDWAKE;
acl_master_wakeup_init(serv); acl_master_wakeup_init(serv);
if (acl_msg_verbose) if (acl_msg_verbose)
acl_msg_info("start conditional timer for %s", acl_msg_info("start timer for %s", serv->name);
serv->name);
} }
break; break;
@ -306,11 +300,11 @@ static void master_delete_child(ACL_MASTER_PROC *proc)
void acl_master_reap_child(void) void acl_master_reap_child(void)
{ {
const char *myname = "acl_master_reap_child"; const char *myname = "acl_master_reap_child";
ACL_MASTER_SERV *serv; ACL_MASTER_SERV *serv;
ACL_MASTER_PROC *proc; ACL_MASTER_PROC *proc;
ACL_MASTER_PID pid; ACL_MASTER_PID pid;
ACL_WAIT_STATUS_T status; ACL_WAIT_STATUS_T status;
char buf[256]; char buf[256];
/* /*
* Pick up termination status of all dead children. * 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) { while ((pid = waitpid((pid_t) - 1, &status, WNOHANG)) > 0) {
if (acl_msg_verbose) 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 *) proc = (ACL_MASTER_PROC *) acl_binhash_find(
acl_binhash_find(acl_var_master_child_table, acl_var_master_child_table, &pid, sizeof(pid));
(char *) &pid, sizeof(pid))) == 0) { if (proc == NULL) {
acl_msg_warn("master_reap: unknown pid: %d", pid); acl_msg_warn("master_reap: unknown pid: %d", pid);
continue; continue;
} }
@ -338,12 +332,14 @@ void acl_master_reap_child(void)
serv = proc->serv; serv = proc->serv;
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
acl_msg_warn("%s(%d), %s: process %s pid %d " acl_msg_warn("%s(%d), %s: process %s pid %d "
"exit status %d", __FILE__, __LINE__, "exit status %d", __FILE__, __LINE__,
myname, serv->path, pid, WEXITSTATUS(status)); myname, serv->path, pid, WEXITSTATUS(status));
if (serv->notify_addr != NULL if (serv->notify_addr != NULL
&& serv->notify_recipients != NULL) && serv->notify_recipients != NULL) {
{
snprintf(buf, sizeof(buf), "exit status %d", snprintf(buf, sizeof(buf), "exit status %d",
WEXITSTATUS(status)); WEXITSTATUS(status));
master_warning(serv->notify_addr, master_warning(serv->notify_addr,
@ -353,12 +349,12 @@ void acl_master_reap_child(void)
} }
if (WIFSIGNALED(status)) { if (WIFSIGNALED(status)) {
acl_msg_warn("%s(%d), %s: process %s pid %d killed" acl_msg_warn("%s(%d), %s: process %s pid %d killed"
" by signal %d", __FILE__, __LINE__, myname, " by signal %d", __FILE__, __LINE__, myname,
serv->path, pid, WTERMSIG(status)); 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", snprintf(buf, sizeof(buf), "killed by %d",
WTERMSIG(status)); WTERMSIG(status));
master_warning(serv->notify_addr, master_warning(serv->notify_addr,
@ -419,3 +415,37 @@ void acl_master_delete_all_children(void)
acl_master_ent_free(serv); 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);
}