From 85e77c7f0d7cce6cef2158dfdb3cf57871a25444 Mon Sep 17 00:00:00 2001 From: Emeric Brun Date: Thu, 23 Sep 2010 18:16:52 +0200 Subject: [PATCH] [MEDIUM] Create updates tree on stick table to manage sync. --- include/proto/stick_table.h | 4 ++-- include/types/stick_table.h | 7 +++++++ src/session.c | 6 +++--- src/stick_table.c | 31 ++++++++++++++++++++++++------- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h index 4365fcdfc..5da327ca6 100644 --- a/include/proto/stick_table.h +++ b/include/proto/stick_table.h @@ -41,8 +41,8 @@ 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); struct stksess *stktable_get_entry(struct stktable *table, struct stktable_key *key); -struct stksess *stktable_store(struct stktable *t, struct stksess *ts); -struct stksess *stktable_touch(struct stktable *t, struct stksess *ts); +struct stksess *stktable_store(struct stktable *t, struct stksess *ts, int local); +struct stksess *stktable_touch(struct stktable *t, struct stksess *ts, int local); struct stksess *stktable_lookup(struct stktable *t, struct stksess *ts); struct stksess *stktable_lookup_key(struct stktable *t, struct stktable_key *key); struct stksess *stktable_update_key(struct stktable *table, struct stktable_key *key); diff --git a/include/types/stick_table.h b/include/types/stick_table.h index b83506607..cb3fb3b35 100644 --- a/include/types/stick_table.h +++ b/include/types/stick_table.h @@ -130,16 +130,23 @@ 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 eb32_node upd; /* ebtree node used to hold the update sequence 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 */ }; + /* stick table */ struct stktable { + char *id; /* table id name */ struct eb_root keys; /* head of sticky session tree */ struct eb_root exps; /* head of sticky session expiration tree */ + struct eb_root updates; /* head of sticky updates sequence tree */ struct pool_head *pool; /* pool used to allocate sticky sessions */ struct task *exp_task; /* expiration task */ + struct task *sync_task; /* sync task */ + unsigned int update; + unsigned int localupdate; unsigned long type; /* type of table (determines key format) */ size_t key_size; /* size of a key, maximum size in case of string */ unsigned int size; /* maximum number of sticky sessions in table */ diff --git a/src/session.c b/src/session.c index 4d2b6054e..5432266cd 100644 --- a/src/session.c +++ b/src/session.c @@ -1077,7 +1077,7 @@ int process_sticking_rules(struct session *s, struct buffer *req, int an_bit) } } } - stktable_touch(rule->table.t, ts); + stktable_touch(rule->table.t, ts, 1); } } if (rule->flags & STK_IS_STORE) { @@ -1172,11 +1172,11 @@ int process_store_rules(struct session *s, struct buffer *rep, int an_bit) ts = stktable_lookup(s->store[i].table, s->store[i].ts); if (ts) { /* the entry already existed, we can free ours */ - stktable_touch(s->store[i].table, ts); + stktable_touch(s->store[i].table, ts, 1); stksess_free(s->store[i].table, s->store[i].ts); } else - ts = stktable_store(s->store[i].table, s->store[i].ts); + ts = stktable_store(s->store[i].table, s->store[i].ts, 1); s->store[i].ts = NULL; ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID); diff --git a/src/stick_table.c b/src/stick_table.c index bf8df0f44..fb75d3f5d 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -51,6 +51,7 @@ void stksess_kill(struct stktable *t, struct stksess *ts) return; eb32_delete(&ts->exp); + eb32_delete(&ts->upd); ebmb_delete(&ts->key); stksess_free(t, ts); } @@ -80,6 +81,7 @@ static struct stksess *stksess_init(struct stktable *t, struct stksess * ts) ts->ref_cnt = 0; ts->key.node.leaf_p = NULL; ts->exp.node.leaf_p = NULL; + ts->upd.node.leaf_p = NULL; return ts; } @@ -137,6 +139,7 @@ static int stktable_trash_oldest(struct stktable *t, int to_batch) /* session expired, trash it */ ebmb_delete(&ts->key); + eb32_delete(&ts->upd); stksess_free(t, ts); batched++; } @@ -204,12 +207,12 @@ struct stksess *stktable_update_key(struct stktable *table, struct stktable_key ts = stktable_lookup_key(table, key); if (likely(ts)) - return stktable_touch(table, ts); + return stktable_touch(table, ts, 1); /* entry does not exist, initialize a new one */ ts = stksess_new(table, key); if (likely(ts)) - stktable_store(table, ts); + stktable_store(table, ts, 1); return ts; } @@ -235,13 +238,26 @@ struct stksess *stktable_lookup(struct stktable *t, struct stksess *ts) /* Update the expiration timer for but do not touch its expiration node. * The table's expiration timer is updated if set. */ -struct stksess *stktable_touch(struct stktable *t, struct stksess *ts) +struct stksess *stktable_touch(struct stktable *t, struct stksess *ts, int local) { + struct eb32_node * eb; ts->expire = tick_add(now_ms, MS_TO_TICKS(t->expire)); if (t->expire) { t->exp_task->expire = t->exp_next = tick_first(ts->expire, t->exp_next); task_queue(t->exp_task); } + + if (t->sync_task && local) { + ts->upd.key = ++t->update; + t->localupdate = t->update; + eb32_delete(&ts->upd); + eb = eb32_insert(&t->updates, &ts->upd); + if (eb != &ts->upd) { + eb32_delete(eb); + eb32_insert(&t->updates, &ts->upd); + } + task_wakeup(t->sync_task, TASK_WOKEN_MSG); + } return ts; } @@ -249,10 +265,10 @@ struct stksess *stktable_touch(struct stktable *t, struct stksess *ts) * yet exist (the caller must check this). The table's timeout is updated if it * is set. is returned. */ -struct stksess *stktable_store(struct stktable *t, struct stksess *ts) +struct stksess *stktable_store(struct stktable *t, struct stksess *ts, int local) { ebmb_insert(&t->keys, &ts->key, t->key_size); - stktable_touch(t, ts); + stktable_touch(t, ts, local); ts->exp.key = ts->expire; eb32_insert(&t->exps, &ts->exp); return ts; @@ -275,10 +291,10 @@ struct stksess *stktable_get_entry(struct stktable *table, struct stktable_key * ts = stksess_new(table, key); if (!ts) return NULL; - stktable_store(table, ts); + stktable_store(table, ts, 1); } else - stktable_touch(table, ts); + stktable_touch(table, ts, 1); return ts; } @@ -339,6 +355,7 @@ static int stktable_trash_expired(struct stktable *t) /* session expired, trash it */ ebmb_delete(&ts->key); + eb32_delete(&ts->upd); stksess_free(t, ts); }