static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr) { time_t current = time(NULL); struct uwsgi_rb_timer *urbt; struct corerouter_session *cr_session; for (;;) { urbt = uwsgi_min_rb_timer(ucr->timeouts); if (urbt == NULL) return; if (urbt->key <= current) { cr_session = (struct corerouter_session *) urbt->data; cr_session->timed_out = 1; if (cr_session->retry) { cr_session->retry = 0; ucr->switch_events(ucr, cr_session, -1); if (cr_session->retry) { cr_del_timeout(ucr, cr_session); cr_session->timeout = cr_add_fake_timeout(ucr, cr_session); } else { cr_session->timeout = corerouter_reset_timeout(ucr, cr_session); } } else { corerouter_close_session(ucr, cr_session); } continue; } break; } }
// reset a peer (allows it to connect to another backend) void uwsgi_cr_peer_reset(struct corerouter_peer *peer) { if (peer->tmp_socket_name) { free(peer->tmp_socket_name); peer->tmp_socket_name = NULL; } cr_del_timeout(peer->session->corerouter, peer); if (peer->fd != -1) { close(peer->fd); peer->session->corerouter->cr_table[peer->fd] = NULL; peer->fd = -1; peer->hook_read = NULL; peer->hook_write = NULL; } if (peer->is_buffering) { if (peer->buffering_fd != -1) { close(peer->buffering_fd); } } peer->failed = 0; peer->soopt = 0; peer->timed_out = 0; peer->un = NULL; peer->static_node = NULL; }
struct uwsgi_rb_timer *corerouter_reset_timeout_fast(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer, time_t now) { cr_del_timeout(ucr, peer); return cr_add_timeout_fast(ucr, peer, now); }
static struct uwsgi_rb_timer *corerouter_reset_timeout(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) { cr_del_timeout(ucr, cr_session); return cr_add_timeout(ucr, cr_session); }
void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) { if (cr_session->instance_fd != -1) { close(cr_session->instance_fd); ucr->cr_table[cr_session->instance_fd] = NULL; } if (ucr->subscriptions && cr_session->un && cr_session->un->len > 0) { // decrease reference count #ifdef UWSGI_DEBUG uwsgi_log("[1] node %.*s refcnt: %llu\n", cr_session->un->len, cr_session->un->name, cr_session->un->reference); #endif cr_session->un->reference--; #ifdef UWSGI_DEBUG uwsgi_log("[2] node %.*s refcnt: %llu\n", cr_session->un->len, cr_session->un->name, cr_session->un->reference); #endif } if (cr_session->instance_failed) { if (cr_session->soopt) { if (!ucr->quiet) uwsgi_log("unable to connect() to uwsgi instance \"%.*s\": %s\n", (int) cr_session->instance_address_len, cr_session->instance_address, strerror(cr_session->soopt)); } else if (cr_session->timed_out) { if (cr_session->instance_address_len > 0) { if (cr_session->status == COREROUTER_STATUS_CONNECTING) { if (!ucr->quiet) uwsgi_log("unable to connect() to uwsgi instance \"%.*s\": timeout\n", (int) cr_session->instance_address_len, cr_session->instance_address); } else if (cr_session->status == COREROUTER_STATUS_RESPONSE) { uwsgi_log("timeout waiting for instance \"%.*s\"\n", (int) cr_session->instance_address_len, cr_session->instance_address); } } } // now check for dead nodes if (ucr->subscriptions && cr_session->un && cr_session->un->len > 0) { if (cr_session->un->death_mark == 0) uwsgi_log("[uwsgi-%s] %.*s => marking %.*s as failed\n", ucr->short_name, (int) cr_session->hostname_len, cr_session->hostname, (int) cr_session->instance_address_len, cr_session->instance_address); cr_session->un->failcnt++; cr_session->un->death_mark = 1; // check if i can remove the node if (cr_session->un->reference == 0) { uwsgi_remove_subscribe_node(ucr->subscriptions, cr_session->un); } if (ucr->cheap && !ucr->i_am_cheap && !ucr->fallback && uwsgi_no_subscriptions(ucr->subscriptions)) { uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap); } } else if (cr_session->static_node) { cr_session->static_node->custom = uwsgi_now(); uwsgi_log("[uwsgi-%s] %.*s => marking %.*s as failed\n", ucr->short_name, (int) cr_session->hostname_len, cr_session->hostname, (int) cr_session->instance_address_len, cr_session->instance_address); } if (cr_session->tmp_socket_name) { free(cr_session->tmp_socket_name); cr_session->tmp_socket_name = NULL; } if (ucr->fallback) { // ok let's try with the fallback nodes if (!cr_session->fallback) { cr_session->fallback = ucr->fallback; } else { cr_session->fallback = cr_session->fallback->next; if (!cr_session->fallback) goto end; } cr_session->instance_address = cr_session->fallback->value; cr_session->instance_address_len = cr_session->fallback->len; // reset error and timeout cr_session->timeout = corerouter_reset_timeout(ucr, cr_session); cr_session->timed_out = 0; cr_session->soopt = 0; // reset nodes cr_session->un = NULL; cr_session->static_node = NULL; cr_session->pass_fd = is_unix(cr_session->instance_address, cr_session->instance_address_len); cr_session->instance_fd = uwsgi_connectn(cr_session->instance_address, cr_session->instance_address_len, 0, 1); if (cr_session->instance_fd < 0) { cr_session->instance_failed = 1; cr_session->soopt = errno; corerouter_close_session(ucr, cr_session); return; } ucr->cr_table[cr_session->instance_fd] = cr_session; cr_session->status = COREROUTER_STATUS_CONNECTING; ucr->cr_table[cr_session->instance_fd] = cr_session; event_queue_add_fd_write(ucr->queue, cr_session->instance_fd); return; } } end: if (cr_session->tmp_socket_name) { free(cr_session->tmp_socket_name); } if (cr_session->buf_file) fclose(cr_session->buf_file); if (cr_session->buf_file_name) { if (unlink(cr_session->buf_file_name)) { uwsgi_error("unlink()"); } free(cr_session->buf_file_name); } // could be used to free additional resources if (cr_session->close) cr_session->close(ucr, cr_session); if (cr_session->keepalive) { cr_session->keepalive = 0; return; } close(cr_session->fd); ucr->cr_table[cr_session->fd] = NULL; cr_del_timeout(ucr, cr_session); free(cr_session); }