]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] stick-tables: add a reference counter to each entry
authorWilly Tarreau <w@1wt.eu>
Mon, 14 Jun 2010 12:53:07 +0000 (14:53 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 14 Jun 2010 13:10:26 +0000 (15:10 +0200)
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.

include/types/stick_table.h
src/stick_table.c

index 843f5d73ed8df58160ce1cce4c416f3023330aa0..25bfbd8c15ba5dc35a508b9b867ae69d10c8fbb4 100644 (file)
@@ -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 <keys>, it's used by the key */
index 5723dffd2841c4c6a25bbbc3939ee9d937170faf..09cb96beb19c57d04efa2547621b652296ac2bec 100644 (file)
@@ -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
                         * <now_ms> 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
                         * <now_ms> 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)) {