[MEDIUM] session counters: automatically remove expired entries.

When a ref_cnt goes down to zero and the entry is expired, remove it.
diff --git a/include/proto/session.h b/include/proto/session.h
index 0959320..bf390ca 100644
--- a/include/proto/session.h
+++ b/include/proto/session.h
@@ -60,6 +60,7 @@
 		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 @@
 		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 @@
 	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 e702356..583e32a 100644
--- a/include/proto/stick_table.h
+++ b/include/proto/stick_table.h
@@ -24,6 +24,8 @@
 #define _PROTO_STICK_TABLE_H
 
 #include <common/errors.h>
+#include <common/ticks.h>
+#include <common/time.h>
 #include <types/stick_table.h>
 
 #define stktable_data_size(type) (sizeof(((union stktable_data*)0)->type))
@@ -34,6 +36,7 @@
 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 @@
 	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 a8c832e..a6ce0cf 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -2921,8 +2921,10 @@
 
 	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 @@
 
 			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 ccfd7b5..78a0df7 100644
--- a/src/stick_table.c
+++ b/src/stick_table.c
@@ -43,6 +43,19 @@
 }
 
 /*
+ * 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 <ts> present in table <t>
  * from the value present in <key>.
  */