enhanced the hcl server implementation further while fixing a couple bugs too
This commit is contained in:
parent
3228386c2c
commit
5dcb376907
376
lib/hcl-s.c
376
lib/hcl-s.c
@ -268,6 +268,8 @@ struct hcl_server_t
|
||||
hcl_server_worker_t* tail;
|
||||
} worker_list[2];
|
||||
|
||||
int mux_pipe[2]; /* pipe to break the blocking multiplexer in the main server loop */
|
||||
|
||||
pthread_mutex_t worker_mutex;
|
||||
pthread_mutex_t tmr_mutex;
|
||||
pthread_mutex_t log_mutex;
|
||||
@ -893,11 +895,7 @@ static void vm_cleanup (hcl_t* hcl)
|
||||
static void vm_checkbc (hcl_t* hcl, hcl_oob_t bcode)
|
||||
{
|
||||
worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl);
|
||||
|
||||
if (xtn->proto->worker->server->stopreq) hcl_abort(hcl);
|
||||
|
||||
/* TODO: check how to this vm has been running. too long? abort it */
|
||||
/* check agains xtn->proto->worker->server->cfg.actor_max_runtime */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -906,7 +904,6 @@ static void gc_hcl (hcl_t* hcl)
|
||||
worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl);
|
||||
}
|
||||
|
||||
|
||||
static void fini_hcl (hcl_t* hcl)
|
||||
{
|
||||
worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl);
|
||||
@ -1064,7 +1061,7 @@ static int write_reply_chunk (hcl_server_proto_t* proto)
|
||||
{
|
||||
/* error occurred inside the worker thread shouldn't affect the error information
|
||||
* in the server object. so here, i just log a message */
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "sendmsg failure on %d - %hs\n", proto->worker->sck, strerror(errno));
|
||||
HCL_LOG2 (proto->hcl, SERVER_LOGMASK_ERROR, "sendmsg failure on %d - %hs\n", proto->worker->sck, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1263,7 +1260,7 @@ static HCL_INLINE int add_token_char (hcl_server_proto_t* proto, hcl_ooch_t c)
|
||||
tmp = (hcl_ooch_t*)HCL_MMGR_REALLOC(proto->worker->server->mmgr, proto->tok.ptr, capa * HCL_SIZEOF(*tmp));
|
||||
if (!tmp)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "out of memory in allocating a token buffer\n");
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "out of memory in allocating a token buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1340,7 +1337,7 @@ static int get_token (hcl_server_proto_t* proto)
|
||||
GET_CHAR_TO(proto, c);
|
||||
if (!is_alphachar(c))
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "alphabetic character expected after a period\n");
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "alphabetic character expected after a period\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1357,7 +1354,7 @@ static int get_token (hcl_server_proto_t* proto)
|
||||
break;
|
||||
|
||||
default:
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "unrecognized character - [%jc]\n", c);
|
||||
HCL_LOG1 (proto->hcl, SERVER_LOGMASK_ERROR, "unrecognized character - [%jc]\n", c);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -1365,27 +1362,42 @@ static int get_token (hcl_server_proto_t* proto)
|
||||
|
||||
static void exec_runtime_handler (hcl_tmr_t* tmr, const hcl_ntime_t* now, hcl_tmr_event_t* evt)
|
||||
{
|
||||
/* [NOTE] this handler is executed in the main server thread
|
||||
* when it calls hcl_tmr_fire() */
|
||||
|
||||
hcl_server_proto_t* proto;
|
||||
proto = (hcl_server_proto_t*)evt->ctx;
|
||||
//printf ("aborting hcl for runtime handler timeout...\n");
|
||||
|
||||
HCL_LOG0 (proto->worker->server->dummy_hcl, SERVER_LOGMASK_INFO, "Aborting script execution for max_actor_runtime exceeded\n"); /* TODO: include worker id into the message.. */
|
||||
hcl_abort (proto->hcl);
|
||||
}
|
||||
|
||||
static void exec_runtime_updater (hcl_tmr_t* tmr, hcl_tmr_index_t old_index, hcl_tmr_index_t new_index, hcl_tmr_event_t* evt)
|
||||
{
|
||||
/* [NOTE] this handler is executed in the main server thread
|
||||
* when it calls hcl_tmr_fire() */
|
||||
|
||||
hcl_server_proto_t* proto;
|
||||
proto = (hcl_server_proto_t*)evt->ctx;
|
||||
HCL_ASSERT (proto->hcl, proto->exec_runtime_event_index == old_index);
|
||||
|
||||
/* the event is being removed by hcl_tmr_fire() or by hcl_tmr_delete()
|
||||
* if new_index is HCL_TMR_INVALID_INDEX. it's being updated if not. */
|
||||
proto->exec_runtime_event_index = new_index;
|
||||
}
|
||||
|
||||
static int insert_exec_timer (hcl_server_proto_t* proto, const hcl_ntime_t* tmout)
|
||||
{
|
||||
/* [NOTE] this is executed in the worker thread */
|
||||
|
||||
hcl_tmr_event_t event;
|
||||
hcl_tmr_index_t index;
|
||||
hcl_server_t* server;
|
||||
|
||||
HCL_ASSERT (proto->hcl, proto->exec_runtime_event_index == HCL_TMR_INVALID_INDEX);
|
||||
|
||||
server = proto->worker->server;
|
||||
|
||||
HCL_MEMSET (&event, 0, HCL_SIZEOF(event));
|
||||
event.ctx = proto;
|
||||
proto->hcl->vmprim.vm_gettime (proto->hcl, &event.when);
|
||||
@ -1393,144 +1405,44 @@ static int insert_exec_timer (hcl_server_proto_t* proto, const hcl_ntime_t* tmou
|
||||
event.handler = exec_runtime_handler;
|
||||
event.updater = exec_runtime_updater;
|
||||
|
||||
pthread_mutex_lock (&proto->worker->server->tmr_mutex);
|
||||
index = hcl_tmr_insert(proto->worker->server->tmr, &event);
|
||||
pthread_mutex_unlock (&proto->worker->server->tmr_mutex);
|
||||
if (index == HCL_TMR_INVALID_INDEX) return -1;
|
||||
|
||||
pthread_mutex_lock (&server->tmr_mutex);
|
||||
index = hcl_tmr_insert(server->tmr, &event);
|
||||
proto->exec_runtime_event_index = index;
|
||||
return 0;
|
||||
if (index != HCL_TMR_INVALID_INDEX)
|
||||
{
|
||||
/* inform the server of timer event change */
|
||||
write (server->mux_pipe[1], "X", 1); /* don't care even if it fails */
|
||||
}
|
||||
pthread_mutex_unlock (&server->tmr_mutex);
|
||||
|
||||
return (index == HCL_TMR_INVALID_INDEX)? -1: 0;
|
||||
}
|
||||
|
||||
static void delete_exec_timer (hcl_server_proto_t* proto)
|
||||
{
|
||||
/* [NOTE] this is executed in the worker thread. if the event has been fired
|
||||
* in the server thread, proto->exec_runtime_event_index should be
|
||||
* HCL_TMR_INVALID_INDEX as set by exec_runtime_handler */
|
||||
hcl_server_t* server;
|
||||
|
||||
server = proto->worker->server;
|
||||
|
||||
pthread_mutex_lock (&server->tmr_mutex);
|
||||
if (proto->exec_runtime_event_index != HCL_TMR_INVALID_INDEX)
|
||||
{
|
||||
//printf ("deleted exec timer..........\n");
|
||||
pthread_mutex_lock (&proto->worker->server->tmr_mutex);
|
||||
hcl_tmr_delete (proto->worker->server->tmr, proto->exec_runtime_event_index);
|
||||
pthread_mutex_unlock (&proto->worker->server->tmr_mutex);
|
||||
proto->exec_runtime_event_index = HCL_TMR_INVALID_INDEX;
|
||||
/* the event has not been fired yet. let's delete it
|
||||
* if it has been fired, the index it shall be HCL_TMR_INVALID_INDEX already */
|
||||
|
||||
hcl_tmr_delete (server->tmr, proto->exec_runtime_event_index);
|
||||
HCL_ASSERT (proto->hcl, proto->exec_runtime_event_index == HCL_TMR_INVALID_INDEX);
|
||||
/*proto->exec_runtime_event_index = HCL_TMR_INVALID_INDEX; */
|
||||
}
|
||||
pthread_mutex_unlock (&server->tmr_mutex);
|
||||
}
|
||||
|
||||
int hcl_server_proto_handle_request (hcl_server_proto_t* proto)
|
||||
static int execute_script (hcl_server_proto_t* proto, const hcl_bch_t* trigger)
|
||||
{
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
|
||||
switch (proto->tok.type)
|
||||
{
|
||||
case HCL_SERVER_PROTO_TOKEN_NL:
|
||||
/* ignore new lines */
|
||||
break;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_EOF:
|
||||
if (proto->req.state != HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "unexpected EOF without .END\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* drop connection silently */
|
||||
return 0;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_EXIT:
|
||||
if (proto->req.state != HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, ".EXIT allowed in the top level only\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
if (proto->tok.type != HCL_SERVER_PROTO_TOKEN_NL)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "no new line after .EXIT\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
hcl_server_proto_start_reply (proto);
|
||||
if (hcl_server_proto_end_reply(proto, HCL_NULL) <= -1)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "cannot finalize reply for .EXIT\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_BEGIN:
|
||||
if (proto->req.state != HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, ".BEGIN not allowed to be nested\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
if (proto->tok.type != HCL_SERVER_PROTO_TOKEN_NL)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "no new line after .BEGIN\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
proto->req.state = HCL_SERVER_PROTO_REQ_IN_BLOCK_LEVEL;
|
||||
hcl_reset (proto->hcl);
|
||||
break;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_END:
|
||||
{
|
||||
hcl_oop_t obj;
|
||||
|
||||
if (proto->req.state != HCL_SERVER_PROTO_REQ_IN_BLOCK_LEVEL)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, ".END without opening .BEGIN\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
if (proto->tok.type != HCL_SERVER_PROTO_TOKEN_NL)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "no new line after .BEGIN\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
hcl_server_proto_start_reply (proto);
|
||||
obj = (hcl_getbclen(proto->hcl) > 0)? hcl_execute(proto->hcl): proto->hcl->_nil;
|
||||
if (hcl_server_proto_end_reply(proto, (obj? HCL_NULL: hcl_geterrmsg(proto->hcl))) <= -1)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "cannot finalize reply for .END\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
proto->req.state = HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL;
|
||||
break;
|
||||
}
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_SCRIPT:
|
||||
{
|
||||
hcl_oop_t obj;
|
||||
|
||||
if (proto->req.state == HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL) hcl_reset(proto->hcl);
|
||||
|
||||
obj = hcl_read(proto->hcl);
|
||||
if (!obj)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "cannot read .SCRIPT contents - %js\n", hcl_geterrmsg(proto->hcl));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
if (proto->tok.type != HCL_SERVER_PROTO_TOKEN_NL)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "no new line after .SCRIPT contest\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hcl_compile(proto->hcl, obj) <= -1)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "cannot compile .SCRIPT contents - %js\n", hcl_geterrmsg(proto->hcl));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (proto->req.state == HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL)
|
||||
{
|
||||
const hcl_ooch_t* failmsg = HCL_NULL;
|
||||
hcl_server_t* server;
|
||||
|
||||
@ -1546,29 +1458,136 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto)
|
||||
{
|
||||
if (insert_exec_timer(proto, &server->cfg.actor_max_runtime) <= -1)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "cannot start execution timer\n");
|
||||
/* use proto->hcl's error formatting instead of server's to avoid using mutex over the shared server->dummy_hcl */
|
||||
hcl_seterrbfmt (proto->hcl, HCL_ESYSMEM, "cannot start execution timer");
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "Cannot start execution timer\n");
|
||||
hcl_seterrbfmt (proto->hcl, HCL_ESYSMEM, "cannot start execution timer"); /* i do this just to compose the error message */
|
||||
failmsg = hcl_geterrmsg(proto->hcl);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf ("inserted exec timer..........\n");
|
||||
obj = hcl_execute(proto->hcl);
|
||||
if (!obj) failmsg = hcl_geterrmsg(proto->hcl);
|
||||
|
||||
delete_exec_timer (proto);
|
||||
}
|
||||
}
|
||||
|
||||
if (hcl_server_proto_end_reply(proto, failmsg) <= -1)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "cannot finalize reply for .SCRIPT\n");
|
||||
HCL_LOG1 (proto->hcl, SERVER_LOGMASK_ERROR, "Cannot finalize reply for %hs\n", trigger);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hcl_server_proto_handle_request (hcl_server_proto_t* proto)
|
||||
{
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
|
||||
switch (proto->tok.type)
|
||||
{
|
||||
case HCL_SERVER_PROTO_TOKEN_NL:
|
||||
/* ignore new lines */
|
||||
break;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_EOF:
|
||||
if (proto->req.state != HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "Unexpected EOF without .END\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* drop connection silently */
|
||||
return 0;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_EXIT:
|
||||
if (proto->req.state != HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, ".EXIT allowed in the top level only\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
if (proto->tok.type != HCL_SERVER_PROTO_TOKEN_NL)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "No new line after .EXIT\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
hcl_server_proto_start_reply (proto);
|
||||
if (hcl_server_proto_end_reply(proto, HCL_NULL) <= -1)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "Unable to finalize reply for .EXIT\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_BEGIN:
|
||||
if (proto->req.state != HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, ".BEGIN not allowed to be nested\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
if (proto->tok.type != HCL_SERVER_PROTO_TOKEN_NL)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "No new line after .BEGIN\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
proto->req.state = HCL_SERVER_PROTO_REQ_IN_BLOCK_LEVEL;
|
||||
hcl_reset (proto->hcl);
|
||||
break;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_END:
|
||||
if (proto->req.state != HCL_SERVER_PROTO_REQ_IN_BLOCK_LEVEL)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, ".END without opening .BEGIN\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
if (proto->tok.type != HCL_SERVER_PROTO_TOKEN_NL)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "No new line after .BEGIN\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (execute_script(proto, ".END") <= -1) return -1;
|
||||
proto->req.state = HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL;
|
||||
break;
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_SCRIPT:
|
||||
{
|
||||
hcl_oop_t obj;
|
||||
|
||||
if (proto->req.state == HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL) hcl_reset(proto->hcl);
|
||||
|
||||
obj = hcl_read(proto->hcl);
|
||||
if (!obj)
|
||||
{
|
||||
HCL_LOG1 (proto->hcl, SERVER_LOGMASK_ERROR, "Unable to read .SCRIPT contents - %js\n", hcl_geterrmsg(proto->hcl));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_token(proto) <= -1) return -1;
|
||||
if (proto->tok.type != HCL_SERVER_PROTO_TOKEN_NL)
|
||||
{
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "No new line after .SCRIPT contest\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hcl_compile(proto->hcl, obj) <= -1)
|
||||
{
|
||||
HCL_LOG1 (proto->hcl, SERVER_LOGMASK_ERROR, "Unable to compile .SCRIPT contents - %js\n", hcl_geterrmsg(proto->hcl));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (proto->req.state == HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL)
|
||||
{
|
||||
if (execute_script(proto, ".SCRIPT") <= -1) return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case HCL_SERVER_PROTO_TOKEN_SHOW_WORKERS:
|
||||
@ -1580,7 +1599,7 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto)
|
||||
|
||||
if (hcl_server_proto_end_reply(proto, HCL_NULL) <= -1)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "cannot finalize reply for .SHOW-WORKERS\n");
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "Unable to finalize reply for .SHOW-WORKERS\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1595,13 +1614,13 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto)
|
||||
|
||||
if (hcl_server_proto_end_reply(proto, HCL_NULL) <= -1)
|
||||
{
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "cannot finalize reply for .KILL-WORKER\n");
|
||||
HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "Unable to finalize reply for .KILL-WORKER\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
hcl_logbfmt (proto->hcl, SERVER_LOGMASK_ERROR, "unknown token - %d - %.*js\n", (int)proto->tok.type, proto->tok.len, proto->tok.ptr);
|
||||
HCL_LOG3 (proto->hcl, SERVER_LOGMASK_ERROR, "Unknown token - %d - %.*js\n", (int)proto->tok.type, proto->tok.len, proto->tok.ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1617,6 +1636,7 @@ hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_p
|
||||
hcl_vmprim_t vmprim;
|
||||
hcl_tmr_t* tmr;
|
||||
dummy_hcl_xtn_t* xtn;
|
||||
int pfd[2], fcv;
|
||||
|
||||
server = (hcl_server_t*)HCL_MMGR_ALLOC(mmgr, HCL_SIZEOF(*server) + xtnsize);
|
||||
if (!server)
|
||||
@ -1646,8 +1666,30 @@ hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_p
|
||||
{
|
||||
hcl_close (hcl);
|
||||
HCL_MMGR_FREE (mmgr, server);
|
||||
return HCL_NULL;
|
||||
}
|
||||
|
||||
if (pipe(pfd) <= -1)
|
||||
{
|
||||
hcl_tmr_close (tmr);
|
||||
hcl_close (hcl);
|
||||
HCL_MMGR_FREE (mmgr, server);
|
||||
return HCL_NULL;
|
||||
}
|
||||
|
||||
#if defined(O_CLOEXEC)
|
||||
fcv = fcntl(pfd[0], F_GETFD, 0);
|
||||
if (fcv >= 0) fcntl(pfd[0], F_SETFD, fcv | O_CLOEXEC);
|
||||
fcv = fcntl(pfd[1], F_GETFD, 0);
|
||||
if (fcv >= 0) fcntl(pfd[1], F_SETFD, fcv | O_CLOEXEC);
|
||||
#endif
|
||||
#if defined(O_NONBLOCK)
|
||||
fcv = fcntl(pfd[0], F_GETFL, 0);
|
||||
if (fcv >= 0) fcntl(pfd[0], F_SETFL, fcv | O_NONBLOCK);
|
||||
fcv = fcntl(pfd[1], F_GETFL, 0);
|
||||
if (fcv >= 0) fcntl(pfd[1], F_SETFL, fcv | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
xtn = (dummy_hcl_xtn_t*)hcl_getxtn(hcl);
|
||||
xtn->server = server;
|
||||
|
||||
@ -1665,6 +1707,9 @@ hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_p
|
||||
HCL_INITNTIME (&server->cfg.worker_idle_timeout, 0, 0);
|
||||
HCL_INITNTIME (&server->cfg.actor_max_runtime, 0, 0);
|
||||
|
||||
server->mux_pipe[0] = pfd[0];
|
||||
server->mux_pipe[1] = pfd[1];
|
||||
|
||||
pthread_mutex_init (&server->worker_mutex, HCL_NULL);
|
||||
pthread_mutex_init (&server->tmr_mutex, HCL_NULL);
|
||||
pthread_mutex_init (&server->log_mutex, HCL_NULL);
|
||||
@ -1678,6 +1723,8 @@ void hcl_server_close (hcl_server_t* server)
|
||||
pthread_mutex_destroy (&server->tmr_mutex);
|
||||
pthread_mutex_destroy (&server->worker_mutex);
|
||||
|
||||
close (server->mux_pipe[0]);
|
||||
close (server->mux_pipe[1]);
|
||||
hcl_tmr_close (server->tmr);
|
||||
hcl_close (server->dummy_hcl);
|
||||
HCL_MMGR_FREE (server->mmgr, server);
|
||||
@ -1702,11 +1749,11 @@ static void close_worker_socket (hcl_server_worker_t* worker)
|
||||
{
|
||||
if (worker->proto)
|
||||
{
|
||||
hcl_logbfmt (worker->proto->hcl, SERVER_LOGMASK_INFO, "closing worker socket %d\n", worker->sck);
|
||||
HCL_LOG1 (worker->proto->hcl, SERVER_LOGMASK_INFO, "Closing worker socket %d\n", worker->sck);
|
||||
}
|
||||
else
|
||||
{
|
||||
hcl_server_logbfmt (worker->server, SERVER_LOGMASK_INFO, "closing worker socket %d\n", worker->sck);
|
||||
HCL_LOG1 (worker->server->dummy_hcl, SERVER_LOGMASK_INFO, "Closing worker socket %d\n", worker->sck);
|
||||
}
|
||||
close (worker->sck);
|
||||
worker->sck = -1;
|
||||
@ -1948,19 +1995,24 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs)
|
||||
pthread_t thr;
|
||||
hcl_ntime_t tmout;
|
||||
hcl_server_worker_t* worker;
|
||||
struct pollfd pfd[1];
|
||||
int n;
|
||||
struct pollfd pfd[2];
|
||||
int n, pc;
|
||||
|
||||
purge_all_workers (server, HCL_SERVER_WORKER_STATE_DEAD);
|
||||
|
||||
pthread_mutex_lock (&server->tmr_mutex);
|
||||
n = hcl_tmr_gettmout(server->tmr, HCL_NULL, &tmout);
|
||||
pthread_mutex_unlock (&server->tmr_mutex);
|
||||
if (n <= -1) HCL_INITNTIME (&tmout, 1, 0);
|
||||
if (n <= -1) HCL_INITNTIME (&tmout, 10, 0);
|
||||
|
||||
pfd[0].fd = srv_fd;
|
||||
pfd[0].events = POLLIN | POLLERR;
|
||||
n = poll(pfd, 1, HCL_SECNSEC_TO_MSEC(tmout.sec, tmout.nsec));
|
||||
/* TODO: swtich to faster multiplexer like epoll or kqueue */
|
||||
pc = 0;
|
||||
pfd[pc].fd = server->mux_pipe[0];
|
||||
pfd[pc++].events = POLLIN | POLLERR;
|
||||
pfd[pc].fd = srv_fd;
|
||||
pfd[pc++].events = POLLIN | POLLERR;
|
||||
|
||||
n = poll(pfd, pc, HCL_SECNSEC_TO_MSEC(tmout.sec, tmout.nsec));
|
||||
if (n <= -1)
|
||||
{
|
||||
if (server->stopreq) break; /* normal termination requested */
|
||||
@ -1975,11 +2027,16 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs)
|
||||
hcl_tmr_fire (server->tmr, HCL_NULL, HCL_NULL);
|
||||
pthread_mutex_unlock (&server->tmr_mutex);
|
||||
|
||||
while (n > 0)
|
||||
for (n = 0; n < pc; n++)
|
||||
{
|
||||
--n;
|
||||
if (!pfd[n].revents /*& (POLLIN | POLLHUP | POLLERR) */) continue;
|
||||
|
||||
if (pfd[n].revents /*& (POLLIN | POLLHUP | POLLERR) */)
|
||||
if (pfd[n].fd == server->mux_pipe[0])
|
||||
{
|
||||
char tmp[128];
|
||||
while (read(server->mux_pipe[0], tmp, HCL_SIZEOF(tmp)) > 0) /* nothing */;
|
||||
}
|
||||
else if (pfd[n].fd == srv_fd)
|
||||
{
|
||||
cli_len = HCL_SIZEOF(cli_addr);
|
||||
cli_fd = accept(pfd[n].fd, (struct sockaddr*)&cli_addr, &cli_len);
|
||||
@ -1993,7 +2050,7 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs)
|
||||
break;
|
||||
}
|
||||
|
||||
hcl_server_logbfmt (server, SERVER_LOGMASK_INFO, "accepted worker - socket %d\n", cli_fd);
|
||||
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_INFO, "Accepted worker - socket %d\n", cli_fd);
|
||||
|
||||
worker = alloc_worker(server, cli_fd);
|
||||
if (pthread_create(&thr, &thr_attr, worker_main, worker) != 0)
|
||||
@ -2008,12 +2065,15 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs)
|
||||
purge_all_workers (server, HCL_SERVER_WORKER_STATE_DEAD);
|
||||
|
||||
pthread_attr_destroy (&thr_attr);
|
||||
|
||||
close (srv_fd);
|
||||
return xret;
|
||||
}
|
||||
|
||||
void hcl_server_stop (hcl_server_t* server)
|
||||
{
|
||||
server->stopreq = 1;
|
||||
write (server->mux_pipe[1], "Q", 1); /* don't care about failure */
|
||||
}
|
||||
|
||||
int hcl_server_setoption (hcl_server_t* server, hcl_server_option_t id, const void* value)
|
||||
|
42
lib/main2.c
42
lib/main2.c
@ -402,7 +402,8 @@ static int handle_dbgopt (hcl_server_t* server, const char* str)
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#define MIN_MEMSIZE 512000ul
|
||||
#define MIN_WORKER_STACK_SIZE 512000ul
|
||||
#define MIN_ACTOR_HEAP_SIZE 512000ul
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
@ -410,8 +411,11 @@ int main (int argc, char* argv[])
|
||||
static hcl_bopt_lng_t lopt[] =
|
||||
{
|
||||
{ ":log", 'l' },
|
||||
{ ":memsize", 'm' },
|
||||
{ "large-pages", '\0' },
|
||||
{ ":worker-stack-size", '\0' },
|
||||
{ ":worker-idle-timeout",'\0' },
|
||||
{ ":actor-heap-size", 'm' },
|
||||
{ ":actor-max-runtime", '\0' },
|
||||
#if defined(HCL_BUILD_DEBUG)
|
||||
{ ":debug", '\0' }, /* NOTE: there is no short option for --debug */
|
||||
#endif
|
||||
@ -430,8 +434,10 @@ int main (int argc, char* argv[])
|
||||
|
||||
const char* logopt = HCL_NULL;
|
||||
const char* dbgopt = HCL_NULL;
|
||||
hcl_oow_t memsize = MIN_MEMSIZE;
|
||||
hcl_ntime_t tmout = { 0, 0 };
|
||||
hcl_oow_t worker_stack_size = MIN_ACTOR_HEAP_SIZE;
|
||||
hcl_ntime_t worker_idle_timeout = { 0, 0 };
|
||||
hcl_oow_t actor_heap_size = MIN_ACTOR_HEAP_SIZE;
|
||||
hcl_ntime_t actor_max_runtime = { 0, 0 };
|
||||
int large_pages = 0;
|
||||
unsigned int trait;
|
||||
|
||||
@ -453,8 +459,8 @@ int main (int argc, char* argv[])
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
memsize = strtoul(opt.arg, HCL_NULL, 0);
|
||||
if (memsize <= MIN_MEMSIZE) memsize = MIN_MEMSIZE;
|
||||
actor_heap_size = strtoul(opt.arg, HCL_NULL, 0);
|
||||
if (actor_heap_size <= MIN_ACTOR_HEAP_SIZE) actor_heap_size = MIN_ACTOR_HEAP_SIZE;
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
@ -463,6 +469,21 @@ int main (int argc, char* argv[])
|
||||
large_pages = 1;
|
||||
break;
|
||||
}
|
||||
else if (hcl_compbcstr(opt.lngopt, "worker-stack-size") == 0)
|
||||
{
|
||||
worker_stack_size = strtoul(opt.arg, HCL_NULL, 0);
|
||||
if (worker_stack_size <= MIN_WORKER_STACK_SIZE) actor_heap_size = MIN_WORKER_STACK_SIZE;
|
||||
}
|
||||
else if (hcl_compbcstr(opt.lngopt, "worker-idle-timeout") == 0)
|
||||
{
|
||||
worker_idle_timeout.sec = strtoul(opt.arg, HCL_NULL, 0);
|
||||
break;
|
||||
}
|
||||
else if (hcl_compbcstr(opt.lngopt, "actor-max-runtime") == 0)
|
||||
{
|
||||
actor_max_runtime.sec = strtoul(opt.arg, HCL_NULL, 0);
|
||||
break;
|
||||
}
|
||||
#if defined(HCL_BUILD_DEBUG)
|
||||
else if (hcl_compbcstr(opt.lngopt, "debug") == 0)
|
||||
{
|
||||
@ -521,11 +542,10 @@ int main (int argc, char* argv[])
|
||||
else trait &= ~HCL_SERVER_TRAIT_USE_LARGE_PAGES;
|
||||
hcl_server_setoption (server, HCL_SERVER_TRAIT, &trait);
|
||||
|
||||
/*hcl_server_setoption (server, HCL_SERVER_WORKER_STACK_SIZE, ???);*/
|
||||
hcl_server_setoption (server, HCL_SERVER_ACTOR_HEAP_SIZE, &memsize);
|
||||
|
||||
HCL_INITNTIME (&tmout, 5, 0);
|
||||
hcl_server_setoption (server, HCL_SERVER_ACTOR_MAX_RUNTIME, &tmout);
|
||||
hcl_server_setoption (server, HCL_SERVER_WORKER_STACK_SIZE, &worker_stack_size);
|
||||
hcl_server_setoption (server, HCL_SERVER_WORKER_IDLE_TIMEOUT, &worker_idle_timeout);
|
||||
hcl_server_setoption (server, HCL_SERVER_ACTOR_HEAP_SIZE, &actor_heap_size);
|
||||
hcl_server_setoption (server, HCL_SERVER_ACTOR_MAX_RUNTIME, &actor_max_runtime);
|
||||
|
||||
g_server = server;
|
||||
set_signal (SIGINT, handle_sigint);
|
||||
|
Loading…
Reference in New Issue
Block a user