From 03cdf55e696816eece92158de4276709b29bf6c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Mon, 20 May 2019 10:08:27 +0200 Subject: [PATCH] MINOR: stream: Stickiness server lookup by name. With this patch we modify the stickiness server targets lookup behavior. First we look for this server targets by their names before looking for them by their IDs if not found. We also insert a dictionary entry for the name of the server targets and store the address of this entry in the underlying stick-table. --- src/stream.c | 77 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/src/stream.c b/src/stream.c index a29b77566c..0623ee8d4b 100644 --- a/src/stream.c +++ b/src/stream.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -1483,6 +1484,49 @@ static int process_server_rules(struct stream *s, struct channel *req, int an_bi return 1; } +static inline void sticking_rule_find_target(struct stream *s, + struct stktable *t, struct stksess *ts) +{ + struct proxy *px = s->be; + struct eb32_node *node; + struct dict_entry *de; + void *ptr; + struct server *srv; + + /* Look for the server name previously stored in stick-table */ + HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock); + ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_NAME); + de = stktable_data_cast(ptr, server_name); + HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock); + + if (de) { + struct ebpt_node *name; + + name = ebis_lookup(&px->conf.used_server_name, de->value.key); + if (name) { + srv = container_of(name, struct server, conf.name); + goto found; + } + } + + /* Look for the server ID */ + HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock); + ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_ID); + node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id)); + HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock); + + if (!node) + return; + + srv = container_of(node, struct server, conf.id); + found: + if ((srv->cur_state != SRV_ST_STOPPED) || + (px->options & PR_O_PERSIST) || (s->flags & SF_FORCE_PRST)) { + s->flags |= SF_DIRECT | SF_ASSIGNED; + s->target = &srv->obj_type; + } +} + /* This stream analyser works on a request. It applies all sticking rules on * it then returns 1. The data must already be present in the buffer otherwise * they won't match. It always returns 1. @@ -1539,27 +1583,8 @@ static int process_sticking_rules(struct stream *s, struct channel *req, int an_ struct stksess *ts; if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) { - if (!(s->flags & SF_ASSIGNED)) { - struct eb32_node *node; - void *ptr; - - /* srv found in table */ - HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock); - ptr = __stktable_data_ptr(rule->table.t, ts, STKTABLE_DT_SERVER_ID); - node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id)); - HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock); - if (node) { - struct server *srv; - - srv = container_of(node, struct server, conf.id); - if ((srv->cur_state != SRV_ST_STOPPED) || - (px->options & PR_O_PERSIST) || - (s->flags & SF_FORCE_PRST)) { - s->flags |= SF_DIRECT | SF_ASSIGNED; - s->target = &srv->obj_type; - } - } - } + if (!(s->flags & SF_ASSIGNED)) + sticking_rule_find_target(s, rule->table.t, ts); stktable_touch_local(rule->table.t, ts, 1); } } @@ -1657,6 +1682,7 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit for (i = 0; i < s->store_count; i++) { struct stksess *ts; void *ptr; + struct dict_entry *de; if (objt_server(s->target) && objt_server(s->target)->flags & SRV_F_NON_STICK) { stksess_free(s->store[i].table, s->store[i].ts); @@ -1675,6 +1701,15 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit ptr = __stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID); stktable_data_cast(ptr, server_id) = __objt_server(s->target)->puid; HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); + + HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); + de = dict_insert(&server_name_dict, __objt_server(s->target)->id); + if (de) { + ptr = __stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_NAME); + stktable_data_cast(ptr, server_name) = de; + } + HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); + stktable_touch_local(s->store[i].table, ts, 1); } s->store_count = 0; /* everything is stored */