From 36ee74f0ece6d49f353a294e15839b073a16de85 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 16 Mar 2018 16:20:40 +0000 Subject: [PATCH] enhanced the log_write callback to use as few write system calls as possible. changed the hcl server to raise an error if .SCRIPT is not followed by actual script text on the same line --- configure | 4 +-- configure.ac | 4 +-- lib/hcl-cfg.h.in | 9 +++++ lib/hcl-s.c | 28 ++++++++++----- lib/main.c | 89 ++++++++++++++++++++++++++++++++++++++++----- lib/main2.c | 94 ++++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 198 insertions(+), 30 deletions(-) diff --git a/configure b/configure index 5209704..11e16ac 100755 --- a/configure +++ b/configure @@ -18220,7 +18220,7 @@ fi done -for ac_header in dlfcn.h ltdl.h sys/mman.h +for ac_header in dlfcn.h ltdl.h sys/mman.h sys/uio.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -18296,7 +18296,7 @@ _ACEOF fi done -for ac_func in isatty mmap munmap +for ac_func in isatty mmap munmap readv writev do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.ac b/configure.ac index 87cd3b7..b0f26f7 100644 --- a/configure.ac +++ b/configure.ac @@ -120,7 +120,7 @@ dnl check header files. AC_HEADER_STDC AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h fcntl.h dirent.h]) AC_CHECK_HEADERS([time.h sys/time.h utime.h spawn.h execinfo.h ucontext.h]) -AC_CHECK_HEADERS([dlfcn.h ltdl.h sys/mman.h]) +AC_CHECK_HEADERS([dlfcn.h ltdl.h sys/mman.h sys/uio.h]) dnl check data types dnl AC_CHECK_TYPE([wchar_t], @@ -136,7 +136,7 @@ AC_CHECK_FUNCS([backtrace backtrace_symbols]) AC_CHECK_FUNCS([makecontext swapcontext getcontext setcontext]) AC_CHECK_FUNCS([clock_nanosleep nanosleep usleep]) AC_CHECK_FUNCS([snprintf _vsnprintf _vsnwprintf]) -AC_CHECK_FUNCS([isatty mmap munmap]) +AC_CHECK_FUNCS([isatty mmap munmap readv writev]) save_LIBS="$LIBS" AC_SEARCH_LIBS([dlopen], [dl dld], [ diff --git a/lib/hcl-cfg.h.in b/lib/hcl-cfg.h.in index dd346c7..8f7f1ca 100644 --- a/lib/hcl-cfg.h.in +++ b/lib/hcl-cfg.h.in @@ -117,6 +117,9 @@ /* Define to 1 if you have the `quadmath_snprintf' function. */ #undef HAVE_QUADMATH_SNPRINTF +/* Define to 1 if you have the `readv' function. */ +#undef HAVE_READV + /* Define to 1 if you have the `roundq' function. */ #undef HAVE_ROUNDQ @@ -183,6 +186,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + /* Define to 1 if you have the `tanhq' function. */ #undef HAVE_TANHQ @@ -213,6 +219,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_WCTYPE_H +/* Define to 1 if you have the `writev' function. */ +#undef HAVE_WRITEV + /* Define to 1 if you have the `_vsnprintf' function. */ #undef HAVE__VSNPRINTF diff --git a/lib/hcl-s.c b/lib/hcl-s.c index 79d48e4..2686b36 100644 --- a/lib/hcl-s.c +++ b/lib/hcl-s.c @@ -32,8 +32,9 @@ #include #include -#define TOKEN_NAME_ALIGN 64 -#define WID_MAP_ALIGN 512 +#define HCL_SERVER_TOKEN_NAME_ALIGN 64 +#define HCL_SERVER_WID_MAP_ALIGN 512 +#define HCL_SERVER_PROTO_REPLY_BUF_SIZE 1300 #if defined(_WIN32) # include @@ -86,6 +87,9 @@ # if defined(HAVE_SYS_MMAN_H) # include # endif +# if defined(HAVE_SYS_UIO_H) +# include +# endif # include # include @@ -93,7 +97,6 @@ # include # include # include -# include # include #endif @@ -183,8 +186,6 @@ enum hcl_server_proto_req_state_t HCL_SERVER_PROTO_REQ_IN_BLOCK_LEVEL }; -#define HCL_SERVER_PROTO_REPLY_BUF_SIZE 1300 - enum hcl_server_proto_reply_type_t { HCL_SERVER_PROTO_REPLY_SIMPLE = 0, @@ -1278,7 +1279,7 @@ static HCL_INLINE int add_token_char (hcl_server_proto_t* proto, hcl_ooch_t c) hcl_ooch_t* tmp; hcl_oow_t capa; - capa = HCL_ALIGN_POW2(proto->tok.len + 1, TOKEN_NAME_ALIGN); + capa = HCL_ALIGN_POW2(proto->tok.len + 1, HCL_SERVER_TOKEN_NAME_ALIGN); tmp = (hcl_ooch_t*)HCL_MMGR_REALLOC(proto->worker->server->mmgr, proto->tok.ptr, capa * HCL_SIZEOF(*tmp)); if (!tmp) { @@ -1582,6 +1583,18 @@ int hcl_server_proto_handle_request (hcl_server_proto_t* proto) case HCL_SERVER_PROTO_TOKEN_SCRIPT: { hcl_oop_t obj; + hcl_ooci_t c; + + /* do a special check bypassing get_token(). it checks if the script contents + * come on the same line as .SCRIPT */ + GET_CHAR_TO (proto, c); + while (is_spacechar(c)) GET_CHAR_TO (proto, c); + if (c == HCL_OOCI_EOF || c == '\n') + { + HCL_LOG0 (proto->hcl, SERVER_LOGMASK_ERROR, "No contents on the .SCRIPT line\n"); + return -1; + } + UNGET_LAST_CHAR (proto); if (proto->req.state == HCL_SERVER_PROTO_REQ_IN_TOP_LEVEL) hcl_reset(proto->hcl); @@ -1785,7 +1798,7 @@ static HCL_INLINE int prepare_to_acquire_wid (hcl_server_t* server) HCL_ASSERT (server->dummy_hcl, server->wid_map.free_first == HCL_SERVER_WID_INVALID); HCL_ASSERT (server->dummy_hcl, server->wid_map.free_last == HCL_SERVER_WID_INVALID); - new_capa = HCL_ALIGN_POW2(server->wid_map.capa + 1, WID_MAP_ALIGN); + new_capa = HCL_ALIGN_POW2(server->wid_map.capa + 1, HCL_SERVER_WID_MAP_ALIGN); if (new_capa > HCL_SERVER_WID_MAX) { if (server->wid_map.capa >= HCL_SERVER_WID_MAX) @@ -2029,7 +2042,6 @@ void hcl_server_logufmt (hcl_server_t* server, unsigned int mask, const hcl_uch_ va_end (ap); } - static void set_err_with_syserr (hcl_server_t* server, int syserr, const char* bfmt, ...) { hcl_t* hcl = server->dummy_hcl; diff --git a/lib/main.c b/lib/main.c index 2a16528..623a2ff 100644 --- a/lib/main.c +++ b/lib/main.c @@ -144,6 +144,12 @@ struct xtn_t int logfd; unsigned int logmask; int logfd_istty; + + struct + { + hcl_bch_t buf[4096]; + hcl_oow_t len; + } logbuf; int reader_istty; @@ -511,7 +517,7 @@ static void free_heap (hcl_t* hcl, void* ptr) #endif } -static int write_all (int fd, const char* ptr, hcl_oow_t len) +static int write_all (int fd, const hcl_bch_t* ptr, hcl_oow_t len) { while (len > 0) { @@ -545,6 +551,71 @@ static int write_all (int fd, const char* ptr, hcl_oow_t len) return 0; } + +static int write_log (hcl_t* hcl, const hcl_bch_t* ptr, hcl_oow_t len) +{ + xtn_t* xtn; + + xtn = hcl_getxtn(hcl); + + while (len > 0) + { + if (xtn->logbuf.len > 0) + { + hcl_oow_t rcapa, cplen; + + rcapa = HCL_COUNTOF(xtn->logbuf.buf) - xtn->logbuf.len; + cplen = (len >= rcapa)? rcapa: len; + + memcpy (&xtn->logbuf.buf[xtn->logbuf.len], ptr, cplen); + xtn->logbuf.len += cplen; + ptr += cplen; + len -= cplen; + + if (xtn->logbuf.len >= HCL_COUNTOF(xtn->logbuf.buf)) + { + int n; + n = write_all(xtn->logfd, xtn->logbuf.buf, xtn->logbuf.len); + xtn->logbuf.len = 0; + if (n <= -1) return -1; + } + } + else + { + hcl_oow_t rcapa; + + rcapa = HCL_COUNTOF(xtn->logbuf.buf); + if (len >= rcapa) + { + if (write_all(xtn->logfd, ptr, rcapa) <= -1) return -1; + ptr += rcapa; + len -= rcapa; + } + else + { + memcpy (xtn->logbuf.buf, ptr, len); + xtn->logbuf.len += len; + ptr += len; + len -= len; + + } + } + } + + return 0; +} + +static void flush_log (hcl_t* hcl) +{ + xtn_t* xtn; + xtn = hcl_getxtn(hcl); + if (xtn->logbuf.len > 0) + { + write_all (xtn->logfd, xtn->logbuf.buf, xtn->logbuf.len); + xtn->logbuf.len = 0; + } +} + static void log_write (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) { hcl_bch_t buf[256]; @@ -604,14 +675,14 @@ static void log_write (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl tslen = 25; } #endif - write_all (logfd, ts, tslen); + write_log (hcl, 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 (mask & HCL_LOG_FATAL) write_log (hcl, "\x1B[1;31m", 7); + else if (mask & HCL_LOG_ERROR) write_log (hcl, "\x1B[1;32m", 7); + else if (mask & HCL_LOG_WARN) write_log (hcl, "\x1B[1;33m", 7); } #if defined(HCL_OOCH_IS_UCH) @@ -633,7 +704,7 @@ static void log_write (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl HCL_ASSERT (hcl, ucslen > 0); /* if this fails, the buffer size must be increased */ /* attempt to write all converted characters */ - if (write_all (logfd, buf, bcslen) <= -1) break; + if (write_log (hcl, buf, bcslen) <= -1) break; if (n == 0) break; else @@ -649,13 +720,15 @@ static void log_write (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl } } #else - write_all (logfd, msg, len); + write_log (hcl, msg, len); #endif if (xtn->logfd_istty) { - if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_all (logfd, "\x1B[0m", 4); + if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_log (hcl, "\x1B[0m", 4); } + + flush_log (hcl); } diff --git a/lib/main2.c b/lib/main2.c index fe74ddc..640da59 100644 --- a/lib/main2.c +++ b/lib/main2.c @@ -43,6 +43,9 @@ #if defined(HAVE_SIGNAL_H) # include #endif +#if defined(HAVE_SYS_UIO_H) +# include +#endif #include #include @@ -55,6 +58,12 @@ struct server_xtn_t int logfd; unsigned int logmask; int logfd_istty; + + struct + { + hcl_bch_t buf[4096]; + hcl_oow_t len; + } logbuf; }; /* ========================================================================= */ @@ -83,7 +92,7 @@ static hcl_mmgr_t sys_mmgr = }; /* ========================================================================= */ -static int write_all (int fd, const char* ptr, hcl_oow_t len) +static int write_all (int fd, const hcl_bch_t* ptr, hcl_oow_t len) { while (len > 0) { @@ -117,6 +126,70 @@ static int write_all (int fd, const char* ptr, hcl_oow_t len) return 0; } + +static int write_log (hcl_server_t* server, const hcl_bch_t* ptr, hcl_oow_t len) +{ + server_xtn_t* xtn; + + + xtn = hcl_server_getxtn(server); + + while (len > 0) + { + if (xtn->logbuf.len > 0) + { + hcl_oow_t rcapa, cplen; + + rcapa = HCL_COUNTOF(xtn->logbuf.buf) - xtn->logbuf.len; + cplen = (len >= rcapa)? rcapa: len; + + memcpy (&xtn->logbuf.buf[xtn->logbuf.len], ptr, cplen); + xtn->logbuf.len += cplen; + ptr += cplen; + len -= cplen; + + if (xtn->logbuf.len >= HCL_COUNTOF(xtn->logbuf.buf)) + { + write_all(xtn->logfd, xtn->logbuf.buf, xtn->logbuf.len); + xtn->logbuf.len = 0; + } + } + else + { + hcl_oow_t rcapa; + + rcapa = HCL_COUNTOF(xtn->logbuf.buf); + if (len >= rcapa) + { + write_all (xtn->logfd, ptr, rcapa); + ptr += rcapa; + len -= rcapa; + } + else + { + memcpy (xtn->logbuf.buf, ptr, len); + xtn->logbuf.len += len; + ptr += len; + len -= len; + + } + } + } + + return 0; +} + +static void flush_log (hcl_server_t* server) +{ + server_xtn_t* xtn; + xtn = hcl_server_getxtn(server); + if (xtn->logbuf.len > 0) + { + write_all (xtn->logfd, xtn->logbuf.buf, xtn->logbuf.len); + xtn->logbuf.len = 0; + } +} + static void log_write (hcl_server_t* server, hcl_oow_t wid, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) { hcl_bch_t buf[256]; @@ -154,7 +227,6 @@ static void log_write (hcl_server_t* server, hcl_oow_t wid, unsigned int mask, c size_t tslen; struct tm tm, *tmp; - now = time(NULL); tmp = localtime_r (&now, &tm); @@ -170,21 +242,21 @@ static void log_write (hcl_server_t* server, hcl_oow_t wid, unsigned int mask, c } /* TODO: less write system calls by having a buffer */ - write_all (logfd, ts, tslen); + write_log (server, ts, tslen); if (wid != HCL_SERVER_WID_INVALID) { /* TODO: check if the underlying snprintf support %zd */ tslen = snprintf (ts, sizeof(ts), "[%zu] ", wid); - write_all (logfd, ts, tslen); + write_log (server, 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 (mask & HCL_LOG_FATAL) write_log (server, "\x1B[1;31m", 7); + else if (mask & HCL_LOG_ERROR) write_log (server, "\x1B[1;32m", 7); + else if (mask & HCL_LOG_WARN) write_log (server, "\x1B[1;33m", 7); } #if defined(HCL_OOCH_IS_UCH) @@ -207,7 +279,7 @@ static void log_write (hcl_server_t* server, hcl_oow_t wid, unsigned int mask, c /*assert (ucslen > 0);*/ /* attempt to write all converted characters */ - if (write_all(logfd, buf, bcslen) <= -1) break; + if (write_log(server, buf, bcslen) <= -1) break; if (n == 0) break; else @@ -223,13 +295,15 @@ static void log_write (hcl_server_t* server, hcl_oow_t wid, unsigned int mask, c } } #else - write_all (logfd, msg, len); + write_log (server, msg, len); #endif if (xtn->logfd_istty) { - if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_all (logfd, "\x1B[0m", 4); + if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_log (server, "\x1B[0m", 4); } + + flush_log (server); } /* ========================================================================= */