mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-28 16:40:37 +00:00
MEDIUM: stick-table: Stop handling stick-tables as proxies.
This patch adds the support for the "table" line parsing in "peers" sections to declare stick-table in such sections. This also prevents the user from having to declare dummy backends sections with a unique stick-table inside. Even if still supported, this usage will become deprecated. To do so, the ->table member of proxy struct which is a stktable struct is replaced by a pointer to a stktable struct allocated at parsing time in src/cfgparse-listen.c for the dummy stick-table backends and in src/cfgparse.c for "peers" sections. This has an impact on the code for stick-table sample converters and on the stickiness rules parsers which first store the name of the dummy before resolving the rules. This patch replaces proxy_tbl_by_name() calls by stktable_find_by_name() calls to lookup for stick-tables stored in "stktable_by_name" ebtree at parsing time. There is only one remaining place where proxy_tbl_by_name() is used: src/hlua.c. At several places in the code we relied on the fact that ->size member of stick-table was equal to zero to consider the stick-table was present by not configured, this do not make sense anymore as ->table member of struct proxyis fow now on a pointer. These tests are replaced by a test on ->table value itself. In "peers" section we do not have to temporary store the name of the section the stick-table are attached to because this name is obviously already known just after having entered this "peers" section. About the CLI stick-table I/O handler, the pointer to proxy struct is replaced by a pointer to a stktable struct.
This commit is contained in:
parent
f92da38222
commit
1b8e68e89a
@ -28,9 +28,13 @@
|
||||
#include <common/time.h>
|
||||
#include <types/stick_table.h>
|
||||
|
||||
extern struct stktable *stktables_list;
|
||||
|
||||
#define stktable_data_size(type) (sizeof(((union stktable_data*)0)->type))
|
||||
#define stktable_data_cast(ptr, type) ((union stktable_data*)(ptr))->type
|
||||
|
||||
void stktable_store_name(struct stktable *t);
|
||||
struct stktable *stktable_find_by_name(const char *name);
|
||||
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);
|
||||
|
@ -144,7 +144,7 @@ struct appctx {
|
||||
} errors;
|
||||
struct {
|
||||
void *target; /* table we want to dump, or NULL for all */
|
||||
struct proxy *proxy; /* table being currently dumped (first if NULL) */
|
||||
struct stktable *t; /* table being currently dumped (first if NULL) */
|
||||
struct stksess *entry; /* last entry we were trying to dump (or first if NULL) */
|
||||
long long value; /* value to compare against */
|
||||
signed char data_type; /* type of data to compare, or -1 if none */
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <types/vars.h>
|
||||
#include <types/protocol_buffers.h>
|
||||
#include <types/stick_table.h>
|
||||
|
||||
/* encoding of each arg type : up to 31 types are supported */
|
||||
#define ARGT_BITS 5
|
||||
@ -99,6 +100,7 @@ union arg_data {
|
||||
struct in6_addr ipv6;
|
||||
struct proxy *prx; /* used for fe, be, tables */
|
||||
struct server *srv;
|
||||
struct stktable *t;
|
||||
struct userlist *usr;
|
||||
struct map_descriptor *map;
|
||||
struct my_regex *reg;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <types/proto_http.h>
|
||||
#include <types/proxy.h>
|
||||
#include <types/server.h>
|
||||
#include <types/stick_table.h>
|
||||
|
||||
#define CLASS_CORE "Core"
|
||||
#define CLASS_TXN "TXN"
|
||||
|
@ -416,7 +416,7 @@ struct proxy {
|
||||
struct fe_counters fe_counters; /* frontend statistics counters */
|
||||
|
||||
struct list listener_queue; /* list of the temporarily limited listeners because of lack of a proxy resource */
|
||||
struct stktable table; /* table for storing sticking streams */
|
||||
struct stktable *table; /* table for storing sticking streams */
|
||||
|
||||
struct task *task; /* the associated task, mandatory to manage rate limiting, stopping and resource shortage, NULL if disabled */
|
||||
struct list tcpcheck_rules; /* tcp-check send / expect rules */
|
||||
|
@ -152,6 +152,7 @@ struct stktable {
|
||||
const char *file; /* The file where the stick-table is declared. */
|
||||
int line; /* The line in this <file> the stick-table is declared. */
|
||||
} conf;
|
||||
struct ebpt_node name; /* Stick-table are lookup by name here. */
|
||||
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 */
|
||||
|
21
src/action.c
21
src/action.c
@ -30,37 +30,34 @@
|
||||
*/
|
||||
int check_trk_action(struct act_rule *rule, struct proxy *px, char **err)
|
||||
{
|
||||
struct proxy *target;
|
||||
struct stktable *target;
|
||||
|
||||
if (rule->arg.trk_ctr.table.n)
|
||||
target = proxy_tbl_by_name(rule->arg.trk_ctr.table.n);
|
||||
target = stktable_find_by_name(rule->arg.trk_ctr.table.n);
|
||||
else
|
||||
target = px;
|
||||
target = px->table;
|
||||
|
||||
if (!target) {
|
||||
memprintf(err, "unable to find table '%s' referenced by track-sc%d",
|
||||
rule->arg.trk_ctr.table.n, trk_idx(rule->action));
|
||||
rule->arg.trk_ctr.table.n ? rule->arg.trk_ctr.table.n : px->id,
|
||||
trk_idx(rule->action));
|
||||
return 0;
|
||||
}
|
||||
else if (target->table.size == 0) {
|
||||
memprintf(err, "table '%s' used but not configured",
|
||||
rule->arg.trk_ctr.table.n ? rule->arg.trk_ctr.table.n : px->id);
|
||||
return 0;
|
||||
}
|
||||
else if (!stktable_compatible_sample(rule->arg.trk_ctr.expr, target->table.type)) {
|
||||
|
||||
if (!stktable_compatible_sample(rule->arg.trk_ctr.expr, target->type)) {
|
||||
memprintf(err, "stick-table '%s' uses a type incompatible with the 'track-sc%d' rule",
|
||||
rule->arg.trk_ctr.table.n ? rule->arg.trk_ctr.table.n : px->id,
|
||||
trk_idx(rule->action));
|
||||
return 0;
|
||||
}
|
||||
else if (px->bind_proc & ~target->bind_proc) {
|
||||
else if (target->proxy && (px->bind_proc & ~target->proxy->bind_proc)) {
|
||||
memprintf(err, "stick-table '%s' referenced by 'track-sc%d' rule not present on all processes covered by proxy '%s'",
|
||||
target->id, trk_idx(rule->action), px->id);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
free(rule->arg.trk_ctr.table.n);
|
||||
rule->arg.trk_ctr.table.t = &target->table;
|
||||
rule->arg.trk_ctr.table.t = target;
|
||||
/* Note: if we decide to enhance the track-sc syntax, we may be
|
||||
* able to pass a list of counters to track and allocate them
|
||||
* right here using stktable_alloc_data_type().
|
||||
|
@ -1711,7 +1711,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
LIST_ADDQ(&curproxy->persist_rules, &rule->list);
|
||||
}
|
||||
else if (!strcmp(args[0], "stick-table")) {
|
||||
struct proxy *other;
|
||||
struct stktable *other;
|
||||
|
||||
if (curproxy == &defproxy) {
|
||||
ha_alert("parsing [%s:%d] : 'stick-table' is not supported in 'defaults' section.\n",
|
||||
@ -1720,20 +1720,35 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
goto out;
|
||||
}
|
||||
|
||||
other = proxy_tbl_by_name(curproxy->id);
|
||||
other = stktable_find_by_name(curproxy->id);
|
||||
if (other) {
|
||||
ha_alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
|
||||
file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
|
||||
file, linenum, curproxy->id,
|
||||
other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
|
||||
other->proxy ? other->id : other->peers.p->id,
|
||||
other->conf.file, other->conf.line);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err_code |= parse_stick_table(file, linenum, args, &curproxy->table, curproxy->id, NULL);
|
||||
curproxy->table = calloc(1, sizeof *curproxy->table);
|
||||
if (!curproxy->table) {
|
||||
ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
|
||||
file, linenum, args[0], args[1]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err_code |= parse_stick_table(file, linenum, args, curproxy->table, curproxy->id, NULL);
|
||||
if (err_code & ERR_FATAL)
|
||||
goto out;
|
||||
|
||||
/* Store the proxy in the stick-table. */
|
||||
curproxy->table->proxy = curproxy;
|
||||
|
||||
stktable_store_name(curproxy->table);
|
||||
curproxy->table->next = stktables_list;
|
||||
stktables_list = curproxy->table;
|
||||
}
|
||||
else if (!strcmp(args[0], "stick")) {
|
||||
struct sticking_rule *rule;
|
||||
|
118
src/cfgparse.c
118
src/cfgparse.c
@ -856,7 +856,45 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
|
||||
l->default_target = curpeers->peers_fe->default_target;
|
||||
l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
|
||||
global.maxsock++; /* for the listening socket */
|
||||
} /* neither "peer" nor "peers" */
|
||||
}
|
||||
else if (!strcmp(args[0], "table")) {
|
||||
struct stktable *t, *other;
|
||||
char *id;
|
||||
|
||||
/* Line number and peer ID are updated only if this peer is the local one. */
|
||||
if (init_peers_frontend(file, -1, NULL, curpeers) != 0) {
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
other = stktable_find_by_name(args[1]);
|
||||
if (other) {
|
||||
ha_alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
|
||||
file, linenum, args[1],
|
||||
other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
|
||||
other->proxy ? other->id : other->peers.p->id,
|
||||
other->conf.file, other->conf.line);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
t = calloc(1, sizeof *t);
|
||||
id = strdup(args[1]);
|
||||
if (!t || !id) {
|
||||
ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
|
||||
file, linenum, args[0], args[1]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err_code |= parse_stick_table(file, linenum, args, t, id, curpeers);
|
||||
if (err_code & ERR_FATAL)
|
||||
goto out;
|
||||
|
||||
stktable_store_name(t);
|
||||
t->next = stktables_list;
|
||||
stktables_list = t;
|
||||
}
|
||||
else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
|
||||
curpeers->state = PR_STSTOPPED;
|
||||
}
|
||||
@ -2171,6 +2209,7 @@ int check_config_validity()
|
||||
{
|
||||
int cfgerr = 0;
|
||||
struct proxy *curproxy = NULL;
|
||||
struct stktable *t;
|
||||
struct server *newsrv = NULL;
|
||||
int err_code = 0;
|
||||
unsigned int next_pxid = 1;
|
||||
@ -2261,8 +2300,8 @@ int check_config_validity()
|
||||
if (curproxy->state == PR_STSTOPPED) {
|
||||
/* ensure we don't keep listeners uselessly bound */
|
||||
stop_proxy(curproxy);
|
||||
free((void *)curproxy->table.peers.name);
|
||||
curproxy->table.peers.p = NULL;
|
||||
free((void *)curproxy->table->peers.name);
|
||||
curproxy->table->peers.p = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2624,79 +2663,69 @@ int check_config_validity()
|
||||
|
||||
/* find the target table for 'stick' rules */
|
||||
list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
|
||||
struct proxy *target;
|
||||
struct stktable *target;
|
||||
|
||||
curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
|
||||
if (mrule->flags & STK_IS_STORE)
|
||||
curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
|
||||
|
||||
if (mrule->table.name)
|
||||
target = proxy_tbl_by_name(mrule->table.name);
|
||||
target = stktable_find_by_name(mrule->table.name);
|
||||
else
|
||||
target = curproxy;
|
||||
target = curproxy->table;
|
||||
|
||||
if (!target) {
|
||||
ha_alert("Proxy '%s': unable to find stick-table '%s'.\n",
|
||||
curproxy->id, mrule->table.name);
|
||||
cfgerr++;
|
||||
}
|
||||
else if (target->table.size == 0) {
|
||||
ha_alert("Proxy '%s': stick-table '%s' used but not configured.\n",
|
||||
curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
|
||||
else if (!stktable_compatible_sample(mrule->expr, target->type)) {
|
||||
ha_alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
|
||||
curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
else if (curproxy->bind_proc & ~target->bind_proc) {
|
||||
else if (target->proxy && curproxy->bind_proc & ~target->proxy->bind_proc) {
|
||||
ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n",
|
||||
curproxy->id, target->id, curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
else {
|
||||
free((void *)mrule->table.name);
|
||||
mrule->table.t = &(target->table);
|
||||
stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
|
||||
mrule->table.t = target;
|
||||
stktable_alloc_data_type(target, STKTABLE_DT_SERVER_ID, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* find the target table for 'store response' rules */
|
||||
list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
|
||||
struct proxy *target;
|
||||
struct stktable *target;
|
||||
|
||||
curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
|
||||
|
||||
if (mrule->table.name)
|
||||
target = proxy_tbl_by_name(mrule->table.name);
|
||||
target = stktable_find_by_name(mrule->table.name);
|
||||
else
|
||||
target = curproxy;
|
||||
target = curproxy->table;
|
||||
|
||||
if (!target) {
|
||||
ha_alert("Proxy '%s': unable to find store table '%s'.\n",
|
||||
curproxy->id, mrule->table.name);
|
||||
cfgerr++;
|
||||
}
|
||||
else if (target->table.size == 0) {
|
||||
ha_alert("Proxy '%s': stick-table '%s' used but not configured.\n",
|
||||
curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
|
||||
else if (!stktable_compatible_sample(mrule->expr, target->type)) {
|
||||
ha_alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
|
||||
curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
else if (curproxy->bind_proc & ~target->bind_proc) {
|
||||
else if (target->proxy && (curproxy->bind_proc & ~target->proxy->bind_proc)) {
|
||||
ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n",
|
||||
curproxy->id, target->id, curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
else {
|
||||
free((void *)mrule->table.name);
|
||||
mrule->table.t = &(target->table);
|
||||
stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
|
||||
mrule->table.t = target;
|
||||
stktable_alloc_data_type(target, STKTABLE_DT_SERVER_ID, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2760,32 +2789,32 @@ int check_config_validity()
|
||||
LIST_INIT(&curproxy->block_rules);
|
||||
}
|
||||
|
||||
if (curproxy->table.peers.name) {
|
||||
if (curproxy->table && curproxy->table->peers.name) {
|
||||
struct peers *curpeers;
|
||||
|
||||
for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
|
||||
if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
|
||||
free((void *)curproxy->table.peers.name);
|
||||
curproxy->table.peers.p = curpeers;
|
||||
if (strcmp(curpeers->id, curproxy->table->peers.name) == 0) {
|
||||
free((void *)curproxy->table->peers.name);
|
||||
curproxy->table->peers.p = curpeers;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!curpeers) {
|
||||
ha_alert("Proxy '%s': unable to find sync peers '%s'.\n",
|
||||
curproxy->id, curproxy->table.peers.name);
|
||||
free((void *)curproxy->table.peers.name);
|
||||
curproxy->table.peers.p = NULL;
|
||||
curproxy->id, curproxy->table->peers.name);
|
||||
free((void *)curproxy->table->peers.name);
|
||||
curproxy->table->peers.p = NULL;
|
||||
cfgerr++;
|
||||
}
|
||||
else if (curpeers->state == PR_STSTOPPED) {
|
||||
/* silently disable this peers section */
|
||||
curproxy->table.peers.p = NULL;
|
||||
curproxy->table->peers.p = NULL;
|
||||
}
|
||||
else if (!curpeers->peers_fe) {
|
||||
ha_alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
|
||||
curproxy->id, localpeer, curpeers->id);
|
||||
curproxy->table.peers.p = NULL;
|
||||
curproxy->table->peers.p = NULL;
|
||||
cfgerr++;
|
||||
}
|
||||
}
|
||||
@ -3829,8 +3858,8 @@ out_uri_auth_compat:
|
||||
|
||||
/* compute the required process bindings for the peers */
|
||||
for (curproxy = proxies_list; curproxy; curproxy = curproxy->next)
|
||||
if (curproxy->table.peers.p)
|
||||
curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
|
||||
if (curproxy->table && curproxy->table->peers.p)
|
||||
curproxy->table->peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
|
||||
|
||||
if (cfg_peers) {
|
||||
struct peers *curpeers = cfg_peers, **last;
|
||||
@ -3920,15 +3949,24 @@ out_uri_auth_compat:
|
||||
}
|
||||
}
|
||||
|
||||
for (t = stktables_list; t; t = t->next) {
|
||||
if (t->proxy)
|
||||
continue;
|
||||
if (!stktable_init(t)) {
|
||||
ha_alert("Proxy '%s': failed to initialize stick-table.\n", t->id);
|
||||
cfgerr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize stick-tables on backend capable proxies. This must not
|
||||
* be done earlier because the data size may be discovered while parsing
|
||||
* other proxies.
|
||||
*/
|
||||
for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
|
||||
if (curproxy->state == PR_STSTOPPED)
|
||||
if (curproxy->state == PR_STSTOPPED || !curproxy->table)
|
||||
continue;
|
||||
|
||||
if (!stktable_init(&curproxy->table)) {
|
||||
if (!stktable_init(curproxy->table)) {
|
||||
ha_alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
|
||||
cfgerr++;
|
||||
}
|
||||
|
@ -2369,7 +2369,7 @@ void deinit(void)
|
||||
|
||||
pool_destroy(p->req_cap_pool);
|
||||
pool_destroy(p->rsp_cap_pool);
|
||||
pool_destroy(p->table.pool);
|
||||
pool_destroy(p->table->pool);
|
||||
|
||||
p0 = p;
|
||||
p = p->next;
|
||||
|
@ -1269,9 +1269,9 @@ int hlua_fcn_new_proxy(lua_State *L, struct proxy *px)
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
|
||||
if (px->table.id) {
|
||||
if (px->table && px->table->id) {
|
||||
lua_pushstring(L, "stktable");
|
||||
hlua_fcn_new_stktable(L, &px->table);
|
||||
hlua_fcn_new_stktable(L, px->table);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
|
16
src/proxy.c
16
src/proxy.c
@ -587,7 +587,7 @@ struct proxy *proxy_find_by_id(int id, int cap, int table)
|
||||
if ((px->cap & cap) != cap)
|
||||
continue;
|
||||
|
||||
if (table && !px->table.size)
|
||||
if (table && (!px->table || !px->table->size))
|
||||
continue;
|
||||
|
||||
return px;
|
||||
@ -620,7 +620,7 @@ struct proxy *proxy_find_by_name(const char *name, int cap, int table)
|
||||
if ((curproxy->cap & cap) != cap)
|
||||
continue;
|
||||
|
||||
if (table && !curproxy->table.size)
|
||||
if (table && (!curproxy->table || !curproxy->table->size))
|
||||
continue;
|
||||
|
||||
return curproxy;
|
||||
@ -993,12 +993,12 @@ struct task *manage_proxy(struct task *t, void *context, unsigned short state)
|
||||
* be in neither list. Any entry being dumped will have ref_cnt > 0.
|
||||
* However we protect tables that are being synced to peers.
|
||||
*/
|
||||
if (unlikely(stopping && p->state == PR_STSTOPPED && p->table.current)) {
|
||||
if (!p->table.syncing) {
|
||||
stktable_trash_oldest(&p->table, p->table.current);
|
||||
if (unlikely(stopping && p->state == PR_STSTOPPED && p->table && p->table->current)) {
|
||||
if (!p->table->syncing) {
|
||||
stktable_trash_oldest(p->table, p->table->current);
|
||||
pool_gc(NULL);
|
||||
}
|
||||
if (p->table.current) {
|
||||
if (p->table->current) {
|
||||
/* some entries still remain, let's recheck in one second */
|
||||
next = tick_first(next, tick_add(now_ms, 1000));
|
||||
}
|
||||
@ -1138,8 +1138,8 @@ void soft_stop(void)
|
||||
/* Note: do not wake up stopped proxies' task nor their tables'
|
||||
* tasks as these ones might point to already released entries.
|
||||
*/
|
||||
if (p->table.size && p->table.sync_task)
|
||||
task_wakeup(p->table.sync_task, TASK_WOKEN_MSG);
|
||||
if (p->table && p->table->size && p->table->sync_task)
|
||||
task_wakeup(p->table->sync_task, TASK_WOKEN_MSG);
|
||||
|
||||
if (p->task)
|
||||
task_wakeup(p->task, TASK_WOKEN_MSG);
|
||||
|
28
src/sample.c
28
src/sample.c
@ -1109,7 +1109,8 @@ int smp_resolve_args(struct proxy *p)
|
||||
list_for_each_entry_safe(cur, bak, &p->conf.args.list, list) {
|
||||
struct proxy *px;
|
||||
struct server *srv;
|
||||
char *pname, *sname;
|
||||
struct stktable *t;
|
||||
char *pname, *sname, *stktname;
|
||||
char *err;
|
||||
|
||||
arg = cur->arg;
|
||||
@ -1244,30 +1245,35 @@ int smp_resolve_args(struct proxy *p)
|
||||
break;
|
||||
|
||||
case ARGT_TAB:
|
||||
if (arg->data.str.data) {
|
||||
pname = arg->data.str.area;
|
||||
px = proxy_tbl_by_name(pname);
|
||||
if (!arg->data.str.data) {
|
||||
ha_alert("parsing [%s:%d] : missing table name in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
|
||||
cur->file, cur->line,
|
||||
cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
|
||||
cfgerr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!px) {
|
||||
stktname = arg->data.str.area;
|
||||
t = stktable_find_by_name(stktname);
|
||||
if (!t) {
|
||||
ha_alert("parsing [%s:%d] : unable to find table '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
|
||||
cur->file, cur->line, pname,
|
||||
cur->file, cur->line, stktname,
|
||||
cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
|
||||
cfgerr++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!px->table.size) {
|
||||
if (!t->size) {
|
||||
ha_alert("parsing [%s:%d] : no table in proxy '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
|
||||
cur->file, cur->line, pname,
|
||||
cur->file, cur->line, stktname,
|
||||
cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
|
||||
cfgerr++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p->bind_proc & ~px->bind_proc) {
|
||||
if (t->proxy && (p->bind_proc & ~t->proxy->bind_proc)) {
|
||||
ha_alert("parsing [%s:%d] : stick-table '%s' not present on all processes covered by proxy '%s'.\n",
|
||||
cur->file, cur->line, px->id, p->id);
|
||||
cur->file, cur->line, t->proxy->id, p->id);
|
||||
cfgerr++;
|
||||
break;
|
||||
}
|
||||
@ -1275,7 +1281,7 @@ int smp_resolve_args(struct proxy *p)
|
||||
free(arg->data.str.area);
|
||||
arg->data.str.area = NULL;
|
||||
arg->unresolved = 0;
|
||||
arg->data.prx = px;
|
||||
arg->data.t = t;
|
||||
break;
|
||||
|
||||
case ARGT_USR:
|
||||
|
@ -47,7 +47,36 @@
|
||||
/* structure used to return a table key built from a sample */
|
||||
static THREAD_LOCAL struct stktable_key static_table_key;
|
||||
|
||||
struct stktable *stktables_list;
|
||||
struct eb_root stktable_by_name = EB_ROOT;
|
||||
|
||||
#define round_ptr_size(i) (((i) + (sizeof(void *) - 1)) &~ (sizeof(void *) - 1))
|
||||
|
||||
/* This function inserts stktable <t> into the tree of known stick-table.
|
||||
* The stick-table ID is used as the storing key so it must already have
|
||||
* been initialized.
|
||||
*/
|
||||
void stktable_store_name(struct stktable *t)
|
||||
{
|
||||
t->name.key = t->id;
|
||||
ebis_insert(&stktable_by_name, &t->name);
|
||||
}
|
||||
|
||||
struct stktable *stktable_find_by_name(const char *name)
|
||||
{
|
||||
struct ebpt_node *node;
|
||||
struct stktable *t;
|
||||
|
||||
node = ebis_lookup(&stktable_by_name, name);
|
||||
if (node) {
|
||||
t = container_of(node, struct stktable, name);
|
||||
if (!strcmp(t->id, name))
|
||||
return t;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an allocated sticky session <ts>, and decrease sticky sessions counter
|
||||
* in table <t>.
|
||||
@ -1063,7 +1092,7 @@ static int sample_conv_in_table(const struct arg *arg_p, struct sample *smp, voi
|
||||
struct stktable_key *key;
|
||||
struct stksess *ts;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1091,7 +1120,7 @@ static int sample_conv_table_bytes_in_rate(const struct arg *arg_p, struct sampl
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1128,7 +1157,7 @@ static int sample_conv_table_conn_cnt(const struct arg *arg_p, struct sample *sm
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1164,7 +1193,7 @@ static int sample_conv_table_conn_cur(const struct arg *arg_p, struct sample *sm
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1200,7 +1229,7 @@ static int sample_conv_table_conn_rate(const struct arg *arg_p, struct sample *s
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1237,7 +1266,7 @@ static int sample_conv_table_bytes_out_rate(const struct arg *arg_p, struct samp
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1274,7 +1303,7 @@ static int sample_conv_table_gpt0(const struct arg *arg_p, struct sample *smp, v
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1310,7 +1339,7 @@ static int sample_conv_table_gpc0(const struct arg *arg_p, struct sample *smp, v
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1346,7 +1375,7 @@ static int sample_conv_table_gpc0_rate(const struct arg *arg_p, struct sample *s
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1383,7 +1412,7 @@ static int sample_conv_table_gpc1(const struct arg *arg_p, struct sample *smp, v
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1419,7 +1448,7 @@ static int sample_conv_table_gpc1_rate(const struct arg *arg_p, struct sample *s
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1456,7 +1485,7 @@ static int sample_conv_table_http_err_cnt(const struct arg *arg_p, struct sample
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1492,7 +1521,7 @@ static int sample_conv_table_http_err_rate(const struct arg *arg_p, struct sampl
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1529,7 +1558,7 @@ static int sample_conv_table_http_req_cnt(const struct arg *arg_p, struct sample
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1565,7 +1594,7 @@ static int sample_conv_table_http_req_rate(const struct arg *arg_p, struct sampl
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1602,7 +1631,7 @@ static int sample_conv_table_kbytes_in(const struct arg *arg_p, struct sample *s
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1638,7 +1667,7 @@ static int sample_conv_table_kbytes_out(const struct arg *arg_p, struct sample *
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1674,7 +1703,7 @@ static int sample_conv_table_server_id(const struct arg *arg_p, struct sample *s
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1710,7 +1739,7 @@ static int sample_conv_table_sess_cnt(const struct arg *arg_p, struct sample *sm
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1746,7 +1775,7 @@ static int sample_conv_table_sess_rate(const struct arg *arg_p, struct sample *s
|
||||
struct stksess *ts;
|
||||
void *ptr;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -1782,7 +1811,7 @@ static int sample_conv_table_trackers(const struct arg *arg_p, struct sample *sm
|
||||
struct stktable_key *key;
|
||||
struct stksess *ts;
|
||||
|
||||
t = &arg_p[0].data.prx->table;
|
||||
t = arg_p[0].data.t;
|
||||
|
||||
key = smp_to_stkey(smp, t);
|
||||
if (!key)
|
||||
@ -2062,7 +2091,7 @@ smp_fetch_table_cnt(const struct arg *args, struct sample *smp, const char *kw,
|
||||
{
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
smp->data.type = SMP_T_SINT;
|
||||
smp->data.u.sint = args->data.prx->table.current;
|
||||
smp->data.u.sint = args->data.t->current;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2072,12 +2101,12 @@ smp_fetch_table_cnt(const struct arg *args, struct sample *smp, const char *kw,
|
||||
static int
|
||||
smp_fetch_table_avl(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
struct stktable *t;
|
||||
|
||||
px = args->data.prx;
|
||||
t = args->data.t;
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
smp->data.type = SMP_T_SINT;
|
||||
smp->data.u.sint = px->table.size - px->table.current;
|
||||
smp->data.u.sint = t->size - t->current;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2125,11 +2154,11 @@ smp_fetch_sc_stkctr(struct session *sess, struct stream *strm, const struct arg
|
||||
return NULL;
|
||||
|
||||
/* Converts into key. */
|
||||
key = smp_to_stkey(&smp, &args->data.prx->table);
|
||||
key = smp_to_stkey(&smp, args->data.t);
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
stkctr->table = &args->data.prx->table;
|
||||
stkctr->table = args->data.t;
|
||||
stkctr_set_entry(stkctr, stktable_lookup_key(stkctr->table, key));
|
||||
return stkctr;
|
||||
}
|
||||
@ -2154,7 +2183,7 @@ smp_fetch_sc_stkctr(struct session *sess, struct stream *strm, const struct arg
|
||||
|
||||
if (unlikely(args[arg].type == ARGT_TAB)) {
|
||||
/* an alternate table was specified, let's look up the same key there */
|
||||
stkctr->table = &args[arg].data.prx->table;
|
||||
stkctr->table = args[arg].data.t;
|
||||
stkctr_set_entry(stkctr, stktable_lookup(stkctr->table, stksess));
|
||||
return stkctr;
|
||||
}
|
||||
@ -2187,11 +2216,11 @@ smp_create_src_stkctr(struct session *sess, struct stream *strm, const struct ar
|
||||
return NULL;
|
||||
|
||||
/* Converts into key. */
|
||||
key = smp_to_stkey(&smp, &args->data.prx->table);
|
||||
key = smp_to_stkey(&smp, args->data.t);
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
stkctr->table = &args->data.prx->table;
|
||||
stkctr->table = args->data.t;
|
||||
stkctr_set_entry(stkctr, stktable_get_entry(stkctr->table, key));
|
||||
return stkctr;
|
||||
}
|
||||
@ -2709,7 +2738,7 @@ smp_fetch_src_updt_conn_cnt(const struct arg *args, struct sample *smp, const ch
|
||||
struct stksess *ts;
|
||||
struct stktable_key *key;
|
||||
void *ptr;
|
||||
struct proxy *px;
|
||||
struct stktable *t;
|
||||
|
||||
if (!conn)
|
||||
return 0;
|
||||
@ -2719,17 +2748,17 @@ smp_fetch_src_updt_conn_cnt(const struct arg *args, struct sample *smp, const ch
|
||||
return 0;
|
||||
|
||||
/* Converts into key. */
|
||||
key = smp_to_stkey(smp, &args->data.prx->table);
|
||||
key = smp_to_stkey(smp, args->data.t);
|
||||
if (!key)
|
||||
return 0;
|
||||
|
||||
px = args->data.prx;
|
||||
t = args->data.t;
|
||||
|
||||
if ((ts = stktable_get_entry(&px->table, key)) == NULL)
|
||||
if ((ts = stktable_get_entry(t, key)) == NULL)
|
||||
/* entry does not exist and could not be created */
|
||||
return 0;
|
||||
|
||||
ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT);
|
||||
ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_CNT);
|
||||
if (!ptr) {
|
||||
return 0; /* parameter not stored in this table */
|
||||
}
|
||||
@ -2744,7 +2773,7 @@ smp_fetch_src_updt_conn_cnt(const struct arg *args, struct sample *smp, const ch
|
||||
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
|
||||
stktable_touch_local(&px->table, ts, 1);
|
||||
stktable_touch_local(t, ts, 1);
|
||||
|
||||
/* Touch was previously performed by stktable_update_key */
|
||||
return 1;
|
||||
@ -3229,12 +3258,12 @@ enum {
|
||||
*/
|
||||
static int table_dump_head_to_buffer(struct buffer *msg,
|
||||
struct stream_interface *si,
|
||||
struct proxy *proxy, struct proxy *target)
|
||||
struct stktable *t, struct stktable *target)
|
||||
{
|
||||
struct stream *s = si_strm(si);
|
||||
|
||||
chunk_appendf(msg, "# table: %s, type: %s, size:%d, used:%d\n",
|
||||
proxy->id, stktable_types[proxy->table.type].kw, proxy->table.size, proxy->table.current);
|
||||
t->id, stktable_types[t->type].kw, t->size, t->current);
|
||||
|
||||
/* any other information should be dumped here */
|
||||
|
||||
@ -3255,32 +3284,32 @@ static int table_dump_head_to_buffer(struct buffer *msg,
|
||||
*/
|
||||
static int table_dump_entry_to_buffer(struct buffer *msg,
|
||||
struct stream_interface *si,
|
||||
struct proxy *proxy, struct stksess *entry)
|
||||
struct stktable *t, struct stksess *entry)
|
||||
{
|
||||
int dt;
|
||||
|
||||
chunk_appendf(msg, "%p:", entry);
|
||||
|
||||
if (proxy->table.type == SMP_T_IPV4) {
|
||||
if (t->type == SMP_T_IPV4) {
|
||||
char addr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, (const void *)&entry->key.key, addr, sizeof(addr));
|
||||
chunk_appendf(msg, " key=%s", addr);
|
||||
}
|
||||
else if (proxy->table.type == SMP_T_IPV6) {
|
||||
else if (t->type == SMP_T_IPV6) {
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, (const void *)&entry->key.key, addr, sizeof(addr));
|
||||
chunk_appendf(msg, " key=%s", addr);
|
||||
}
|
||||
else if (proxy->table.type == SMP_T_SINT) {
|
||||
else if (t->type == SMP_T_SINT) {
|
||||
chunk_appendf(msg, " key=%u", *(unsigned int *)entry->key.key);
|
||||
}
|
||||
else if (proxy->table.type == SMP_T_STR) {
|
||||
else if (t->type == SMP_T_STR) {
|
||||
chunk_appendf(msg, " key=");
|
||||
dump_text(msg, (const char *)entry->key.key, proxy->table.key_size);
|
||||
dump_text(msg, (const char *)entry->key.key, t->key_size);
|
||||
}
|
||||
else {
|
||||
chunk_appendf(msg, " key=");
|
||||
dump_binary(msg, (const char *)entry->key.key, proxy->table.key_size);
|
||||
dump_binary(msg, (const char *)entry->key.key, t->key_size);
|
||||
}
|
||||
|
||||
chunk_appendf(msg, " use=%d exp=%d", entry->ref_cnt - 1, tick_remain(now_ms, entry->expire));
|
||||
@ -3288,14 +3317,14 @@ static int table_dump_entry_to_buffer(struct buffer *msg,
|
||||
for (dt = 0; dt < STKTABLE_DATA_TYPES; dt++) {
|
||||
void *ptr;
|
||||
|
||||
if (proxy->table.data_ofs[dt] == 0)
|
||||
if (t->data_ofs[dt] == 0)
|
||||
continue;
|
||||
if (stktable_data_types[dt].arg_type == ARG_T_DELAY)
|
||||
chunk_appendf(msg, " %s(%d)=", stktable_data_types[dt].name, proxy->table.data_arg[dt].u);
|
||||
chunk_appendf(msg, " %s(%d)=", stktable_data_types[dt].name, t->data_arg[dt].u);
|
||||
else
|
||||
chunk_appendf(msg, " %s=", stktable_data_types[dt].name);
|
||||
|
||||
ptr = stktable_data_ptr(&proxy->table, entry, dt);
|
||||
ptr = stktable_data_ptr(t, entry, dt);
|
||||
switch (stktable_data_types[dt].std_type) {
|
||||
case STD_T_SINT:
|
||||
chunk_appendf(msg, "%d", stktable_data_cast(ptr, std_t_sint));
|
||||
@ -3309,7 +3338,7 @@ static int table_dump_entry_to_buffer(struct buffer *msg,
|
||||
case STD_T_FRQP:
|
||||
chunk_appendf(msg, "%d",
|
||||
read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
|
||||
proxy->table.data_arg[dt].u));
|
||||
t->data_arg[dt].u));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3330,7 +3359,7 @@ static int table_dump_entry_to_buffer(struct buffer *msg,
|
||||
static int table_process_entry_per_key(struct appctx *appctx, char **args)
|
||||
{
|
||||
struct stream_interface *si = appctx->owner;
|
||||
struct proxy *px = appctx->ctx.table.target;
|
||||
struct stktable *t = appctx->ctx.table.target;
|
||||
struct stksess *ts;
|
||||
uint32_t uint32_key;
|
||||
unsigned char ip6_key[sizeof(struct in6_addr)];
|
||||
@ -3347,7 +3376,7 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (px->table.type) {
|
||||
switch (t->type) {
|
||||
case SMP_T_IPV4:
|
||||
uint32_key = htonl(inetaddr_host(args[4]));
|
||||
static_table_key.key = &uint32_key;
|
||||
@ -3408,30 +3437,30 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
|
||||
|
||||
switch (appctx->ctx.table.action) {
|
||||
case STK_CLI_ACT_SHOW:
|
||||
ts = stktable_lookup_key(&px->table, &static_table_key);
|
||||
ts = stktable_lookup_key(t, &static_table_key);
|
||||
if (!ts)
|
||||
return 1;
|
||||
chunk_reset(&trash);
|
||||
if (!table_dump_head_to_buffer(&trash, si, px, px)) {
|
||||
stktable_release(&px->table, ts);
|
||||
if (!table_dump_head_to_buffer(&trash, si, t, t)) {
|
||||
stktable_release(t, ts);
|
||||
return 0;
|
||||
}
|
||||
HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock);
|
||||
if (!table_dump_entry_to_buffer(&trash, si, px, ts)) {
|
||||
if (!table_dump_entry_to_buffer(&trash, si, t, ts)) {
|
||||
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
|
||||
stktable_release(&px->table, ts);
|
||||
stktable_release(t, ts);
|
||||
return 0;
|
||||
}
|
||||
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
|
||||
stktable_release(&px->table, ts);
|
||||
stktable_release(t, ts);
|
||||
break;
|
||||
|
||||
case STK_CLI_ACT_CLR:
|
||||
ts = stktable_lookup_key(&px->table, &static_table_key);
|
||||
ts = stktable_lookup_key(t, &static_table_key);
|
||||
if (!ts)
|
||||
return 1;
|
||||
|
||||
if (!stksess_kill(&px->table, ts, 1)) {
|
||||
if (!stksess_kill(t, ts, 1)) {
|
||||
/* don't delete an entry which is currently referenced */
|
||||
appctx->ctx.cli.severity = LOG_ERR;
|
||||
appctx->ctx.cli.msg = "Entry currently in use, cannot remove\n";
|
||||
@ -3442,7 +3471,7 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
|
||||
break;
|
||||
|
||||
case STK_CLI_ACT_SET:
|
||||
ts = stktable_get_entry(&px->table, &static_table_key);
|
||||
ts = stktable_get_entry(t, &static_table_key);
|
||||
if (!ts) {
|
||||
/* don't delete an entry which is currently referenced */
|
||||
appctx->ctx.cli.severity = LOG_ERR;
|
||||
@ -3458,7 +3487,7 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
|
||||
appctx->ctx.cli.msg = "\"data.<type>\" followed by a value expected\n";
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
|
||||
stktable_touch_local(&px->table, ts, 1);
|
||||
stktable_touch_local(t, ts, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -3468,16 +3497,16 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
|
||||
appctx->ctx.cli.msg = "Unknown data type\n";
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
|
||||
stktable_touch_local(&px->table, ts, 1);
|
||||
stktable_touch_local(t, ts, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!px->table.data_ofs[data_type]) {
|
||||
if (!t->data_ofs[data_type]) {
|
||||
appctx->ctx.cli.severity = LOG_ERR;
|
||||
appctx->ctx.cli.msg = "Data type not stored in this table\n";
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
|
||||
stktable_touch_local(&px->table, ts, 1);
|
||||
stktable_touch_local(t, ts, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -3486,11 +3515,11 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
|
||||
appctx->ctx.cli.msg = "Require a valid integer value to store\n";
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
|
||||
stktable_touch_local(&px->table, ts, 1);
|
||||
stktable_touch_local(t, ts, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr = stktable_data_ptr(&px->table, ts, data_type);
|
||||
ptr = stktable_data_ptr(t, ts, data_type);
|
||||
|
||||
switch (stktable_data_types[data_type].std_type) {
|
||||
case STD_T_SINT:
|
||||
@ -3520,7 +3549,7 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
|
||||
}
|
||||
}
|
||||
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
|
||||
stktable_touch_local(&px->table, ts, 1);
|
||||
stktable_touch_local(t, ts, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -3553,7 +3582,7 @@ static int table_prepare_data_request(struct appctx *appctx, char **args)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!((struct proxy *)appctx->ctx.table.target)->table.data_ofs[appctx->ctx.table.data_type]) {
|
||||
if (!((struct proxy *)appctx->ctx.table.target)->table->data_ofs[appctx->ctx.table.data_type]) {
|
||||
appctx->ctx.cli.severity = LOG_ERR;
|
||||
appctx->ctx.cli.msg = "Data type not stored in this table\n";
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
@ -3584,12 +3613,11 @@ static int cli_parse_table_req(char **args, char *payload, struct appctx *appctx
|
||||
{
|
||||
appctx->ctx.table.data_type = -1;
|
||||
appctx->ctx.table.target = NULL;
|
||||
appctx->ctx.table.proxy = NULL;
|
||||
appctx->ctx.table.entry = NULL;
|
||||
appctx->ctx.table.action = (long)private; // keyword argument, one of STK_CLI_ACT_*
|
||||
|
||||
if (*args[2]) {
|
||||
appctx->ctx.table.target = proxy_tbl_by_name(args[2]);
|
||||
appctx->ctx.table.target = stktable_find_by_name(args[2]);
|
||||
if (!appctx->ctx.table.target) {
|
||||
appctx->ctx.cli.severity = LOG_ERR;
|
||||
appctx->ctx.cli.msg = "No such table\n";
|
||||
@ -3663,7 +3691,7 @@ static int cli_io_handler_table(struct appctx *appctx)
|
||||
if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW))) {
|
||||
/* in case of abort, remove any refcount we might have set on an entry */
|
||||
if (appctx->st2 == STAT_ST_LIST) {
|
||||
stksess_kill_if_expired(&appctx->ctx.table.proxy->table, appctx->ctx.table.entry, 1);
|
||||
stksess_kill_if_expired(appctx->ctx.table.t, appctx->ctx.table.entry, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -3673,42 +3701,42 @@ static int cli_io_handler_table(struct appctx *appctx)
|
||||
while (appctx->st2 != STAT_ST_FIN) {
|
||||
switch (appctx->st2) {
|
||||
case STAT_ST_INIT:
|
||||
appctx->ctx.table.proxy = appctx->ctx.table.target;
|
||||
if (!appctx->ctx.table.proxy)
|
||||
appctx->ctx.table.proxy = proxies_list;
|
||||
appctx->ctx.table.t = appctx->ctx.table.target;
|
||||
if (!appctx->ctx.table.t)
|
||||
appctx->ctx.table.t = stktables_list;
|
||||
|
||||
appctx->ctx.table.entry = NULL;
|
||||
appctx->st2 = STAT_ST_INFO;
|
||||
break;
|
||||
|
||||
case STAT_ST_INFO:
|
||||
if (!appctx->ctx.table.proxy ||
|
||||
if (!appctx->ctx.table.t ||
|
||||
(appctx->ctx.table.target &&
|
||||
appctx->ctx.table.proxy != appctx->ctx.table.target)) {
|
||||
appctx->ctx.table.t != appctx->ctx.table.target)) {
|
||||
appctx->st2 = STAT_ST_END;
|
||||
break;
|
||||
}
|
||||
|
||||
if (appctx->ctx.table.proxy->table.size) {
|
||||
if (show && !table_dump_head_to_buffer(&trash, si, appctx->ctx.table.proxy, appctx->ctx.table.target))
|
||||
if (appctx->ctx.table.t->size) {
|
||||
if (show && !table_dump_head_to_buffer(&trash, si, appctx->ctx.table.t, appctx->ctx.table.target))
|
||||
return 0;
|
||||
|
||||
if (appctx->ctx.table.target &&
|
||||
(strm_li(s)->bind_conf->level & ACCESS_LVL_MASK) >= ACCESS_LVL_OPER) {
|
||||
/* dump entries only if table explicitly requested */
|
||||
HA_SPIN_LOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
|
||||
eb = ebmb_first(&appctx->ctx.table.proxy->table.keys);
|
||||
HA_SPIN_LOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
|
||||
eb = ebmb_first(&appctx->ctx.table.t->keys);
|
||||
if (eb) {
|
||||
appctx->ctx.table.entry = ebmb_entry(eb, struct stksess, key);
|
||||
appctx->ctx.table.entry->ref_cnt++;
|
||||
appctx->st2 = STAT_ST_LIST;
|
||||
HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
|
||||
HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
|
||||
break;
|
||||
}
|
||||
HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
|
||||
HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
|
||||
}
|
||||
}
|
||||
appctx->ctx.table.proxy = appctx->ctx.table.proxy->next;
|
||||
appctx->ctx.table.t = appctx->ctx.table.t->next;
|
||||
break;
|
||||
|
||||
case STAT_ST_LIST:
|
||||
@ -3723,7 +3751,7 @@ static int cli_io_handler_table(struct appctx *appctx)
|
||||
|
||||
|
||||
dt = appctx->ctx.table.data_type;
|
||||
ptr = stktable_data_ptr(&appctx->ctx.table.proxy->table,
|
||||
ptr = stktable_data_ptr(appctx->ctx.table.t,
|
||||
appctx->ctx.table.entry,
|
||||
dt);
|
||||
|
||||
@ -3740,7 +3768,7 @@ static int cli_io_handler_table(struct appctx *appctx)
|
||||
break;
|
||||
case STD_T_FRQP:
|
||||
data = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
|
||||
appctx->ctx.table.proxy->table.data_arg[dt].u);
|
||||
appctx->ctx.table.t->data_arg[dt].u);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3761,14 +3789,14 @@ static int cli_io_handler_table(struct appctx *appctx)
|
||||
}
|
||||
|
||||
if (show && !skip_entry &&
|
||||
!table_dump_entry_to_buffer(&trash, si, appctx->ctx.table.proxy, appctx->ctx.table.entry)) {
|
||||
!table_dump_entry_to_buffer(&trash, si, appctx->ctx.table.t, appctx->ctx.table.entry)) {
|
||||
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &appctx->ctx.table.entry->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &appctx->ctx.table.entry->lock);
|
||||
|
||||
HA_SPIN_LOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
|
||||
HA_SPIN_LOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
|
||||
appctx->ctx.table.entry->ref_cnt--;
|
||||
|
||||
eb = ebmb_next(&appctx->ctx.table.entry->key);
|
||||
@ -3776,23 +3804,23 @@ static int cli_io_handler_table(struct appctx *appctx)
|
||||
struct stksess *old = appctx->ctx.table.entry;
|
||||
appctx->ctx.table.entry = ebmb_entry(eb, struct stksess, key);
|
||||
if (show)
|
||||
__stksess_kill_if_expired(&appctx->ctx.table.proxy->table, old);
|
||||
__stksess_kill_if_expired(appctx->ctx.table.t, old);
|
||||
else if (!skip_entry && !appctx->ctx.table.entry->ref_cnt)
|
||||
__stksess_kill(&appctx->ctx.table.proxy->table, old);
|
||||
__stksess_kill(appctx->ctx.table.t, old);
|
||||
appctx->ctx.table.entry->ref_cnt++;
|
||||
HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
|
||||
HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (show)
|
||||
__stksess_kill_if_expired(&appctx->ctx.table.proxy->table, appctx->ctx.table.entry);
|
||||
__stksess_kill_if_expired(appctx->ctx.table.t, appctx->ctx.table.entry);
|
||||
else if (!skip_entry && !appctx->ctx.table.entry->ref_cnt)
|
||||
__stksess_kill(&appctx->ctx.table.proxy->table, appctx->ctx.table.entry);
|
||||
__stksess_kill(appctx->ctx.table.t, appctx->ctx.table.entry);
|
||||
|
||||
HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
|
||||
HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
|
||||
|
||||
appctx->ctx.table.proxy = appctx->ctx.table.proxy->next;
|
||||
appctx->ctx.table.t = appctx->ctx.table.t->next;
|
||||
appctx->st2 = STAT_ST_INFO;
|
||||
break;
|
||||
|
||||
@ -3807,7 +3835,7 @@ static int cli_io_handler_table(struct appctx *appctx)
|
||||
static void cli_release_show_table(struct appctx *appctx)
|
||||
{
|
||||
if (appctx->st2 == STAT_ST_LIST) {
|
||||
stksess_kill_if_expired(&appctx->ctx.table.proxy->table, appctx->ctx.table.entry, 1);
|
||||
stksess_kill_if_expired(appctx->ctx.table.t, appctx->ctx.table.entry, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user