int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */
int st_code; /* the status code returned by an action */
struct buffer chunk; /* temporary buffer which holds a single-line output */
+ struct watcher px_watch; /* watcher to automatically update obj1 on backend deletion */
struct watcher srv_watch; /* watcher to automatically update obj2 on server deletion */
enum stat_state state; /* phase of output production */
};
ctx->flags |= STAT_F_FMT_HTML; /* assume HTML mode by default */
if ((msg->flags & HTTP_MSGF_VER_11) && (txn->meth != HTTP_METH_HEAD))
ctx->flags |= STAT_F_CHUNKED;
+
+ watcher_init(&ctx->px_watch, &ctx->obj1, offsetof(struct proxy, watcher_list));
watcher_init(&ctx->srv_watch, &ctx->obj2, offsetof(struct server, watcher_list));
htx = htxbuf(&req->buf);
static void http_stats_release(struct appctx *appctx)
{
struct show_stat_ctx *ctx = appctx->svcctx;
+ if (ctx->domain == STATS_DOMAIN_PROXY && ctx->obj1)
+ watcher_detach(&ctx->px_watch);
if (ctx->px_st == STAT_PX_ST_SV && ctx->obj2)
watcher_detach(&ctx->srv_watch);
}
struct proxy *px;
/* dump proxies */
- while (ctx->obj1) {
+ /* obj1 is updated and returned through watcher_next() */
+ for (px = ctx->obj1; px;
+ px = watcher_next(&ctx->px_watch, px->next)) {
+
if (stats_is_full(appctx, buf, htx))
goto full;
- px = ctx->obj1;
/* Skip the global frontend proxies and non-networked ones.
* Also skip proxies that were disabled in the configuration
* This change allows retrieving stats from "old" proxies after a reload.
return 0;
}
- ctx->obj1 = px->next;
ctx->px_st = STAT_PX_ST_INIT;
ctx->field = 0;
}
goto full;
}
- if (domain == STATS_DOMAIN_PROXY)
- ctx->obj1 = proxies_list;
-
ctx->px_st = STAT_PX_ST_INIT;
ctx->field = 0;
ctx->state = STAT_STATE_LIST;
+ /* Update ctx->obj1 via watcher to point on the first proxy. */
+ if (domain == STATS_DOMAIN_PROXY)
+ watcher_attach(&ctx->px_watch, proxies_list);
+
__fallthrough;
case STAT_STATE_LIST:
ctx->scope_len = 0;
ctx->http_px = NULL; // not under http context
ctx->flags = STAT_F_SHNODE | STAT_F_SHDESC;
+
+ watcher_init(&ctx->px_watch, &ctx->obj1, offsetof(struct proxy, watcher_list));
watcher_init(&ctx->srv_watch, &ctx->obj2, offsetof(struct server, watcher_list));
if ((strm_li(appctx_strm(appctx))->bind_conf->level & ACCESS_LVL_MASK) >= ACCESS_LVL_OPER)
static void cli_io_handler_release_stat(struct appctx *appctx)
{
struct show_stat_ctx *ctx = appctx->svcctx;
- if (ctx->px_st == STAT_PX_ST_SV && ctx->obj2)
- watcher_detach(&ctx->srv_watch);
+
+ if (ctx->state == STAT_STATE_LIST && ctx->domain == STATS_DOMAIN_PROXY) {
+ watcher_detach(&ctx->px_watch);
+ if (ctx->px_st == STAT_PX_ST_SV)
+ watcher_detach(&ctx->srv_watch);
+ }
}
static int cli_io_handler_dump_json_schema(struct appctx *appctx)
static void cli_io_handler_release_dump_stat_file(struct appctx *appctx)
{
struct show_stat_ctx *ctx = appctx->svcctx;
- if (ctx->px_st == STAT_PX_ST_SV && ctx->obj2)
- watcher_detach(&ctx->srv_watch);
+
+ if (ctx->state == STAT_STATE_LIST && ctx->domain == STATS_DOMAIN_PROXY) {
+ watcher_detach(&ctx->px_watch);
+ if (ctx->px_st == STAT_PX_ST_SV)
+ watcher_detach(&ctx->srv_watch);
+ }
}
int stats_allocate_proxy_counters_internal(struct extra_counters **counters,