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 { 13*133Sigor@sysoev.ru nxt_str_t type; 14*133Sigor@sysoev.ru uint32_t workers; 15*133Sigor@sysoev.ru } nxt_router_app_conf_t; 16*133Sigor@sysoev.ru 17*133Sigor@sysoev.ru 18*133Sigor@sysoev.ru typedef struct { 19*133Sigor@sysoev.ru nxt_str_t application; 20115Sigor@sysoev.ru } nxt_router_listener_conf_t; 21115Sigor@sysoev.ru 22115Sigor@sysoev.ru 2353Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task, 2453Sigor@sysoev.ru nxt_router_t *router); 2553Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router, 2653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 2753Sigor@sysoev.ru 28115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 29115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 30*133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 31*133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, 32*133Sigor@sysoev.ru nxt_str_t *name); 3353Sigor@sysoev.ru static nxt_int_t nxt_router_listen_sockets_stub_create(nxt_task_t *task, 3453Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 3565Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, 3665Sigor@sysoev.ru nxt_sockaddr_t *sa); 3753Sigor@sysoev.ru 3853Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 3953Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 4053Sigor@sysoev.ru const nxt_event_interface_t *interface); 41115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 42115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 43115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 44115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 45115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 46115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 47115Sigor@sysoev.ru static void nxt_router_engine_socket_count(nxt_queue_t *sockets); 48115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_mp_t *mp, 4965Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, nxt_array_t *array, 5065Sigor@sysoev.ru nxt_work_handler_t handler); 51115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_engine_conf_t *recf, 52115Sigor@sysoev.ru nxt_queue_t *sockets); 5353Sigor@sysoev.ru 5453Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 5553Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 5653Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 5753Sigor@sysoev.ru nxt_event_engine_t *engine); 58*133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router, 59*133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 6053Sigor@sysoev.ru 6153Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_temp_conf_t *tmcf); 6253Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_engine_conf_t *recf); 6353Sigor@sysoev.ru 6453Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 6553Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 6653Sigor@sysoev.ru void *data); 6753Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 6853Sigor@sysoev.ru void *data); 6953Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 7053Sigor@sysoev.ru void *data); 7153Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 7253Sigor@sysoev.ru void *data); 7353Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 7453Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 7553Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 7653Sigor@sysoev.ru void *data); 7753Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 7853Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 7953Sigor@sysoev.ru 8053Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data); 8153Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, 8253Sigor@sysoev.ru void *data); 8388Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task, 8488Smax.romanov@nginx.com nxt_conn_t *c, nxt_app_parse_ctx_t *ap); 8588Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data); 8653Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); 8753Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); 8853Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data); 8953Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data); 9062Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data); 9120Sigor@sysoev.ru 92119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 9320Sigor@sysoev.ru 9420Sigor@sysoev.ru nxt_int_t 9520Sigor@sysoev.ru nxt_router_start(nxt_task_t *task, nxt_runtime_t *rt) 9620Sigor@sysoev.ru { 97115Sigor@sysoev.ru nxt_int_t ret; 98115Sigor@sysoev.ru nxt_router_t *router; 9953Sigor@sysoev.ru 10088Smax.romanov@nginx.com ret = nxt_app_http_init(task, rt); 10188Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 10288Smax.romanov@nginx.com return ret; 10388Smax.romanov@nginx.com } 10488Smax.romanov@nginx.com 10553Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 10653Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 10753Sigor@sysoev.ru return NXT_ERROR; 10853Sigor@sysoev.ru } 10953Sigor@sysoev.ru 11053Sigor@sysoev.ru nxt_queue_init(&router->engines); 11153Sigor@sysoev.ru nxt_queue_init(&router->sockets); 112*133Sigor@sysoev.ru nxt_queue_init(&router->apps); 11353Sigor@sysoev.ru 114119Smax.romanov@nginx.com nxt_router = router; 115119Smax.romanov@nginx.com 116115Sigor@sysoev.ru return NXT_OK; 117115Sigor@sysoev.ru } 118115Sigor@sysoev.ru 119115Sigor@sysoev.ru 120115Sigor@sysoev.ru nxt_int_t 121115Sigor@sysoev.ru nxt_router_new_conf(nxt_task_t *task, nxt_runtime_t *rt, nxt_router_t *router, 122115Sigor@sysoev.ru u_char *start, u_char *end) 123115Sigor@sysoev.ru { 124115Sigor@sysoev.ru nxt_int_t ret; 125115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 126115Sigor@sysoev.ru const nxt_event_interface_t *interface; 12753Sigor@sysoev.ru 12853Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task, router); 12953Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 13020Sigor@sysoev.ru return NXT_ERROR; 13120Sigor@sysoev.ru } 13220Sigor@sysoev.ru 133115Sigor@sysoev.ru ret = nxt_router_conf_create(task, tmcf, start, end); 13453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 13553Sigor@sysoev.ru return ret; 13653Sigor@sysoev.ru } 13753Sigor@sysoev.ru 13853Sigor@sysoev.ru nxt_router_listen_sockets_sort(router, tmcf); 13953Sigor@sysoev.ru 14053Sigor@sysoev.ru ret = nxt_router_listen_sockets_stub_create(task, tmcf); 14153Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 14253Sigor@sysoev.ru return ret; 14353Sigor@sysoev.ru } 14453Sigor@sysoev.ru 14553Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 14653Sigor@sysoev.ru 14753Sigor@sysoev.ru ret = nxt_router_engines_create(task, router, tmcf, interface); 14853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 14953Sigor@sysoev.ru return ret; 15053Sigor@sysoev.ru } 15153Sigor@sysoev.ru 15253Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf); 15353Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 15453Sigor@sysoev.ru return ret; 15553Sigor@sysoev.ru } 15653Sigor@sysoev.ru 157*133Sigor@sysoev.ru nxt_router_apps_sort(router, tmcf); 158*133Sigor@sysoev.ru 15953Sigor@sysoev.ru nxt_router_engines_post(tmcf); 16053Sigor@sysoev.ru 16153Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->updating); 16253Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->creating); 16353Sigor@sysoev.ru 164115Sigor@sysoev.ru // nxt_mp_destroy(tmcf->mem_pool); 165115Sigor@sysoev.ru 16653Sigor@sysoev.ru return NXT_OK; 16753Sigor@sysoev.ru } 16853Sigor@sysoev.ru 16953Sigor@sysoev.ru 17053Sigor@sysoev.ru static nxt_router_temp_conf_t * 17153Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task, nxt_router_t *router) 17253Sigor@sysoev.ru { 17365Sigor@sysoev.ru nxt_mp_t *mp, *tmp; 17453Sigor@sysoev.ru nxt_router_conf_t *rtcf; 17553Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 17653Sigor@sysoev.ru 17765Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 17853Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 17953Sigor@sysoev.ru return NULL; 18053Sigor@sysoev.ru } 18153Sigor@sysoev.ru 18265Sigor@sysoev.ru rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 18353Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) { 18453Sigor@sysoev.ru goto fail; 18553Sigor@sysoev.ru } 18653Sigor@sysoev.ru 18753Sigor@sysoev.ru rtcf->mem_pool = mp; 18853Sigor@sysoev.ru rtcf->router = router; 18953Sigor@sysoev.ru rtcf->count = 1; 19053Sigor@sysoev.ru 19165Sigor@sysoev.ru tmp = nxt_mp_create(1024, 128, 256, 32); 19253Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) { 19353Sigor@sysoev.ru goto fail; 19453Sigor@sysoev.ru } 19553Sigor@sysoev.ru 19665Sigor@sysoev.ru tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 19753Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 19853Sigor@sysoev.ru goto temp_fail; 19953Sigor@sysoev.ru } 20053Sigor@sysoev.ru 20153Sigor@sysoev.ru tmcf->mem_pool = tmp; 20253Sigor@sysoev.ru tmcf->conf = rtcf; 20353Sigor@sysoev.ru 20453Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 20553Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 20653Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 20753Sigor@sysoev.ru goto temp_fail; 20853Sigor@sysoev.ru } 20953Sigor@sysoev.ru 21053Sigor@sysoev.ru nxt_queue_init(&tmcf->deleting); 21153Sigor@sysoev.ru nxt_queue_init(&tmcf->keeping); 21253Sigor@sysoev.ru nxt_queue_init(&tmcf->updating); 21353Sigor@sysoev.ru nxt_queue_init(&tmcf->pending); 21453Sigor@sysoev.ru nxt_queue_init(&tmcf->creating); 215*133Sigor@sysoev.ru nxt_queue_init(&tmcf->apps); 216*133Sigor@sysoev.ru nxt_queue_init(&tmcf->previous); 21753Sigor@sysoev.ru 21853Sigor@sysoev.ru return tmcf; 21953Sigor@sysoev.ru 22053Sigor@sysoev.ru temp_fail: 22153Sigor@sysoev.ru 22265Sigor@sysoev.ru nxt_mp_destroy(tmp); 22353Sigor@sysoev.ru 22453Sigor@sysoev.ru fail: 22553Sigor@sysoev.ru 22665Sigor@sysoev.ru nxt_mp_destroy(mp); 22753Sigor@sysoev.ru 22853Sigor@sysoev.ru return NULL; 22953Sigor@sysoev.ru } 23053Sigor@sysoev.ru 23153Sigor@sysoev.ru 232115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = { 233115Sigor@sysoev.ru { 234*133Sigor@sysoev.ru nxt_string("listeners_threads"), 235115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 236115Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads), 237115Sigor@sysoev.ru }, 238115Sigor@sysoev.ru 239115Sigor@sysoev.ru { 240115Sigor@sysoev.ru nxt_null_string, 0, 0, 241115Sigor@sysoev.ru }, 242115Sigor@sysoev.ru }; 243115Sigor@sysoev.ru 244115Sigor@sysoev.ru 245*133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = { 246115Sigor@sysoev.ru { 247*133Sigor@sysoev.ru nxt_string("type"), 248115Sigor@sysoev.ru NXT_CONF_MAP_STR, 249*133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type), 250115Sigor@sysoev.ru }, 251115Sigor@sysoev.ru 252115Sigor@sysoev.ru { 253*133Sigor@sysoev.ru nxt_string("workers"), 254115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 255*133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, workers), 256*133Sigor@sysoev.ru }, 257*133Sigor@sysoev.ru 258*133Sigor@sysoev.ru { 259*133Sigor@sysoev.ru nxt_null_string, 0, 0, 260*133Sigor@sysoev.ru }, 261*133Sigor@sysoev.ru }; 262*133Sigor@sysoev.ru 263*133Sigor@sysoev.ru 264*133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_listener_conf[] = { 265*133Sigor@sysoev.ru { 266*133Sigor@sysoev.ru nxt_string("application"), 267*133Sigor@sysoev.ru NXT_CONF_MAP_STR, 268*133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application), 269115Sigor@sysoev.ru }, 270115Sigor@sysoev.ru 271115Sigor@sysoev.ru { 272115Sigor@sysoev.ru nxt_null_string, 0, 0, 273115Sigor@sysoev.ru }, 274115Sigor@sysoev.ru }; 275115Sigor@sysoev.ru 276115Sigor@sysoev.ru 277115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = { 278115Sigor@sysoev.ru { 279115Sigor@sysoev.ru nxt_string("header_buffer_size"), 280115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 281115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size), 282115Sigor@sysoev.ru }, 283115Sigor@sysoev.ru 284115Sigor@sysoev.ru { 285115Sigor@sysoev.ru nxt_string("large_header_buffer_size"), 286115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 287115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size), 288115Sigor@sysoev.ru }, 289115Sigor@sysoev.ru 290115Sigor@sysoev.ru { 291115Sigor@sysoev.ru nxt_string("header_read_timeout"), 292115Sigor@sysoev.ru NXT_CONF_MAP_MSEC, 293115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout), 294115Sigor@sysoev.ru }, 295115Sigor@sysoev.ru 296115Sigor@sysoev.ru { 297115Sigor@sysoev.ru nxt_null_string, 0, 0, 298115Sigor@sysoev.ru }, 299115Sigor@sysoev.ru }; 300115Sigor@sysoev.ru 301115Sigor@sysoev.ru 30253Sigor@sysoev.ru static nxt_int_t 303115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 304115Sigor@sysoev.ru u_char *start, u_char *end) 30553Sigor@sysoev.ru { 306*133Sigor@sysoev.ru u_char *p; 307*133Sigor@sysoev.ru size_t size; 308115Sigor@sysoev.ru nxt_mp_t *mp; 309115Sigor@sysoev.ru uint32_t next; 310115Sigor@sysoev.ru nxt_int_t ret; 311115Sigor@sysoev.ru nxt_str_t name; 312*133Sigor@sysoev.ru nxt_app_t *app, *prev; 313*133Sigor@sysoev.ru nxt_app_type_t type; 314115Sigor@sysoev.ru nxt_sockaddr_t *sa; 315*133Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 316*133Sigor@sysoev.ru nxt_conf_value_t *conf, *http; 317*133Sigor@sysoev.ru nxt_conf_value_t *applications, *application; 318*133Sigor@sysoev.ru nxt_conf_value_t *listeners, *listener; 319115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 320*133Sigor@sysoev.ru nxt_router_app_conf_t apcf; 321115Sigor@sysoev.ru nxt_router_listener_conf_t lscf; 322115Sigor@sysoev.ru 323115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/http"); 324*133Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications"); 325115Sigor@sysoev.ru static nxt_str_t listeners_path = nxt_string("/listeners"); 326115Sigor@sysoev.ru 327115Sigor@sysoev.ru conf = nxt_conf_json_parse(tmcf->mem_pool, start, end); 328115Sigor@sysoev.ru if (conf == NULL) { 329115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "configuration parsing error"); 330115Sigor@sysoev.ru return NXT_ERROR; 331115Sigor@sysoev.ru } 332115Sigor@sysoev.ru 333*133Sigor@sysoev.ru ret = nxt_conf_map_object(conf, nxt_router_conf, tmcf->conf); 334115Sigor@sysoev.ru if (ret != NXT_OK) { 335*133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "root map error"); 336115Sigor@sysoev.ru return NXT_ERROR; 337115Sigor@sysoev.ru } 338115Sigor@sysoev.ru 339117Sigor@sysoev.ru if (tmcf->conf->threads == 0) { 340117Sigor@sysoev.ru tmcf->conf->threads = nxt_ncpu; 341117Sigor@sysoev.ru } 342117Sigor@sysoev.ru 343*133Sigor@sysoev.ru applications = nxt_conf_get_path(conf, &applications_path); 344*133Sigor@sysoev.ru if (applications == NULL) { 345*133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block"); 346115Sigor@sysoev.ru return NXT_ERROR; 347115Sigor@sysoev.ru } 348115Sigor@sysoev.ru 349*133Sigor@sysoev.ru next = 0; 350*133Sigor@sysoev.ru 351*133Sigor@sysoev.ru for ( ;; ) { 352*133Sigor@sysoev.ru application = nxt_conf_next_object_member(applications, &name, &next); 353*133Sigor@sysoev.ru if (application == NULL) { 354*133Sigor@sysoev.ru break; 355*133Sigor@sysoev.ru } 356*133Sigor@sysoev.ru 357*133Sigor@sysoev.ru nxt_debug(task, "application \"%V\"", &name); 358*133Sigor@sysoev.ru 359*133Sigor@sysoev.ru app = nxt_zalloc(sizeof(nxt_app_t)); 360*133Sigor@sysoev.ru if (app == NULL) { 361*133Sigor@sysoev.ru goto fail; 362*133Sigor@sysoev.ru } 363*133Sigor@sysoev.ru 364*133Sigor@sysoev.ru size = nxt_conf_json_length(application, NULL); 365*133Sigor@sysoev.ru 366*133Sigor@sysoev.ru app->conf.start = nxt_malloc(size); 367*133Sigor@sysoev.ru if (app->conf.start == NULL) { 368*133Sigor@sysoev.ru nxt_free(app); 369*133Sigor@sysoev.ru goto fail; 370*133Sigor@sysoev.ru } 371*133Sigor@sysoev.ru 372*133Sigor@sysoev.ru p = nxt_conf_json_print(app->conf.start, application, NULL); 373*133Sigor@sysoev.ru app->conf.length = p - app->conf.start; 374*133Sigor@sysoev.ru 375*133Sigor@sysoev.ru nxt_debug(task, "application conf \"%V\"", &app->conf); 376*133Sigor@sysoev.ru 377*133Sigor@sysoev.ru prev = nxt_router_app_find(&tmcf->conf->router->apps, &name); 378*133Sigor@sysoev.ru 379*133Sigor@sysoev.ru if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 380*133Sigor@sysoev.ru nxt_free(app->conf.start); 381*133Sigor@sysoev.ru nxt_free(app); 382*133Sigor@sysoev.ru 383*133Sigor@sysoev.ru nxt_queue_remove(&prev->link); 384*133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->previous, &prev->link); 385*133Sigor@sysoev.ru continue; 386*133Sigor@sysoev.ru } 387*133Sigor@sysoev.ru 388*133Sigor@sysoev.ru ret = nxt_conf_map_object(application, nxt_router_app_conf, &apcf); 389*133Sigor@sysoev.ru if (ret != NXT_OK) { 390*133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "application map error"); 391*133Sigor@sysoev.ru goto app_fail; 392*133Sigor@sysoev.ru } 393115Sigor@sysoev.ru 394*133Sigor@sysoev.ru nxt_debug(task, "application type: %V", &apcf.type); 395*133Sigor@sysoev.ru nxt_debug(task, "application workers: %D", apcf.workers); 396*133Sigor@sysoev.ru 397*133Sigor@sysoev.ru if (nxt_str_eq(&apcf.type, "python", 6)) { 398*133Sigor@sysoev.ru type = NXT_APP_PYTHON; 399*133Sigor@sysoev.ru 400*133Sigor@sysoev.ru } else if (nxt_str_eq(&apcf.type, "php", 3)) { 401*133Sigor@sysoev.ru type = NXT_APP_PHP; 402*133Sigor@sysoev.ru 403*133Sigor@sysoev.ru } else if (nxt_str_eq(&apcf.type, "ruby", 4)) { 404*133Sigor@sysoev.ru type = NXT_APP_RUBY; 405*133Sigor@sysoev.ru 406*133Sigor@sysoev.ru } else if (nxt_str_eq(&apcf.type, "go", 2)) { 407*133Sigor@sysoev.ru type = NXT_APP_GO; 408*133Sigor@sysoev.ru 409*133Sigor@sysoev.ru } else { 410*133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", 411*133Sigor@sysoev.ru &apcf.type); 412*133Sigor@sysoev.ru goto app_fail; 413*133Sigor@sysoev.ru } 414*133Sigor@sysoev.ru 415*133Sigor@sysoev.ru ret = nxt_thread_mutex_create(&app->mutex); 416*133Sigor@sysoev.ru if (ret != NXT_OK) { 417*133Sigor@sysoev.ru goto app_fail; 418*133Sigor@sysoev.ru } 419*133Sigor@sysoev.ru 420*133Sigor@sysoev.ru app->name = name; 421*133Sigor@sysoev.ru app->type = type; 422*133Sigor@sysoev.ru app->max_workers = apcf.workers; 423*133Sigor@sysoev.ru app->live = 1; 424*133Sigor@sysoev.ru 425*133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->apps, &app->link); 426*133Sigor@sysoev.ru } 427*133Sigor@sysoev.ru 428*133Sigor@sysoev.ru http = nxt_conf_get_path(conf, &http_path); 429*133Sigor@sysoev.ru #if 0 430*133Sigor@sysoev.ru if (http == NULL) { 431*133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"http\" block"); 432*133Sigor@sysoev.ru return NXT_ERROR; 433*133Sigor@sysoev.ru } 434*133Sigor@sysoev.ru #endif 435*133Sigor@sysoev.ru 436*133Sigor@sysoev.ru listeners = nxt_conf_get_path(conf, &listeners_path); 437115Sigor@sysoev.ru if (listeners == NULL) { 438*133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block"); 439115Sigor@sysoev.ru return NXT_ERROR; 440115Sigor@sysoev.ru } 44153Sigor@sysoev.ru 442*133Sigor@sysoev.ru next = 0; 44353Sigor@sysoev.ru 444*133Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 445115Sigor@sysoev.ru 446115Sigor@sysoev.ru for ( ;; ) { 447115Sigor@sysoev.ru listener = nxt_conf_next_object_member(listeners, &name, &next); 448115Sigor@sysoev.ru if (listener == NULL) { 449115Sigor@sysoev.ru break; 450115Sigor@sysoev.ru } 45153Sigor@sysoev.ru 452115Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 453115Sigor@sysoev.ru if (sa == NULL) { 454115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name); 455*133Sigor@sysoev.ru goto fail; 456115Sigor@sysoev.ru } 457115Sigor@sysoev.ru 458115Sigor@sysoev.ru sa->type = SOCK_STREAM; 459115Sigor@sysoev.ru 460115Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"", 461115Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa)); 46253Sigor@sysoev.ru 463115Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 464115Sigor@sysoev.ru if (skcf == NULL) { 465*133Sigor@sysoev.ru goto fail; 466115Sigor@sysoev.ru } 46753Sigor@sysoev.ru 468115Sigor@sysoev.ru ret = nxt_conf_map_object(listener, nxt_router_listener_conf, &lscf); 469115Sigor@sysoev.ru if (ret != NXT_OK) { 470115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "listener map error"); 471*133Sigor@sysoev.ru goto fail; 472115Sigor@sysoev.ru } 47353Sigor@sysoev.ru 474*133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application); 475*133Sigor@sysoev.ru 476*133Sigor@sysoev.ru // STUB, default values if http block is not defined. 477*133Sigor@sysoev.ru skcf->header_buffer_size = 2048; 478*133Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 479*133Sigor@sysoev.ru skcf->header_read_timeout = 5000; 48053Sigor@sysoev.ru 481*133Sigor@sysoev.ru if (http != NULL) { 482*133Sigor@sysoev.ru ret = nxt_conf_map_object(http, nxt_router_http_conf, skcf); 483*133Sigor@sysoev.ru if (ret != NXT_OK) { 484*133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "http map error"); 485*133Sigor@sysoev.ru goto fail; 486*133Sigor@sysoev.ru } 487115Sigor@sysoev.ru } 488115Sigor@sysoev.ru 489115Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 490115Sigor@sysoev.ru skcf->router_conf = tmcf->conf; 491*133Sigor@sysoev.ru skcf->application = nxt_router_listener_application(tmcf, 492*133Sigor@sysoev.ru &lscf.application); 493115Sigor@sysoev.ru 494115Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 495115Sigor@sysoev.ru } 49653Sigor@sysoev.ru 49753Sigor@sysoev.ru return NXT_OK; 498*133Sigor@sysoev.ru 499*133Sigor@sysoev.ru app_fail: 500*133Sigor@sysoev.ru 501*133Sigor@sysoev.ru nxt_free(app->conf.start); 502*133Sigor@sysoev.ru nxt_free(app); 503*133Sigor@sysoev.ru 504*133Sigor@sysoev.ru fail: 505*133Sigor@sysoev.ru 506*133Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->apps); 507*133Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->apps); 508*133Sigor@sysoev.ru qlk = nqlk) 509*133Sigor@sysoev.ru { 510*133Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 511*133Sigor@sysoev.ru app = nxt_queue_link_data(qlk, nxt_app_t, link); 512*133Sigor@sysoev.ru 513*133Sigor@sysoev.ru nxt_thread_mutex_destroy(&app->mutex); 514*133Sigor@sysoev.ru nxt_free(app); 515*133Sigor@sysoev.ru } 516*133Sigor@sysoev.ru 517*133Sigor@sysoev.ru return NXT_ERROR; 518*133Sigor@sysoev.ru } 519*133Sigor@sysoev.ru 520*133Sigor@sysoev.ru 521*133Sigor@sysoev.ru static nxt_app_t * 522*133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 523*133Sigor@sysoev.ru { 524*133Sigor@sysoev.ru nxt_app_t *app; 525*133Sigor@sysoev.ru nxt_queue_link_t *qlk; 526*133Sigor@sysoev.ru 527*133Sigor@sysoev.ru for (qlk = nxt_queue_first(queue); 528*133Sigor@sysoev.ru qlk != nxt_queue_tail(queue); 529*133Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 530*133Sigor@sysoev.ru { 531*133Sigor@sysoev.ru app = nxt_queue_link_data(qlk, nxt_app_t, link); 532*133Sigor@sysoev.ru 533*133Sigor@sysoev.ru if (nxt_strstr_eq(name, &app->name)) { 534*133Sigor@sysoev.ru return app; 535*133Sigor@sysoev.ru } 536*133Sigor@sysoev.ru } 537*133Sigor@sysoev.ru 538*133Sigor@sysoev.ru return NULL; 539*133Sigor@sysoev.ru } 540*133Sigor@sysoev.ru 541*133Sigor@sysoev.ru 542*133Sigor@sysoev.ru static nxt_app_t * 543*133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name) 544*133Sigor@sysoev.ru { 545*133Sigor@sysoev.ru nxt_app_t *app; 546*133Sigor@sysoev.ru 547*133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->apps, name); 548*133Sigor@sysoev.ru 549*133Sigor@sysoev.ru if (app == NULL) { 550*133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->conf->router->apps, name); 551*133Sigor@sysoev.ru } 552*133Sigor@sysoev.ru 553*133Sigor@sysoev.ru return app; 55453Sigor@sysoev.ru } 55553Sigor@sysoev.ru 55653Sigor@sysoev.ru 55753Sigor@sysoev.ru static nxt_socket_conf_t * 55865Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa) 55953Sigor@sysoev.ru { 56053Sigor@sysoev.ru nxt_socket_conf_t *conf; 56153Sigor@sysoev.ru 56265Sigor@sysoev.ru conf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); 56353Sigor@sysoev.ru if (nxt_slow_path(conf == NULL)) { 56453Sigor@sysoev.ru return NULL; 56553Sigor@sysoev.ru } 56653Sigor@sysoev.ru 567115Sigor@sysoev.ru conf->sockaddr = sa; 568115Sigor@sysoev.ru 56953Sigor@sysoev.ru conf->listen.sockaddr = sa; 570103Sigor@sysoev.ru conf->listen.socklen = sa->socklen; 571103Sigor@sysoev.ru conf->listen.address_length = sa->length; 57253Sigor@sysoev.ru 57353Sigor@sysoev.ru conf->listen.socket = -1; 57453Sigor@sysoev.ru conf->listen.backlog = NXT_LISTEN_BACKLOG; 57553Sigor@sysoev.ru conf->listen.flags = NXT_NONBLOCK; 57653Sigor@sysoev.ru conf->listen.read_after_accept = 1; 57753Sigor@sysoev.ru 57853Sigor@sysoev.ru return conf; 57953Sigor@sysoev.ru } 58053Sigor@sysoev.ru 58153Sigor@sysoev.ru 58253Sigor@sysoev.ru static void 58353Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router, 58453Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 58553Sigor@sysoev.ru { 58653Sigor@sysoev.ru nxt_queue_link_t *nqlk, *oqlk, *next; 58753Sigor@sysoev.ru nxt_socket_conf_t *nskcf, *oskcf; 58853Sigor@sysoev.ru 58953Sigor@sysoev.ru for (nqlk = nxt_queue_first(&tmcf->pending); 59053Sigor@sysoev.ru nqlk != nxt_queue_tail(&tmcf->pending); 59153Sigor@sysoev.ru nqlk = next) 59253Sigor@sysoev.ru { 59353Sigor@sysoev.ru next = nxt_queue_next(nqlk); 59453Sigor@sysoev.ru nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link); 59553Sigor@sysoev.ru 59653Sigor@sysoev.ru for (oqlk = nxt_queue_first(&router->sockets); 59753Sigor@sysoev.ru oqlk != nxt_queue_tail(&router->sockets); 59853Sigor@sysoev.ru oqlk = nxt_queue_next(oqlk)) 59953Sigor@sysoev.ru { 60053Sigor@sysoev.ru oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link); 60153Sigor@sysoev.ru 602115Sigor@sysoev.ru if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) { 603115Sigor@sysoev.ru nskcf->socket = oskcf->socket; 604115Sigor@sysoev.ru nskcf->listen.socket = oskcf->listen.socket; 605115Sigor@sysoev.ru 60653Sigor@sysoev.ru nxt_queue_remove(oqlk); 60753Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->keeping, oqlk); 60853Sigor@sysoev.ru 60953Sigor@sysoev.ru nxt_queue_remove(nqlk); 61053Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->updating, nqlk); 61153Sigor@sysoev.ru 61253Sigor@sysoev.ru break; 61353Sigor@sysoev.ru } 61453Sigor@sysoev.ru } 61553Sigor@sysoev.ru } 61653Sigor@sysoev.ru 61753Sigor@sysoev.ru nxt_queue_add(&tmcf->deleting, &router->sockets); 618115Sigor@sysoev.ru nxt_queue_init(&router->sockets); 61953Sigor@sysoev.ru } 62053Sigor@sysoev.ru 62153Sigor@sysoev.ru 62253Sigor@sysoev.ru static nxt_int_t 62353Sigor@sysoev.ru nxt_router_listen_sockets_stub_create(nxt_task_t *task, 62453Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 62553Sigor@sysoev.ru { 626115Sigor@sysoev.ru nxt_int_t ret; 627115Sigor@sysoev.ru nxt_socket_t s; 628115Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 629115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 630115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 63153Sigor@sysoev.ru 63253Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->pending); 63353Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->pending); 63453Sigor@sysoev.ru qlk = nqlk) 63553Sigor@sysoev.ru { 636115Sigor@sysoev.ru rtsk = nxt_malloc(sizeof(nxt_router_socket_t)); 637115Sigor@sysoev.ru if (nxt_slow_path(rtsk == NULL)) { 63853Sigor@sysoev.ru return NXT_ERROR; 63953Sigor@sysoev.ru } 64053Sigor@sysoev.ru 641115Sigor@sysoev.ru rtsk->count = 0; 642115Sigor@sysoev.ru 643115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 644115Sigor@sysoev.ru skcf->socket = rtsk; 645115Sigor@sysoev.ru 646115Sigor@sysoev.ru s = nxt_listen_socket_create0(task, skcf->sockaddr, NXT_NONBLOCK); 647115Sigor@sysoev.ru if (nxt_slow_path(s == -1)) { 648115Sigor@sysoev.ru return NXT_ERROR; 649115Sigor@sysoev.ru } 650115Sigor@sysoev.ru 651115Sigor@sysoev.ru ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 652115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 653115Sigor@sysoev.ru return NXT_ERROR; 654115Sigor@sysoev.ru } 655115Sigor@sysoev.ru 656115Sigor@sysoev.ru skcf->listen.socket = s; 657115Sigor@sysoev.ru 658115Sigor@sysoev.ru rtsk->fd = s; 659115Sigor@sysoev.ru 66053Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 66153Sigor@sysoev.ru nxt_queue_remove(qlk); 66253Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 66353Sigor@sysoev.ru } 66453Sigor@sysoev.ru 66553Sigor@sysoev.ru return NXT_OK; 66653Sigor@sysoev.ru } 66753Sigor@sysoev.ru 66853Sigor@sysoev.ru 66953Sigor@sysoev.ru static nxt_int_t 67053Sigor@sysoev.ru nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 67153Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 67253Sigor@sysoev.ru { 67353Sigor@sysoev.ru nxt_int_t ret; 67453Sigor@sysoev.ru nxt_uint_t n, threads; 67553Sigor@sysoev.ru nxt_queue_link_t *qlk; 67653Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 67753Sigor@sysoev.ru 67853Sigor@sysoev.ru threads = tmcf->conf->threads; 67953Sigor@sysoev.ru 68053Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 68153Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 68253Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 68353Sigor@sysoev.ru return NXT_ERROR; 68453Sigor@sysoev.ru } 68553Sigor@sysoev.ru 68653Sigor@sysoev.ru n = 0; 68753Sigor@sysoev.ru 68853Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines); 68953Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines); 69053Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 69153Sigor@sysoev.ru { 69253Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 69353Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 69453Sigor@sysoev.ru return NXT_ERROR; 69553Sigor@sysoev.ru } 69653Sigor@sysoev.ru 697115Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 69853Sigor@sysoev.ru // STUB 69953Sigor@sysoev.ru recf->task = recf->engine->task; 70053Sigor@sysoev.ru 70153Sigor@sysoev.ru if (n < threads) { 702115Sigor@sysoev.ru ret = nxt_router_engine_conf_update(tmcf, recf); 70353Sigor@sysoev.ru 70453Sigor@sysoev.ru } else { 705115Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(tmcf, recf); 70653Sigor@sysoev.ru } 70753Sigor@sysoev.ru 70853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 70953Sigor@sysoev.ru return ret; 71053Sigor@sysoev.ru } 71153Sigor@sysoev.ru 71253Sigor@sysoev.ru n++; 71353Sigor@sysoev.ru } 71453Sigor@sysoev.ru 71553Sigor@sysoev.ru tmcf->new_threads = n; 71653Sigor@sysoev.ru 71753Sigor@sysoev.ru while (n < threads) { 71853Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 71953Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 72053Sigor@sysoev.ru return NXT_ERROR; 72153Sigor@sysoev.ru } 72253Sigor@sysoev.ru 72353Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 72453Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) { 72553Sigor@sysoev.ru return NXT_ERROR; 72653Sigor@sysoev.ru } 72753Sigor@sysoev.ru // STUB 72853Sigor@sysoev.ru recf->task = recf->engine->task; 72953Sigor@sysoev.ru 730115Sigor@sysoev.ru ret = nxt_router_engine_conf_create(tmcf, recf); 73153Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 73253Sigor@sysoev.ru return ret; 73353Sigor@sysoev.ru } 73453Sigor@sysoev.ru 735115Sigor@sysoev.ru nxt_queue_insert_tail(&router->engines, &recf->engine->link0); 736115Sigor@sysoev.ru 73753Sigor@sysoev.ru n++; 73853Sigor@sysoev.ru } 73953Sigor@sysoev.ru 74053Sigor@sysoev.ru return NXT_OK; 74153Sigor@sysoev.ru } 74253Sigor@sysoev.ru 74353Sigor@sysoev.ru 74453Sigor@sysoev.ru static nxt_int_t 745115Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 746115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 74753Sigor@sysoev.ru { 748115Sigor@sysoev.ru nxt_mp_t *mp; 749115Sigor@sysoev.ru nxt_int_t ret; 750115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 75153Sigor@sysoev.ru 75253Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 75353Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 75453Sigor@sysoev.ru return NXT_ERROR; 75553Sigor@sysoev.ru } 75653Sigor@sysoev.ru 757115Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 758115Sigor@sysoev.ru 759115Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, recf, &tmcf->creating, 760115Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 761115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 762115Sigor@sysoev.ru return ret; 763115Sigor@sysoev.ru } 764115Sigor@sysoev.ru 765115Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, recf, &tmcf->updating, 76653Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 76753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 76853Sigor@sysoev.ru return ret; 76953Sigor@sysoev.ru } 77053Sigor@sysoev.ru 771115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 772115Sigor@sysoev.ru 773115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 774115Sigor@sysoev.ru 775115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 776115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->updating); 777115Sigor@sysoev.ru 778115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 779115Sigor@sysoev.ru 780115Sigor@sysoev.ru return ret; 78153Sigor@sysoev.ru } 78253Sigor@sysoev.ru 78353Sigor@sysoev.ru 78453Sigor@sysoev.ru static nxt_int_t 785115Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 786115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 78753Sigor@sysoev.ru { 788115Sigor@sysoev.ru nxt_mp_t *mp; 789115Sigor@sysoev.ru nxt_int_t ret; 790115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 79153Sigor@sysoev.ru 79253Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 79353Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 79453Sigor@sysoev.ru return NXT_ERROR; 79553Sigor@sysoev.ru } 79653Sigor@sysoev.ru 797115Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 798115Sigor@sysoev.ru 799115Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, recf, &tmcf->creating, 80053Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 80153Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 80253Sigor@sysoev.ru return ret; 80353Sigor@sysoev.ru } 80453Sigor@sysoev.ru 80553Sigor@sysoev.ru recf->updating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 80653Sigor@sysoev.ru if (nxt_slow_path(recf->updating == NULL)) { 80753Sigor@sysoev.ru return NXT_ERROR; 80853Sigor@sysoev.ru } 80953Sigor@sysoev.ru 810115Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, recf, &tmcf->updating, 81153Sigor@sysoev.ru recf->updating, nxt_router_listen_socket_update); 81253Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 81353Sigor@sysoev.ru return ret; 81453Sigor@sysoev.ru } 81553Sigor@sysoev.ru 81653Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 81753Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 81853Sigor@sysoev.ru return NXT_ERROR; 81953Sigor@sysoev.ru } 82053Sigor@sysoev.ru 821115Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(recf, &tmcf->deleting); 822115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 823115Sigor@sysoev.ru return ret; 824115Sigor@sysoev.ru } 825115Sigor@sysoev.ru 826115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 827115Sigor@sysoev.ru 828115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 829115Sigor@sysoev.ru 830115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 831115Sigor@sysoev.ru 832115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 833115Sigor@sysoev.ru 834115Sigor@sysoev.ru return ret; 83553Sigor@sysoev.ru } 83653Sigor@sysoev.ru 83753Sigor@sysoev.ru 83853Sigor@sysoev.ru static nxt_int_t 839115Sigor@sysoev.ru nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 840115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 84153Sigor@sysoev.ru { 84253Sigor@sysoev.ru nxt_int_t ret; 84353Sigor@sysoev.ru 84453Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 84553Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 84653Sigor@sysoev.ru return NXT_ERROR; 84753Sigor@sysoev.ru } 84853Sigor@sysoev.ru 849115Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(recf, &tmcf->updating); 85053Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 85153Sigor@sysoev.ru return ret; 85253Sigor@sysoev.ru } 85353Sigor@sysoev.ru 854115Sigor@sysoev.ru return nxt_router_engine_joints_delete(recf, &tmcf->deleting); 85553Sigor@sysoev.ru } 85653Sigor@sysoev.ru 85753Sigor@sysoev.ru 85853Sigor@sysoev.ru static nxt_int_t 859115Sigor@sysoev.ru nxt_router_engine_joints_create(nxt_mp_t *mp, nxt_router_engine_conf_t *recf, 860115Sigor@sysoev.ru nxt_queue_t *sockets, nxt_array_t *array, 86153Sigor@sysoev.ru nxt_work_handler_t handler) 86253Sigor@sysoev.ru { 86353Sigor@sysoev.ru nxt_work_t *work; 86453Sigor@sysoev.ru nxt_queue_link_t *qlk; 86553Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 86653Sigor@sysoev.ru 86753Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 86853Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 86953Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 87053Sigor@sysoev.ru { 87153Sigor@sysoev.ru work = nxt_array_add(array); 87253Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 87353Sigor@sysoev.ru return NXT_ERROR; 87453Sigor@sysoev.ru } 87553Sigor@sysoev.ru 87653Sigor@sysoev.ru work->next = NULL; 87753Sigor@sysoev.ru work->handler = handler; 87853Sigor@sysoev.ru work->task = &recf->task; 87953Sigor@sysoev.ru work->obj = recf->engine; 88053Sigor@sysoev.ru 88165Sigor@sysoev.ru joint = nxt_mp_alloc(mp, sizeof(nxt_socket_conf_joint_t)); 88253Sigor@sysoev.ru if (nxt_slow_path(joint == NULL)) { 88353Sigor@sysoev.ru return NXT_ERROR; 88453Sigor@sysoev.ru } 88553Sigor@sysoev.ru 88653Sigor@sysoev.ru work->data = joint; 88753Sigor@sysoev.ru 88853Sigor@sysoev.ru joint->count = 1; 88953Sigor@sysoev.ru joint->socket_conf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 89088Smax.romanov@nginx.com joint->engine = recf->engine; 891115Sigor@sysoev.ru 892115Sigor@sysoev.ru nxt_queue_insert_tail(&joint->engine->joints, &joint->link); 89353Sigor@sysoev.ru } 89453Sigor@sysoev.ru 89520Sigor@sysoev.ru return NXT_OK; 89620Sigor@sysoev.ru } 89720Sigor@sysoev.ru 89820Sigor@sysoev.ru 899115Sigor@sysoev.ru static void 900115Sigor@sysoev.ru nxt_router_engine_socket_count(nxt_queue_t *sockets) 901115Sigor@sysoev.ru { 902115Sigor@sysoev.ru nxt_queue_link_t *qlk; 903115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 904115Sigor@sysoev.ru 905115Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 906115Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 907115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 908115Sigor@sysoev.ru { 909115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 910115Sigor@sysoev.ru skcf->socket->count++; 911115Sigor@sysoev.ru } 912115Sigor@sysoev.ru } 913115Sigor@sysoev.ru 914115Sigor@sysoev.ru 91520Sigor@sysoev.ru static nxt_int_t 916115Sigor@sysoev.ru nxt_router_engine_joints_delete(nxt_router_engine_conf_t *recf, 917115Sigor@sysoev.ru nxt_queue_t *sockets) 91820Sigor@sysoev.ru { 91953Sigor@sysoev.ru nxt_work_t *work; 92053Sigor@sysoev.ru nxt_queue_link_t *qlk; 92120Sigor@sysoev.ru 92253Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 92353Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 92453Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 92553Sigor@sysoev.ru { 926115Sigor@sysoev.ru work = nxt_array_add(recf->deleting); 92753Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 92853Sigor@sysoev.ru return NXT_ERROR; 92953Sigor@sysoev.ru } 93020Sigor@sysoev.ru 93153Sigor@sysoev.ru work->next = NULL; 93253Sigor@sysoev.ru work->handler = nxt_router_listen_socket_delete; 93353Sigor@sysoev.ru work->task = &recf->task; 93453Sigor@sysoev.ru work->obj = recf->engine; 93553Sigor@sysoev.ru work->data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 93620Sigor@sysoev.ru } 93720Sigor@sysoev.ru 93853Sigor@sysoev.ru return NXT_OK; 93953Sigor@sysoev.ru } 94020Sigor@sysoev.ru 94120Sigor@sysoev.ru 94253Sigor@sysoev.ru static nxt_int_t 94353Sigor@sysoev.ru nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 94453Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 94553Sigor@sysoev.ru { 94653Sigor@sysoev.ru nxt_int_t ret; 94753Sigor@sysoev.ru nxt_uint_t i, threads; 94853Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 94920Sigor@sysoev.ru 95053Sigor@sysoev.ru recf = tmcf->engines->elts; 95153Sigor@sysoev.ru threads = tmcf->conf->threads; 95220Sigor@sysoev.ru 95353Sigor@sysoev.ru for (i = tmcf->new_threads; i < threads; i++) { 95453Sigor@sysoev.ru ret = nxt_router_thread_create(task, rt, recf[i].engine); 95553Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 95653Sigor@sysoev.ru return ret; 95753Sigor@sysoev.ru } 95820Sigor@sysoev.ru } 95920Sigor@sysoev.ru 96020Sigor@sysoev.ru return NXT_OK; 96120Sigor@sysoev.ru } 96253Sigor@sysoev.ru 96353Sigor@sysoev.ru 96453Sigor@sysoev.ru static nxt_int_t 96553Sigor@sysoev.ru nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 96653Sigor@sysoev.ru nxt_event_engine_t *engine) 96753Sigor@sysoev.ru { 96853Sigor@sysoev.ru nxt_int_t ret; 96988Smax.romanov@nginx.com nxt_port_t *port; 97088Smax.romanov@nginx.com nxt_process_t *process; 97153Sigor@sysoev.ru nxt_thread_link_t *link; 97253Sigor@sysoev.ru nxt_thread_handle_t handle; 97353Sigor@sysoev.ru 97453Sigor@sysoev.ru link = nxt_zalloc(sizeof(nxt_thread_link_t)); 97553Sigor@sysoev.ru 97653Sigor@sysoev.ru if (nxt_slow_path(link == NULL)) { 97753Sigor@sysoev.ru return NXT_ERROR; 97853Sigor@sysoev.ru } 97953Sigor@sysoev.ru 98053Sigor@sysoev.ru link->start = nxt_router_thread_start; 98153Sigor@sysoev.ru link->engine = engine; 98253Sigor@sysoev.ru link->work.handler = nxt_router_thread_exit_handler; 98353Sigor@sysoev.ru link->work.task = task; 98453Sigor@sysoev.ru link->work.data = link; 98553Sigor@sysoev.ru 98653Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link); 98753Sigor@sysoev.ru 98888Smax.romanov@nginx.com process = nxt_runtime_process_find(rt, nxt_pid); 98988Smax.romanov@nginx.com if (nxt_slow_path(process == NULL)) { 99088Smax.romanov@nginx.com return NXT_ERROR; 99188Smax.romanov@nginx.com } 99288Smax.romanov@nginx.com 99388Smax.romanov@nginx.com port = nxt_process_port_new(process); 99488Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 99588Smax.romanov@nginx.com return NXT_ERROR; 99688Smax.romanov@nginx.com } 99788Smax.romanov@nginx.com 99888Smax.romanov@nginx.com ret = nxt_port_socket_init(task, port, 0); 99988Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 100088Smax.romanov@nginx.com return ret; 100188Smax.romanov@nginx.com } 100288Smax.romanov@nginx.com 100388Smax.romanov@nginx.com port->engine = 0; 100488Smax.romanov@nginx.com port->type = NXT_PROCESS_ROUTER; 100588Smax.romanov@nginx.com 100688Smax.romanov@nginx.com engine->port = port; 100788Smax.romanov@nginx.com 100888Smax.romanov@nginx.com nxt_runtime_port_add(rt, port); 100988Smax.romanov@nginx.com 101053Sigor@sysoev.ru ret = nxt_thread_create(&handle, link); 101153Sigor@sysoev.ru 101253Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 101353Sigor@sysoev.ru nxt_queue_remove(&engine->link); 101453Sigor@sysoev.ru } 101553Sigor@sysoev.ru 101653Sigor@sysoev.ru return ret; 101753Sigor@sysoev.ru } 101853Sigor@sysoev.ru 101953Sigor@sysoev.ru 102053Sigor@sysoev.ru static void 1021*133Sigor@sysoev.ru nxt_router_apps_sort(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) 1022*133Sigor@sysoev.ru { 1023*133Sigor@sysoev.ru nxt_app_t *app; 1024*133Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 1025*133Sigor@sysoev.ru 1026*133Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->apps); 1027*133Sigor@sysoev.ru qlk != nxt_queue_tail(&router->apps); 1028*133Sigor@sysoev.ru qlk = nqlk) 1029*133Sigor@sysoev.ru { 1030*133Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 1031*133Sigor@sysoev.ru app = nxt_queue_link_data(qlk, nxt_app_t, link); 1032*133Sigor@sysoev.ru 1033*133Sigor@sysoev.ru nxt_queue_remove(&app->link); 1034*133Sigor@sysoev.ru 1035*133Sigor@sysoev.ru // RELEASE APP 1036*133Sigor@sysoev.ru } 1037*133Sigor@sysoev.ru 1038*133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->previous); 1039*133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->apps); 1040*133Sigor@sysoev.ru } 1041*133Sigor@sysoev.ru 1042*133Sigor@sysoev.ru 1043*133Sigor@sysoev.ru static void 104453Sigor@sysoev.ru nxt_router_engines_post(nxt_router_temp_conf_t *tmcf) 104553Sigor@sysoev.ru { 104653Sigor@sysoev.ru nxt_uint_t n; 104753Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 104853Sigor@sysoev.ru 104953Sigor@sysoev.ru recf = tmcf->engines->elts; 105053Sigor@sysoev.ru 105153Sigor@sysoev.ru for (n = tmcf->engines->nelts; n != 0; n--) { 105253Sigor@sysoev.ru nxt_router_engine_post(recf); 105353Sigor@sysoev.ru recf++; 105453Sigor@sysoev.ru } 105553Sigor@sysoev.ru } 105653Sigor@sysoev.ru 105753Sigor@sysoev.ru 105853Sigor@sysoev.ru static void 105953Sigor@sysoev.ru nxt_router_engine_post(nxt_router_engine_conf_t *recf) 106053Sigor@sysoev.ru { 106153Sigor@sysoev.ru nxt_uint_t n; 106253Sigor@sysoev.ru nxt_work_t *work; 1063