diff options
author | Valentin Bartenev <vbart@nginx.com> | 2018-04-11 18:23:33 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2018-04-11 18:23:33 +0300 |
commit | 204c39472166440f54435edcef8d286f429e0aae (patch) | |
tree | 25fb74d5a547bc96c72d1f8a70d434d3cbdedc75 | |
parent | c7e575d5c61c2b301207c751ae73186d7568857e (diff) | |
download | unit-204c39472166440f54435edcef8d286f429e0aae.tar.gz unit-204c39472166440f54435edcef8d286f429e0aae.tar.bz2 |
Initial access log support.
Diffstat (limited to '')
-rw-r--r-- | src/nxt_conf_validation.c | 5 | ||||
-rw-r--r-- | src/nxt_h1proto.c | 31 | ||||
-rw-r--r-- | src/nxt_http.h | 19 | ||||
-rw-r--r-- | src/nxt_http_request.c | 18 | ||||
-rw-r--r-- | src/nxt_main_process.c | 37 | ||||
-rw-r--r-- | src/nxt_port.h | 3 | ||||
-rw-r--r-- | src/nxt_router.c | 303 | ||||
-rw-r--r-- | src/nxt_router.h | 34 |
8 files changed, 422 insertions, 28 deletions
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 828b2ee2..62ca4b06 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -75,6 +75,11 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { &nxt_conf_vldt_object_iterator, (void *) &nxt_conf_vldt_app }, + { nxt_string("access_log"), + NXT_CONF_VLDT_STRING, + NULL, + NULL }, + NXT_CONF_VLDT_END }; diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 5a27c3d8..b9849ee8 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -35,6 +35,8 @@ static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out); static void nxt_h1p_conn_request_sent(nxt_task_t *task, void *obj, void *data); +static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task, + nxt_http_proto_t proto); static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *last); static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto); @@ -87,6 +89,13 @@ const nxt_http_proto_send_t nxt_http_proto_send[3] = { }; +const nxt_http_proto_body_bytes_sent_t nxt_http_proto_body_bytes_sent[3] = { + nxt_h1p_request_body_bytes_sent, + NULL, + NULL, +}; + + const nxt_http_proto_discard_t nxt_http_proto_discard[3] = { nxt_h1p_request_discard, NULL, @@ -110,6 +119,10 @@ static nxt_http_field_proc_t nxt_h1p_fields[] = { { nxt_string("Host"), &nxt_http_request_host, 0 }, { nxt_string("Cookie"), &nxt_http_request_field, offsetof(nxt_http_request_t, cookie) }, + { nxt_string("Referer"), &nxt_http_request_field, + offsetof(nxt_http_request_t, referer) }, + { nxt_string("User-Agent"), &nxt_http_request_field, + offsetof(nxt_http_request_t, user_agent) }, { nxt_string("Content-Type"), &nxt_http_request_field, offsetof(nxt_http_request_t, content_type) }, { nxt_string("Content-Length"), &nxt_http_request_content_length, 0 }, @@ -802,6 +815,8 @@ nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r) header->mem.free = p; + h1p->header_size = nxt_buf_mem_used_size(&header->mem); + c = h1p->conn; c->write = header; @@ -930,6 +945,20 @@ nxt_h1p_conn_request_sent(nxt_task_t *task, void *obj, void *data) } +static nxt_off_t +nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto) +{ + nxt_off_t sent; + nxt_h1proto_t *h1p; + + h1p = proto.h1; + + sent = h1p->conn->sent - h1p->header_size; + + return (sent > 0) ? sent : 0; +} + + static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *last) @@ -993,6 +1022,8 @@ nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c) nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn)); + c->sent = 0; + in = c->read; if (in == NULL) { diff --git a/src/nxt_http.h b/src/nxt_http.h index 5d31be88..57abb8e0 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -56,6 +56,8 @@ typedef struct { uint8_t chunked; /* 1 bit */ nxt_http_te_t transfer_encoding:8; /* 2 bits */ + uint32_t header_size; + nxt_http_request_t *request; nxt_buf_t *buffers; /* @@ -118,6 +120,8 @@ struct nxt_http_request_s { nxt_http_field_t *content_type; nxt_http_field_t *content_length; nxt_http_field_t *cookie; + nxt_http_field_t *referer; + nxt_http_field_t *user_agent; nxt_off_t content_length_n; nxt_sockaddr_t *remote; @@ -144,6 +148,8 @@ typedef void (*nxt_http_proto_header_send_t)(nxt_task_t *task, nxt_http_request_t *r); typedef void (*nxt_http_proto_send_t)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out); +typedef nxt_off_t (*nxt_http_proto_body_bytes_sent_t)(nxt_task_t *task, + nxt_http_proto_t proto); typedef void (*nxt_http_proto_discard_t)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *last); typedef void (*nxt_http_proto_close_t)(nxt_task_t *task, @@ -180,12 +186,13 @@ nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, extern nxt_lvlhsh_t nxt_response_fields_hash; extern const nxt_conn_state_t nxt_router_conn_close_state; -extern const nxt_http_proto_body_read_t nxt_http_proto_body_read[]; -extern const nxt_http_proto_local_addr_t nxt_http_proto_local_addr[]; -extern const nxt_http_proto_header_send_t nxt_http_proto_header_send[]; -extern const nxt_http_proto_send_t nxt_http_proto_send[]; -extern const nxt_http_proto_discard_t nxt_http_proto_discard[]; -extern const nxt_http_proto_close_t nxt_http_proto_close[]; +extern const nxt_http_proto_body_read_t nxt_http_proto_body_read[]; +extern const nxt_http_proto_local_addr_t nxt_http_proto_local_addr[]; +extern const nxt_http_proto_header_send_t nxt_http_proto_header_send[]; +extern const nxt_http_proto_send_t nxt_http_proto_send[]; +extern const nxt_http_proto_body_bytes_sent_t nxt_http_proto_body_bytes_sent[]; +extern const nxt_http_proto_discard_t nxt_http_proto_discard[]; +extern const nxt_http_proto_close_t nxt_http_proto_close[]; #endif /* _NXT_HTTP_H_INCLUDED_ */ diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index b1d52dd5..02075b19 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -442,9 +442,10 @@ nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data) void nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) { - nxt_http_proto_t proto; - nxt_http_request_t *r; - nxt_http_proto_close_t handler; + nxt_http_proto_t proto; + nxt_http_request_t *r; + nxt_http_proto_close_t handler; + nxt_router_access_log_t *access_log; r = obj; proto.any = data; @@ -453,11 +454,12 @@ nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) if (!r->logged) { r->logged = 1; - // STUB - nxt_debug(task, "http request log: \"%*s \"%V %V %V\" %d\"", - (size_t) r->remote->address_length, - nxt_sockaddr_address(r->remote), - r->method, &r->target, &r->version, r->status); + + access_log = r->socket_conf->router_conf->access_log; + + if (access_log != NULL) { + access_log->handler(task, r, access_log); + } } handler = nxt_http_proto_close[r->protocol]; diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 51303e5a..c6caaf56 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -59,6 +59,8 @@ static void nxt_main_port_modules_handler(nxt_task_t *task, static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2); static void nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); +static void nxt_main_port_access_log_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg); const nxt_sig_event_t nxt_main_process_signals[] = { @@ -314,6 +316,7 @@ static nxt_port_handlers_t nxt_main_process_port_handlers = { .socket = nxt_main_port_socket_handler, .modules = nxt_main_port_modules_handler, .conf_store = nxt_main_port_conf_store_handler, + .access_log = nxt_main_port_access_log_handler, .rpc_ready = nxt_port_rpc_handler, .rpc_error = nxt_port_rpc_handler, }; @@ -1282,3 +1285,37 @@ error: nxt_alert(task, "failed to store current configuration"); } + + +static void +nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) +{ + u_char *path; + nxt_int_t ret; + nxt_file_t file; + nxt_port_t *port; + nxt_port_msg_type_t type; + + nxt_debug(task, "opening access log file"); + + path = msg->buf->mem.pos; + + nxt_memzero(&file, sizeof(nxt_file_t)); + + file.name = (nxt_file_name_t *) path; + file.log_level = NXT_LOG_ERR; + + ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, + NXT_FILE_OWNER_ACCESS); + + type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD + : NXT_PORT_MSG_RPC_ERROR; + + port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); + + if (nxt_fast_path(port != NULL)) { + (void) nxt_port_socket_write(task, port, type, file.fd, + msg->port_msg.stream, 0, NULL); + } +} diff --git a/src/nxt_port.h b/src/nxt_port.h index 038ab0ef..1d070a89 100644 --- a/src/nxt_port.h +++ b/src/nxt_port.h @@ -18,6 +18,7 @@ struct nxt_port_handlers_s { nxt_port_handler_t socket; nxt_port_handler_t modules; nxt_port_handler_t conf_store; + nxt_port_handler_t access_log; /* File descriptor exchange. */ nxt_port_handler_t change_file; @@ -56,6 +57,7 @@ typedef enum { _NXT_PORT_MSG_SOCKET = nxt_port_handler_idx(socket), _NXT_PORT_MSG_MODULES = nxt_port_handler_idx(modules), _NXT_PORT_MSG_CONF_STORE = nxt_port_handler_idx(conf_store), + _NXT_PORT_MSG_ACCESS_LOG = nxt_port_handler_idx(access_log), _NXT_PORT_MSG_CHANGE_FILE = nxt_port_handler_idx(change_file), _NXT_PORT_MSG_NEW_PORT = nxt_port_handler_idx(new_port), @@ -79,6 +81,7 @@ typedef enum { NXT_PORT_MSG_SOCKET = _NXT_PORT_MSG_SOCKET | NXT_PORT_MSG_LAST, NXT_PORT_MSG_MODULES = _NXT_PORT_MSG_MODULES | NXT_PORT_MSG_LAST, NXT_PORT_MSG_CONF_STORE = _NXT_PORT_MSG_CONF_STORE | NXT_PORT_MSG_LAST, + NXT_PORT_MSG_ACCESS_LOG = _NXT_PORT_MSG_ACCESS_LOG | NXT_PORT_MSG_LAST, NXT_PORT_MSG_CHANGE_FILE = _NXT_PORT_MSG_CHANGE_FILE | NXT_PORT_MSG_LAST, NXT_PORT_MSG_NEW_PORT = _NXT_PORT_MSG_NEW_PORT | NXT_PORT_MSG_LAST, diff --git a/src/nxt_router.c b/src/nxt_router.c index 947f7235..d305c2f0 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -208,6 +208,19 @@ static void nxt_router_listen_socket_release(nxt_task_t *task, static void nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint); +static void nxt_router_access_log_writer(nxt_task_t *task, + nxt_http_request_t *r, nxt_router_access_log_t *access_log); +static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, const char *format); +static void nxt_router_access_log_open(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf); +static void nxt_router_access_log_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_release(nxt_task_t *task, + nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); + static void nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); static void nxt_router_app_port_error(nxt_task_t *task, @@ -904,6 +917,7 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) nxt_runtime_t *rt; nxt_queue_link_t *qlk; nxt_socket_conf_t *skcf; + nxt_router_conf_t *rtcf; nxt_router_temp_conf_t *tmcf; const nxt_event_interface_t *interface; @@ -931,11 +945,18 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) } nxt_queue_loop; + rtcf = tmcf->router_conf; + + if (rtcf->access_log != NULL && rtcf->access_log->fd == -1) { + nxt_router_access_log_open(task, tmcf); + return; + } + rt = task->thread->runtime; interface = nxt_service_get(rt->services, "engine", NULL); - router = tmcf->router_conf->router; + router = rtcf->router; ret = nxt_router_engines_create(task, router, tmcf, interface); if (nxt_slow_path(ret != NXT_OK)) { @@ -954,6 +975,8 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) nxt_queue_add(&router->sockets, &tmcf->updating); nxt_queue_add(&router->sockets, &tmcf->creating); + router->access_log = rtcf->access_log; + nxt_router_conf_ready(task, tmcf); return; @@ -997,6 +1020,7 @@ nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) nxt_router_t *router; nxt_queue_link_t *qlk; nxt_socket_conf_t *skcf; + nxt_router_conf_t *rtcf; nxt_alert(task, "failed to apply new conf"); @@ -1034,7 +1058,8 @@ nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) } nxt_queue_loop; - router = tmcf->router_conf->router; + rtcf = tmcf->router_conf; + router = rtcf->router; nxt_queue_add(&router->sockets, &tmcf->keeping); nxt_queue_add(&router->sockets, &tmcf->deleting); @@ -1043,7 +1068,9 @@ nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) // TODO: new engines and threads - nxt_mp_destroy(tmcf->router_conf->mem_pool); + nxt_router_access_log_release(task, &router->lock, rtcf->access_log); + + nxt_mp_destroy(rtcf->mem_pool); nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR); } @@ -1210,21 +1237,23 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_mp_t *mp; uint32_t next; nxt_int_t ret; - nxt_str_t name; + nxt_str_t name, path; nxt_app_t *app, *prev; nxt_router_t *router; - nxt_conf_value_t *conf, *http; + nxt_conf_value_t *conf, *http, *value; nxt_conf_value_t *applications, *application; nxt_conf_value_t *listeners, *listener; nxt_socket_conf_t *skcf; nxt_event_engine_t *engine; nxt_app_lang_module_t *lang; nxt_router_app_conf_t apcf; + nxt_router_access_log_t *access_log; nxt_router_listener_conf_t lscf; static nxt_str_t http_path = nxt_string("/http"); static nxt_str_t applications_path = nxt_string("/applications"); static nxt_str_t listeners_path = nxt_string("/listeners"); + static nxt_str_t access_log_path = nxt_string("/access_log"); conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); if (conf == NULL) { @@ -1468,6 +1497,40 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_router_app_use(task, skcf->application, 1); } + value = nxt_conf_get_path(conf, &access_log_path); + + if (value != NULL) { + nxt_conf_get_string(value, &path); + + access_log = router->access_log; + + if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { + nxt_thread_spin_lock(&router->lock); + access_log->count++; + nxt_thread_spin_unlock(&router->lock); + + } else { + access_log = nxt_malloc(sizeof(nxt_router_access_log_t) + + path.length); + if (access_log == NULL) { + nxt_alert(task, "failed to allocate access log structure"); + goto fail; + } + + access_log->fd = -1; + access_log->handler = &nxt_router_access_log_writer; + access_log->count = 1; + + access_log->path.length = path.length; + access_log->path.start = (u_char *) access_log + + sizeof(nxt_router_access_log_t); + + nxt_memcpy(access_log->path.start, path.start, path.length); + } + + tmcf->router_conf->access_log = access_log; + } + nxt_queue_add(&tmcf->deleting, &router->sockets); nxt_queue_init(&router->sockets); @@ -2589,6 +2652,8 @@ nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) if (rtcf != NULL) { nxt_debug(task, "old router conf is destroyed"); + nxt_router_access_log_release(task, lock, rtcf->access_log); + nxt_mp_thread_adopt(rtcf->mem_pool); nxt_mp_destroy(rtcf->mem_pool); @@ -2601,6 +2666,234 @@ nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) static void +nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, + nxt_router_access_log_t *access_log) +{ + size_t size; + u_char *buf, *p; + nxt_off_t bytes; + + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t) -1, + nxt_router_access_log_date, + "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", + sizeof("31/Dec/1986:19:40:00 +0300") - 1, + NXT_THREAD_TIME_LOCAL, + NXT_THREAD_TIME_SEC, + }; + + size = r->remote->address_length + + 6 /* ' - - [' */ + + date_cache.size + + 3 /* '] "' */ + + r->method->length + + 1 /* space */ + + r->target.length + + 1 /* space */ + + r->version.length + + 2 /* '" ' */ + + 3 /* status */ + + 1 /* space */ + + NXT_OFF_T_LEN + + 2 /* ' "' */ + + (r->referer != NULL ? r->referer->value_length : 1) + + 3 /* '" "' */ + + (r->user_agent != NULL ? r->user_agent->value_length : 1) + + 2 /* '"\n' */ + ; + + buf = nxt_mp_nget(r->mem_pool, size); + if (nxt_slow_path(buf == NULL)) { + return; + } + + p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), + r->remote->address_length); + + p = nxt_cpymem(p, " - - [", 6); + + p = nxt_thread_time_string(task->thread, &date_cache, p); + + p = nxt_cpymem(p, "] \"", 3); + + if (r->method->length != 0) { + p = nxt_cpymem(p, r->method->start, r->method->length); + + if (r->target.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->target.start, r->target.length); + + if (r->version.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->version.start, r->version.length); + } + } + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\" ", 2); + + p = nxt_sprintf(p, p + 3, "%03d", r->status); + + *p++ = ' '; + + bytes = nxt_http_proto_body_bytes_sent[r->protocol](task, r->proto); + + p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); + + p = nxt_cpymem(p, " \"", 2); + + if (r->referer != NULL) { + p = nxt_cpymem(p, r->referer->value, r->referer->value_length); + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\" \"", 3); + + if (r->user_agent != NULL) { + p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\"\n", 2); + + nxt_fd_write(access_log->fd, buf, p - buf); +} + + +static u_char * +nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, + size_t size, const char *format) +{ + u_char sign; + time_t gmtoff; + + static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + gmtoff = nxt_timezone(tm) / 60; + + if (gmtoff < 0) { + gmtoff = -gmtoff; + sign = '-'; + + } else { + sign = '+'; + } + + return nxt_sprintf(buf, buf + size, format, + tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, gmtoff / 60, gmtoff % 60); +} + + +static void +nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) +{ + uint32_t stream; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; + + access_log = tmcf->router_conf->access_log; + + b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } + + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; + + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + stream = nxt_port_rpc_register_handler(task, router_port, + nxt_router_access_log_ready, + nxt_router_access_log_error, + -1, tmcf); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); + + return; + +fail: + + nxt_router_conf_error(task, tmcf); +} + + +static void +nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_temp_conf_t *tmcf; + nxt_router_access_log_t *access_log; + + tmcf = data; + + access_log = tmcf->router_conf->access_log; + + access_log->fd = msg->fd; + + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_router_conf_apply, task, tmcf, NULL); +} + + +static void +nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_temp_conf_t *tmcf; + + tmcf = data; + + nxt_router_conf_error(task, tmcf); +} + + +static void +nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) +{ + if (access_log == NULL) { + return; + } + + nxt_thread_spin_lock(lock); + + if (--access_log->count != 0) { + access_log = NULL; + } + + nxt_thread_spin_unlock(lock); + + if (access_log != NULL) { + + if (access_log->fd != -1) { + nxt_fd_close(access_log->fd); + } + + nxt_free(access_log); + } +} + + +static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) { nxt_port_t *port; diff --git a/src/nxt_router.h b/src/nxt_router.h index ffcad3b9..da3dc26f 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -12,24 +12,31 @@ #include <nxt_runtime.h> #include <nxt_main_process.h> -typedef struct nxt_http_request_s nxt_http_request_t; +typedef struct nxt_http_request_s nxt_http_request_t; #include <nxt_application.h> +typedef struct nxt_router_access_log_s nxt_router_access_log_t; + + typedef struct { - nxt_thread_spinlock_t lock; - nxt_queue_t engines; + nxt_thread_spinlock_t lock; + nxt_queue_t engines; - nxt_queue_t sockets; /* of nxt_socket_conf_t */ - nxt_queue_t apps; /* of nxt_app_t */ + nxt_queue_t sockets; /* of nxt_socket_conf_t */ + nxt_queue_t apps; /* of nxt_app_t */ + + nxt_router_access_log_t *access_log; } nxt_router_t; typedef struct { - uint32_t count; - uint32_t threads; - nxt_router_t *router; - nxt_mp_t *mem_pool; + uint32_t count; + uint32_t threads; + nxt_router_t *router; + nxt_mp_t *mem_pool; + + nxt_router_access_log_t *access_log; } nxt_router_conf_t; @@ -157,6 +164,15 @@ typedef struct { } nxt_socket_conf_joint_t; +struct nxt_router_access_log_s { + void (*handler)(nxt_task_t *task, nxt_http_request_t *r, + nxt_router_access_log_t *access_log); + nxt_fd_t fd; + nxt_str_t path; + uint32_t count; +}; + + void nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); |