rstatus_t core_loop(struct context *ctx) { int nsd, delta; int64_t now; now = nc_msec_now(); while (now >= ctx->next_tick) { core_tick(ctx); ctx->next_tick += NC_TICK_INTERVAL; } delta = (int)(ctx->next_tick - now); ASSERT(delta > 0); ctx->timeout = MIN(delta, ctx->timeout); nsd = event_wait(ctx->evb, ctx->timeout); if (nsd < 0) { return nsd; } core_timeout(ctx); stats_swap(ctx->stats); return NC_OK; }
static void core_timeout(struct context *ctx) { for (;;) { struct msg *msg; struct conn *conn; int64_t now, then; msg = msg_tmo_min(); if (msg == NULL) { ctx->timeout = ctx->max_timeout; return; } /* skip over req that are in-error or done */ if (msg->error || msg->done) { msg_tmo_delete(msg); continue; } /* * timeout expired req and all the outstanding req on the timing * out server */ conn = msg->tmo_rbe.data; then = msg->tmo_rbe.key; now = nc_msec_now(); if (now < then) { int delta = (int)(then - now); ctx->timeout = MIN(delta, ctx->max_timeout); return; } log_debug(LOG_INFO, "req %"PRIu64" on s %d timedout", msg->id, conn->sd); msg_tmo_delete(msg); conn->err = ETIMEDOUT; core_close(ctx, conn); } }
static struct context * core_ctx_create(struct instance *nci) { rstatus_t status; struct context *ctx; int64_t now; uint32_t npool; ctx = nc_alloc(sizeof(*ctx)); if (ctx == NULL) { return NULL; } now = nc_msec_now(); if (now < 0) { nc_free(ctx); return NULL; } ctx->id = ++ctx_id; ctx->cf = NULL; ctx->stats = NULL; ctx->evb = NULL; array_null(&ctx->pool); ctx->max_timeout = nci->stats_interval; ctx->timeout = ctx->max_timeout; ctx->next_tick = now + NC_TICK_INTERVAL; /* parse and create configuration */ ctx->cf = conf_create(nci->conf_filename); if (ctx->cf == NULL) { nc_free(ctx); return NULL; } npool = array_n(&ctx->cf->pool); /* initialize server pool from configuration */ if (npool != 0) { status = server_pool_init(&ctx->pool, &ctx->cf->pool, ctx); if (status != NC_OK) { conf_destroy(ctx->cf); nc_free(ctx); return NULL; } } /* create stats per server pool */ if (npool != 0) { ctx->stats = stats_create(nci->stats_port, nci->stats_addr, nci->stats_interval, nci->hostname, &ctx->pool); if (ctx->stats == NULL) { server_pool_deinit(&ctx->pool); conf_destroy(ctx->cf); nc_free(ctx); return NULL; } } /* initialize event handling for client, proxy and server */ ctx->evb = evbase_create(NC_EVENT_SIZE, &core_core); if (ctx->evb == NULL) { stats_destroy(ctx->stats); server_pool_deinit(&ctx->pool); conf_destroy(ctx->cf); nc_free(ctx); return NULL; } /* preconnect? servers in server pool */ if (npool != 0) { status = server_pool_preconnect(ctx); if (status != NC_OK) { server_pool_disconnect(ctx); evbase_destroy(ctx->evb); stats_destroy(ctx->stats); server_pool_deinit(&ctx->pool); conf_destroy(ctx->cf); nc_free(ctx); return NULL; } } /* initialize proxy per server pool */ if (npool != 0) { status = proxy_init(ctx); if (status != NC_OK) { server_pool_disconnect(ctx); evbase_destroy(ctx->evb); stats_destroy(ctx->stats); server_pool_deinit(&ctx->pool); conf_destroy(ctx->cf); nc_free(ctx); return NULL; } } log_debug(LOG_VVERB, "created ctx %p id %"PRIu32"", ctx, ctx->id); return ctx; }