From: Willy Tarreau Date: Fri, 30 Apr 2021 11:31:43 +0000 (+0200) Subject: MINOR: map/acl: add the possibility to specify the version in "clear map/acl" X-Git-Tag: v2.4-dev18~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ff3feeb5cf2f8fb3d1c4b8e0984a6249a516de7e;p=thirdparty%2Fhaproxy.git MINOR: map/acl: add the possibility to specify the version in "clear map/acl" This will ease maintenance of versionned maps by allowing to clear old or failed updates instead of the current version. Nothing was done to allow clearing everyhing, though if there was a need for this, implementing "@all" or something equivalent wouldn't require more than 3 lines of code. --- diff --git a/doc/management.txt b/doc/management.txt index c15e71af99..6ccd468f44 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1495,15 +1495,19 @@ 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 acl +clear acl [@] Remove all entries from the acl . is the # or the returned by "show acl". Note that if the reference is a file and is - shared with a map, this map will be also cleared. + shared with a map, this map will be also cleared. By default only the current + version of the ACL is cleared (the one being matched against). However it is + possible to specify another version using '@' followed by this version. -clear map +clear map [@] Remove all entries from the map . is the # or the returned by "show map". Note that if the reference is a file and is - shared with a acl, this acl will be also cleared. + shared with a acl, this acl will be also cleared. By default only the current + version of the map is cleared (the one being matched against). However it is + possible to specify another version using '@' followed by this version. clear table [ data. ] | [ key ] Remove entries from the stick-table
. diff --git a/src/map.c b/src/map.c index 080fee85d1..42b3bdcaad 100644 --- a/src/map.c +++ b/src/map.c @@ -935,15 +935,17 @@ static int cli_parse_del_map(char **args, char *payload, struct appctx *appctx, return 1; } - -/* continue to clear a map which was started in the parser */ +/* continue to clear a map which was started in the parser. The range of + * generations this applies to is taken from appctx->ctx.cli.i0 for the oldest + * and appctx->ctx.cli.i1 for the latest. + */ static int cli_io_handler_clear_map(struct appctx *appctx) { struct stream_interface *si = appctx->owner; int finished; HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); - finished = pat_ref_prune(appctx->ctx.map.ref); + finished = pat_ref_purge_range(appctx->ctx.map.ref, appctx->ctx.cli.i0, appctx->ctx.cli.i1, 100); HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); if (!finished) { @@ -954,15 +956,30 @@ static int cli_io_handler_clear_map(struct appctx *appctx) return 1; } +/* note: sets appctx->ctx.cli.i0 and appctx->ctx.cli.i1 to the oldest and + * latest generations to clear, respectively, and will call the clear_map + * handler. + */ static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx, void *private) { if (strcmp(args[1], "map") == 0 || strcmp(args[1], "acl") == 0) { + const char *gen = NULL; + /* Set ACL or MAP flags. */ if (args[1][0] == 'm') appctx->ctx.map.display_flags = PAT_REF_MAP; else appctx->ctx.map.display_flags = PAT_REF_ACL; + /* For both "map" and "acl" we may have an optional generation + * number specified using a "@" character before the pattern + * file name. + */ + if (*args[2] == '@') { + gen = args[2] + 1; + args++; + } + /* no parameter */ if (!*args[2]) { if (appctx->ctx.map.display_flags == PAT_REF_MAP) @@ -981,6 +998,12 @@ static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx return cli_err(appctx, "Unknown ACL identifier. Please use # or .\n"); } + /* set the desired generation id in cli.i0/i1 */ + if (gen) + appctx->ctx.cli.i1 = appctx->ctx.cli.i0 = str2uic(gen); + else + appctx->ctx.cli.i1 = appctx->ctx.cli.i0 = appctx->ctx.map.ref->curr_gen; + /* delegate the clearing to the I/O handler which can yield */ return 0; } @@ -991,12 +1014,12 @@ static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx static struct cli_kw_list cli_kws = {{ },{ { { "add", "acl", NULL }, "add acl : add acl entry", cli_parse_add_map, NULL }, - { { "clear", "acl", NULL }, "clear acl : clear the content of this acl", cli_parse_clear_map, cli_io_handler_clear_map, NULL }, + { { "clear", "acl", NULL }, "clear acl [@ver] : clear the content of this acl", cli_parse_clear_map, cli_io_handler_clear_map, NULL }, { { "del", "acl", NULL }, "del acl : delete acl entry", cli_parse_del_map, NULL }, { { "get", "acl", NULL }, "get acl : report the patterns matching a sample for an ACL", cli_parse_get_map, cli_io_handler_map_lookup, cli_release_mlook }, { { "show", "acl", NULL }, "show acl [@ver] [id] : report available acls or dump an acl's contents", cli_parse_show_map, NULL }, { { "add", "map", NULL }, "add map : add map entry", cli_parse_add_map, NULL }, - { { "clear", "map", NULL }, "clear map : clear the content of this map", cli_parse_clear_map, cli_io_handler_clear_map, NULL }, + { { "clear", "map", NULL }, "clear map [@ver] : clear the content of this map", cli_parse_clear_map, cli_io_handler_clear_map, NULL }, { { "del", "map", NULL }, "del map : delete map entry", cli_parse_del_map, NULL }, { { "get", "map", NULL }, "get map : report the keys and values matching a sample for a map", cli_parse_get_map, cli_io_handler_map_lookup, cli_release_mlook }, { { "set", "map", NULL }, "set map : modify map entry", cli_parse_set_map, NULL },