From: Willy Tarreau Date: Mon, 14 Jun 2010 12:53:07 +0000 (+0200) Subject: [MEDIUM] stick-tables: add a reference counter to each entry X-Git-Tag: v1.5-dev8~556 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e7f3d7ab9f95584f5bf5154b18fd028ccccd93b9;p=thirdparty%2Fhaproxy.git [MEDIUM] stick-tables: add a reference counter to each entry We'll soon have to maintain links from sessions to entries, so let's add a refcount in entries to avoid purging them if it's not null. --- diff --git a/include/types/stick_table.h b/include/types/stick_table.h index 843f5d73ed..25bfbd8c15 100644 --- a/include/types/stick_table.h +++ b/include/types/stick_table.h @@ -75,6 +75,7 @@ struct stktable_type { */ struct stksess { unsigned int expire; /* session expiration date */ + unsigned int ref_cnt; /* reference count, can only purge when zero */ struct eb32_node exp; /* ebtree node used to hold the session in expiration tree */ struct ebmb_node key; /* ebtree node used to hold the session in table */ /* WARNING! do not put anything after , it's used by the key */ diff --git a/src/stick_table.c b/src/stick_table.c index 5723dffd28..09cb96beb1 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -64,6 +64,7 @@ void stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key static struct stksess *stksess_init(struct stktable *t, struct stksess * ts) { memset((void *)ts - t->data_size, 0, t->data_size); + ts->ref_cnt = 0; ts->key.node.leaf_p = NULL; ts->exp.node.leaf_p = NULL; return ts; @@ -78,6 +79,7 @@ static int stktable_trash_oldest(struct stktable *t, int to_batch) struct stksess *ts; struct eb32_node *eb; int batched = 0; + int looped = 0; eb = eb32_lookup_ge(&t->exps, now_ms - TIMER_LOOK_BACK); @@ -86,8 +88,12 @@ static int stktable_trash_oldest(struct stktable *t, int to_batch) if (unlikely(!eb)) { /* we might have reached the end of the tree, typically because * is in the first half and we're first scanning the last - * half. Let's loop back to the beginning of the tree now. + * half. Let's loop back to the beginning of the tree now if we + * have not yet visited it. */ + if (looped) + break; + looped = 1; eb = eb32_first(&t->exps); if (likely(!eb)) break; @@ -97,6 +103,10 @@ static int stktable_trash_oldest(struct stktable *t, int to_batch) ts = eb32_entry(eb, struct stksess, exp); eb = eb32_next(eb); + /* don't delete an entry which is currently referenced */ + if (ts->ref_cnt) + continue; + eb32_delete(&ts->exp); if (ts->expire != ts->exp.key) { @@ -223,6 +233,7 @@ static int stktable_trash_expired(struct stktable *t) { struct stksess *ts; struct eb32_node *eb; + int looped = 0; eb = eb32_lookup_ge(&t->exps, now_ms - TIMER_LOOK_BACK); @@ -230,8 +241,12 @@ static int stktable_trash_expired(struct stktable *t) if (unlikely(!eb)) { /* we might have reached the end of the tree, typically because * is in the first half and we're first scanning the last - * half. Let's loop back to the beginning of the tree now. + * half. Let's loop back to the beginning of the tree now if we + * have not yet visited it. */ + if (looped) + break; + looped = 1; eb = eb32_first(&t->exps); if (likely(!eb)) break; @@ -247,6 +262,10 @@ static int stktable_trash_expired(struct stktable *t) ts = eb32_entry(eb, struct stksess, exp); eb = eb32_next(eb); + /* don't delete an entry which is currently referenced */ + if (ts->ref_cnt) + continue; + eb32_delete(&ts->exp); if (!tick_is_expired(ts->expire, now_ms)) {