From c88b887d8d500b3382dec1a41c0c7f1bd742a5a9 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 15 Jun 2011 15:18:49 +0900 Subject: [PATCH] [MINOR] More flexible clearing of stick table * Allow clearing of all entries of a table * Allow clearing of all entries of a table that match a data filter --- doc/configuration.txt | 47 ++++++++++++++++++++++++++++----------- include/proto/dumpstats.h | 1 + src/dumpstats.c | 41 +++++++++++++++++++++++----------- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index a21c43a9e..9bf990038 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -9309,15 +9309,34 @@ clear counters all server. This has the same effect as restarting. This command is restricted and can only be issued on sockets configured for level "admin". -clear table key - Remove entry from the stick-table
. The key must be of the same - type as the table, which currently is limited to IPv4. This is typically used - un unblock some users complaining they have been abusively denied access to a - service, but this can also be used to clear some stickiness entries matching - a server that is going to be replaced (see "show table" below for details). - Note that sometimes, removal of a key will be refused because it is currently - tracked by a session. Retrying a few seconds later after the session ends is - usuall enough. +clear table
[ data. ] | [ key ] + Remove entries from the stick-table
. + + This is typically used to unblock some users complaining they have been + abusively denied access to a service, but this can also be used to clear some + stickiness entries matching a server that is going to be replaced (see "show + table" below for details). Note that sometimes, removal of an entry will be + refused because it is currently tracked by a session. Retrying a few seconds + later after the session ends is usual enough. + + In the case where no options arguments are given all entries will be removed. + + When the "data." form is used entries matching a filter applied using the + stored data (see "stick-table" in section 4.2) are removed. A stored data + type must be specified in , and this data type must be stored in the + table otherwise an error is reported. The data is compared according to + with the 64-bit integer . Operators are the same as with + the ACLs : + + - eq : match entries whose data is equal to this value + - ne : match entries whose data is not equal to this value + - le : match entries whose data is less than or equal to this value + - ge : match entries whose data is greater than or equal to this value + - lt : match entries whose data is less than this value + - gt : match entries whose data is greater than this value + + When the key form is used the entry is removed. The key must be of the + same type as the table, which currently is limited to IPv4. Example : $ echo "show table http_proxy" | socat stdio /tmp/sock1 @@ -9333,6 +9352,9 @@ clear table
key >>> # table: http_proxy, type: ip, size:204800, used:1 >>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \ bytes_out_rate(60000)=191 + $ echo "clear table http_proxy data.gpc0 eq 1" | socat stdio /tmp/sock1 + $ echo "show table http_proxy" | socat stdio /tmp/sock1 + >>> # table: http_proxy, type: ip, size:204800, used:1 disable server / Mark the server DOWN for maintenance. In this mode, no more checks will be @@ -9538,10 +9560,9 @@ show table [ data. ] | [ key ] - lt : match entries whose data is less than this value - gt : match entries whose data is greater than this value - When the key form is used the filter applies to the key of - the stick table entry (see "stick-table" in section 4.2). - The stick table must be of type ip otherwise an error will - be reported. + + When the key form is used the entry is shown. The key must be of the + same type as the table, which currently is limited to IPv4. Example : $ echo "show table http_proxy" | socat stdio /tmp/sock1 diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h index 850819a2a..eb44a3632 100644 --- a/include/proto/dumpstats.h +++ b/include/proto/dumpstats.h @@ -53,6 +53,7 @@ #define STAT_CLI_O_SESS 6 /* dump sessions */ #define STAT_CLI_O_ERR 7 /* dump errors */ #define STAT_CLI_O_TAB 8 /* dump tables */ +#define STAT_CLI_O_CLR 9 /* clear tables */ /* status codes (strictly 4 chars) used in the URL to display a message */ #define STAT_STATUS_UNKN "UNKN" /* an unknown error occured, shouldn't happen */ diff --git a/src/dumpstats.c b/src/dumpstats.c index 6adcee281..8cd82ad8c 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -59,7 +59,7 @@ static int stats_dump_raw_to_buffer(struct stream_interface *si); static int stats_dump_full_sess_to_buffer(struct stream_interface *si); static int stats_dump_sess_to_buffer(struct stream_interface *si); static int stats_dump_errors_to_buffer(struct stream_interface *si); -static int stats_dump_table_to_buffer(struct stream_interface *si); +static int stats_table_request(struct stream_interface *si, bool show); static int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struct uri_auth *uri); static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri); @@ -599,7 +599,10 @@ static void stats_sock_table_request(struct stream_interface *si, char **args, b si->applet.state = STAT_ST_INIT; si->applet.ctx.table.proxy = NULL; si->applet.ctx.table.entry = NULL; - si->applet.st0 = STAT_CLI_O_TAB; // stats_dump_table_to_buffer + if (show) + si->applet.st0 = STAT_CLI_O_TAB; + else + si->applet.st0 = STAT_CLI_O_CLR; if (*args[2]) { si->applet.ctx.table.target = find_stktable(args[2]); @@ -617,9 +620,9 @@ static void stats_sock_table_request(struct stream_interface *si, char **args, b if (strcmp(args[3], "key") == 0) stats_sock_table_key_request(si, args, show); - else if (show && strncmp(args[3], "data.", 5) == 0) + else if (strncmp(args[3], "data.", 5) == 0) stats_sock_table_data_request(si, args); - else if (!show || *args[3]) + else if (*args[3]) goto err_args; return; @@ -628,7 +631,7 @@ err_args: if (show) si->applet.ctx.cli.msg = "Optional argument only supports \"data.\" and key \n"; else - si->applet.ctx.cli.msg = "Required arguments:
key \n"; + si->applet.ctx.cli.msg = "Required arguments:
\"data.\" or
key \n"; si->applet.st0 = STAT_CLI_PRINT; } @@ -1181,7 +1184,11 @@ static void cli_io_handler(struct stream_interface *si) si->applet.st0 = STAT_CLI_PROMPT; break; case STAT_CLI_O_TAB: - if (stats_dump_table_to_buffer(si)) + if (stats_table_request(si, true)) + si->applet.st0 = STAT_CLI_PROMPT; + break; + case STAT_CLI_O_CLR: + if (stats_table_request(si, false)) si->applet.st0 = STAT_CLI_PROMPT; break; default: /* abnormal state */ @@ -3306,12 +3313,13 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si) * properly set. It returns 0 if the output buffer is full and it needs * to be called again, otherwise non-zero. */ -static int stats_dump_table_to_buffer(struct stream_interface *si) +static int stats_table_request(struct stream_interface *si, bool show) { struct session *s = si->applet.private; struct chunk msg; struct ebmb_node *eb; int dt; + bool skip_entry; /* * We have 3 possible states in si->applet.state : @@ -3356,8 +3364,8 @@ static int stats_dump_table_to_buffer(struct stream_interface *si) } if (si->applet.ctx.table.proxy->table.size) { - if (!stats_dump_table_head_to_buffer(&msg, si, si->applet.ctx.table.proxy, - si->applet.ctx.table.target)) + if (show && !stats_dump_table_head_to_buffer(&msg, si, si->applet.ctx.table.proxy, + si->applet.ctx.table.target)) return 0; if (si->applet.ctx.table.target && @@ -3376,6 +3384,8 @@ static int stats_dump_table_to_buffer(struct stream_interface *si) break; case STAT_ST_LIST: + skip_entry = false; + if (si->applet.ctx.table.data_type >= 0) { /* we're filtering on some data contents */ void *ptr; @@ -3416,14 +3426,14 @@ static int stats_dump_table_to_buffer(struct stream_interface *si) (si->applet.ctx.table.data_op == STD_OP_EQ || si->applet.ctx.table.data_op == STD_OP_LT || si->applet.ctx.table.data_op == STD_OP_LE))) - goto skip_entry; + skip_entry = true; } - if (!stats_dump_table_entry_to_buffer(&msg, si, si->applet.ctx.table.proxy, + if (show && !skip_entry && + !stats_dump_table_entry_to_buffer(&msg, si, si->applet.ctx.table.proxy, si->applet.ctx.table.entry)) return 0; - skip_entry: si->applet.ctx.table.entry->ref_cnt--; eb = ebmb_next(&si->applet.ctx.table.entry->key); @@ -3435,7 +3445,12 @@ static int stats_dump_table_to_buffer(struct stream_interface *si) break; } - stksess_kill_if_expired(&si->applet.ctx.table.proxy->table, si->applet.ctx.table.entry); + + if (show) + stksess_kill_if_expired(&si->applet.ctx.table.proxy->table, si->applet.ctx.table.entry); + else if (!skip_entry && !si->applet.ctx.table.entry->ref_cnt) + stksess_kill(&si->applet.ctx.table.proxy->table, si->applet.ctx.table.entry); + si->applet.ctx.table.proxy = si->applet.ctx.table.proxy->next; si->applet.state = STAT_ST_INFO; break;