From 39749ab84721440d7db8745527fbc0845c8806f6 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 14 Mar 2018 10:14:38 +0000 Subject: [PATCH] put the hcl server code into a library --- lib/hcl-prv.h | 1 - lib/hcl-s.c | 484 +++++++++++++++++++++----------------------------- lib/hcl-s.h | 81 ++++++--- lib/hcl.h | 66 +++++-- lib/logfmt.c | 35 +++- lib/main.c | 2 +- lib/main2.c | 247 +++++++++++++++++++++++--- 7 files changed, 561 insertions(+), 355 deletions(-) diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index f9233eb..594bb61 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -648,7 +648,6 @@ typedef hcl_ooi_t (*hcl_outbfmt_t) ( ... ); - /* i don't want an error raised inside the callback to override * the existing error number and message. */ #define vmprim_log_write(hcl,mask,ptr,len) do { \ diff --git a/lib/hcl-s.c b/lib/hcl-s.c index fe6cfbc..ebef423 100644 --- a/lib/hcl-s.c +++ b/lib/hcl-s.c @@ -146,17 +146,20 @@ struct bb_t hcl_bch_t* fn; }; -typedef struct xtn_t xtn_t; -struct xtn_t +typedef struct worker_hcl_xtn_t worker_hcl_xtn_t; +struct worker_hcl_xtn_t { hcl_server_proto_t* proto; int vm_running; - - int logfd; - unsigned int logmask; - int logfd_istty; }; +typedef struct dummy_hcl_xtn_t dummy_hcl_xtn_t; +struct dummy_hcl_xtn_t +{ + hcl_server_t* server; +}; + + enum hcl_server_proto_token_type_t { HCL_SERVER_PROTO_TOKEN_EOF, @@ -173,7 +176,6 @@ enum hcl_server_proto_token_type_t HCL_SERVER_PROTO_TOKEN_IDENT }; - typedef enum hcl_server_proto_token_type_t hcl_server_proto_token_type_t; typedef struct hcl_server_proto_token_t hcl_server_proto_token_t; @@ -251,22 +253,25 @@ struct hcl_server_t { hcl_mmgr_t* mmgr; hcl_cmgr_t* cmgr; + hcl_server_prim_t prim; + hcl_t* dummy_hcl; hcl_errnum_t errnum; - + struct + { + union + { + hcl_ooch_t ooch[2048]; + hcl_bch_t bch[2048]; + hcl_uch_t uch[2048]; + } tmpbuf; + hcl_ooch_t buf[2048]; + hcl_oow_t len; + } errmsg; int stopreq; - int logfd; - int logfd_istty; - struct { - hcl_oow_t memsize; /* hcl heap memory size */ - unsigned int dbgopt; - - unsigned int idle_timeout; /* idle timeout */ - - unsigned int trait; unsigned int logmask; hcl_oow_t worker_stack_size; @@ -288,31 +293,6 @@ int hcl_server_proto_feed_reply (hcl_server_proto_t* proto, const hcl_ooch_t* pt /* ========================================================================= */ -static void* sys_alloc (hcl_mmgr_t* mmgr, hcl_oow_t size) -{ - return malloc(size); -} - -static void* sys_realloc (hcl_mmgr_t* mmgr, void* ptr, hcl_oow_t size) -{ - return realloc(ptr, size); -} - -static void sys_free (hcl_mmgr_t* mmgr, void* ptr) -{ - free (ptr); -} - -static hcl_mmgr_t sys_mmgr = -{ - sys_alloc, - sys_realloc, - sys_free, - HCL_NULL -}; - -/* ========================================================================= */ - #if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) # define IS_PATH_SEP(c) ((c) == '/' || (c) == '\\') @@ -334,7 +314,7 @@ static const hcl_bch_t* get_base_name (const hcl_bch_t* path) static HCL_INLINE int open_input (hcl_t* hcl, hcl_ioinarg_t* arg) { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl); bb_t* bb = HCL_NULL; /* TOOD: support predefined include directory as well */ @@ -400,7 +380,7 @@ oops: static HCL_INLINE int close_input (hcl_t* hcl, hcl_ioinarg_t* arg) { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl); bb_t* bb; bb = (bb_t*)arg->handle; @@ -416,7 +396,7 @@ static HCL_INLINE int close_input (hcl_t* hcl, hcl_ioinarg_t* arg) static HCL_INLINE int read_input (hcl_t* hcl, hcl_ioinarg_t* arg) { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl); bb_t* bb; hcl_oow_t bcslen, ucslen, remlen; int x; @@ -530,7 +510,7 @@ static int print_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) case HCL_IO_WRITE: { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl); hcl_iooutarg_t* outarg = (hcl_iooutarg_t*)arg; if (hcl_server_proto_feed_reply(xtn->proto, outarg->ptr, outarg->len, 0) <= -1) @@ -615,168 +595,26 @@ static void free_heap (hcl_t* hcl, void* ptr) #endif } -static int write_all (int fd, const char* ptr, hcl_oow_t len) +static void log_write (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) { - while (len > 0) - { - hcl_ooi_t wr; + worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl); + hcl_server_t* server; - wr = write (fd, ptr, len); - - if (wr <= -1) - { - #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK) - if (errno == EAGAIN) continue; - #else - # if defined(EAGAIN) - if (errno == EAGAIN) continue; - #elif defined(EWOULDBLOCK) - if (errno == EWOULDBLOCK) continue; - #endif - #endif - - #if defined(EINTR) - /* TODO: would this interfere with non-blocking nature of this VM? */ - if (errno == EINTR) continue; - #endif - return -1; - } - - ptr += wr; - len -= wr; - } - - return 0; + server = xtn->proto->worker->server; + pthread_mutex_lock (&server->log_mutex); + server->prim.log_write (server, xtn->proto->worker->sck, mask, msg, len); + pthread_mutex_unlock (&server->log_mutex); } -static void __log_write (hcl_server_t* server, int mask, const void* vmsg, hcl_oow_t len, int force_bch) +static void log_write_for_dummy (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) { - hcl_bch_t buf[256]; - hcl_oow_t ucslen, bcslen; - int n; + dummy_hcl_xtn_t* xtn = (dummy_hcl_xtn_t*)hcl_getxtn(hcl); + hcl_server_t* server; - int logfd; - - if (mask & HCL_LOG_STDERR) - { - /* the messages that go to STDERR don't get masked out */ - logfd = 2; - } - else - { - if (!(server->cfg.logmask & mask & ~HCL_LOG_ALL_LEVELS)) return; /* check log types */ - if (!(server->cfg.logmask & mask & ~HCL_LOG_ALL_TYPES)) return; /* check log levels */ - - if (mask & HCL_LOG_STDOUT) logfd = 1; - else - { - logfd = server->logfd; - if (logfd <= -1) return; - } - } - -/* TODO: beautify the log message. - * do classification based on mask. */ - if (!(mask & (HCL_LOG_STDOUT | HCL_LOG_STDERR))) - { - time_t now; - char ts[32]; - size_t tslen; - struct tm tm, *tmp; - - now = time(NULL); - - tmp = localtime_r (&now, &tm); - #if defined(HAVE_STRFTIME_SMALL_Z) - tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); - #else - tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp); - #endif - if (tslen == 0) - { - strcpy (ts, "0000-00-00 00:00:00 +0000"); - tslen = 25; - } - -/* TODO: less write system calls by having a buffer */ - write_all (logfd, ts, tslen); - -/* - * TODO: print IDs - //tslen = snprintf (ts, sizeof(ts), "[%d] ", xtn->proto->worker->sck); - //write_all (logfd, ts, tslen); -*/ - } - - if (server->logfd_istty) - { - if (mask & HCL_LOG_FATAL) write_all (logfd, "\x1B[1;31m", 7); - else if (mask & HCL_LOG_ERROR) write_all (logfd, "\x1B[1;32m", 7); - else if (mask & HCL_LOG_WARN) write_all (logfd, "\x1B[1;33m", 7); - } - -#if defined(HCL_OOCH_IS_UCH) - if (force_bch) - { - const hcl_bch_t* msg = (const hcl_bch_t*)vmsg; - write_all (logfd, msg, len); - } - else - { - hcl_oow_t msgidx; - const hcl_ooch_t* msg = (const hcl_ooch_t*)vmsg; - - msgidx = 0; - while (len > 0) - { - ucslen = len; - bcslen = HCL_COUNTOF(buf); - - n = hcl_conv_oocsn_to_bcsn_with_cmgr(&msg[msgidx], &ucslen, buf, &bcslen, hcl_get_utf8_cmgr()); - if (n == 0 || n == -2) - { - /* n = 0: - * converted all successfully - * n == -2: - * buffer not sufficient. not all got converted yet. - * write what have been converted this round. */ - - /*HCL_ASSERT (hcl, ucslen > 0); */ /* if this fails, the buffer size must be increased */ - assert (ucslen > 0); - - /* attempt to write all converted characters */ - if (write_all(logfd, buf, bcslen) <= -1) break; - - if (n == 0) break; - else - { - msgidx += ucslen; - len -= ucslen; - } - } - else if (n <= -1) - { - /* conversion error */ - break; - } - } - } -#else - write_all (logfd, vmsg, len); -#endif - - if (server->logfd_istty) - { - if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_all (logfd, "\x1B[0m", 4); - } -} - -static void log_write (hcl_t* hcl, int mask, const hcl_ooch_t* msg, hcl_oow_t len) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - pthread_mutex_lock (&xtn->proto->worker->server->log_mutex); - __log_write (xtn->proto->worker->server, mask, msg, len, 0); - pthread_mutex_unlock (&xtn->proto->worker->server->log_mutex); + server = xtn->server; + pthread_mutex_lock (&server->log_mutex); + server->prim.log_write (server, -1, mask, msg, len); + pthread_mutex_unlock (&server->log_mutex); } static void syserrstrb (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len) @@ -1057,20 +895,20 @@ static void vm_sleep (hcl_t* hcl, const hcl_ntime_t* dur) static int vm_startup (hcl_t* hcl) { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl); xtn->vm_running = 1; return 0; } static void vm_cleanup (hcl_t* hcl) { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl); xtn->vm_running = 0; } static void vm_checkbc (hcl_t* hcl, hcl_oob_t bcode) { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + 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 */ @@ -1082,11 +920,11 @@ static void vm_checkbc (hcl_t* hcl, hcl_oob_t bcode) static void gc_hcl (hcl_t* hcl) { } -*/ + static void fini_hcl (hcl_t* hcl) { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl); if (xtn->logfd >= 0) { close (xtn->logfd); @@ -1094,7 +932,7 @@ static void fini_hcl (hcl_t* hcl) xtn->logfd_istty = 0; } } - +*/ /* ========================================================================= */ #define HCL_SERVER_PROTO_LOG_MASK (HCL_LOG_ERROR | HCL_LOG_APP) @@ -1104,7 +942,7 @@ hcl_server_proto_t* hcl_server_proto_open (hcl_oow_t xtnsize, hcl_server_worker_ hcl_server_proto_t* proto; hcl_vmprim_t vmprim; hcl_cb_t hclcb; - xtn_t* xtn; + worker_hcl_xtn_t* xtn; unsigned int trait; HCL_MEMSET (&vmprim, 0, HCL_SIZEOF(vmprim)); @@ -1121,29 +959,31 @@ hcl_server_proto_t* hcl_server_proto_open (hcl_oow_t xtnsize, hcl_server_worker_ vmprim.vm_gettime = vm_gettime; vmprim.vm_sleep = vm_sleep; - proto = (hcl_server_proto_t*)malloc(sizeof(*proto)); - if (!proto) return NULL; + proto = (hcl_server_proto_t*)HCL_MMGR_ALLOC(worker->server->mmgr, HCL_SIZEOF(*proto)); + if (!proto) return HCL_NULL; - HCL_MEMSET (proto, 0, sizeof(*proto)); + HCL_MEMSET (proto, 0, HCL_SIZEOF(*proto)); proto->worker = worker; - proto->hcl = hcl_open(&sys_mmgr, HCL_SIZEOF(xtn_t), worker->server->cfg.actor_heap_size, &vmprim, HCL_NULL); - if (!proto->hcl) goto oops; + proto->hcl = hcl_open(proto->worker->server->mmgr, HCL_SIZEOF(*xtn), worker->server->cfg.actor_heap_size, &vmprim, HCL_NULL); + if (!proto->hcl) goto oops; - xtn = (xtn_t*)hcl_getxtn(proto->hcl); - xtn->logfd = -1; - xtn->logfd_istty = 0; + xtn = (worker_hcl_xtn_t*)hcl_getxtn(proto->hcl); xtn->proto = proto; - hcl_setcmgr (proto->hcl, hcl_get_utf8_cmgr()); + hcl_setoption (proto->hcl, HCL_LOG_MASK, &proto->worker->server->cfg.logmask); + hcl_setcmgr (proto->hcl, proto->worker->server->cmgr); hcl_getoption (proto->hcl, HCL_TRAIT, &trait); - trait |= proto->worker->server->cfg.dbgopt; +#if defined(HCL_BUILD_DEBUG) + if (proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_DEBUG_GC) trait |= HCL_DEBUG_GC; + if (proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_DEBUG_BIGINT) trait |= HCL_DEBUG_BIGINT; +#endif hcl_setoption (proto->hcl, HCL_TRAIT, &trait); HCL_MEMSET (&hclcb, 0, HCL_SIZEOF(hclcb)); - hclcb.fini = fini_hcl; - /*hclcb.gc = gc_hcl;*/ + /*hclcb.fini = fini_hcl; + hclcb.gc = gc_hcl;*/ hclcb.vm_startup = vm_startup; hclcb.vm_cleanup = vm_cleanup; hclcb.vm_checkbc = vm_checkbc; @@ -1159,16 +999,16 @@ oops: if (proto) { if (proto->hcl) hcl_close (proto->hcl); - free (proto); + HCL_MMGR_FREE (proto->worker->server->mmgr, proto); } - return NULL; + return HCL_NULL; } void hcl_server_proto_close (hcl_server_proto_t* proto) { - if (proto->tok.ptr) free (proto->tok.ptr); + if (proto->tok.ptr) HCL_MMGR_FREE (proto->worker->server->mmgr, proto->tok.ptr); hcl_close (proto->hcl); - free (proto); + HCL_MMGR_FREE (proto->worker->server->mmgr, proto); } static int write_reply_chunk (hcl_server_proto_t* proto) @@ -1188,7 +1028,7 @@ static int write_reply_chunk (hcl_server_proto_t* proto) } iov[count].iov_base = cl, - iov[count++].iov_len = snprintf(cl, sizeof(cl), "%s%zu:", (((proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_READABLE_PROTO) && proto->reply.nchunks > 0)? "\n": ""), proto->reply.len); + iov[count++].iov_len = snprintf(cl, HCL_SIZEOF(cl), "%s%zu:", (((proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_READABLE_PROTO) && proto->reply.nchunks > 0)? "\n": ""), proto->reply.len); } iov[count].iov_base = proto->reply.buf; iov[count++].iov_len = proto->reply.len; @@ -1197,7 +1037,7 @@ static int write_reply_chunk (hcl_server_proto_t* proto) { ssize_t nwritten; - HCL_MEMSET (&msg, 0, sizeof(msg)); + HCL_MEMSET (&msg, 0, HCL_SIZEOF(msg)); msg.msg_iov = (struct iovec*)&iov[index]; msg.msg_iovlen = count - index; nwritten = sendmsg(proto->worker->sck, &msg, 0); @@ -1400,7 +1240,7 @@ static HCL_INLINE int add_token_char (hcl_server_proto_t* proto, hcl_ooch_t c) hcl_oow_t capa; capa = HCL_ALIGN_POW2(proto->tok.len + 1, 64); - tmp = (hcl_ooch_t*)realloc(proto->tok.ptr, capa * sizeof(*tmp)); + tmp = (hcl_ooch_t*)HCL_MMGR_REALLOC(proto->worker->server->mmgr, proto->tok.ptr, capa * HCL_SIZEOF(*tmp)); if (!tmp) { hcl_logbfmt (proto->hcl, HCL_SERVER_PROTO_LOG_MASK, "out of memory in allocating a token buffer\n"); @@ -1538,7 +1378,7 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto) } hcl_server_proto_start_reply (proto); - if (hcl_server_proto_end_reply(proto, NULL) <= -1) + if (hcl_server_proto_end_reply(proto, HCL_NULL) <= -1) { hcl_logbfmt (proto->hcl, HCL_SERVER_PROTO_LOG_MASK, "cannot finalize reply for .EXIT\n"); return -1; @@ -1582,7 +1422,7 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto) 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? NULL: hcl_geterrmsg(proto->hcl))) <= -1) + if (hcl_server_proto_end_reply(proto, (obj? HCL_NULL: hcl_geterrmsg(proto->hcl))) <= -1) { hcl_logbfmt (proto->hcl, HCL_SERVER_PROTO_LOG_MASK, "cannot finalize reply for .END\n"); return -1; @@ -1622,7 +1462,7 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto) { hcl_server_proto_start_reply (proto); obj = hcl_execute(proto->hcl); - if (hcl_server_proto_end_reply(proto, (obj? NULL: hcl_geterrmsg(proto->hcl))) <= -1) + if (hcl_server_proto_end_reply(proto, (obj? HCL_NULL: hcl_geterrmsg(proto->hcl))) <= -1) { hcl_logbfmt (proto->hcl, HCL_SERVER_PROTO_LOG_MASK, "cannot finalize reply for .SCRIPT\n"); return -1; @@ -1639,7 +1479,7 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto) //print_hcl_server_workers (proto); pthread_mutex_unlock (&proto->worker->server->worker_mutex); - if (hcl_server_proto_end_reply(proto, NULL) <= -1) + if (hcl_server_proto_end_reply(proto, HCL_NULL) <= -1) { hcl_logbfmt (proto->hcl, HCL_SERVER_PROTO_LOG_MASK, "cannot finalize reply for .SHOW-WORKERS\n"); return -1; @@ -1654,7 +1494,7 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto) //kill_hcl_server_worker (proto); pthread_mutex_unlock (&proto->worker->server->worker_mutex); - if (hcl_server_proto_end_reply(proto, NULL) <= -1) + if (hcl_server_proto_end_reply(proto, HCL_NULL) <= -1) { hcl_logbfmt (proto->hcl, HCL_SERVER_PROTO_LOG_MASK, "cannot finalize reply for .KILL-WORKER\n"); return -1; @@ -1671,46 +1511,73 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto) /* ========================================================================= */ -hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, unsigned int dbgopt) +hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_prim_t* prim, hcl_errnum_t* errnum) { hcl_server_t* server; + hcl_t* hcl; + hcl_vmprim_t vmprim; + dummy_hcl_xtn_t* xtn; - server = (hcl_server_t*)malloc(sizeof(*server) + xtnsize); - if (!server) return NULL; + server = (hcl_server_t*)HCL_MMGR_ALLOC(mmgr, HCL_SIZEOF(*server) + xtnsize); + if (!server) + { + if (errnum) *errnum = HCL_ESYSMEM; + return HCL_NULL; + } - HCL_MEMSET (server, 0, sizeof(*server) + xtnsize); + HCL_MEMSET (&vmprim, 0, HCL_SIZEOF(vmprim)); + vmprim.log_write = log_write_for_dummy; + vmprim.syserrstrb = syserrstrb; + vmprim.dl_open = dl_open; + vmprim.dl_close = dl_close; + vmprim.dl_getsym = dl_getsym; + vmprim.vm_gettime = vm_gettime; + vmprim.vm_sleep = vm_sleep; - server->logfd = -1; - server->logfd_istty = 0; + hcl = hcl_open(mmgr, HCL_SIZEOF(*xtn), 10240, &vmprim, errnum); + if (!hcl) + { + HCL_MMGR_FREE (mmgr, server); + return HCL_NULL; + } - server->cfg.dbgopt = dbgopt; - server->cfg.trait = HCL_SERVER_TRAIT_READABLE_PROTO | HCL_SERVER_TRAIT_USE_LARGE_PAGES; /* TODO: make it configurable */ + xtn = (dummy_hcl_xtn_t*)hcl_getxtn(hcl); + xtn->server = server; + HCL_MEMSET (server, 0, HCL_SIZEOF(*server) + xtnsize); + server->mmgr = mmgr; + server->cmgr = hcl_get_utf8_cmgr(); + server->prim = *prim; + server->dummy_hcl = hcl; + + server->cfg.logmask = ~0u; server->cfg.worker_stack_size = 512000UL; server->cfg.actor_heap_size = 512000UL; - pthread_mutex_init (&server->worker_mutex, NULL); - pthread_mutex_init (&server->log_mutex, NULL); + pthread_mutex_init (&server->worker_mutex, HCL_NULL); + pthread_mutex_init (&server->log_mutex, HCL_NULL); + return server; } void hcl_server_close (hcl_server_t* server) { - if (server->logfd >= 0) close (server->logfd); pthread_mutex_destroy (&server->log_mutex); pthread_mutex_destroy (&server->worker_mutex); - free (server); + + hcl_close (server->dummy_hcl); + HCL_MMGR_FREE (server->mmgr, server); } static hcl_server_worker_t* alloc_worker (hcl_server_t* server, int cli_sck) { hcl_server_worker_t* worker; - worker = (hcl_server_worker_t*)malloc(sizeof(*worker)); - if (!worker) return NULL; + worker = (hcl_server_worker_t*)HCL_MMGR_ALLOC (server->mmgr, HCL_SIZEOF(*worker)); + if (!worker) return HCL_NULL; - HCL_MEMSET (worker, 0, sizeof(*worker)); + HCL_MEMSET (worker, 0, HCL_SIZEOF(*worker)); worker->sck = cli_sck; worker->server = server; return worker; @@ -1719,7 +1586,7 @@ static hcl_server_worker_t* alloc_worker (hcl_server_t* server, int cli_sck) static void free_worker (hcl_server_worker_t* worker) { if (worker->sck >= 0) close (worker->sck); - free (worker); + HCL_MMGR_FREE (worker->server->mmgr, worker); } static void add_hcl_server_worker_to_server (hcl_server_t* server, hcl_server_worker_state_t wstate, hcl_server_worker_t* worker) @@ -1731,14 +1598,14 @@ static void add_hcl_server_worker_to_server (hcl_server_t* server, hcl_server_wo server->worker_list[wstate].tail->next_worker = worker; worker->prev_worker = server->worker_list[wstate].tail; server->worker_list[wstate].tail = worker; - worker->next_worker = NULL; + worker->next_worker = HCL_NULL; } else { server->worker_list[wstate].tail = worker; server->worker_list[wstate].head = worker; - worker->prev_worker = NULL; - worker->next_worker = NULL; + worker->prev_worker = HCL_NULL; + worker->next_worker = HCL_NULL; } worker->state = wstate; @@ -1756,8 +1623,8 @@ static void zap_worker_in_server (hcl_server_t* server, hcl_server_worker_t* wor if (worker->next_worker) worker->next_worker->prev_worker = worker->prev_worker; else server->worker_list[wstate].tail = worker->prev_worker; - worker->prev_worker = NULL; - worker->next_worker = NULL; + worker->prev_worker = HCL_NULL; + worker->next_worker = HCL_NULL; } static void* worker_main (void* ctx) @@ -1767,14 +1634,14 @@ static void* worker_main (void* ctx) sigset_t set; sigfillset (&set); - pthread_sigmask (SIG_BLOCK, &set, NULL); + pthread_sigmask (SIG_BLOCK, &set, HCL_NULL); worker->thr = pthread_self(); worker->proto = hcl_server_proto_open(0, worker); /* TODO: get this from argumen */ if (!worker->proto) { free_worker (worker); - return NULL; + return HCL_NULL; } pthread_mutex_lock (&server->worker_mutex); @@ -1787,7 +1654,7 @@ static void* worker_main (void* ctx) } hcl_server_proto_close (worker->proto); - worker->proto = NULL; + worker->proto = HCL_NULL; pthread_mutex_lock (&server->worker_mutex); @@ -1802,7 +1669,7 @@ static void* worker_main (void* ctx) } pthread_mutex_unlock (&server->worker_mutex); - return NULL; + return HCL_NULL; } static void purge_all_workers (hcl_server_t* server, hcl_server_worker_state_t wstate) @@ -1823,26 +1690,25 @@ static void purge_all_workers (hcl_server_t* server, hcl_server_worker_state_t w pthread_mutex_unlock (&server->worker_mutex); if (!worker) break; - pthread_join (worker->thr, NULL); + pthread_join (worker->thr, HCL_NULL); free_worker (worker); } } -static void hcl_server_write_log (hcl_server_t* server, int mask, const char* fmt, ...) +void hcl_server_logbfmt (hcl_server_t* server, unsigned int mask, const hcl_bch_t* fmt, ...) { - char esbuf[256]; - int eslen; va_list ap; - va_start (ap, fmt); - eslen = vsnprintf (esbuf, HCL_COUNTOF(esbuf), fmt, ap); + hcl_logbfmtv (server->dummy_hcl, mask, fmt, ap); + va_end (ap); +} + +void hcl_server_logufmt (hcl_server_t* server, unsigned int mask, const hcl_uch_t* fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + hcl_logufmtv (server->dummy_hcl, mask, fmt, ap); va_end (ap); - - if (eslen >= HCL_COUNTOF(esbuf)) eslen = HCL_COUNTOF(esbuf) - 1; - - pthread_mutex_lock (&server->log_mutex); - __log_write (server, mask, esbuf, eslen, 1); - pthread_mutex_unlock (&server->log_mutex); } int hcl_server_start (hcl_server_t* server, const char* addrs) @@ -1856,7 +1722,7 @@ int hcl_server_start (hcl_server_t* server, const char* addrs) /* TODO: interprete 'addrs' as a command-separated address list * 192.168.1.1:20,[::1]:20,127.0.0.1:345 */ - HCL_MEMSET (&srv_addr, 0, sizeof(srv_addr)); + HCL_MEMSET (&srv_addr, 0, HCL_SIZEOF(srv_addr)); if (inet_pton(AF_INET6, addrs, &srv_addr.in6.sin6_addr) != 1) { if (inet_pton(AF_INET, addrs, &srv_addr.in4.sin_addr) != 1) @@ -1868,7 +1734,7 @@ int hcl_server_start (hcl_server_t* server, const char* addrs) { srv_addr.in4.sin_family = AF_INET; srv_addr.in4.sin_port = htons(8888); /* TODO: change it */ - srv_len = sizeof(srv_addr.in4); + srv_len = HCL_SIZEOF(srv_addr.in4); sck_fam = AF_INET; } } @@ -1876,30 +1742,36 @@ int hcl_server_start (hcl_server_t* server, const char* addrs) { srv_addr.in6.sin6_family = AF_INET6; srv_addr.in6.sin6_port = htons(8888); /* TODO: change it */ - srv_len = sizeof(srv_addr.in6); + srv_len = HCL_SIZEOF(srv_addr.in6); sck_fam = AF_INET6; } srv_fd = socket(sck_fam, SOCK_STREAM, 0); if (srv_fd == -1) { - hcl_server_write_log (server, HCL_SERVER_PROTO_LOG_MASK, "cannot open server socket - %s\n", strerror(errno)); + int xerrno = errno; + hcl_server_seterrnum (server, hcl_syserr_to_errnum(xerrno)); + hcl_server_logbfmt (server, HCL_SERVER_PROTO_LOG_MASK, "cannot open server socket - %s\n", strerror(xerrno)); return -1; } optval = 1; - setsockopt (srv_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)); + setsockopt (srv_fd, SOL_SOCKET, SO_REUSEADDR, &optval, HCL_SIZEOF(int)); if (bind(srv_fd, (struct sockaddr*)&srv_addr, srv_len) == -1) { - hcl_server_write_log (server, HCL_SERVER_PROTO_LOG_MASK, "cannot bind server socket %d - %s\n", srv_fd, strerror(errno)); + int xerrno = errno; + hcl_server_seterrnum (server, hcl_syserr_to_errnum(xerrno)); + hcl_server_logbfmt (server, HCL_SERVER_PROTO_LOG_MASK, "cannot bind server socket %d - %s\n", srv_fd, strerror(xerrno)); close (srv_fd); return -1; } if (listen (srv_fd, 128) == -1) { - hcl_server_write_log (server, HCL_SERVER_PROTO_LOG_MASK, "cannot listen on server socket %d - %s\n", srv_fd, strerror(errno)); + int xerrno = errno; + hcl_server_seterrnum (server, hcl_syserr_to_errnum(xerrno)); + hcl_server_logbfmt (server, HCL_SERVER_PROTO_LOG_MASK, "cannot listen on server socket %d - %s\n", srv_fd, strerror(xerrno)); close (srv_fd); return -1; } @@ -1914,24 +1786,25 @@ int hcl_server_start (hcl_server_t* server, const char* addrs) int cli_fd; socklen_t cli_len; pthread_t thr; - + hcl_server_worker_t* worker; purge_all_workers (server, HCL_SERVER_WORKER_STATE_DEAD); - cli_len = sizeof(cli_addr); + cli_len = HCL_SIZEOF(cli_addr); cli_fd = accept(srv_fd, (struct sockaddr*)&cli_addr, &cli_len); if (cli_fd == -1) { if (errno != EINTR || !server->stopreq) { - hcl_server_write_log (server, HCL_SERVER_PROTO_LOG_MASK, "cannot accept worker on socket %d - %s\n", srv_fd, strerror(errno)); + int xerrno = errno; + hcl_server_seterrnum (server, hcl_syserr_to_errnum(xerrno)); + hcl_server_logbfmt (server, HCL_SERVER_PROTO_LOG_MASK, "cannot accept worker on socket %d - %s\n", srv_fd, strerror(xerrno)); } break; } worker = alloc_worker(server, cli_fd); - if (pthread_create(&thr, &thr_attr, worker_main, worker) != 0) { free_worker (worker); @@ -1969,10 +1842,10 @@ int hcl_server_setoption (hcl_server_t* server, hcl_server_option_t id, const vo case HCL_SERVER_ACTOR_HEAP_SIZE: server->cfg.actor_heap_size = *(hcl_oow_t*)value; return 0; -// TODO: add more options + } - //hcl_server_seterrnum (server, HCL_SERVER_EINVAL); + hcl_server_seterrnum (server, HCL_EINVAL); return -1; } @@ -1997,6 +1870,49 @@ int hcl_server_getoption (hcl_server_t* server, hcl_server_option_t id, void* va return 0; }; - //hcl_server_seterrnum (server, HCL_SERVER_EINVAL); + hcl_server_seterrnum (server, HCL_EINVAL); return -1; } + +void* hcl_server_getxtn (hcl_server_t* server) +{ + return (void*)(server + 1); +} + +hcl_mmgr_t* hcl_server_getmmgr (hcl_server_t* server) +{ + return server->mmgr; +} + +hcl_cmgr_t* hcl_server_getcmgr (hcl_server_t* server) +{ + return server->cmgr; +} + +void hcl_server_setcmgr (hcl_server_t* server, hcl_cmgr_t* cmgr) +{ + server->cmgr = cmgr; +} + +hcl_errnum_t hcl_server_geterrnum (hcl_server_t* server) +{ + return server->errnum; +} + +const hcl_ooch_t* hcl_server_geterrstr (hcl_server_t* server) +{ + return hcl_errnum_to_errstr(server->errnum); +} + +const hcl_ooch_t* hcl_server_geterrmsg (hcl_server_t* server) +{ + if (server->errmsg.len <= 0) return hcl_errnum_to_errstr(server->errnum); + return server->errmsg.buf; +} + +void hcl_server_seterrnum (hcl_server_t* server, hcl_errnum_t errnum) +{ + /*if (server->shuterr) return; */ + server->errnum = errnum; + server->errmsg.len = 0; +} diff --git a/lib/hcl-s.h b/lib/hcl-s.h index 64a91c9..2a7e762 100644 --- a/lib/hcl-s.h +++ b/lib/hcl-s.h @@ -44,27 +44,47 @@ typedef enum hcl_server_option_t hcl_server_option_t; enum hcl_server_trait_t { - HCL_SERVER_TRAIT_READABLE_PROTO = (1 << 0), - HCL_SERVER_TRAIT_USE_LARGE_PAGES = (1 << 1) +#if defined(HCL_BUILD_DEBUG) + HCL_SERVER_TRAIT_DEBUG_GC = (1 << 0), + HCL_SERVER_TRAIT_DEBUG_BIGINT = (1 << 1), +#endif + + HCL_SERVER_TRAIT_READABLE_PROTO = (1 << 2), + HCL_SERVER_TRAIT_USE_LARGE_PAGES = (1 << 3) }; typedef enum hcl_server_trait_t hcl_server_trait_t; +typedef void (*hcl_server_log_write_t) ( + hcl_server_t* server, + int wid, + unsigned int mask, + const hcl_ooch_t* msg, + hcl_oow_t len +); + +struct hcl_server_prim_t +{ + hcl_server_log_write_t log_write; +}; +typedef struct hcl_server_prim_t hcl_server_prim_t; + + #if defined(__cplusplus) extern "C" { #endif HCL_EXPORT hcl_server_t* hcl_server_open ( - hcl_mmgr_t* mmgr, - hcl_oow_t xtnsize, - unsigned int dbgopt + hcl_mmgr_t* mmgr, + hcl_oow_t xtnsize, + hcl_server_prim_t* prim, + hcl_errnum_t* errnum ); HCL_EXPORT void hcl_server_close ( hcl_server_t* server ); - HCL_EXPORT int hcl_server_start ( hcl_server_t* server, const char* addrs @@ -86,26 +106,47 @@ HCL_EXPORT int hcl_server_getoption ( void* value ); +HCL_EXPORT void* hcl_server_getxtn ( + hcl_server_t* server +); -#if defined(HCL_HAVE_INLINE) - static HCL_INLINE hcl_mmgr_t* hcl_server_getmmgr (hcl_server_t* server) { return server->mmgr; } - static HCL_INLINE void* hcl_server_getxtn (hcl_server_t* server) { return (void*)(hcl + 1); } - /*static HCL_INLINE hcl_server_cmgr_t* hcl_server_getcmgr (hcl_server_t* server) { return server->cmgr; } - static HCL_INLINE void hcl_server_setcmgr (hcl_server_t* hcl, hcl_server_cmgr_t* cmgr) { server->cmgr = cmgr; }*/ +HCL_EXPORT hcl_mmgr_t* hcl_server_getmmgr ( + hcl_server_t* server +); - static HCL_INLINE hcl_server_errnum_t hcl_server_geterrnum (hcl_server_t* server) { return server->errnum; } - -#else -# define hcl_server_getmmgr(server) ((server)->mmgr) -# define hcl_server_getxtn(server) ((void*)((server) + 1)) -/*# define hcl_server_getcmgr(server) ((server)->cmgr) -# define hcl_server_setcmgr(hcl,mgr) ((server)->cmgr = (mgr))*/ +HCL_EXPORT hcl_cmgr_t* hcl_server_getcmgr ( + hcl_server_t* server +); -# define hcl_server_geterrnum(server) ((server)->errnum) -#endif +HCL_EXPORT void hcl_server_setcmgr ( + hcl_server_t* server, + hcl_cmgr_t* cmgr +); +HCL_EXPORT hcl_errnum_t hcl_server_geterrnum ( + hcl_server_t* server +); + +HCL_EXPORT void hcl_server_seterrnum ( + hcl_server_t* server, + hcl_errnum_t errnum +); + +HCL_EXPORT void hcl_server_logbfmt ( + hcl_server_t* server, + unsigned int mask, + const hcl_bch_t* fmt, + ... +); + +HCL_EXPORT void hcl_server_logufmt ( + hcl_server_t* server, + unsigned int mask, + const hcl_uch_t* fmt, + ... +); #if defined(__cplusplus) } diff --git a/lib/hcl.h b/lib/hcl.h index 7b80103..4b5508b 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -29,6 +29,7 @@ #include "hcl-cmn.h" #include "hcl-rbt.h" +#include /* TODO: move this macro out to the build files.... */ #define HCL_INCLUDE_COMPILER @@ -692,7 +693,7 @@ struct hcl_heap_t typedef void* (*hcl_alloc_heap_t) (hcl_t* hcl, hcl_oow_t size); typedef void (*hcl_free_heap_t) (hcl_t* hcl, void* ptr); -typedef void (*hcl_log_write_t) (hcl_t* hcl, int mask, const hcl_ooch_t* msg, hcl_oow_t len); +typedef void (*hcl_log_write_t) (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len); typedef void (*hcl_syserrstrb_t) (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len); typedef void (*hcl_syserrstru_t) (hcl_t* hcl, int syserr, hcl_uch_t* buf, hcl_oow_t len); @@ -1214,29 +1215,33 @@ struct hcl_t enum hcl_log_mask_t { - HCL_LOG_DEBUG = (1 << 0), - HCL_LOG_INFO = (1 << 1), - HCL_LOG_WARN = (1 << 2), - HCL_LOG_ERROR = (1 << 3), - HCL_LOG_FATAL = (1 << 4), + HCL_LOG_DEBUG = (1u << 0), + HCL_LOG_INFO = (1u << 1), + HCL_LOG_WARN = (1u << 2), + HCL_LOG_ERROR = (1u << 3), + HCL_LOG_FATAL = (1u << 4), - HCL_LOG_UNTYPED = (1 << 6), /* only to be used by HCL_DEBUGx() and HCL_INFOx() */ - HCL_LOG_COMPILER = (1 << 7), - HCL_LOG_VM = (1 << 8), - HCL_LOG_MNEMONIC = (1 << 9), /* bytecode mnemonic */ - HCL_LOG_GC = (1 << 10), - HCL_LOG_IC = (1 << 11), /* instruction cycle, fetch-decode-execute */ - HCL_LOG_PRIMITIVE = (1 << 12), - HCL_LOG_APP = (1 << 13), /* hcl applications, set by hcl logging primitive */ + HCL_LOG_UNTYPED = (1u << 6), /* only to be used by HCL_DEBUGx() and HCL_INFOx() */ + HCL_LOG_COMPILER = (1u << 7), + HCL_LOG_VM = (1u << 8), + HCL_LOG_MNEMONIC = (1u << 9), /* bytecode mnemonic */ + HCL_LOG_GC = (1u << 10), + HCL_LOG_IC = (1u << 11), /* instruction cycle, fetch-decode-execute */ + HCL_LOG_PRIMITIVE = (1u << 12), + + HCL_LOG_APP = (1u << 13), /* hcl applications, set by hcl logging primitive */ + HCL_LOG_APP_X1 = (1u << 14), /* more hcl applications, you can choose to use one of APP_X? randomly */ + HCL_LOG_APP_X2 = (1u << 15), + HCL_LOG_APP_X3 = (1u << 16), HCL_LOG_ALL_LEVELS = (HCL_LOG_DEBUG | HCL_LOG_INFO | HCL_LOG_WARN | HCL_LOG_ERROR | HCL_LOG_FATAL), - HCL_LOG_ALL_TYPES = (HCL_LOG_UNTYPED | HCL_LOG_COMPILER | HCL_LOG_VM | HCL_LOG_MNEMONIC | HCL_LOG_GC | HCL_LOG_IC | HCL_LOG_PRIMITIVE | HCL_LOG_APP), + HCL_LOG_ALL_TYPES = (HCL_LOG_UNTYPED | HCL_LOG_COMPILER | HCL_LOG_VM | HCL_LOG_MNEMONIC | HCL_LOG_GC | HCL_LOG_IC | HCL_LOG_PRIMITIVE | HCL_LOG_APP | HCL_LOG_APP_X1 | HCL_LOG_APP_X2 | HCL_LOG_APP_X3), - HCL_LOG_STDOUT = (1 << 14), /* write log messages to stdout without timestamp. HCL_LOG_STDOUT wins over HCL_LOG_STDERR. */ - HCL_LOG_STDERR = (1 << 15), /* write log messages to stderr without timestamp. */ + HCL_LOG_STDOUT = (1u << 20), /* write log messages to stdout without timestamp. HCL_LOG_STDOUT wins over HCL_LOG_STDERR. */ + HCL_LOG_STDERR = (1u << 21), /* write log messages to stderr without timestamp. */ - HCL_LOG_PREFER_JSON = (1 << 30) /* write a object in the json format. don't set this explicitly. use %J instead */ + HCL_LOG_PREFER_JSON = (1u << 30) /* write a object in the json format. don't set this explicitly. use %J instead */ }; typedef enum hcl_log_mask_t hcl_log_mask_t; @@ -1478,6 +1483,14 @@ HCL_EXPORT const hcl_ooch_t* hcl_backuperrmsg ( hcl_t* hcl ); +HCL_EXPORT const hcl_ooch_t* hcl_errnum_to_errstr ( + hcl_errnum_t errnum +); + +HCL_EXPORT hcl_errnum_t hcl_syserr_to_errnum ( + int syserr +); + /** * The hcl_getoption() function gets the value of an option * specified by \a id into the buffer pointed to by \a value. @@ -1722,6 +1735,7 @@ HCL_EXPORT hcl_pfbase_t* hcl_findpfbase ( /* ========================================================================= * LOGGING * ========================================================================= */ + HCL_EXPORT hcl_ooi_t hcl_logbfmt ( hcl_t* hcl, int mask, @@ -1729,6 +1743,13 @@ HCL_EXPORT hcl_ooi_t hcl_logbfmt ( ... ); +HCL_EXPORT hcl_ooi_t hcl_logbfmtv ( + hcl_t* hcl, + int mask, + const hcl_bch_t* fmt, + va_list ap +); + HCL_EXPORT hcl_ooi_t hcl_logufmt ( hcl_t* hcl, int mask, @@ -1736,10 +1757,19 @@ HCL_EXPORT hcl_ooi_t hcl_logufmt ( ... ); +HCL_EXPORT hcl_ooi_t hcl_logufmtv ( + hcl_t* hcl, + int mask, + const hcl_uch_t* fmt, + va_list ap +); + #if defined(HCL_OOCH_IS_UCH) # define hcl_logoofmt hcl_logufmt +# define hcl_logoofmtv hcl_logufmtv #else # define hcl_logoofmt hcl_logbfmt +# define hcl_logoofmtv hcl_logbfmtv #endif diff --git a/lib/logfmt.c b/lib/logfmt.c index bda5503..c2e8f19 100644 --- a/lib/logfmt.c +++ b/lib/logfmt.c @@ -406,10 +406,9 @@ static int _logufmtv (hcl_t* hcl, const hcl_uch_t* fmt, hcl_fmtout_t* data, va_l return __logufmtv (hcl, fmt, data, ap, hcl_logbfmt); } -hcl_ooi_t hcl_logbfmt (hcl_t* hcl, int mask, const hcl_bch_t* fmt, ...) +hcl_ooi_t hcl_logbfmtv (hcl_t* hcl, int mask, const hcl_bch_t* fmt, va_list ap) { int x; - va_list ap; hcl_fmtout_t fo; if (hcl->log.default_type_mask & HCL_LOG_ALL_TYPES) @@ -427,9 +426,7 @@ hcl_ooi_t hcl_logbfmt (hcl_t* hcl, int mask, const hcl_bch_t* fmt, ...) fo.putch = put_logch; fo.putcs = put_logcs; - va_start (ap, fmt); x = _logbfmtv (hcl, fmt, &fo, ap); - va_end (ap); if (hcl->log.len > 0 && hcl->log.ptr[hcl->log.len - 1] == '\n') { @@ -439,10 +436,21 @@ hcl_ooi_t hcl_logbfmt (hcl_t* hcl, int mask, const hcl_bch_t* fmt, ...) return (x <= -1)? -1: fo.count; } -hcl_ooi_t hcl_logufmt (hcl_t* hcl, int mask, const hcl_uch_t* fmt, ...) +hcl_ooi_t hcl_logbfmt (hcl_t* hcl, int mask, const hcl_bch_t* fmt, ...) +{ + va_list ap; + hcl_ooi_t x; + + va_start (ap, fmt); + x = hcl_logbfmtv (hcl, mask, fmt, ap); + va_end (ap); + + return x; +} + +hcl_ooi_t hcl_logufmtv (hcl_t* hcl, int mask, const hcl_uch_t* fmt, va_list ap) { int x; - va_list ap; hcl_fmtout_t fo; if (hcl->log.default_type_mask & HCL_LOG_ALL_TYPES) @@ -455,9 +463,7 @@ hcl_ooi_t hcl_logufmt (hcl_t* hcl, int mask, const hcl_uch_t* fmt, ...) fo.putch = put_logch; fo.putcs = put_logcs; - va_start (ap, fmt); x = _logufmtv (hcl, fmt, &fo, ap); - va_end (ap); if (hcl->log.len > 0 && hcl->log.ptr[hcl->log.len - 1] == '\n') { @@ -468,6 +474,19 @@ hcl_ooi_t hcl_logufmt (hcl_t* hcl, int mask, const hcl_uch_t* fmt, ...) return (x <= -1)? -1: fo.count; } +hcl_ooi_t hcl_logufmt (hcl_t* hcl, int mask, const hcl_uch_t* fmt, ...) +{ + va_list ap; + hcl_ooi_t x; + + va_start (ap, fmt); + x = hcl_logufmtv (hcl, mask, fmt, ap); + va_end (ap); + + return x; +} + + /* -------------------------------------------------------------------------- * HELPER FOR PRINTING * -------------------------------------------------------------------------- */ diff --git a/lib/main.c b/lib/main.c index 03367b3..9e5c993 100644 --- a/lib/main.c +++ b/lib/main.c @@ -545,7 +545,7 @@ static int write_all (int fd, const char* ptr, hcl_oow_t len) return 0; } -static void log_write (hcl_t* hcl, int mask, const hcl_ooch_t* msg, hcl_oow_t len) +static void log_write (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) { hcl_bch_t buf[256]; hcl_oow_t ucslen, bcslen, msgidx; diff --git a/lib/main2.c b/lib/main2.c index 4982716..cebe244 100644 --- a/lib/main2.c +++ b/lib/main2.c @@ -62,7 +62,7 @@ /* ========================================================================= */ typedef struct server_xtn_t server_xtn_t; -struct xtn_t +struct server_xtn_t { int logfd; unsigned int logmask; @@ -71,6 +71,180 @@ struct xtn_t /* ========================================================================= */ +static void* sys_alloc (hcl_mmgr_t* mmgr, hcl_oow_t size) +{ + return malloc(size); +} + +static void* sys_realloc (hcl_mmgr_t* mmgr, void* ptr, hcl_oow_t size) +{ + return realloc(ptr, size); +} + +static void sys_free (hcl_mmgr_t* mmgr, void* ptr) +{ + free (ptr); +} + +static hcl_mmgr_t sys_mmgr = +{ + sys_alloc, + sys_realloc, + sys_free, + HCL_NULL +}; +/* ========================================================================= */ + +static int write_all (int fd, const char* ptr, hcl_oow_t len) +{ + while (len > 0) + { + hcl_ooi_t wr; + + wr = write(fd, ptr, len); + + if (wr <= -1) + { + #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK) + if (errno == EAGAIN) continue; + #else + #if defined(EAGAIN) + if (errno == EAGAIN) continue; + #elif defined(EWOULDBLOCK) + if (errno == EWOULDBLOCK) continue; + #endif + #endif + + #if defined(EINTR) + /* TODO: would this interfere with non-blocking nature of this VM? */ + if (errno == EINTR) continue; + #endif + return -1; + } + + ptr += wr; + len -= wr; + } + + return 0; +} + +static void log_write (hcl_server_t* server, int wid, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) +{ + hcl_bch_t buf[256]; + hcl_oow_t ucslen, bcslen; + server_xtn_t* xtn; + hcl_oow_t msgidx; + int n, logfd; + + xtn = hcl_server_getxtn(server); + + if (mask & HCL_LOG_STDERR) + { + /* the messages that go to STDERR don't get masked out */ + logfd = 2; + } + else + { + if (!(xtn->logmask & mask & ~HCL_LOG_ALL_LEVELS)) return; /* check log types */ + if (!(xtn->logmask & mask & ~HCL_LOG_ALL_TYPES)) return; /* check log levels */ + + if (mask & HCL_LOG_STDOUT) logfd = 1; + else + { + logfd = xtn->logfd; + if (logfd <= -1) return; + } + } + +/* TODO: beautify the log message. + * do classification based on mask. */ + if (!(mask & (HCL_LOG_STDOUT | HCL_LOG_STDERR))) + { + time_t now; + char ts[32]; + size_t tslen; + struct tm tm, *tmp; + + + now = time(NULL); + + tmp = localtime_r (&now, &tm); + #if defined(HAVE_STRFTIME_SMALL_Z) + tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); + #else + tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp); + #endif + if (tslen == 0) + { + strcpy (ts, "0000-00-00 00:00:00 +0000"); + tslen = 25; + } + +/* TODO: less write system calls by having a buffer */ + write_all (logfd, ts, tslen); + + if (wid >= 0) + { + tslen = snprintf (ts, sizeof(ts), "[%x] ", wid); + write_all (logfd, ts, tslen); + } + } + + if (xtn->logfd_istty) + { + if (mask & HCL_LOG_FATAL) write_all (logfd, "\x1B[1;31m", 7); + else if (mask & HCL_LOG_ERROR) write_all (logfd, "\x1B[1;32m", 7); + else if (mask & HCL_LOG_WARN) write_all (logfd, "\x1B[1;33m", 7); + } + +#if defined(HCL_OOCH_IS_UCH) + msgidx = 0; + while (len > 0) + { + ucslen = len; + bcslen = HCL_COUNTOF(buf); + + n = hcl_conv_oocsn_to_bcsn_with_cmgr(&msg[msgidx], &ucslen, buf, &bcslen, hcl_get_utf8_cmgr()); + if (n == 0 || n == -2) + { + /* n = 0: + * converted all successfully + * n == -2: + * buffer not sufficient. not all got converted yet. + * write what have been converted this round. */ + + /*HCL_ASSERT (hcl, ucslen > 0); */ /* if this fails, the buffer size must be increased */ + assert (ucslen > 0); + + /* attempt to write all converted characters */ + if (write_all(logfd, buf, bcslen) <= -1) break; + + if (n == 0) break; + else + { + msgidx += ucslen; + len -= ucslen; + } + } + else if (n <= -1) + { + /* conversion error */ + break; + } + } +#else + write_all (logfd, vmsg, len); +#endif + + if (xtn->logfd_istty) + { + if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_all (logfd, "\x1B[0m", 4); + } +} + +/* ========================================================================= */ + static hcl_server_t* g_server = HCL_NULL; /* ========================================================================= */ @@ -126,10 +300,12 @@ static int handle_logopt (hcl_server_t* server, const hcl_bch_t* str) hcl_bch_t* xstr = (hcl_bch_t*)str; hcl_bch_t* cm, * flt; unsigned int logmask; + server_xtn_t* xtn; + xtn = (server_xtn_t*)hcl_server_getxtn(server); hcl_server_getoption (server, HCL_SERVER_LOG_MASK, &logmask); - cm = strchr(xstr, ','); + cm = hcl_findbcharinbcstr(xstr, ','); if (cm) { /* i duplicate this string for open() below as open() doesn't @@ -141,14 +317,14 @@ static int handle_logopt (hcl_server_t* server, const hcl_bch_t* str) return -1; } - cm = strchr(xstr, ','); + cm = hcl_findbcharinbcstr(xstr, ','); *cm = '\0'; do { flt = cm + 1; - cm = strchr(flt, ','); + cm = hcl_findbcharinbcstr(flt, ','); if (cm) *cm = '\0'; if (hcl_compbcstr(flt, "app") == 0) logmask |= HCL_LOG_APP; @@ -188,10 +364,9 @@ static int handle_logopt (hcl_server_t* server, const hcl_bch_t* str) logmask = HCL_LOG_ALL_LEVELS | HCL_LOG_ALL_TYPES; } - hcl_server_setoption (server, HCL_SERVER_LOG_MASK, &logmask); - - server->logfd = open(xstr, O_CREAT | O_WRONLY | O_APPEND , 0644); - if (server->logfd == -1) + xtn->logmask = logmask; + xtn->logfd = open(xstr, O_CREAT | O_WRONLY | O_APPEND , 0644); + if (xtn->logfd == -1) { fprintf (stderr, "ERROR: cannot open a log file %s\n", xstr); if (str != xstr) free (xstr); @@ -199,7 +374,7 @@ static int handle_logopt (hcl_server_t* server, const hcl_bch_t* str) } #if defined(HAVE_ISATTY) - server->logfd_istty = isatty(server->logfd); + xtn->logfd_istty = isatty(xtn->logfd); #endif if (str != xstr) free (xstr); @@ -207,21 +382,23 @@ static int handle_logopt (hcl_server_t* server, const hcl_bch_t* str) } #if defined(HCL_BUILD_DEBUG) -static int parse_dbgopt (const char* str, unsigned int* dbgoptp) +static int handle_dbgopt (hcl_server_t* server, const char* str) { const hcl_bch_t* cm, * flt; hcl_oow_t len; - unsigned int dbgopt = 0; + unsigned int trait; + + hcl_server_getoption (server, HCL_SERVER_TRAIT, &trait); cm = str - 1; do { flt = cm + 1; - cm = strchr(flt, ','); - len = cm? (cm - flt): strlen(flt); - if (strncasecmp(flt, "gc", len) == 0) dbgopt |= HCL_DEBUG_GC; - else if (strncasecmp (flt, "bigint", len) == 0) dbgopt |= HCL_DEBUG_BIGINT; + cm = hcl_findbcharinbcstr(flt, ','); + len = cm? (cm - flt): hcl_countbcstr(flt); + if (hcl_compbcharsbcstr(flt, len, "gc") == 0) trait |= HCL_SERVER_TRAIT_DEBUG_GC; + else if (hcl_compbcharsbcstr(flt, len, "bigint") == 0) trait |= HCL_SERVER_TRAIT_DEBUG_BIGINT; else { fprintf (stderr, "ERROR: unknown debug option value - %.*s\n", (int)len, flt); @@ -230,7 +407,7 @@ static int parse_dbgopt (const char* str, unsigned int* dbgoptp) } while (cm); - *dbgoptp = dbgopt; + hcl_server_setoption (server, HCL_SERVER_TRAIT, &trait); return 0; } #endif @@ -260,12 +437,13 @@ int main (int argc, char* argv[]) hcl_server_t* server; server_xtn_t* xtn; + hcl_server_prim_t server_prim; int n; const char* logopt = HCL_NULL; + const char* dbgopt = HCL_NULL; hcl_oow_t memsize = MIN_MEMSIZE; int large_pages = 0; - unsigned int dbgopt = 0; unsigned int trait; setlocale (LC_ALL, ""); @@ -299,7 +477,7 @@ int main (int argc, char* argv[]) #if defined(HCL_BUILD_DEBUG) else if (hcl_compbcstr(opt.lngopt, "debug") == 0) { - if (parse_dbgopt (opt.arg, &dbgopt) <= -1) return -1; + dbgopt = opt.arg; break; } #endif @@ -321,7 +499,10 @@ int main (int argc, char* argv[]) if (opt.ind >= argc) goto print_usage; - server = hcl_server_open(HCL_SIZEOF(xtn_t), dbgopt); + memset (&server_prim, 0, HCL_SIZEOF(server_prim)); + server_prim.log_write = log_write; + + server = hcl_server_open(&sys_mmgr, HCL_SIZEOF(server_xtn_t), &server_prim, HCL_NULL); if (!server) { fprintf (stderr, "cannot open server\n"); @@ -332,27 +513,47 @@ int main (int argc, char* argv[]) xtn->logfd = -1; xtn->logfd_istty = 0; - if (handle_logopt(server, logopt) <= -1) goto oops; + if (logopt) + { + if (handle_logopt(server, logopt) <= -1) goto oops; + } + else + { + xtn->logmask = HCL_LOG_ALL_TYPES | HCL_LOG_ERROR | HCL_LOG_FATAL; + } + + if (dbgopt) + { + if (handle_dbgopt(server, dbgopt) <= -1) goto oops; + } hcl_server_getoption (server, HCL_SERVER_TRAIT, &trait); if (large_pages) trait |= HCL_SERVER_TRAIT_USE_LARGE_PAGES; - else trait &= HCL_SERVER_TRAIT_USE_LARGE_PAGES; + 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_server_setoption (server, HCL_SERVER_ACTOR_DEBUG, &memsize);*/ g_server = server; set_signal (SIGINT, handle_sigint); set_signal_to_ignore (SIGPIPE); n = hcl_server_start(server, argv[opt.ind]); - + set_signal_to_default (SIGINT); set_signal_to_default (SIGPIPE); g_server = NULL; + if (n <= -1) + { + hcl_server_logbfmt (server, HCL_LOG_APP | HCL_LOG_FATAL, "server error[%d] - %js\n", hcl_server_geterrnum(server), hcl_server_geterrmsg(server)); + } + + close (xtn->logfd); + xtn->logfd = -1; + xtn->logfd_istty = 0; + hcl_server_close (server); return n;