From f6efda11891078ed8d2eb747e5cfed62a7c764ec Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 3 Aug 2010 20:34:06 +0200 Subject: [PATCH] [MEDIUM] session counters: automatically remove expired entries. When a ref_cnt goes down to zero and the entry is expired, remove it. --- include/proto/session.h | 3 +++ include/proto/stick_table.h | 10 ++++++++++ src/dumpstats.c | 7 ++++++- src/stick_table.c | 13 +++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/proto/session.h b/include/proto/session.h index 095932071..bf390caca 100644 --- a/include/proto/session.h +++ b/include/proto/session.h @@ -60,6 +60,7 @@ static inline void session_store_counters(struct session *s) if (ptr) stktable_data_cast(ptr, conn_cur)--; s->be_tracked_counters->ref_cnt--; + stksess_kill_if_expired(s->be_tracked_table, s->be_tracked_counters); s->be_tracked_counters = NULL; } @@ -68,6 +69,7 @@ static inline void session_store_counters(struct session *s) if (ptr) stktable_data_cast(ptr, conn_cur)--; s->fe_tracked_counters->ref_cnt--; + stksess_kill_if_expired(s->fe_tracked_table, s->fe_tracked_counters); s->fe_tracked_counters = NULL; } } @@ -87,6 +89,7 @@ static inline void session_stop_backend_counters(struct session *s) if (ptr) stktable_data_cast(ptr, conn_cur)--; s->be_tracked_counters->ref_cnt--; + stksess_kill_if_expired(s->be_tracked_table, s->be_tracked_counters); s->be_tracked_counters = NULL; } diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h index e702356fd..583e32acd 100644 --- a/include/proto/stick_table.h +++ b/include/proto/stick_table.h @@ -24,6 +24,8 @@ #define _PROTO_STICK_TABLE_H #include +#include +#include #include #define stktable_data_size(type) (sizeof(((union stktable_data*)0)->type)) @@ -34,6 +36,7 @@ extern struct stktable_key static_table_key; struct stksess *stksess_new(struct stktable *t, struct stktable_key *key); void stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key *key); void stksess_free(struct stktable *t, struct stksess *ts); +void stksess_kill(struct stktable *t, struct stksess *ts); int stktable_init(struct stktable *t); int stktable_parse_type(char **args, int *idx, unsigned long *type, size_t *key_size); @@ -122,4 +125,11 @@ static inline void *stktable_data_ptr(struct stktable *t, struct stksess *ts, in return (void *)ts + t->data_ofs[type]; } +/* kill an entry if it's expired and its ref_cnt is zero */ +static inline void stksess_kill_if_expired(struct stktable *t, struct stksess *ts) +{ + if (tick_is_expired(ts->expire, now_ms)) + stksess_kill(t, ts); +} + #endif /* _PROTO_STICK_TABLE_H */ diff --git a/src/dumpstats.c b/src/dumpstats.c index a8c832ef8..a6ce0cf50 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -2921,8 +2921,10 @@ int stats_dump_table_to_buffer(struct session *s, struct buffer *rep) if (unlikely(rep->flags & (BF_WRITE_ERROR|BF_SHUTW))) { /* in case of abort, remove any refcount we might have set on an entry */ - if (s->data_state == DATA_ST_LIST) + if (s->data_state == DATA_ST_LIST) { s->data_ctx.table.entry->ref_cnt--; + stksess_kill_if_expired(&s->data_ctx.table.proxy->table, s->data_ctx.table.entry); + } return 1; } @@ -3080,11 +3082,14 @@ int stats_dump_table_to_buffer(struct session *s, struct buffer *rep) eb = ebmb_next(&s->data_ctx.table.entry->key); if (eb) { + struct stksess *old = s->data_ctx.table.entry; s->data_ctx.table.entry = ebmb_entry(eb, struct stksess, key); + stksess_kill_if_expired(&s->data_ctx.table.proxy->table, old); s->data_ctx.table.entry->ref_cnt++; break; } + stksess_kill_if_expired(&s->data_ctx.table.proxy->table, s->data_ctx.table.entry); s->data_ctx.table.proxy = s->data_ctx.table.proxy->next; s->data_state = DATA_ST_INFO; break; diff --git a/src/stick_table.c b/src/stick_table.c index ccfd7b579..78a0df751 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -42,6 +42,19 @@ void stksess_free(struct stktable *t, struct stksess *ts) pool_free2(t->pool, (void *)ts - t->data_size); } +/* + * Kill an stksess (only if its ref_cnt is zero). + */ +void stksess_kill(struct stktable *t, struct stksess *ts) +{ + if (ts->ref_cnt) + return; + + eb32_delete(&ts->exp); + ebmb_delete(&ts->key); + stksess_free(t, ts); +} + /* * Initialize or update the key in the sticky session present in table * from the value present in .