diff --git a/doc/management.txt b/doc/management.txt index c15e71af9..6ccd468f4 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 080fee85d..42b3bdcaa 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 },