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 { 13133Sigor@sysoev.ru nxt_str_t type; 14133Sigor@sysoev.ru uint32_t workers; 15133Sigor@sysoev.ru } nxt_router_app_conf_t; 16133Sigor@sysoev.ru 17133Sigor@sysoev.ru 18133Sigor@sysoev.ru typedef struct { 19133Sigor@sysoev.ru nxt_str_t application; 20115Sigor@sysoev.ru } nxt_router_listener_conf_t; 21115Sigor@sysoev.ru 22115Sigor@sysoev.ru 23*139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 24*139Sigor@sysoev.ru static nxt_int_t nxt_router_conf_new(nxt_task_t *task, 25*139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 26*139Sigor@sysoev.ru static void nxt_router_conf_success(nxt_task_t *task, 27*139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 28*139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 29*139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 30*139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 31*139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, size_t size); 32*139Sigor@sysoev.ru static void nxt_router_conf_buf_completion(nxt_task_t *task, void *obj, 33*139Sigor@sysoev.ru void *data); 3453Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router, 3553Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 3653Sigor@sysoev.ru 37115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 38115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 39133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 40133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, 41133Sigor@sysoev.ru nxt_str_t *name); 4253Sigor@sysoev.ru static nxt_int_t nxt_router_listen_sockets_stub_create(nxt_task_t *task, 4353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 4465Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, 4565Sigor@sysoev.ru nxt_sockaddr_t *sa); 4653Sigor@sysoev.ru 4753Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 4853Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 4953Sigor@sysoev.ru const nxt_event_interface_t *interface); 50115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 51115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 52115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 53115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 54115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 55115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 56115Sigor@sysoev.ru static void nxt_router_engine_socket_count(nxt_queue_t *sockets); 57115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_mp_t *mp, 58*139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_router_engine_conf_t *recf, 59*139Sigor@sysoev.ru nxt_queue_t *sockets, nxt_array_t *array, nxt_work_handler_t handler); 60*139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 61*139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 6253Sigor@sysoev.ru 6353Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 6453Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 6553Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 6653Sigor@sysoev.ru nxt_event_engine_t *engine); 67133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router, 68133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 6953Sigor@sysoev.ru 7053Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_temp_conf_t *tmcf); 71*139Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_temp_conf_t *tmcf, 72*139Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 7353Sigor@sysoev.ru 7453Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 7553Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 7653Sigor@sysoev.ru void *data); 7753Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 7853Sigor@sysoev.ru void *data); 7953Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 8053Sigor@sysoev.ru void *data); 8153Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 8253Sigor@sysoev.ru void *data); 8353Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 8453Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 8553Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 8653Sigor@sysoev.ru void *data); 8753Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 8853Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 8953Sigor@sysoev.ru 9053Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data); 9153Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, 9253Sigor@sysoev.ru void *data); 9388Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task, 9488Smax.romanov@nginx.com nxt_conn_t *c, nxt_app_parse_ctx_t *ap); 9588Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data); 9653Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); 9753Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); 9853Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data); 9953Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data); 10062Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data); 10120Sigor@sysoev.ru 102119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 10320Sigor@sysoev.ru 10420Sigor@sysoev.ru nxt_int_t 10520Sigor@sysoev.ru nxt_router_start(nxt_task_t *task, nxt_runtime_t *rt) 10620Sigor@sysoev.ru { 107115Sigor@sysoev.ru nxt_int_t ret; 108115Sigor@sysoev.ru nxt_router_t *router; 10953Sigor@sysoev.ru 11088Smax.romanov@nginx.com ret = nxt_app_http_init(task, rt); 11188Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 11288Smax.romanov@nginx.com return ret; 11388Smax.romanov@nginx.com } 11488Smax.romanov@nginx.com 11553Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 11653Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 11753Sigor@sysoev.ru return NXT_ERROR; 11853Sigor@sysoev.ru } 11953Sigor@sysoev.ru 12053Sigor@sysoev.ru nxt_queue_init(&router->engines); 12153Sigor@sysoev.ru nxt_queue_init(&router->sockets); 122133Sigor@sysoev.ru nxt_queue_init(&router->apps); 12353Sigor@sysoev.ru 124119Smax.romanov@nginx.com nxt_router = router; 125119Smax.romanov@nginx.com 126115Sigor@sysoev.ru return NXT_OK; 127115Sigor@sysoev.ru } 128115Sigor@sysoev.ru 129115Sigor@sysoev.ru 130*139Sigor@sysoev.ru void 131*139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 132115Sigor@sysoev.ru { 133*139Sigor@sysoev.ru size_t dump_size; 134*139Sigor@sysoev.ru nxt_buf_t *b; 135*139Sigor@sysoev.ru nxt_int_t ret; 136*139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 137*139Sigor@sysoev.ru 138*139Sigor@sysoev.ru b = msg->buf; 139*139Sigor@sysoev.ru 140*139Sigor@sysoev.ru dump_size = nxt_buf_used_size(b); 141*139Sigor@sysoev.ru 142*139Sigor@sysoev.ru if (dump_size > 300) { 143*139Sigor@sysoev.ru dump_size = 300; 14453Sigor@sysoev.ru } 14553Sigor@sysoev.ru 146*139Sigor@sysoev.ru nxt_debug(task, "router conf data (%z): %*s", 147*139Sigor@sysoev.ru msg->size, dump_size, b->mem.pos); 148*139Sigor@sysoev.ru 149*139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task); 150*139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 151*139Sigor@sysoev.ru return; 15253Sigor@sysoev.ru } 15353Sigor@sysoev.ru 154*139Sigor@sysoev.ru tmcf->conf->router = nxt_router; 155*139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream; 156*139Sigor@sysoev.ru tmcf->port = nxt_runtime_port_find(task->thread->runtime, 157*139Sigor@sysoev.ru msg->port_msg.pid, 0); 158*139Sigor@sysoev.ru 159*139Sigor@sysoev.ru ret = nxt_router_conf_new(task, tmcf, b->mem.pos, b->mem.free); 160*139Sigor@sysoev.ru 161*139Sigor@sysoev.ru b->mem.pos = b->mem.free; 162*139Sigor@sysoev.ru 163*139Sigor@sysoev.ru if (ret == NXT_OK) { 164*139Sigor@sysoev.ru return nxt_router_conf_success(task, tmcf); 165*139Sigor@sysoev.ru } 166*139Sigor@sysoev.ru 167*139Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf"); 168*139Sigor@sysoev.ru 169*139Sigor@sysoev.ru return nxt_router_conf_error(task, tmcf); 17053Sigor@sysoev.ru } 17153Sigor@sysoev.ru 17253Sigor@sysoev.ru 17353Sigor@sysoev.ru static nxt_router_temp_conf_t * 174*139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task) 17553Sigor@sysoev.ru { 17665Sigor@sysoev.ru nxt_mp_t *mp, *tmp; 17753Sigor@sysoev.ru nxt_router_conf_t *rtcf; 17853Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 17953Sigor@sysoev.ru 18065Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 18153Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 18253Sigor@sysoev.ru return NULL; 18353Sigor@sysoev.ru } 18453Sigor@sysoev.ru 18565Sigor@sysoev.ru rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 18653Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) { 18753Sigor@sysoev.ru goto fail; 18853Sigor@sysoev.ru } 18953Sigor@sysoev.ru 19053Sigor@sysoev.ru rtcf->mem_pool = mp; 19153Sigor@sysoev.ru rtcf->count = 1; 19253Sigor@sysoev.ru 19365Sigor@sysoev.ru tmp = nxt_mp_create(1024, 128, 256, 32); 19453Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) { 19553Sigor@sysoev.ru goto fail; 19653Sigor@sysoev.ru } 19753Sigor@sysoev.ru 19865Sigor@sysoev.ru tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 19953Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 20053Sigor@sysoev.ru goto temp_fail; 20153Sigor@sysoev.ru } 20253Sigor@sysoev.ru 20353Sigor@sysoev.ru tmcf->mem_pool = tmp; 20453Sigor@sysoev.ru tmcf->conf = rtcf; 205*139Sigor@sysoev.ru tmcf->count = 1; 206*139Sigor@sysoev.ru tmcf->engine = task->thread->engine; 20753Sigor@sysoev.ru 20853Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 20953Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 21053Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 21153Sigor@sysoev.ru goto temp_fail; 21253Sigor@sysoev.ru } 21353Sigor@sysoev.ru 21453Sigor@sysoev.ru nxt_queue_init(&tmcf->deleting); 21553Sigor@sysoev.ru nxt_queue_init(&tmcf->keeping); 21653Sigor@sysoev.ru nxt_queue_init(&tmcf->updating); 21753Sigor@sysoev.ru nxt_queue_init(&tmcf->pending); 21853Sigor@sysoev.ru nxt_queue_init(&tmcf->creating); 219133Sigor@sysoev.ru nxt_queue_init(&tmcf->apps); 220133Sigor@sysoev.ru nxt_queue_init(&tmcf->previous); 22153Sigor@sysoev.ru 22253Sigor@sysoev.ru return tmcf; 22353Sigor@sysoev.ru 22453Sigor@sysoev.ru temp_fail: 22553Sigor@sysoev.ru 22665Sigor@sysoev.ru nxt_mp_destroy(tmp); 22753Sigor@sysoev.ru 22853Sigor@sysoev.ru fail: 22953Sigor@sysoev.ru 23065Sigor@sysoev.ru nxt_mp_destroy(mp); 23153Sigor@sysoev.ru 23253Sigor@sysoev.ru return NULL; 23353Sigor@sysoev.ru } 23453Sigor@sysoev.ru 23553Sigor@sysoev.ru 236*139Sigor@sysoev.ru static nxt_int_t 237*139Sigor@sysoev.ru nxt_router_conf_new(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 238*139Sigor@sysoev.ru u_char *start, u_char *end) 239*139Sigor@sysoev.ru { 240*139Sigor@sysoev.ru nxt_int_t ret; 241*139Sigor@sysoev.ru nxt_router_t *router; 242*139Sigor@sysoev.ru nxt_runtime_t *rt; 243*139Sigor@sysoev.ru const nxt_event_interface_t *interface; 244*139Sigor@sysoev.ru 245*139Sigor@sysoev.ru ret = nxt_router_conf_create(task, tmcf, start, end); 246*139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 247*139Sigor@sysoev.ru return ret; 248*139Sigor@sysoev.ru } 249*139Sigor@sysoev.ru 250*139Sigor@sysoev.ru router = tmcf->conf->router; 251*139Sigor@sysoev.ru 252*139Sigor@sysoev.ru nxt_router_listen_sockets_sort(router, tmcf); 253*139Sigor@sysoev.ru 254*139Sigor@sysoev.ru ret = nxt_router_listen_sockets_stub_create(task, tmcf); 255*139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 256*139Sigor@sysoev.ru return ret; 257*139Sigor@sysoev.ru } 258*139Sigor@sysoev.ru 259*139Sigor@sysoev.ru rt = task->thread->runtime; 260*139Sigor@sysoev.ru 261*139Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 262*139Sigor@sysoev.ru 263*139Sigor@sysoev.ru ret = nxt_router_engines_create(task, router, tmcf, interface); 264*139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 265*139Sigor@sysoev.ru return ret; 266*139Sigor@sysoev.ru } 267*139Sigor@sysoev.ru 268*139Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf); 269*139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 270*139Sigor@sysoev.ru return ret; 271*139Sigor@sysoev.ru } 272*139Sigor@sysoev.ru 273*139Sigor@sysoev.ru nxt_router_apps_sort(router, tmcf); 274*139Sigor@sysoev.ru 275*139Sigor@sysoev.ru nxt_router_engines_post(tmcf); 276*139Sigor@sysoev.ru 277*139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->updating); 278*139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->creating); 279*139Sigor@sysoev.ru 280*139Sigor@sysoev.ru return NXT_OK; 281*139Sigor@sysoev.ru } 282*139Sigor@sysoev.ru 283*139Sigor@sysoev.ru 284*139Sigor@sysoev.ru static void 285*139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) 286*139Sigor@sysoev.ru { 287*139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 288*139Sigor@sysoev.ru 289*139Sigor@sysoev.ru tmcf = obj; 290*139Sigor@sysoev.ru 291*139Sigor@sysoev.ru nxt_router_conf_success(task, tmcf); 292*139Sigor@sysoev.ru } 293*139Sigor@sysoev.ru 294*139Sigor@sysoev.ru 295*139Sigor@sysoev.ru static void 296*139Sigor@sysoev.ru nxt_router_conf_success(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 297*139Sigor@sysoev.ru { 298*139Sigor@sysoev.ru nxt_debug(task, "temp conf count:%D", tmcf->count); 299*139Sigor@sysoev.ru 300*139Sigor@sysoev.ru if (--tmcf->count == 0) { 301*139Sigor@sysoev.ru nxt_router_conf_send(task, tmcf, (u_char *) "OK", 2); 302*139Sigor@sysoev.ru } 303*139Sigor@sysoev.ru } 304*139Sigor@sysoev.ru 305*139Sigor@sysoev.ru 306*139Sigor@sysoev.ru static void 307*139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 308*139Sigor@sysoev.ru { 309*139Sigor@sysoev.ru nxt_mp_destroy(tmcf->conf->mem_pool); 310*139Sigor@sysoev.ru 311*139Sigor@sysoev.ru nxt_router_conf_send(task, tmcf, (u_char *) "ERROR", 5); 312*139Sigor@sysoev.ru } 313*139Sigor@sysoev.ru 314*139Sigor@sysoev.ru 315*139Sigor@sysoev.ru static void 316*139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 317*139Sigor@sysoev.ru u_char *start, size_t size) 318*139Sigor@sysoev.ru { 319*139Sigor@sysoev.ru nxt_buf_t *b; 320*139Sigor@sysoev.ru 321*139Sigor@sysoev.ru b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 322*139Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 323*139Sigor@sysoev.ru return; 324*139Sigor@sysoev.ru } 325*139Sigor@sysoev.ru 326*139Sigor@sysoev.ru b->parent = tmcf->mem_pool; 327*139Sigor@sysoev.ru b->completion_handler = nxt_router_conf_buf_completion; 328*139Sigor@sysoev.ru 329*139Sigor@sysoev.ru nxt_port_socket_write(task, tmcf->port, NXT_PORT_MSG_DATA, -1, 330*139Sigor@sysoev.ru tmcf->stream, 0, b); 331*139Sigor@sysoev.ru } 332*139Sigor@sysoev.ru 333*139Sigor@sysoev.ru 334*139Sigor@sysoev.ru static void 335*139Sigor@sysoev.ru nxt_router_conf_buf_completion(nxt_task_t *task, void *obj, void *data) 336*139Sigor@sysoev.ru { 337*139Sigor@sysoev.ru nxt_mp_t *mp; 338*139Sigor@sysoev.ru 339*139Sigor@sysoev.ru /* nxt_router_temp_conf_t mem pool. */ 340*139Sigor@sysoev.ru mp = data; 341*139Sigor@sysoev.ru 342*139Sigor@sysoev.ru nxt_mp_destroy(mp); 343*139Sigor@sysoev.ru } 344*139Sigor@sysoev.ru 345*139Sigor@sysoev.ru 346115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = { 347115Sigor@sysoev.ru { 348133Sigor@sysoev.ru nxt_string("listeners_threads"), 349115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 350115Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads), 351115Sigor@sysoev.ru }, 352115Sigor@sysoev.ru }; 353115Sigor@sysoev.ru 354115Sigor@sysoev.ru 355133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = { 356115Sigor@sysoev.ru { 357133Sigor@sysoev.ru nxt_string("type"), 358115Sigor@sysoev.ru NXT_CONF_MAP_STR, 359133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type), 360115Sigor@sysoev.ru }, 361115Sigor@sysoev.ru 362115Sigor@sysoev.ru { 363133Sigor@sysoev.ru nxt_string("workers"), 364115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 365133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, workers), 366133Sigor@sysoev.ru }, 367133Sigor@sysoev.ru }; 368133Sigor@sysoev.ru 369133Sigor@sysoev.ru 370133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_listener_conf[] = { 371133Sigor@sysoev.ru { 372133Sigor@sysoev.ru nxt_string("application"), 373133Sigor@sysoev.ru NXT_CONF_MAP_STR, 374133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application), 375115Sigor@sysoev.ru }, 376115Sigor@sysoev.ru }; 377115Sigor@sysoev.ru 378115Sigor@sysoev.ru 379115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = { 380115Sigor@sysoev.ru { 381115Sigor@sysoev.ru nxt_string("header_buffer_size"), 382115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 383115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size), 384115Sigor@sysoev.ru }, 385115Sigor@sysoev.ru 386115Sigor@sysoev.ru { 387115Sigor@sysoev.ru nxt_string("large_header_buffer_size"), 388115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 389115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size), 390115Sigor@sysoev.ru }, 391115Sigor@sysoev.ru 392115Sigor@sysoev.ru { 393115Sigor@sysoev.ru nxt_string("header_read_timeout"), 394115Sigor@sysoev.ru NXT_CONF_MAP_MSEC, 395115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout), 396115Sigor@sysoev.ru }, 397115Sigor@sysoev.ru }; 398115Sigor@sysoev.ru 399115Sigor@sysoev.ru 40053Sigor@sysoev.ru static nxt_int_t 401115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 402115Sigor@sysoev.ru u_char *start, u_char *end) 40353Sigor@sysoev.ru { 404133Sigor@sysoev.ru u_char *p; 405133Sigor@sysoev.ru size_t size; 406115Sigor@sysoev.ru nxt_mp_t *mp; 407115Sigor@sysoev.ru uint32_t next; 408115Sigor@sysoev.ru nxt_int_t ret; 409115Sigor@sysoev.ru nxt_str_t name; 410133Sigor@sysoev.ru nxt_app_t *app, *prev; 411133Sigor@sysoev.ru nxt_app_type_t type; 412115Sigor@sysoev.ru nxt_sockaddr_t *sa; 413133Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 414133Sigor@sysoev.ru nxt_conf_value_t *conf, *http; 415133Sigor@sysoev.ru nxt_conf_value_t *applications, *application; 416133Sigor@sysoev.ru nxt_conf_value_t *listeners, *listener; 417115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 418133Sigor@sysoev.ru nxt_router_app_conf_t apcf; 419115Sigor@sysoev.ru nxt_router_listener_conf_t lscf; 420115Sigor@sysoev.ru 421115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/http"); 422133Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications"); 423115Sigor@sysoev.ru static nxt_str_t listeners_path = nxt_string("/listeners"); 424115Sigor@sysoev.ru 425115Sigor@sysoev.ru conf = nxt_conf_json_parse(tmcf->mem_pool, start, end); 426115Sigor@sysoev.ru if (conf == NULL) { 427115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "configuration parsing error"); 428115Sigor@sysoev.ru return NXT_ERROR; 429115Sigor@sysoev.ru } 430115Sigor@sysoev.ru 431136Svbart@nginx.com ret = nxt_conf_map_object(conf, nxt_router_conf, 432136Svbart@nginx.com nxt_nitems(nxt_router_conf), tmcf->conf); 433115Sigor@sysoev.ru if (ret != NXT_OK) { 434133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "root map error"); 435115Sigor@sysoev.ru return NXT_ERROR; 436115Sigor@sysoev.ru } 437115Sigor@sysoev.ru 438117Sigor@sysoev.ru if (tmcf->conf->threads == 0) { 439117Sigor@sysoev.ru tmcf->conf->threads = nxt_ncpu; 440117Sigor@sysoev.ru } 441117Sigor@sysoev.ru 442133Sigor@sysoev.ru applications = nxt_conf_get_path(conf, &applications_path); 443133Sigor@sysoev.ru if (applications == NULL) { 444133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block"); 445115Sigor@sysoev.ru return NXT_ERROR; 446115Sigor@sysoev.ru } 447115Sigor@sysoev.ru 448133Sigor@sysoev.ru next = 0; 449133Sigor@sysoev.ru 450133Sigor@sysoev.ru for ( ;; ) { 451133Sigor@sysoev.ru application = nxt_conf_next_object_member(applications, &name, &next); 452133Sigor@sysoev.ru if (application == NULL) { 453133Sigor@sysoev.ru break; 454133Sigor@sysoev.ru } 455133Sigor@sysoev.ru 456133Sigor@sysoev.ru nxt_debug(task, "application \"%V\"", &name); 457133Sigor@sysoev.ru 458133Sigor@sysoev.ru app = nxt_zalloc(sizeof(nxt_app_t)); 459133Sigor@sysoev.ru if (app == NULL) { 460133Sigor@sysoev.ru goto fail; 461133Sigor@sysoev.ru } 462133Sigor@sysoev.ru 463133Sigor@sysoev.ru size = nxt_conf_json_length(application, NULL); 464133Sigor@sysoev.ru 465133Sigor@sysoev.ru app->conf.start = nxt_malloc(size); 466133Sigor@sysoev.ru if (app->conf.start == NULL) { 467133Sigor@sysoev.ru nxt_free(app); 468133Sigor@sysoev.ru goto fail; 469133Sigor@sysoev.ru } 470133Sigor@sysoev.ru 471133Sigor@sysoev.ru p = nxt_conf_json_print(app->conf.start, application, NULL); 472133Sigor@sysoev.ru app->conf.length = p - app->conf.start; 473133Sigor@sysoev.ru 474133Sigor@sysoev.ru nxt_debug(task, "application conf \"%V\"", &app->conf); 475133Sigor@sysoev.ru 476133Sigor@sysoev.ru prev = nxt_router_app_find(&tmcf->conf->router->apps, &name); 477133Sigor@sysoev.ru 478133Sigor@sysoev.ru if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 479133Sigor@sysoev.ru nxt_free(app->conf.start); 480133Sigor@sysoev.ru nxt_free(app); 481133Sigor@sysoev.ru 482133Sigor@sysoev.ru nxt_queue_remove(&prev->link); 483133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->previous, &prev->link); 484133Sigor@sysoev.ru continue; 485133Sigor@sysoev.ru } 486133Sigor@sysoev.ru 487136Svbart@nginx.com ret = nxt_conf_map_object(application, nxt_router_app_conf, 488136Svbart@nginx.com nxt_nitems(nxt_router_app_conf), &apcf); 489133Sigor@sysoev.ru if (ret != NXT_OK) { 490133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "application map error"); 491133Sigor@sysoev.ru goto app_fail; 492133Sigor@sysoev.ru } 493115Sigor@sysoev.ru 494133Sigor@sysoev.ru nxt_debug(task, "application type: %V", &apcf.type); 495133Sigor@sysoev.ru nxt_debug(task, "application workers: %D", apcf.workers); 496133Sigor@sysoev.ru 497133Sigor@sysoev.ru if (nxt_str_eq(&apcf.type, "python", 6)) { 498133Sigor@sysoev.ru type = NXT_APP_PYTHON; 499133Sigor@sysoev.ru 500133Sigor@sysoev.ru } else if (nxt_str_eq(&apcf.type, "php", 3)) { 501133Sigor@sysoev.ru type = NXT_APP_PHP; 502133Sigor@sysoev.ru 503133Sigor@sysoev.ru } else if (nxt_str_eq(&apcf.type, "ruby", 4)) { 504133Sigor@sysoev.ru type = NXT_APP_RUBY; 505133Sigor@sysoev.ru 506133Sigor@sysoev.ru } else if (nxt_str_eq(&apcf.type, "go", 2)) { 507133Sigor@sysoev.ru type = NXT_APP_GO; 508133Sigor@sysoev.ru 509133Sigor@sysoev.ru } else { 510133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", 511133Sigor@sysoev.ru &apcf.type); 512133Sigor@sysoev.ru goto app_fail; 513133Sigor@sysoev.ru } 514133Sigor@sysoev.ru 515133Sigor@sysoev.ru ret = nxt_thread_mutex_create(&app->mutex); 516133Sigor@sysoev.ru if (ret != NXT_OK) { 517133Sigor@sysoev.ru goto app_fail; 518133Sigor@sysoev.ru } 519133Sigor@sysoev.ru 520133Sigor@sysoev.ru app->name = name; 521133Sigor@sysoev.ru app->type = type; 522133Sigor@sysoev.ru app->max_workers = apcf.workers; 523133Sigor@sysoev.ru app->live = 1; 524133Sigor@sysoev.ru 525133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->apps, &app->link); 526133Sigor@sysoev.ru } 527133Sigor@sysoev.ru 528133Sigor@sysoev.ru http = nxt_conf_get_path(conf, &http_path); 529133Sigor@sysoev.ru #if 0 530133Sigor@sysoev.ru if (http == NULL) { 531133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"http\" block"); 532133Sigor@sysoev.ru return NXT_ERROR; 533133Sigor@sysoev.ru } 534133Sigor@sysoev.ru #endif 535133Sigor@sysoev.ru 536133Sigor@sysoev.ru listeners = nxt_conf_get_path(conf, &listeners_path); 537115Sigor@sysoev.ru if (listeners == NULL) { 538133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block"); 539115Sigor@sysoev.ru return NXT_ERROR; 540115Sigor@sysoev.ru } 54153Sigor@sysoev.ru 542133Sigor@sysoev.ru next = 0; 54353Sigor@sysoev.ru 544133Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 545115Sigor@sysoev.ru 546115Sigor@sysoev.ru for ( ;; ) { 547115Sigor@sysoev.ru listener = nxt_conf_next_object_member(listeners, &name, &next); 548115Sigor@sysoev.ru if (listener == NULL) { 549115Sigor@sysoev.ru break; 550115Sigor@sysoev.ru } 55153Sigor@sysoev.ru 552115Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 553115Sigor@sysoev.ru if (sa == NULL) { 554115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name); 555133Sigor@sysoev.ru goto fail; 556115Sigor@sysoev.ru } 557115Sigor@sysoev.ru 558115Sigor@sysoev.ru sa->type = SOCK_STREAM; 559115Sigor@sysoev.ru 560115Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"", 561115Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa)); 56253Sigor@sysoev.ru 563115Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 564115Sigor@sysoev.ru if (skcf == NULL) { 565133Sigor@sysoev.ru goto fail; 566115Sigor@sysoev.ru } 56753Sigor@sysoev.ru 568136Svbart@nginx.com ret = nxt_conf_map_object(listener, nxt_router_listener_conf, 569136Svbart@nginx.com nxt_nitems(nxt_router_listener_conf), &lscf); 570115Sigor@sysoev.ru if (ret != NXT_OK) { 571115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "listener map error"); 572133Sigor@sysoev.ru goto fail; 573115Sigor@sysoev.ru } 57453Sigor@sysoev.ru 575133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application); 576133Sigor@sysoev.ru 577133Sigor@sysoev.ru // STUB, default values if http block is not defined. 578133Sigor@sysoev.ru skcf->header_buffer_size = 2048; 579133Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 580133Sigor@sysoev.ru skcf->header_read_timeout = 5000; 58153Sigor@sysoev.ru 582133Sigor@sysoev.ru if (http != NULL) { 583136Svbart@nginx.com ret = nxt_conf_map_object(http, nxt_router_http_conf, 584136Svbart@nginx.com nxt_nitems(nxt_router_http_conf), skcf); 585133Sigor@sysoev.ru if (ret != NXT_OK) { 586133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "http map error"); 587133Sigor@sysoev.ru goto fail; 588133Sigor@sysoev.ru } 589115Sigor@sysoev.ru } 590115Sigor@sysoev.ru 591115Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 592115Sigor@sysoev.ru skcf->router_conf = tmcf->conf; 593133Sigor@sysoev.ru skcf->application = nxt_router_listener_application(tmcf, 594133Sigor@sysoev.ru &lscf.application); 595115Sigor@sysoev.ru 596115Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 597115Sigor@sysoev.ru } 59853Sigor@sysoev.ru 59953Sigor@sysoev.ru return NXT_OK; 600133Sigor@sysoev.ru 601133Sigor@sysoev.ru app_fail: 602133Sigor@sysoev.ru 603133Sigor@sysoev.ru nxt_free(app->conf.start); 604133Sigor@sysoev.ru nxt_free(app); 605133Sigor@sysoev.ru 606133Sigor@sysoev.ru fail: 607133Sigor@sysoev.ru 608133Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->apps); 609133Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->apps); 610133Sigor@sysoev.ru qlk = nqlk) 611133Sigor@sysoev.ru { 612133Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 613133Sigor@sysoev.ru app = nxt_queue_link_data(qlk, nxt_app_t, link); 614133Sigor@sysoev.ru 615133Sigor@sysoev.ru nxt_thread_mutex_destroy(&app->mutex); 616133Sigor@sysoev.ru nxt_free(app); 617133Sigor@sysoev.ru } 618133Sigor@sysoev.ru 619133Sigor@sysoev.ru return NXT_ERROR; 620133Sigor@sysoev.ru } 621133Sigor@sysoev.ru 622133Sigor@sysoev.ru 623133Sigor@sysoev.ru static nxt_app_t * 624133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 625133Sigor@sysoev.ru { 626133Sigor@sysoev.ru nxt_app_t *app; 627133Sigor@sysoev.ru nxt_queue_link_t *qlk; 628133Sigor@sysoev.ru 629133Sigor@sysoev.ru for (qlk = nxt_queue_first(queue); 630133Sigor@sysoev.ru qlk != nxt_queue_tail(queue); 631133Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 632133Sigor@sysoev.ru { 633133Sigor@sysoev.ru app = nxt_queue_link_data(qlk, nxt_app_t, link); 634133Sigor@sysoev.ru 635133Sigor@sysoev.ru if (nxt_strstr_eq(name, &app->name)) { 636133Sigor@sysoev.ru return app; 637133Sigor@sysoev.ru } 638133Sigor@sysoev.ru } 639133Sigor@sysoev.ru 640133Sigor@sysoev.ru return NULL; 641133Sigor@sysoev.ru } 642133Sigor@sysoev.ru 643133Sigor@sysoev.ru 644133Sigor@sysoev.ru static nxt_app_t * 645133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name) 646133Sigor@sysoev.ru { 647133Sigor@sysoev.ru nxt_app_t *app; 648133Sigor@sysoev.ru 649133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->apps, name); 650133Sigor@sysoev.ru 651133Sigor@sysoev.ru if (app == NULL) { 652134Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->previous, name); 653133Sigor@sysoev.ru } 654133Sigor@sysoev.ru 655133Sigor@sysoev.ru return app; 65653Sigor@sysoev.ru } 65753Sigor@sysoev.ru 65853Sigor@sysoev.ru 65953Sigor@sysoev.ru static nxt_socket_conf_t * 66065Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa) 66153Sigor@sysoev.ru { 66253Sigor@sysoev.ru nxt_socket_conf_t *conf; 66353Sigor@sysoev.ru 66465Sigor@sysoev.ru conf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); 66553Sigor@sysoev.ru if (nxt_slow_path(conf == NULL)) { 66653Sigor@sysoev.ru return NULL; 66753Sigor@sysoev.ru } 66853Sigor@sysoev.ru 669115Sigor@sysoev.ru conf->sockaddr = sa; 670115Sigor@sysoev.ru 67153Sigor@sysoev.ru conf->listen.sockaddr = sa; 672103Sigor@sysoev.ru conf->listen.socklen = sa->socklen; 673103Sigor@sysoev.ru conf->listen.address_length = sa->length; 67453Sigor@sysoev.ru 67553Sigor@sysoev.ru conf->listen.socket = -1; 67653Sigor@sysoev.ru conf->listen.backlog = NXT_LISTEN_BACKLOG; 67753Sigor@sysoev.ru conf->listen.flags = NXT_NONBLOCK; 67853Sigor@sysoev.ru conf->listen.read_after_accept = 1; 67953Sigor@sysoev.ru 68053Sigor@sysoev.ru return conf; 68153Sigor@sysoev.ru } 68253Sigor@sysoev.ru 68353Sigor@sysoev.ru 68453Sigor@sysoev.ru static void 68553Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router, 68653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 68753Sigor@sysoev.ru { 68853Sigor@sysoev.ru nxt_queue_link_t *nqlk, *oqlk, *next; 68953Sigor@sysoev.ru nxt_socket_conf_t *nskcf, *oskcf; 69053Sigor@sysoev.ru 69153Sigor@sysoev.ru for (nqlk = nxt_queue_first(&tmcf->pending); 69253Sigor@sysoev.ru nqlk != nxt_queue_tail(&tmcf->pending); 69353Sigor@sysoev.ru nqlk = next) 69453Sigor@sysoev.ru { 69553Sigor@sysoev.ru next = nxt_queue_next(nqlk); 69653Sigor@sysoev.ru nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link); 69753Sigor@sysoev.ru 69853Sigor@sysoev.ru for (oqlk = nxt_queue_first(&router->sockets); 69953Sigor@sysoev.ru oqlk != nxt_queue_tail(&router->sockets); 70053Sigor@sysoev.ru oqlk = nxt_queue_next(oqlk)) 70153Sigor@sysoev.ru { 70253Sigor@sysoev.ru oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link); 70353Sigor@sysoev.ru 704115Sigor@sysoev.ru if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) { 705115Sigor@sysoev.ru nskcf->socket = oskcf->socket; 706115Sigor@sysoev.ru nskcf->listen.socket = oskcf->listen.socket; 707115Sigor@sysoev.ru 70853Sigor@sysoev.ru nxt_queue_remove(oqlk); 70953Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->keeping, oqlk); 71053Sigor@sysoev.ru 71153Sigor@sysoev.ru nxt_queue_remove(nqlk); 71253Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->updating, nqlk); 71353Sigor@sysoev.ru 71453Sigor@sysoev.ru break; 71553Sigor@sysoev.ru } 71653Sigor@sysoev.ru } 71753Sigor@sysoev.ru } 71853Sigor@sysoev.ru 71953Sigor@sysoev.ru nxt_queue_add(&tmcf->deleting, &router->sockets); 720115Sigor@sysoev.ru nxt_queue_init(&router->sockets); 72153Sigor@sysoev.ru } 72253Sigor@sysoev.ru 72353Sigor@sysoev.ru 72453Sigor@sysoev.ru static nxt_int_t 72553Sigor@sysoev.ru nxt_router_listen_sockets_stub_create(nxt_task_t *task, 72653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 72753Sigor@sysoev.ru { 728115Sigor@sysoev.ru nxt_int_t ret; 729115Sigor@sysoev.ru nxt_socket_t s; 730115Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 731115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 732115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 73353Sigor@sysoev.ru 73453Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->pending); 73553Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->pending); 73653Sigor@sysoev.ru qlk = nqlk) 73753Sigor@sysoev.ru { 738115Sigor@sysoev.ru rtsk = nxt_malloc(sizeof(nxt_router_socket_t)); 739115Sigor@sysoev.ru if (nxt_slow_path(rtsk == NULL)) { 74053Sigor@sysoev.ru return NXT_ERROR; 74153Sigor@sysoev.ru } 74253Sigor@sysoev.ru 743115Sigor@sysoev.ru rtsk->count = 0; 744115Sigor@sysoev.ru 745115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 746115Sigor@sysoev.ru skcf->socket = rtsk; 747115Sigor@sysoev.ru 748115Sigor@sysoev.ru s = nxt_listen_socket_create0(task, skcf->sockaddr, NXT_NONBLOCK); 749115Sigor@sysoev.ru if (nxt_slow_path(s == -1)) { 750115Sigor@sysoev.ru return NXT_ERROR; 751115Sigor@sysoev.ru } 752115Sigor@sysoev.ru 753115Sigor@sysoev.ru ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 754115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 755115Sigor@sysoev.ru return NXT_ERROR; 756115Sigor@sysoev.ru } 757115Sigor@sysoev.ru 758115Sigor@sysoev.ru skcf->listen.socket = s; 759115Sigor@sysoev.ru 760115Sigor@sysoev.ru rtsk->fd = s; 761115Sigor@sysoev.ru 76253Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 76353Sigor@sysoev.ru nxt_queue_remove(qlk); 76453Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 76553Sigor@sysoev.ru } 76653Sigor@sysoev.ru 76753Sigor@sysoev.ru return NXT_OK; 76853Sigor@sysoev.ru } 76953Sigor@sysoev.ru 77053Sigor@sysoev.ru 77153Sigor@sysoev.ru static nxt_int_t 77253Sigor@sysoev.ru nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 77353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 77453Sigor@sysoev.ru { 77553Sigor@sysoev.ru nxt_int_t ret; 77653Sigor@sysoev.ru nxt_uint_t n, threads; 77753Sigor@sysoev.ru nxt_queue_link_t *qlk; 77853Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 77953Sigor@sysoev.ru 78053Sigor@sysoev.ru threads = tmcf->conf->threads; 78153Sigor@sysoev.ru 78253Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 78353Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 78453Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 78553Sigor@sysoev.ru return NXT_ERROR; 78653Sigor@sysoev.ru } 78753Sigor@sysoev.ru 78853Sigor@sysoev.ru n = 0; 78953Sigor@sysoev.ru 79053Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines); 79153Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines); 79253Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 79353Sigor@sysoev.ru { 79453Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 79553Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 79653Sigor@sysoev.ru return NXT_ERROR; 79753Sigor@sysoev.ru } 79853Sigor@sysoev.ru 799115Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 80053Sigor@sysoev.ru 80153Sigor@sysoev.ru if (n < threads) { 802115Sigor@sysoev.ru ret = nxt_router_engine_conf_update(tmcf, recf); 80353Sigor@sysoev.ru 80453Sigor@sysoev.ru } else { 805115Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(tmcf, recf); 80653Sigor@sysoev.ru } 80753Sigor@sysoev.ru 80853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 80953Sigor@sysoev.ru return ret; 81053Sigor@sysoev.ru } 81153Sigor@sysoev.ru 81253Sigor@sysoev.ru n++; 81353Sigor@sysoev.ru } 81453Sigor@sysoev.ru 81553Sigor@sysoev.ru tmcf->new_threads = n; 81653Sigor@sysoev.ru 81753Sigor@sysoev.ru while (n < threads) { 81853Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 81953Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 82053Sigor@sysoev.ru return NXT_ERROR; 82153Sigor@sysoev.ru } 82253Sigor@sysoev.ru 82353Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 82453Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) { 82553Sigor@sysoev.ru return NXT_ERROR; 82653Sigor@sysoev.ru } 82753Sigor@sysoev.ru 828115Sigor@sysoev.ru ret = nxt_router_engine_conf_create(tmcf, recf); 82953Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 83053Sigor@sysoev.ru return ret; 83153Sigor@sysoev.ru } 83253Sigor@sysoev.ru 833115Sigor@sysoev.ru nxt_queue_insert_tail(&router->engines, &recf->engine->link0); 834115Sigor@sysoev.ru 83553Sigor@sysoev.ru n++; 83653Sigor@sysoev.ru } 83753Sigor@sysoev.ru 83853Sigor@sysoev.ru return NXT_OK; 83953Sigor@sysoev.ru } 84053Sigor@sysoev.ru 84153Sigor@sysoev.ru 84253Sigor@sysoev.ru static nxt_int_t 843115Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 844115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 84553Sigor@sysoev.ru { 846115Sigor@sysoev.ru nxt_mp_t *mp; 847115Sigor@sysoev.ru nxt_int_t ret; 848115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 84953Sigor@sysoev.ru 85053Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 85153Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 85253Sigor@sysoev.ru return NXT_ERROR; 85353Sigor@sysoev.ru } 85453Sigor@sysoev.ru 855115Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 856115Sigor@sysoev.ru 857*139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->creating, 858115Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 859115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 860115Sigor@sysoev.ru return ret; 861115Sigor@sysoev.ru } 862115Sigor@sysoev.ru 863*139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->updating, 86453Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 86553Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 86653Sigor@sysoev.ru return ret; 86753Sigor@sysoev.ru } 86853Sigor@sysoev.ru 869115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 870115Sigor@sysoev.ru 871115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 872115Sigor@sysoev.ru 873115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 874115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->updating); 875115Sigor@sysoev.ru 876115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 877115Sigor@sysoev.ru 878115Sigor@sysoev.ru return ret; 87953Sigor@sysoev.ru } 88053Sigor@sysoev.ru 88153Sigor@sysoev.ru 88253Sigor@sysoev.ru static nxt_int_t 883115Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 884115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 88553Sigor@sysoev.ru { 886115Sigor@sysoev.ru nxt_mp_t *mp; 887115Sigor@sysoev.ru nxt_int_t ret; 888115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 88953Sigor@sysoev.ru 89053Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 89153Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 89253Sigor@sysoev.ru return NXT_ERROR; 89353Sigor@sysoev.ru } 89453Sigor@sysoev.ru 895115Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 896115Sigor@sysoev.ru 897*139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->creating, 89853Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 89953Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 90053Sigor@sysoev.ru return ret; 90153Sigor@sysoev.ru } 90253Sigor@sysoev.ru 90353Sigor@sysoev.ru recf->updating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 90453Sigor@sysoev.ru if (nxt_slow_path(recf->updating == NULL)) { 90553Sigor@sysoev.ru return NXT_ERROR; 90653Sigor@sysoev.ru } 90753Sigor@sysoev.ru 908*139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->updating, 90953Sigor@sysoev.ru recf->updating, nxt_router_listen_socket_update); 91053Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 91153Sigor@sysoev.ru return ret; 91253Sigor@sysoev.ru } 91353Sigor@sysoev.ru 91453Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 91553Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 91653Sigor@sysoev.ru return NXT_ERROR; 91753Sigor@sysoev.ru } 91853Sigor@sysoev.ru 919*139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 920115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 921115Sigor@sysoev.ru return ret; 922115Sigor@sysoev.ru } 923115Sigor@sysoev.ru 924115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 925115Sigor@sysoev.ru 926115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 927115Sigor@sysoev.ru 928115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 929115Sigor@sysoev.ru 930115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 931115Sigor@sysoev.ru 932115Sigor@sysoev.ru return ret; 93353Sigor@sysoev.ru } 93453Sigor@sysoev.ru 93553Sigor@sysoev.ru 93653Sigor@sysoev.ru static nxt_int_t 937115Sigor@sysoev.ru nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 938115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 93953Sigor@sysoev.ru { 94053Sigor@sysoev.ru nxt_int_t ret; 94153Sigor@sysoev.ru 94253Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 94353Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 94453Sigor@sysoev.ru return NXT_ERROR; 94553Sigor@sysoev.ru } 94653Sigor@sysoev.ru 947*139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->updating); 94853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 94953Sigor@sysoev.ru return ret; 95053Sigor@sysoev.ru } 95153Sigor@sysoev.ru 952*139Sigor@sysoev.ru return nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 95353Sigor@sysoev.ru } 95453Sigor@sysoev.ru 95553Sigor@sysoev.ru 95653Sigor@sysoev.ru static nxt_int_t 957*139Sigor@sysoev.ru nxt_router_engine_joints_create(nxt_mp_t *mp, nxt_router_temp_conf_t *tmcf, 958*139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, nxt_array_t *array, 95953Sigor@sysoev.ru nxt_work_handler_t handler) 96053Sigor@sysoev.ru { 961*139Sigor@sysoev.ru nxt_work_t *work, *back; 96253Sigor@sysoev.ru nxt_queue_link_t *qlk; 96353Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 96453Sigor@sysoev.ru 96553Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 96653Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 96753Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 96853Sigor@sysoev.ru { 969*139Sigor@sysoev.ru back = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_work_t)); 970*139Sigor@sysoev.ru if (nxt_slow_path(back == NULL)) { 971*139Sigor@sysoev.ru return NXT_ERROR; 972*139Sigor@sysoev.ru } 973*139Sigor@sysoev.ru 974*139Sigor@sysoev.ru back->next = NULL; 975*139Sigor@sysoev.ru back->handler = nxt_router_conf_wait; 976*139Sigor@sysoev.ru back->task = &tmcf->engine->task; 977*139Sigor@sysoev.ru back->obj = tmcf; 978*139Sigor@sysoev.ru back->data = NULL; 979*139Sigor@sysoev.ru 98053Sigor@sysoev.ru work = nxt_array_add(array); 98153Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 98253Sigor@sysoev.ru return NXT_ERROR; 98353Sigor@sysoev.ru } 98453Sigor@sysoev.ru 98553Sigor@sysoev.ru work->next = NULL; 98653Sigor@sysoev.ru work->handler = handler; 987*139Sigor@sysoev.ru work->task = &recf->engine->task; 988*139Sigor@sysoev.ru work->obj = back; 98953Sigor@sysoev.ru 99065Sigor@sysoev.ru joint = nxt_mp_alloc(mp, sizeof(nxt_socket_conf_joint_t)); 99153Sigor@sysoev.ru if (nxt_slow_path(joint == NULL)) { 99253Sigor@sysoev.ru return NXT_ERROR; 99353Sigor@sysoev.ru } 99453Sigor@sysoev.ru 99553Sigor@sysoev.ru work->data = joint; 99653Sigor@sysoev.ru 99753Sigor@sysoev.ru joint->count = 1; 99853Sigor@sysoev.ru joint->socket_conf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 99988Smax.romanov@nginx.com joint->engine = recf->engine; 1000115Sigor@sysoev.ru 1001115Sigor@sysoev.ru nxt_queue_insert_tail(&joint->engine->joints, &joint->link); 100253Sigor@sysoev.ru } 100353Sigor@sysoev.ru 100420Sigor@sysoev.ru return NXT_OK; 100520Sigor@sysoev.ru } 100620Sigor@sysoev.ru 100720Sigor@sysoev.ru 1008115Sigor@sysoev.ru static void 1009115Sigor@sysoev.ru nxt_router_engine_socket_count(nxt_queue_t *sockets) 1010115Sigor@sysoev.ru { 1011115Sigor@sysoev.ru nxt_queue_link_t *qlk; 1012115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1013115Sigor@sysoev.ru 1014115Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 1015115Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 1016115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 1017115Sigor@sysoev.ru { 1018115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1019115Sigor@sysoev.ru skcf->socket->count++; 1020115Sigor@sysoev.ru } 1021115Sigor@sysoev.ru } 1022115Sigor@sysoev.ru 1023115Sigor@sysoev.ru 102420Sigor@sysoev.ru static nxt_int_t 1025*139Sigor@sysoev.ru nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 1026*139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets) 102720Sigor@sysoev.ru { 1028*139Sigor@sysoev.ru nxt_work_t *work, *back; 102953Sigor@sysoev.ru nxt_queue_link_t *qlk; 103020Sigor@sysoev.ru 103153Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 103253Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 103353Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 103453Sigor@sysoev.ru { 1035*139Sigor@sysoev.ru back = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_work_t)); 1036*139Sigor@sysoev.ru if (nxt_slow_path(back == NULL)) { 1037*139Sigor@sysoev.ru return NXT_ERROR; 1038*139Sigor@sysoev.ru } 1039*139Sigor@sysoev.ru 1040*139Sigor@sysoev.ru back->next = NULL; 1041*139Sigor@sysoev.ru back->handler = nxt_router_conf_wait; 1042*139Sigor@sysoev.ru back->task = &tmcf->engine->task; 1043*139Sigor@sysoev.ru back->obj = tmcf; 1044*139Sigor@sysoev.ru back->data = NULL; 1045*139Sigor@sysoev.ru 1046115Sigor@sysoev.ru work = nxt_array_add(recf->deleting); 104753Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 104853Sigor@sysoev.ru return NXT_ERROR; 104953Sigor@sysoev.ru } 105020Sigor@sysoev.ru 105153Sigor@sysoev.ru work->next = NULL; 105253Sigor@sysoev.ru work->handler = nxt_router_listen_socket_delete; 1053*139Sigor@sysoev.ru work->task = &recf->engine->task; 1054*139Sigor@sysoev.ru work->obj = back; 105553Sigor@sysoev.ru work->data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1056