120Sigor@sysoev.ru 220Sigor@sysoev.ru /* 320Sigor@sysoev.ru * Copyright (C) Igor Sysoev 420Sigor@sysoev.ru * Copyright (C) Valentin V. Bartenev 520Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 620Sigor@sysoev.ru */ 720Sigor@sysoev.ru 853Sigor@sysoev.ru #include <nxt_router.h> 9115Sigor@sysoev.ru #include <nxt_conf.h> 1020Sigor@sysoev.ru 1120Sigor@sysoev.ru 12115Sigor@sysoev.ru typedef struct { 13318Smax.romanov@nginx.com nxt_str_t type; 14318Smax.romanov@nginx.com uint32_t workers; 15318Smax.romanov@nginx.com nxt_msec_t timeout; 16427Smax.romanov@nginx.com nxt_msec_t res_timeout; 17318Smax.romanov@nginx.com uint32_t requests; 18318Smax.romanov@nginx.com nxt_conf_value_t *limits_value; 19133Sigor@sysoev.ru } nxt_router_app_conf_t; 20133Sigor@sysoev.ru 21133Sigor@sysoev.ru 22133Sigor@sysoev.ru typedef struct { 23133Sigor@sysoev.ru nxt_str_t application; 24115Sigor@sysoev.ru } nxt_router_listener_conf_t; 25115Sigor@sysoev.ru 26115Sigor@sysoev.ru 27423Smax.romanov@nginx.com typedef struct nxt_msg_info_s { 28423Smax.romanov@nginx.com nxt_buf_t *buf; 29423Smax.romanov@nginx.com nxt_port_mmap_tracking_t tracking; 30423Smax.romanov@nginx.com nxt_work_handler_t completion_handler; 31423Smax.romanov@nginx.com } nxt_msg_info_t; 32423Smax.romanov@nginx.com 33423Smax.romanov@nginx.com 34167Smax.romanov@nginx.com typedef struct nxt_req_app_link_s nxt_req_app_link_t; 35141Smax.romanov@nginx.com 36141Smax.romanov@nginx.com 37318Smax.romanov@nginx.com typedef struct { 38318Smax.romanov@nginx.com uint32_t stream; 39318Smax.romanov@nginx.com nxt_conn_t *conn; 40343Smax.romanov@nginx.com nxt_app_t *app; 41318Smax.romanov@nginx.com nxt_port_t *app_port; 42346Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 43423Smax.romanov@nginx.com nxt_msg_info_t msg_info; 44318Smax.romanov@nginx.com nxt_req_app_link_t *ra; 45318Smax.romanov@nginx.com 46318Smax.romanov@nginx.com nxt_queue_link_t link; /* for nxt_conn_t.requests */ 47318Smax.romanov@nginx.com } nxt_req_conn_link_t; 48318Smax.romanov@nginx.com 49318Smax.romanov@nginx.com 50167Smax.romanov@nginx.com struct nxt_req_app_link_s { 51318Smax.romanov@nginx.com uint32_t stream; 52425Smax.romanov@nginx.com nxt_atomic_t use_count; 53167Smax.romanov@nginx.com nxt_port_t *app_port; 54167Smax.romanov@nginx.com nxt_port_t *reply_port; 55167Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 56423Smax.romanov@nginx.com nxt_msg_info_t msg_info; 57167Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 58167Smax.romanov@nginx.com 59427Smax.romanov@nginx.com nxt_nsec_t res_time; 60427Smax.romanov@nginx.com 61425Smax.romanov@nginx.com nxt_queue_link_t link_app_requests; /* for nxt_app_t.requests */ 62425Smax.romanov@nginx.com nxt_queue_link_t link_port_pending; /* for nxt_port_t.pending_requests */ 63427Smax.romanov@nginx.com nxt_queue_link_t link_app_pending; /* for nxt_app_t.pending */ 64167Smax.romanov@nginx.com 65167Smax.romanov@nginx.com nxt_mp_t *mem_pool; 66167Smax.romanov@nginx.com nxt_work_t work; 67345Smax.romanov@nginx.com 68345Smax.romanov@nginx.com int err_code; 69345Smax.romanov@nginx.com const char *err_str; 70167Smax.romanov@nginx.com }; 71167Smax.romanov@nginx.com 72167Smax.romanov@nginx.com 73198Sigor@sysoev.ru typedef struct { 74198Sigor@sysoev.ru nxt_socket_conf_t *socket_conf; 75198Sigor@sysoev.ru nxt_router_temp_conf_t *temp_conf; 76198Sigor@sysoev.ru } nxt_socket_rpc_t; 77198Sigor@sysoev.ru 78198Sigor@sysoev.ru 79427Smax.romanov@nginx.com struct nxt_port_select_state_s { 80427Smax.romanov@nginx.com nxt_app_t *app; 81427Smax.romanov@nginx.com nxt_req_app_link_t *ra; 82427Smax.romanov@nginx.com 83427Smax.romanov@nginx.com nxt_port_t *failed_port; 84427Smax.romanov@nginx.com int failed_port_use_delta; 85427Smax.romanov@nginx.com 86427Smax.romanov@nginx.com nxt_bool_t can_start_worker; 87427Smax.romanov@nginx.com nxt_req_app_link_t *shared_ra; 88427Smax.romanov@nginx.com nxt_port_t *port; 89427Smax.romanov@nginx.com }; 90427Smax.romanov@nginx.com 91427Smax.romanov@nginx.com typedef struct nxt_port_select_state_s nxt_port_select_state_t; 92427Smax.romanov@nginx.com 93427Smax.romanov@nginx.com static void nxt_router_port_select(nxt_task_t *task, 94427Smax.romanov@nginx.com nxt_port_select_state_t *state); 95427Smax.romanov@nginx.com 96427Smax.romanov@nginx.com static nxt_int_t nxt_router_port_post_select(nxt_task_t *task, 97427Smax.romanov@nginx.com nxt_port_select_state_t *state); 98427Smax.romanov@nginx.com 99343Smax.romanov@nginx.com static nxt_int_t nxt_router_start_worker(nxt_task_t *task, nxt_app_t *app); 100343Smax.romanov@nginx.com 101425Smax.romanov@nginx.com nxt_inline void 102425Smax.romanov@nginx.com nxt_router_ra_inc_use(nxt_req_app_link_t *ra) 103425Smax.romanov@nginx.com { 104425Smax.romanov@nginx.com nxt_atomic_fetch_add(&ra->use_count, 1); 105425Smax.romanov@nginx.com } 106425Smax.romanov@nginx.com 107425Smax.romanov@nginx.com nxt_inline void 108425Smax.romanov@nginx.com nxt_router_ra_dec_use(nxt_req_app_link_t *ra) 109425Smax.romanov@nginx.com { 110425Smax.romanov@nginx.com int c; 111425Smax.romanov@nginx.com 112425Smax.romanov@nginx.com c = nxt_atomic_fetch_add(&ra->use_count, -1); 113425Smax.romanov@nginx.com 114425Smax.romanov@nginx.com nxt_assert(c > 1); 115425Smax.romanov@nginx.com } 116425Smax.romanov@nginx.com 117425Smax.romanov@nginx.com static void nxt_router_ra_use(nxt_task_t *task, nxt_req_app_link_t *ra, int i); 118425Smax.romanov@nginx.com 119139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 120198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 121198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task, 122139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 123139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 124139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 125139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 126193Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 12753Sigor@sysoev.ru 128115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 129115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 130133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 131133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, 132133Sigor@sysoev.ru nxt_str_t *name); 133198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 134198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 135198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task, 136198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 137198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task, 138198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 139359Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, 140359Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_str_t *name); 141359Sigor@sysoev.ru static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 142359Sigor@sysoev.ru nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa); 14353Sigor@sysoev.ru 14453Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 14553Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 14653Sigor@sysoev.ru const nxt_event_interface_t *interface); 147115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 148115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 149115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 150115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 151115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 152115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 153154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 154154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 155154Sigor@sysoev.ru nxt_work_handler_t handler); 156313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 157313Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 158139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 159139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 16053Sigor@sysoev.ru 16153Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 16253Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 16353Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 16453Sigor@sysoev.ru nxt_event_engine_t *engine); 165343Smax.romanov@nginx.com static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 166133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 16753Sigor@sysoev.ru 168315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router, 169315Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 170315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine, 171315Sigor@sysoev.ru nxt_work_t *jobs); 17253Sigor@sysoev.ru 17353Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 17453Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 17553Sigor@sysoev.ru void *data); 17653Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 17753Sigor@sysoev.ru void *data); 17853Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 17953Sigor@sysoev.ru void *data); 180313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, 181313Sigor@sysoev.ru void *data); 18253Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 18353Sigor@sysoev.ru void *data); 18453Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 18553Sigor@sysoev.ru void *data); 186359Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 187359Sigor@sysoev.ru nxt_socket_conf_t *skcf); 18853Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 18953Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 19053Sigor@sysoev.ru 191343Smax.romanov@nginx.com static void nxt_router_app_port_ready(nxt_task_t *task, 192343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 193343Smax.romanov@nginx.com static void nxt_router_app_port_error(nxt_task_t *task, 194343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 195343Smax.romanov@nginx.com 196343Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_idle_port(nxt_app_t *app); 197343Smax.romanov@nginx.com static void nxt_router_app_port_release(nxt_task_t *task, nxt_port_t *port, 198343Smax.romanov@nginx.com uint32_t request_failed, uint32_t got_response); 199427Smax.romanov@nginx.com static nxt_int_t nxt_router_app_port(nxt_task_t *task, nxt_app_t *app, 200427Smax.romanov@nginx.com nxt_req_app_link_t *ra); 201141Smax.romanov@nginx.com 20253Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data); 20353Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, 20453Sigor@sysoev.ru void *data); 205359Sigor@sysoev.ru static nxt_sockaddr_t *nxt_router_local_addr(nxt_task_t *task, nxt_conn_t *c); 206206Smax.romanov@nginx.com static void nxt_router_conn_http_body_read(nxt_task_t *task, void *obj, 207206Smax.romanov@nginx.com void *data); 20888Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task, 20988Smax.romanov@nginx.com nxt_conn_t *c, nxt_app_parse_ctx_t *ap); 210425Smax.romanov@nginx.com static void nxt_router_app_prepare_request(nxt_task_t *task, 211343Smax.romanov@nginx.com nxt_req_app_link_t *ra); 212216Sigor@sysoev.ru static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 213216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 214216Sigor@sysoev.ru static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 215216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 216216Sigor@sysoev.ru static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 217216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 21888Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data); 21953Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); 22053Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); 22153Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data); 22253Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data); 223318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); 22462Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data); 22520Sigor@sysoev.ru 226141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 227345Smax.romanov@nginx.com const char* str); 228141Smax.romanov@nginx.com 229119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 23020Sigor@sysoev.ru 231216Sigor@sysoev.ru 232216Sigor@sysoev.ru static nxt_app_prepare_msg_t nxt_app_prepare_msg[] = { 233216Sigor@sysoev.ru nxt_python_prepare_msg, 234216Sigor@sysoev.ru nxt_php_prepare_msg, 235216Sigor@sysoev.ru nxt_go_prepare_msg, 236216Sigor@sysoev.ru }; 237216Sigor@sysoev.ru 238216Sigor@sysoev.ru 23920Sigor@sysoev.ru nxt_int_t 240141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data) 24120Sigor@sysoev.ru { 242141Smax.romanov@nginx.com nxt_int_t ret; 243141Smax.romanov@nginx.com nxt_router_t *router; 244141Smax.romanov@nginx.com nxt_runtime_t *rt; 245141Smax.romanov@nginx.com 246141Smax.romanov@nginx.com rt = task->thread->runtime; 24753Sigor@sysoev.ru 24888Smax.romanov@nginx.com ret = nxt_app_http_init(task, rt); 24988Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 25088Smax.romanov@nginx.com return ret; 25188Smax.romanov@nginx.com } 25288Smax.romanov@nginx.com 25353Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 25453Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 25553Sigor@sysoev.ru return NXT_ERROR; 25653Sigor@sysoev.ru } 25753Sigor@sysoev.ru 25853Sigor@sysoev.ru nxt_queue_init(&router->engines); 25953Sigor@sysoev.ru nxt_queue_init(&router->sockets); 260133Sigor@sysoev.ru nxt_queue_init(&router->apps); 26153Sigor@sysoev.ru 262119Smax.romanov@nginx.com nxt_router = router; 263119Smax.romanov@nginx.com 264115Sigor@sysoev.ru return NXT_OK; 265115Sigor@sysoev.ru } 266115Sigor@sysoev.ru 267115Sigor@sysoev.ru 268343Smax.romanov@nginx.com static void 269343Smax.romanov@nginx.com nxt_router_start_worker_handler(nxt_task_t *task, nxt_port_t *port, void *data) 270167Smax.romanov@nginx.com { 271343Smax.romanov@nginx.com size_t size; 272343Smax.romanov@nginx.com uint32_t stream; 273*430Sigor@sysoev.ru nxt_mp_t *mp; 274343Smax.romanov@nginx.com nxt_app_t *app; 275343Smax.romanov@nginx.com nxt_buf_t *b; 276343Smax.romanov@nginx.com nxt_port_t *main_port; 277343Smax.romanov@nginx.com nxt_runtime_t *rt; 278343Smax.romanov@nginx.com 279343Smax.romanov@nginx.com app = data; 280167Smax.romanov@nginx.com 281167Smax.romanov@nginx.com rt = task->thread->runtime; 282240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 283167Smax.romanov@nginx.com 284343Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p start worker", &app->name, app); 285343Smax.romanov@nginx.com 286343Smax.romanov@nginx.com size = app->name.length + 1 + app->conf.length; 287343Smax.romanov@nginx.com 288343Smax.romanov@nginx.com b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, size); 289343Smax.romanov@nginx.com 290343Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 291343Smax.romanov@nginx.com goto failed; 292167Smax.romanov@nginx.com } 293167Smax.romanov@nginx.com 294343Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->name); 295343Smax.romanov@nginx.com *b->mem.free++ = '\0'; 296343Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->conf); 297343Smax.romanov@nginx.com 298343Smax.romanov@nginx.com stream = nxt_port_rpc_register_handler(task, port, 299343Smax.romanov@nginx.com nxt_router_app_port_ready, 300343Smax.romanov@nginx.com nxt_router_app_port_error, 301343Smax.romanov@nginx.com -1, app); 302343Smax.romanov@nginx.com 303343Smax.romanov@nginx.com if (nxt_slow_path(stream == 0)) { 304*430Sigor@sysoev.ru mp = b->data; 305*430Sigor@sysoev.ru nxt_mp_free(mp, b); 306*430Sigor@sysoev.ru nxt_mp_release(mp); 307343Smax.romanov@nginx.com 308343Smax.romanov@nginx.com goto failed; 309343Smax.romanov@nginx.com } 310343Smax.romanov@nginx.com 311343Smax.romanov@nginx.com nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_WORKER, -1, 312343Smax.romanov@nginx.com stream, port->id, b); 313343Smax.romanov@nginx.com 314343Smax.romanov@nginx.com return; 315343Smax.romanov@nginx.com 316343Smax.romanov@nginx.com failed: 317343Smax.romanov@nginx.com 318343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 319343Smax.romanov@nginx.com 320343Smax.romanov@nginx.com app->pending_workers--; 321343Smax.romanov@nginx.com 322343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 323343Smax.romanov@nginx.com 324343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 325167Smax.romanov@nginx.com } 326167Smax.romanov@nginx.com 327167Smax.romanov@nginx.com 328343Smax.romanov@nginx.com static nxt_int_t 329343Smax.romanov@nginx.com nxt_router_start_worker(nxt_task_t *task, nxt_app_t *app) 330141Smax.romanov@nginx.com { 331343Smax.romanov@nginx.com nxt_int_t res; 332343Smax.romanov@nginx.com nxt_port_t *router_port; 333343Smax.romanov@nginx.com nxt_runtime_t *rt; 334343Smax.romanov@nginx.com 335343Smax.romanov@nginx.com rt = task->thread->runtime; 336343Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 337343Smax.romanov@nginx.com 338343Smax.romanov@nginx.com nxt_router_app_use(task, app, 1); 339343Smax.romanov@nginx.com 340343Smax.romanov@nginx.com res = nxt_port_post(task, router_port, nxt_router_start_worker_handler, 341343Smax.romanov@nginx.com app); 342343Smax.romanov@nginx.com 343343Smax.romanov@nginx.com if (res == NXT_OK) { 344343Smax.romanov@nginx.com return res; 345318Smax.romanov@nginx.com } 346318Smax.romanov@nginx.com 347343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 348343Smax.romanov@nginx.com 349343Smax.romanov@nginx.com app->pending_workers--; 350343Smax.romanov@nginx.com 351343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 352343Smax.romanov@nginx.com 353343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 354343Smax.romanov@nginx.com 355343Smax.romanov@nginx.com return NXT_ERROR; 356318Smax.romanov@nginx.com } 357318Smax.romanov@nginx.com 358318Smax.romanov@nginx.com 359351Smax.romanov@nginx.com nxt_inline void 360351Smax.romanov@nginx.com nxt_router_ra_init(nxt_task_t *task, nxt_req_app_link_t *ra, 361351Smax.romanov@nginx.com nxt_req_conn_link_t *rc) 362167Smax.romanov@nginx.com { 363318Smax.romanov@nginx.com nxt_event_engine_t *engine; 364351Smax.romanov@nginx.com 365318Smax.romanov@nginx.com engine = task->thread->engine; 366167Smax.romanov@nginx.com 367167Smax.romanov@nginx.com nxt_memzero(ra, sizeof(nxt_req_app_link_t)); 368167Smax.romanov@nginx.com 369318Smax.romanov@nginx.com ra->stream = rc->stream; 370425Smax.romanov@nginx.com ra->use_count = 1; 371167Smax.romanov@nginx.com ra->rc = rc; 372318Smax.romanov@nginx.com rc->ra = ra; 373318Smax.romanov@nginx.com ra->reply_port = engine->port; 374351Smax.romanov@nginx.com ra->ap = rc->ap; 375167Smax.romanov@nginx.com 376167Smax.romanov@nginx.com ra->work.handler = NULL; 377318Smax.romanov@nginx.com ra->work.task = &engine->task; 378167Smax.romanov@nginx.com ra->work.obj = ra; 379318Smax.romanov@nginx.com ra->work.data = engine; 380351Smax.romanov@nginx.com } 381351Smax.romanov@nginx.com 382351Smax.romanov@nginx.com 383351Smax.romanov@nginx.com nxt_inline nxt_req_app_link_t * 384351Smax.romanov@nginx.com nxt_router_ra_create(nxt_task_t *task, nxt_req_app_link_t *ra_src) 385351Smax.romanov@nginx.com { 386351Smax.romanov@nginx.com nxt_mp_t *mp; 387351Smax.romanov@nginx.com nxt_req_app_link_t *ra; 388351Smax.romanov@nginx.com 389425Smax.romanov@nginx.com if (ra_src->mem_pool != NULL) { 390425Smax.romanov@nginx.com return ra_src; 391425Smax.romanov@nginx.com } 392425Smax.romanov@nginx.com 393351Smax.romanov@nginx.com mp = ra_src->ap->mem_pool; 394351Smax.romanov@nginx.com 395*430Sigor@sysoev.ru ra = nxt_mp_alloc(mp, sizeof(nxt_req_app_link_t)); 396351Smax.romanov@nginx.com 397351Smax.romanov@nginx.com if (nxt_slow_path(ra == NULL)) { 398351Smax.romanov@nginx.com 399351Smax.romanov@nginx.com ra_src->rc->ra = NULL; 400351Smax.romanov@nginx.com ra_src->rc = NULL; 401351Smax.romanov@nginx.com 402351Smax.romanov@nginx.com return NULL; 403351Smax.romanov@nginx.com } 404351Smax.romanov@nginx.com 405*430Sigor@sysoev.ru nxt_mp_retain(mp); 406*430Sigor@sysoev.ru 407351Smax.romanov@nginx.com nxt_router_ra_init(task, ra, ra_src->rc); 408351Smax.romanov@nginx.com 409351Smax.romanov@nginx.com ra->mem_pool = mp; 410167Smax.romanov@nginx.com 411167Smax.romanov@nginx.com return ra; 412167Smax.romanov@nginx.com } 413167Smax.romanov@nginx.com 414167Smax.romanov@nginx.com 415423Smax.romanov@nginx.com nxt_inline nxt_bool_t 416423Smax.romanov@nginx.com nxt_router_msg_cancel(nxt_task_t *task, nxt_msg_info_t *msg_info, 417423Smax.romanov@nginx.com uint32_t stream) 418423Smax.romanov@nginx.com { 419423Smax.romanov@nginx.com nxt_buf_t *b, *next; 420423Smax.romanov@nginx.com nxt_bool_t cancelled; 421423Smax.romanov@nginx.com 422423Smax.romanov@nginx.com if (msg_info->buf == NULL) { 423423Smax.romanov@nginx.com return 0; 424423Smax.romanov@nginx.com } 425423Smax.romanov@nginx.com 426423Smax.romanov@nginx.com cancelled = nxt_port_mmap_tracking_cancel(task, &msg_info->tracking, 427423Smax.romanov@nginx.com stream); 428423Smax.romanov@nginx.com 429423Smax.romanov@nginx.com if (cancelled) { 430423Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: cancelled by router", stream); 431423Smax.romanov@nginx.com } 432423Smax.romanov@nginx.com 433423Smax.romanov@nginx.com for (b = msg_info->buf; b != NULL; b = next) { 434423Smax.romanov@nginx.com next = b->next; 435423Smax.romanov@nginx.com 436423Smax.romanov@nginx.com b->completion_handler = msg_info->completion_handler; 437423Smax.romanov@nginx.com 438423Smax.romanov@nginx.com if (b->is_port_mmap_sent) { 439423Smax.romanov@nginx.com b->is_port_mmap_sent = cancelled == 0; 440423Smax.romanov@nginx.com b->completion_handler(task, b, b->parent); 441423Smax.romanov@nginx.com } 442423Smax.romanov@nginx.com } 443423Smax.romanov@nginx.com 444423Smax.romanov@nginx.com msg_info->buf = NULL; 445423Smax.romanov@nginx.com 446423Smax.romanov@nginx.com return cancelled; 447423Smax.romanov@nginx.com } 448423Smax.romanov@nginx.com 449423Smax.romanov@nginx.com 450167Smax.romanov@nginx.com static void 451425Smax.romanov@nginx.com nxt_router_ra_update_peer(nxt_task_t *task, nxt_req_app_link_t *ra); 452425Smax.romanov@nginx.com 453425Smax.romanov@nginx.com 454425Smax.romanov@nginx.com static void 455425Smax.romanov@nginx.com nxt_router_ra_update_peer_handler(nxt_task_t *task, void *obj, void *data) 456167Smax.romanov@nginx.com { 457425Smax.romanov@nginx.com nxt_req_app_link_t *ra; 458425Smax.romanov@nginx.com 459425Smax.romanov@nginx.com ra = obj; 460425Smax.romanov@nginx.com 461425Smax.romanov@nginx.com nxt_router_ra_update_peer(task, ra); 462425Smax.romanov@nginx.com 463425Smax.romanov@nginx.com nxt_router_ra_use(task, ra, -1); 464425Smax.romanov@nginx.com } 465425Smax.romanov@nginx.com 466425Smax.romanov@nginx.com 467425Smax.romanov@nginx.com static void 468425Smax.romanov@nginx.com nxt_router_ra_update_peer(nxt_task_t *task, nxt_req_app_link_t *ra) 469425Smax.romanov@nginx.com { 470343Smax.romanov@nginx.com nxt_event_engine_t *engine; 471343Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 472318Smax.romanov@nginx.com 473425Smax.romanov@nginx.com engine = ra->work.data; 474318Smax.romanov@nginx.com 475343Smax.romanov@nginx.com if (task->thread->engine != engine) { 476425Smax.romanov@nginx.com nxt_router_ra_inc_use(ra); 477425Smax.romanov@nginx.com 478425Smax.romanov@nginx.com ra->work.handler = nxt_router_ra_update_peer_handler; 479318Smax.romanov@nginx.com ra->work.task = &engine->task; 480318Smax.romanov@nginx.com ra->work.next = NULL; 481318Smax.romanov@nginx.com 482425Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD post update peer to %p", 483318Smax.romanov@nginx.com ra->stream, engine); 484318Smax.romanov@nginx.com 485318Smax.romanov@nginx.com nxt_event_engine_post(engine, &ra->work); 486318Smax.romanov@nginx.com 487318Smax.romanov@nginx.com return; 488318Smax.romanov@nginx.com } 489318Smax.romanov@nginx.com 490425Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD update peer", ra->stream); 491425Smax.romanov@nginx.com 492425Smax.romanov@nginx.com rc = ra->rc; 493425Smax.romanov@nginx.com 494425Smax.romanov@nginx.com if (rc != NULL && ra->app_port != NULL) { 495425Smax.romanov@nginx.com nxt_port_rpc_ex_set_peer(task, engine->port, rc, ra->app_port->pid); 496425Smax.romanov@nginx.com } 497425Smax.romanov@nginx.com 498425Smax.romanov@nginx.com nxt_router_ra_use(task, ra, -1); 499425Smax.romanov@nginx.com } 500425Smax.romanov@nginx.com 501425Smax.romanov@nginx.com 502425Smax.romanov@nginx.com static void 503425Smax.romanov@nginx.com nxt_router_ra_release(nxt_task_t *task, nxt_req_app_link_t *ra) 504425Smax.romanov@nginx.com { 505*430Sigor@sysoev.ru nxt_mp_t *mp; 506425Smax.romanov@nginx.com nxt_conn_t *c; 507425Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 508425Smax.romanov@nginx.com 509425Smax.romanov@nginx.com nxt_assert(task->thread->engine == ra->work.data); 510425Smax.romanov@nginx.com nxt_assert(ra->use_count == 0); 511425Smax.romanov@nginx.com 512343Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD release", ra->stream); 513343Smax.romanov@nginx.com 514343Smax.romanov@nginx.com rc = ra->rc; 515343Smax.romanov@nginx.com 516343Smax.romanov@nginx.com if (rc != NULL) { 517425Smax.romanov@nginx.com c = rc->conn; 518343Smax.romanov@nginx.com 519423Smax.romanov@nginx.com if (nxt_slow_path(ra->err_code != 0)) { 520425Smax.romanov@nginx.com nxt_router_gen_error(task, c, ra->err_code, ra->err_str); 521423Smax.romanov@nginx.com 522423Smax.romanov@nginx.com } else { 523423Smax.romanov@nginx.com rc->app_port = ra->app_port; 524423Smax.romanov@nginx.com rc->msg_info = ra->msg_info; 525423Smax.romanov@nginx.com 526425Smax.romanov@nginx.com if (rc->app->timeout != 0) { 527425Smax.romanov@nginx.com c->read_timer.handler = nxt_router_app_timeout; 528425Smax.romanov@nginx.com nxt_timer_add(task->thread->engine, &c->read_timer, 529425Smax.romanov@nginx.com rc->app->timeout); 530425Smax.romanov@nginx.com } 531425Smax.romanov@nginx.com 532423Smax.romanov@nginx.com ra->app_port = NULL; 533423Smax.romanov@nginx.com ra->msg_info.buf = NULL; 534423Smax.romanov@nginx.com } 535343Smax.romanov@nginx.com 536343Smax.romanov@nginx.com rc->ra = NULL; 537343Smax.romanov@nginx.com ra->rc = NULL; 538343Smax.romanov@nginx.com } 539343Smax.romanov@nginx.com 540343Smax.romanov@nginx.com if (ra->app_port != NULL) { 541343Smax.romanov@nginx.com nxt_router_app_port_release(task, ra->app_port, 0, 1); 542343Smax.romanov@nginx.com 543343Smax.romanov@nginx.com ra->app_port = NULL; 544167Smax.romanov@nginx.com } 545167Smax.romanov@nginx.com 546423Smax.romanov@nginx.com nxt_router_msg_cancel(task, &ra->msg_info, ra->stream); 547423Smax.romanov@nginx.com 548*430Sigor@sysoev.ru mp = ra->mem_pool; 549*430Sigor@sysoev.ru 550*430Sigor@sysoev.ru if (mp != NULL) { 551*430Sigor@sysoev.ru nxt_mp_free(mp, ra); 552*430Sigor@sysoev.ru nxt_mp_release(mp); 553351Smax.romanov@nginx.com } 554167Smax.romanov@nginx.com } 555167Smax.romanov@nginx.com 556167Smax.romanov@nginx.com 557425Smax.romanov@nginx.com static void 558425Smax.romanov@nginx.com nxt_router_ra_release_handler(nxt_task_t *task, void *obj, void *data) 559425Smax.romanov@nginx.com { 560425Smax.romanov@nginx.com nxt_req_app_link_t *ra; 561425Smax.romanov@nginx.com 562425Smax.romanov@nginx.com ra = obj; 563425Smax.romanov@nginx.com 564425Smax.romanov@nginx.com nxt_assert(ra->work.data == data); 565425Smax.romanov@nginx.com 566425Smax.romanov@nginx.com nxt_atomic_fetch_add(&ra->use_count, -1); 567425Smax.romanov@nginx.com 568425Smax.romanov@nginx.com nxt_router_ra_release(task, ra); 569425Smax.romanov@nginx.com } 570425Smax.romanov@nginx.com 571425Smax.romanov@nginx.com 572425Smax.romanov@nginx.com static void 573425Smax.romanov@nginx.com nxt_router_ra_use(nxt_task_t *task, nxt_req_app_link_t *ra, int i) 574425Smax.romanov@nginx.com { 575425Smax.romanov@nginx.com int c; 576425Smax.romanov@nginx.com nxt_event_engine_t *engine; 577425Smax.romanov@nginx.com 578425Smax.romanov@nginx.com c = nxt_atomic_fetch_add(&ra->use_count, i); 579425Smax.romanov@nginx.com 580425Smax.romanov@nginx.com if (i < 0 && c == -i) { 581425Smax.romanov@nginx.com engine = ra->work.data; 582425Smax.romanov@nginx.com 583425Smax.romanov@nginx.com if (task->thread->engine == engine) { 584425Smax.romanov@nginx.com nxt_router_ra_release(task, ra); 585425Smax.romanov@nginx.com 586425Smax.romanov@nginx.com return; 587425Smax.romanov@nginx.com } 588425Smax.romanov@nginx.com 589425Smax.romanov@nginx.com nxt_router_ra_inc_use(ra); 590425Smax.romanov@nginx.com 591425Smax.romanov@nginx.com ra->work.handler = nxt_router_ra_release_handler; 592425Smax.romanov@nginx.com ra->work.task = &engine->task; 593425Smax.romanov@nginx.com ra->work.next = NULL; 594425Smax.romanov@nginx.com 595425Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD post release to %p", 596425Smax.romanov@nginx.com ra->stream, engine); 597425Smax.romanov@nginx.com 598425Smax.romanov@nginx.com nxt_event_engine_post(engine, &ra->work); 599425Smax.romanov@nginx.com } 600425Smax.romanov@nginx.com } 601425Smax.romanov@nginx.com 602425Smax.romanov@nginx.com 603423Smax.romanov@nginx.com nxt_inline void 604423Smax.romanov@nginx.com nxt_router_ra_error(nxt_req_app_link_t *ra, int code, const char* str) 605345Smax.romanov@nginx.com { 606423Smax.romanov@nginx.com ra->app_port = NULL; 607423Smax.romanov@nginx.com ra->err_code = code; 608423Smax.romanov@nginx.com ra->err_str = str; 609345Smax.romanov@nginx.com } 610345Smax.romanov@nginx.com 611345Smax.romanov@nginx.com 612427Smax.romanov@nginx.com nxt_inline void 613427Smax.romanov@nginx.com nxt_router_ra_pending(nxt_task_t *task, nxt_app_t *app, nxt_req_app_link_t *ra) 614427Smax.romanov@nginx.com { 615427Smax.romanov@nginx.com nxt_queue_insert_tail(&ra->app_port->pending_requests, 616427Smax.romanov@nginx.com &ra->link_port_pending); 617427Smax.romanov@nginx.com nxt_queue_insert_tail(&app->pending, &ra->link_app_pending); 618427Smax.romanov@nginx.com 619427Smax.romanov@nginx.com nxt_router_ra_inc_use(ra); 620427Smax.romanov@nginx.com 621427Smax.romanov@nginx.com ra->res_time = nxt_thread_monotonic_time(task->thread) + app->res_timeout; 622427Smax.romanov@nginx.com 623427Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD enqueue to pending_requests", ra->stream); 624427Smax.romanov@nginx.com } 625427Smax.romanov@nginx.com 626427Smax.romanov@nginx.com 627425Smax.romanov@nginx.com nxt_inline nxt_bool_t 628425Smax.romanov@nginx.com nxt_queue_chk_remove(nxt_queue_link_t *lnk) 629425Smax.romanov@nginx.com { 630425Smax.romanov@nginx.com if (lnk->next != NULL) { 631425Smax.romanov@nginx.com nxt_queue_remove(lnk); 632425Smax.romanov@nginx.com 633425Smax.romanov@nginx.com lnk->next = NULL; 634425Smax.romanov@nginx.com 635425Smax.romanov@nginx.com return 1; 636425Smax.romanov@nginx.com } 637425Smax.romanov@nginx.com 638425Smax.romanov@nginx.com return 0; 639425Smax.romanov@nginx.com } 640425Smax.romanov@nginx.com 641425Smax.romanov@nginx.com 642343Smax.romanov@nginx.com nxt_inline void 643343Smax.romanov@nginx.com nxt_router_rc_unlink(nxt_task_t *task, nxt_req_conn_link_t *rc) 644343Smax.romanov@nginx.com { 645425Smax.romanov@nginx.com int ra_use_delta; 646343Smax.romanov@nginx.com nxt_req_app_link_t *ra; 647343Smax.romanov@nginx.com 648343Smax.romanov@nginx.com if (rc->app_port != NULL) { 649343Smax.romanov@nginx.com nxt_router_app_port_release(task, rc->app_port, 0, 1); 650343Smax.romanov@nginx.com 651343Smax.romanov@nginx.com rc->app_port = NULL; 652343Smax.romanov@nginx.com } 653343Smax.romanov@nginx.com 654423Smax.romanov@nginx.com nxt_router_msg_cancel(task, &rc->msg_info, rc->stream); 655423Smax.romanov@nginx.com 656343Smax.romanov@nginx.com ra = rc->ra; 657343Smax.romanov@nginx.com 658343Smax.romanov@nginx.com if (ra != NULL) { 659343Smax.romanov@nginx.com rc->ra = NULL; 660343Smax.romanov@nginx.com ra->rc = NULL; 661343Smax.romanov@nginx.com 662425Smax.romanov@nginx.com ra_use_delta = 0; 663425Smax.romanov@nginx.com 664343Smax.romanov@nginx.com nxt_thread_mutex_lock(&rc->app->mutex); 665343Smax.romanov@nginx.com 666425Smax.romanov@nginx.com if (ra->link_app_requests.next == NULL 667427Smax.romanov@nginx.com && ra->link_port_pending.next == NULL 668427Smax.romanov@nginx.com && ra->link_app_pending.next == NULL) 669425Smax.romanov@nginx.com { 670425Smax.romanov@nginx.com ra = NULL; 671343Smax.romanov@nginx.com 672343Smax.romanov@nginx.com } else { 673425Smax.romanov@nginx.com ra_use_delta -= nxt_queue_chk_remove(&ra->link_app_requests); 674425Smax.romanov@nginx.com ra_use_delta -= nxt_queue_chk_remove(&ra->link_port_pending); 675427Smax.romanov@nginx.com nxt_queue_chk_remove(&ra->link_app_pending); 676343Smax.romanov@nginx.com } 677343Smax.romanov@nginx.com 678343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&rc->app->mutex); 679425Smax.romanov@nginx.com 680425Smax.romanov@nginx.com if (ra != NULL) { 681425Smax.romanov@nginx.com nxt_router_ra_use(task, ra, ra_use_delta); 682425Smax.romanov@nginx.com } 683343Smax.romanov@nginx.com } 684343Smax.romanov@nginx.com 685343Smax.romanov@nginx.com if (rc->app != NULL) { 686343Smax.romanov@nginx.com nxt_router_app_use(task, rc->app, -1); 687343Smax.romanov@nginx.com 688343Smax.romanov@nginx.com rc->app = NULL; 689343Smax.romanov@nginx.com } 690343Smax.romanov@nginx.com 691346Smax.romanov@nginx.com if (rc->ap != NULL) { 692346Smax.romanov@nginx.com nxt_app_http_req_done(task, rc->ap); 693346Smax.romanov@nginx.com 694346Smax.romanov@nginx.com rc->ap = NULL; 695346Smax.romanov@nginx.com } 696346Smax.romanov@nginx.com 697343Smax.romanov@nginx.com nxt_queue_remove(&rc->link); 698343Smax.romanov@nginx.com 699343Smax.romanov@nginx.com rc->conn = NULL; 700343Smax.romanov@nginx.com } 701343Smax.romanov@nginx.com 702343Smax.romanov@nginx.com 703141Smax.romanov@nginx.com void 704141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 705141Smax.romanov@nginx.com { 706141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 707141Smax.romanov@nginx.com 708192Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 709141Smax.romanov@nginx.com return; 710141Smax.romanov@nginx.com } 711141Smax.romanov@nginx.com 712426Smax.romanov@nginx.com if (msg->u.new_port == NULL 713426Smax.romanov@nginx.com || msg->u.new_port->type != NXT_PROCESS_WORKER) 714347Smax.romanov@nginx.com { 715192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 716141Smax.romanov@nginx.com } 717192Smax.romanov@nginx.com 718192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 719141Smax.romanov@nginx.com } 720141Smax.romanov@nginx.com 721141Smax.romanov@nginx.com 722139Sigor@sysoev.ru void 723139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 724115Sigor@sysoev.ru { 725198Sigor@sysoev.ru nxt_int_t ret; 726139Sigor@sysoev.ru nxt_buf_t *b; 727139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 728139Sigor@sysoev.ru 729139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task); 730139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 731139Sigor@sysoev.ru return; 73253Sigor@sysoev.ru } 73353Sigor@sysoev.ru 734423Smax.romanov@nginx.com nxt_debug(task, "nxt_router_conf_data_handler(%d): %*s", 735423Smax.romanov@nginx.com nxt_buf_used_size(msg->buf), 736423Smax.romanov@nginx.com nxt_buf_used_size(msg->buf), msg->buf->mem.pos); 737423Smax.romanov@nginx.com 738352Smax.romanov@nginx.com b = nxt_buf_chk_make_plain(tmcf->conf->mem_pool, msg->buf, msg->size); 739352Smax.romanov@nginx.com 740352Smax.romanov@nginx.com nxt_assert(b != NULL); 741352Smax.romanov@nginx.com 742139Sigor@sysoev.ru tmcf->conf->router = nxt_router; 743139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream; 744139Sigor@sysoev.ru tmcf->port = nxt_runtime_port_find(task->thread->runtime, 745198Sigor@sysoev.ru msg->port_msg.pid, 746198Sigor@sysoev.ru msg->port_msg.reply_port); 747198Sigor@sysoev.ru 748198Sigor@sysoev.ru ret = nxt_router_conf_create(task, tmcf, b->mem.pos, b->mem.free); 749198Sigor@sysoev.ru 750198Sigor@sysoev.ru if (nxt_fast_path(ret == NXT_OK)) { 751198Sigor@sysoev.ru nxt_router_conf_apply(task, tmcf, NULL); 752198Sigor@sysoev.ru 753198Sigor@sysoev.ru } else { 754198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 755139Sigor@sysoev.ru } 75653Sigor@sysoev.ru } 75753Sigor@sysoev.ru 75853Sigor@sysoev.ru 759347Smax.romanov@nginx.com static void 760347Smax.romanov@nginx.com nxt_router_worker_remove_pid(nxt_task_t *task, nxt_port_t *port, void *data) 761347Smax.romanov@nginx.com { 762347Smax.romanov@nginx.com union { 763347Smax.romanov@nginx.com nxt_pid_t removed_pid; 764347Smax.romanov@nginx.com void *data; 765347Smax.romanov@nginx.com } u; 766347Smax.romanov@nginx.com 767347Smax.romanov@nginx.com u.data = data; 768347Smax.romanov@nginx.com 769347Smax.romanov@nginx.com nxt_port_rpc_remove_peer(task, port, u.removed_pid); 770347Smax.romanov@nginx.com } 771347Smax.romanov@nginx.com 772347Smax.romanov@nginx.com 773192Smax.romanov@nginx.com void 774192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 775192Smax.romanov@nginx.com { 776347Smax.romanov@nginx.com nxt_event_engine_t *engine; 777318Smax.romanov@nginx.com 778192Smax.romanov@nginx.com nxt_port_remove_pid_handler(task, msg); 779192Smax.romanov@nginx.com 780192Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 781192Smax.romanov@nginx.com return; 782192Smax.romanov@nginx.com } 783192Smax.romanov@nginx.com 784318Smax.romanov@nginx.com nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) 785318Smax.romanov@nginx.com { 786347Smax.romanov@nginx.com nxt_port_post(task, engine->port, nxt_router_worker_remove_pid, 787347Smax.romanov@nginx.com msg->u.data); 788318Smax.romanov@nginx.com } 789318Smax.romanov@nginx.com nxt_queue_loop; 790318Smax.romanov@nginx.com 791192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 792192Smax.romanov@nginx.com 793192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 794192Smax.romanov@nginx.com } 795192Smax.romanov@nginx.com 796192Smax.romanov@nginx.com 79753Sigor@sysoev.ru static nxt_router_temp_conf_t * 798139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task) 79953Sigor@sysoev.ru { 80065Sigor@sysoev.ru nxt_mp_t *mp, *tmp; 80153Sigor@sysoev.ru nxt_router_conf_t *rtcf; 80253Sigor@sysoev.ru nxt_router_temp_conf_t *