]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
CLEANUP: map/cli: take the "show map" context definition out of the appctx
authorWilly Tarreau <w@1wt.eu>
Tue, 3 May 2022 09:54:47 +0000 (11:54 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 6 May 2022 16:13:35 +0000 (18:13 +0200)
This makes use of the generic command context allocation so that the
appctx doesn't have to declare a specific one anymore. The context is
created during parsing. Many commands, including pure parsers, use this
context but that's not a problem as it's designed to be used this way.
Due to this, many lines are changed but that's in fact a replacement of
"appctx->ctx.map" with "ctx->". Note that the code also uses st2 which
deserves being addressed in separate commit.

include/haproxy/applet-t.h
src/map.c

index f416f7334c5606810aee081eb8cdc0e4c6faacc9..39338f85879768abc3dc3206088018859fcfd28f 100644 (file)
@@ -149,13 +149,6 @@ struct appctx {
                                int iid, type, sid;     /* proxy id, type and service id if bounding of stats is enabled */
                                int st_code;            /* the status code returned by an action */
                        } stats;
-                       struct {
-                               unsigned int display_flags;
-                               struct pat_ref *ref;
-                               struct bref bref;       /* back-reference from the pat_ref_elt being dumped */
-                               struct pattern_expr *expr;
-                               struct buffer chunk;
-                       } map;
                        struct {
                                struct hlua *hlua;
                                struct task *task;
index 6c35680a7a0b48dd31b7d04921742dac13da73ea..c20998d66c03d6d0d807f4d1c6289ff287169d28 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -14,7 +14,7 @@
 #include <syslog.h>
 
 #include <haproxy/api.h>
-#include <haproxy/applet-t.h>
+#include <haproxy/applet.h>
 #include <haproxy/arg.h>
 #include <haproxy/cli.h>
 #include <haproxy/conn_stream.h>
@@ -321,9 +321,23 @@ struct pattern_expr *pat_expr_get_next(struct pattern_expr *getnext, struct list
        return expr;
 }
 
+/* appctx context for the "{show|get|add|del|*} {map|acl}" commands. This is
+ * used even by commands that only have a parser and no I/O handler because
+ * it provides a unified way to manipulate some fields and will allow to
+ * expand some of them more easily later if needed.
+ */
+struct show_map_ctx {
+       struct pat_ref *ref;
+       struct bref bref;       /* back-reference from the pat_ref_elt being dumped */
+       struct pattern_expr *expr;
+       struct buffer chunk;
+       unsigned int display_flags;
+};
+
 /* expects the current generation ID in appctx->cli.cli.i0 */
 static int cli_io_handler_pat_list(struct appctx *appctx)
 {
+       struct show_map_ctx *ctx = appctx->svcctx;
        struct conn_stream *cs = appctx->owner;
        struct pat_ref_elt *elt;
 
@@ -332,12 +346,12 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
                 * reference to the last ref_elt being dumped.
                 */
                if (appctx->st2 == STAT_ST_LIST) {
-                       HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-                       if (!LIST_ISEMPTY(&appctx->ctx.map.bref.users)) {
-                               LIST_DELETE(&appctx->ctx.map.bref.users);
-                               LIST_INIT(&appctx->ctx.map.bref.users);
+                       HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+                       if (!LIST_ISEMPTY(&ctx->bref.users)) {
+                               LIST_DELETE(&ctx->bref.users);
+                               LIST_INIT(&ctx->bref.users);
                        }
-                       HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+                       HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                }
                return 1;
        }
@@ -349,19 +363,19 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
                /* fall through */
 
        case STAT_ST_LIST:
-               HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
 
-               if (!LIST_ISEMPTY(&appctx->ctx.map.bref.users)) {
-                       LIST_DELETE(&appctx->ctx.map.bref.users);
-                       LIST_INIT(&appctx->ctx.map.bref.users);
+               if (!LIST_ISEMPTY(&ctx->bref.users)) {
+                       LIST_DELETE(&ctx->bref.users);
+                       LIST_INIT(&ctx->bref.users);
                } else {
-                       appctx->ctx.map.bref.ref = appctx->ctx.map.ref->head.n;
+                       ctx->bref.ref = ctx->ref->head.n;
                }
 
-               while (appctx->ctx.map.bref.ref != &appctx->ctx.map.ref->head) {
+               while (ctx->bref.ref != &ctx->ref->head) {
                        chunk_reset(&trash);
 
-                       elt = LIST_ELEM(appctx->ctx.map.bref.ref, struct pat_ref_elt *, list);
+                       elt = LIST_ELEM(ctx->bref.ref, struct pat_ref_elt *, list);
 
                        if (elt->gen_id != appctx->ctx.cli.i0)
                                goto skip;
@@ -379,16 +393,16 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
                                /* let's try again later from this stream. We add ourselves into
                                 * this stream's users so that it can remove us upon termination.
                                 */
-                               LIST_APPEND(&elt->back_refs, &appctx->ctx.map.bref.users);
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+                               LIST_APPEND(&elt->back_refs, &ctx->bref.users);
+                               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                                cs_rx_room_blk(cs);
                                return 0;
                        }
                skip:
                        /* get next list entry and check the end of the list */
-                       appctx->ctx.map.bref.ref = elt->list.n;
+                       ctx->bref.ref = elt->list.n;
                }
-               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                /* fall through */
 
        default:
@@ -399,6 +413,7 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
 
 static int cli_io_handler_pats_list(struct appctx *appctx)
 {
+       struct show_map_ctx *ctx = appctx->svcctx;
        struct conn_stream *cs = appctx->owner;
 
        switch (appctx->st2) {
@@ -419,23 +434,23 @@ static int cli_io_handler_pats_list(struct appctx *appctx)
                 * available field of this pointer is <list>. It is used with the function
                 * pat_list_get_next() for returning the first available entry
                 */
-               appctx->ctx.map.ref = LIST_ELEM(&pattern_reference, struct pat_ref *, list);
-               appctx->ctx.map.ref = pat_list_get_next(appctx->ctx.map.ref, &pattern_reference,
-                                                       appctx->ctx.map.display_flags);
+               ctx->ref = LIST_ELEM(&pattern_reference, struct pat_ref *, list);
+               ctx->ref = pat_list_get_next(ctx->ref, &pattern_reference,
+                                                       ctx->display_flags);
                appctx->st2 = STAT_ST_LIST;
                /* fall through */
 
        case STAT_ST_LIST:
-               while (appctx->ctx.map.ref) {
+               while (ctx->ref) {
                        chunk_reset(&trash);
 
                        /* Build messages. If the reference is used by another category than
                         * the listed categories, display the information in the message.
                         */
-                       chunk_appendf(&trash, "%d (%s) %s. curr_ver=%u next_ver=%u entry_cnt=%llu\n", appctx->ctx.map.ref->unique_id,
-                                     appctx->ctx.map.ref->reference ? appctx->ctx.map.ref->reference : "",
-                                     appctx->ctx.map.ref->display, appctx->ctx.map.ref->curr_gen, appctx->ctx.map.ref->next_gen,
-                                     appctx->ctx.map.ref->entry_cnt);
+                       chunk_appendf(&trash, "%d (%s) %s. curr_ver=%u next_ver=%u entry_cnt=%llu\n", ctx->ref->unique_id,
+                                     ctx->ref->reference ? ctx->ref->reference : "",
+                                     ctx->ref->display, ctx->ref->curr_gen, ctx->ref->next_gen,
+                                     ctx->ref->entry_cnt);
 
                        if (ci_putchk(cs_ic(cs), &trash) == -1) {
                                /* let's try again later from this stream. We add ourselves into
@@ -446,8 +461,8 @@ static int cli_io_handler_pats_list(struct appctx *appctx)
                        }
 
                        /* get next list entry and check the end of the list */
-                       appctx->ctx.map.ref = pat_list_get_next(appctx->ctx.map.ref, &pattern_reference,
-                                                               appctx->ctx.map.display_flags);
+                       ctx->ref = pat_list_get_next(ctx->ref, &pattern_reference,
+                                                               ctx->display_flags);
                }
 
                /* fall through */
@@ -461,6 +476,7 @@ static int cli_io_handler_pats_list(struct appctx *appctx)
 
 static int cli_io_handler_map_lookup(struct appctx *appctx)
 {
+       struct show_map_ctx *ctx = appctx->svcctx;
        struct conn_stream *cs = appctx->owner;
        struct sample sample;
        struct pattern *pat;
@@ -469,48 +485,48 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
        switch (appctx->st2) {
        case STAT_ST_INIT:
                /* Init to the first entry. The list cannot be change */
-               appctx->ctx.map.expr = LIST_ELEM(&appctx->ctx.map.ref->pat, struct pattern_expr *, list);
-               appctx->ctx.map.expr = pat_expr_get_next(appctx->ctx.map.expr, &appctx->ctx.map.ref->pat);
+               ctx->expr = LIST_ELEM(&ctx->ref->pat, struct pattern_expr *, list);
+               ctx->expr = pat_expr_get_next(ctx->expr, &ctx->ref->pat);
                appctx->st2 = STAT_ST_LIST;
                /* fall through */
 
        case STAT_ST_LIST:
-               HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
                /* for each lookup type */
-               while (appctx->ctx.map.expr) {
+               while (ctx->expr) {
                        /* initialise chunk to build new message */
                        chunk_reset(&trash);
 
                        /* execute pattern matching */
                        sample.data.type = SMP_T_STR;
                        sample.flags = SMP_F_CONST;
-                       sample.data.u.str.data = appctx->ctx.map.chunk.data;
-                       sample.data.u.str.area = appctx->ctx.map.chunk.area;
+                       sample.data.u.str.data = ctx->chunk.data;
+                       sample.data.u.str.area = ctx->chunk.area;
 
-                       if (appctx->ctx.map.expr->pat_head->match &&
-                           sample_convert(&sample, appctx->ctx.map.expr->pat_head->expect_type))
-                               pat = appctx->ctx.map.expr->pat_head->match(&sample, appctx->ctx.map.expr, 1);
+                       if (ctx->expr->pat_head->match &&
+                           sample_convert(&sample, ctx->expr->pat_head->expect_type))
+                               pat = ctx->expr->pat_head->match(&sample, ctx->expr, 1);
                        else
                                pat = NULL;
 
                        /* build return message: set type of match */
                        for (match_method=0; match_method<PAT_MATCH_NUM; match_method++)
-                               if (appctx->ctx.map.expr->pat_head->match == pat_match_fcts[match_method])
+                               if (ctx->expr->pat_head->match == pat_match_fcts[match_method])
                                        break;
                        if (match_method >= PAT_MATCH_NUM)
-                               chunk_appendf(&trash, "type=unknown(%p)", appctx->ctx.map.expr->pat_head->match);
+                               chunk_appendf(&trash, "type=unknown(%p)", ctx->expr->pat_head->match);
                        else
                                chunk_appendf(&trash, "type=%s", pat_match_names[match_method]);
 
                        /* case sensitive */
-                       if (appctx->ctx.map.expr->mflags & PAT_MF_IGNORE_CASE)
+                       if (ctx->expr->mflags & PAT_MF_IGNORE_CASE)
                                chunk_appendf(&trash, ", case=insensitive");
                        else
                                chunk_appendf(&trash, ", case=sensitive");
 
                        /* Display no match, and set default value */
                        if (!pat) {
-                               if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+                               if (ctx->display_flags == PAT_REF_MAP)
                                        chunk_appendf(&trash, ", found=no");
                                else
                                        chunk_appendf(&trash, ", match=no");
@@ -519,7 +535,7 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
                        /* Display match and match info */
                        else {
                                /* display match */
-                               if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+                               if (ctx->display_flags == PAT_REF_MAP)
                                        chunk_appendf(&trash, ", found=yes");
                                else
                                        chunk_appendf(&trash, ", match=yes");
@@ -531,7 +547,7 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
                                        chunk_appendf(&trash, ", idx=list");
 
                                /* display pattern */
-                               if (appctx->ctx.map.display_flags == PAT_REF_MAP) {
+                               if (ctx->display_flags == PAT_REF_MAP) {
                                        if (pat->ref && pat->ref->pattern)
                                                chunk_appendf(&trash, ", key=\"%s\"", pat->ref->pattern);
                                        else
@@ -545,7 +561,7 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
                                }
 
                                /* display return value */
-                               if (appctx->ctx.map.display_flags == PAT_REF_MAP) {
+                               if (ctx->display_flags == PAT_REF_MAP) {
                                        if (pat->data && pat->ref && pat->ref->sample)
                                                chunk_appendf(&trash, ", value=\"%s\", type=\"%s\"", pat->ref->sample,
                                                              smp_to_type[pat->data->type]);
@@ -561,16 +577,16 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
                                /* let's try again later from this stream. We add ourselves into
                                 * this stream's users so that it can remove us upon termination.
                                 */
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+                               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                                cs_rx_room_blk(cs);
                                return 0;
                        }
 
                        /* get next entry */
-                       appctx->ctx.map.expr = pat_expr_get_next(appctx->ctx.map.expr,
-                                                                &appctx->ctx.map.ref->pat);
+                       ctx->expr = pat_expr_get_next(ctx->expr,
+                                                                &ctx->ref->pat);
                }
-               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                /* fall through */
 
        default:
@@ -581,31 +597,35 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
 
 static void cli_release_mlook(struct appctx *appctx)
 {
-       ha_free(&appctx->ctx.map.chunk.area);
+       struct show_map_ctx *ctx = appctx->svcctx;
+
+       ha_free(&ctx->chunk.area);
 }
 
 
 static int cli_parse_get_map(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct show_map_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
        if (strcmp(args[1], "map") == 0 || strcmp(args[1], "acl") == 0) {
                /* Set flags. */
                if (args[1][0] == 'm')
-                       appctx->ctx.map.display_flags = PAT_REF_MAP;
+                       ctx->display_flags = PAT_REF_MAP;
                else
-                       appctx->ctx.map.display_flags = PAT_REF_ACL;
+                       ctx->display_flags = PAT_REF_ACL;
 
                /* No parameter. */
                if (!*args[2] || !*args[3]) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Missing map identifier and/or key.\n");
                        else
                                return cli_err(appctx, "Missing ACL identifier and/or key.\n");
                }
 
                /* lookup into the maps */
-               appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
-               if (!appctx->ctx.map.ref) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+               ctx->ref = pat_ref_lookup_ref(args[2]);
+               if (!ctx->ref) {
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
                        else
                                return cli_err(appctx, "Unknown ACL identifier. Please use #<id> or <file>.\n");
@@ -615,10 +635,10 @@ static int cli_parse_get_map(char **args, char *payload, struct appctx *appctx,
                 * it may be used over multiple iterations. It's released
                 * at the end and upon abort anyway.
                 */
-               appctx->ctx.map.chunk.data = strlen(args[3]);
-               appctx->ctx.map.chunk.size = appctx->ctx.map.chunk.data + 1;
-               appctx->ctx.map.chunk.area = strdup(args[3]);
-               if (!appctx->ctx.map.chunk.area)
+               ctx->chunk.data = strlen(args[3]);
+               ctx->chunk.size = ctx->chunk.data + 1;
+               ctx->chunk.area = strdup(args[3]);
+               if (!ctx->chunk.area)
                        return cli_err(appctx,  "Out of memory error.\n");
 
                return 0;
@@ -628,6 +648,8 @@ static int cli_parse_get_map(char **args, char *payload, struct appctx *appctx,
 
 static int cli_parse_prepare_map(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct show_map_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
        if (strcmp(args[1], "map") == 0 ||
            strcmp(args[1], "acl") == 0) {
                uint next_gen;
@@ -635,20 +657,20 @@ static int cli_parse_prepare_map(char **args, char *payload, struct appctx *appc
 
                /* Set ACL or MAP flags. */
                if (args[1][0] == 'm')
-                       appctx->ctx.map.display_flags = PAT_REF_MAP;
+                       ctx->display_flags = PAT_REF_MAP;
                else
-                       appctx->ctx.map.display_flags = PAT_REF_ACL;
+                       ctx->display_flags = PAT_REF_ACL;
 
                /* lookup into the refs and check the map flag */
-               appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
-               if (!appctx->ctx.map.ref ||
-                   !(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags)) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+               ctx->ref = pat_ref_lookup_ref(args[2]);
+               if (!ctx->ref ||
+                   !(ctx->ref->flags & ctx->display_flags)) {
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
                        else
                                return cli_err(appctx, "Unknown ACL identifier. Please use #<id> or <file>.\n");
                }
-               next_gen = pat_ref_newgen(appctx->ctx.map.ref);
+               next_gen = pat_ref_newgen(ctx->ref);
                return cli_dynmsg(appctx, LOG_INFO, memprintf(&msg, "New version created: %u\n", next_gen));
        }
 
@@ -657,25 +679,29 @@ static int cli_parse_prepare_map(char **args, char *payload, struct appctx *appc
 
 static void cli_release_show_map(struct appctx *appctx)
 {
+       struct show_map_ctx *ctx = appctx->svcctx;
+
        if (appctx->st2 == STAT_ST_LIST) {
-               HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-               if (!LIST_ISEMPTY(&appctx->ctx.map.bref.users))
-                       LIST_DELETE(&appctx->ctx.map.bref.users);
-               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+               if (!LIST_ISEMPTY(&ctx->bref.users))
+                       LIST_DELETE(&ctx->bref.users);
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
        }
 }
 
 static int cli_parse_show_map(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct show_map_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
        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;
+                       ctx->display_flags = PAT_REF_MAP;
                else
-                       appctx->ctx.map.display_flags = PAT_REF_ACL;
+                       ctx->display_flags = PAT_REF_ACL;
 
                /* no parameter: display all map available */
                if (!*args[2]) {
@@ -693,10 +719,10 @@ static int cli_parse_show_map(char **args, char *payload, struct appctx *appctx,
                }
 
                /* lookup into the refs and check the map flag */
-               appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
-               if (!appctx->ctx.map.ref ||
-                   !(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags)) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+               ctx->ref = pat_ref_lookup_ref(args[2]);
+               if (!ctx->ref ||
+                   !(ctx->ref->flags & ctx->display_flags)) {
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
                        else
                                return cli_err(appctx, "Unknown ACL identifier. Please use #<id> or <file>.\n");
@@ -706,9 +732,9 @@ static int cli_parse_show_map(char **args, char *payload, struct appctx *appctx,
                if (gen)
                        appctx->ctx.cli.i0 = str2uic(gen);
                else
-                       appctx->ctx.cli.i0 = appctx->ctx.map.ref->curr_gen;
+                       appctx->ctx.cli.i0 = ctx->ref->curr_gen;
 
-               LIST_INIT(&appctx->ctx.map.bref.users);
+               LIST_INIT(&ctx->bref.users);
                appctx->io_handler = cli_io_handler_pat_list;
                appctx->io_release = cli_release_show_map;
                return 0;
@@ -719,19 +745,21 @@ static int cli_parse_show_map(char **args, char *payload, struct appctx *appctx,
 
 static int cli_parse_set_map(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct show_map_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
        if (strcmp(args[1], "map") == 0) {
                char *err;
 
                /* Set flags. */
-               appctx->ctx.map.display_flags = PAT_REF_MAP;
+               ctx->display_flags = PAT_REF_MAP;
 
                /* Expect three parameters: map name, key and new value. */
                if (!*args[2] || !*args[3] || !*args[4])
                        return cli_err(appctx, "'set map' expects three parameters: map identifier, key and value.\n");
 
                /* Lookup the reference in the maps. */
-               appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
-               if (!appctx->ctx.map.ref)
+               ctx->ref = pat_ref_lookup_ref(args[2]);
+               if (!ctx->ref)
                        return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
 
                /* If the entry identifier start with a '#', it is considered as
@@ -754,30 +782,30 @@ static int cli_parse_set_map(char **args, char *payload, struct appctx *appctx,
 
                        /* Try to modify the entry. */
                        err = NULL;
-                       HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-                       if (!pat_ref_set_by_id(appctx->ctx.map.ref, ref, args[4], &err)) {
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+                       HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+                       if (!pat_ref_set_by_id(ctx->ref, ref, args[4], &err)) {
+                               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                                if (err)
                                        return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
                                else
                                        return cli_err(appctx, "Failed to update an entry.\n");
                        }
-                       HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+                       HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                }
                else {
                        /* Else, use the entry identifier as pattern
                         * string, and update the value.
                         */
                        err = NULL;
-                       HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-                       if (!pat_ref_set(appctx->ctx.map.ref, args[3], args[4], &err)) {
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+                       HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+                       if (!pat_ref_set(ctx->ref, args[3], args[4], &err)) {
+                               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                                if (err)
                                        return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
                                else
                                        return cli_err(appctx, "Failed to update an entry.\n");
                        }
-                       HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+                       HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                }
 
                /* The set is done, send message. */
@@ -789,6 +817,8 @@ static int cli_parse_set_map(char **args, char *payload, struct appctx *appctx,
 
 static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct show_map_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
        if (strcmp(args[1], "map") == 0 ||
            strcmp(args[1], "acl") == 0) {
                const char *gen = NULL;
@@ -798,9 +828,9 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx,
 
                /* Set flags. */
                if (args[1][0] == 'm')
-                       appctx->ctx.map.display_flags = PAT_REF_MAP;
+                       ctx->display_flags = PAT_REF_MAP;
                else
-                       appctx->ctx.map.display_flags = PAT_REF_ACL;
+                       ctx->display_flags = PAT_REF_ACL;
 
                /* For both "map" and "acl" we may have an optional generation
                 * number specified using a "@" character before the pattern
@@ -816,7 +846,7 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx,
                 *   - one parameter if there is a payload
                 * If it is "acl", we expect only two parameters
                 */
-               if (appctx->ctx.map.display_flags == PAT_REF_MAP) {
+               if (ctx->display_flags == PAT_REF_MAP) {
                        if ((!payload && (!*args[2] || !*args[3] || !*args[4])) ||
                            (payload && !*args[2]))
                                return cli_err(appctx,
@@ -827,9 +857,9 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx,
                        return cli_err(appctx, "'add acl' expects two parameters: ACL identifier and pattern.\n");
 
                /* Lookup for the reference. */
-               appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
-               if (!appctx->ctx.map.ref) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+               ctx->ref = pat_ref_lookup_ref(args[2]);
+               if (!ctx->ref) {
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
                        else
                                return cli_err(appctx, "Unknown ACL identifier. Please use #<id> or <file>.\n");
@@ -837,8 +867,8 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx,
 
                if (gen) {
                        genid = str2uic(gen);
-                       if ((int)(genid - appctx->ctx.map.ref->next_gen) > 0) {
-                               if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+                       if ((int)(genid - ctx->ref->next_gen) > 0) {
+                               if (ctx->display_flags == PAT_REF_MAP)
                                        return cli_err(appctx, "Version number in the future, please use 'prepare map' before.\n");
                                else
                                        return cli_err(appctx, "Version number in the future, please use 'prepare acl' before.\n");
@@ -848,8 +878,8 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx,
                /* The command "add acl" is prohibited if the reference
                 * use samples.
                 */
-               if ((appctx->ctx.map.display_flags & PAT_REF_ACL) &&
-                   (appctx->ctx.map.ref->flags & PAT_REF_SMP)) {
+               if ((ctx->display_flags & PAT_REF_ACL) &&
+                   (ctx->ref->flags & PAT_REF_SMP)) {
                        return cli_err(appctx,
                                       "This ACL is shared with a map containing samples. "
                                       "You must use the command 'add map' to add values.\n");
@@ -876,7 +906,7 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx,
                                l = strcspn(key, " \t");
                                payload += l;
 
-                               if (!*payload && appctx->ctx.map.display_flags == PAT_REF_MAP)
+                               if (!*payload && ctx->display_flags == PAT_REF_MAP)
                                        return cli_dynerr(appctx, memprintf(&err, "Missing value for key '%s'.\n", key));
 
                                key[l] = 0;
@@ -892,12 +922,12 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx,
                                value[l] = 0;
                        }
 
-                       if (appctx->ctx.map.display_flags != PAT_REF_MAP)
+                       if (ctx->display_flags != PAT_REF_MAP)
                                value = NULL;
 
-                       HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-                       ret = !!pat_ref_load(appctx->ctx.map.ref, gen ? genid : appctx->ctx.map.ref->curr_gen, key, value, -1, &err);
-                       HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+                       HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+                       ret = !!pat_ref_load(ctx->ref, gen ? genid : ctx->ref->curr_gen, key, value, -1, &err);
+                       HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
 
                        if (!ret) {
                                if (err)
@@ -917,23 +947,25 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx,
 
 static int cli_parse_del_map(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct show_map_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
        if (args[1][0] == 'm')
-               appctx->ctx.map.display_flags = PAT_REF_MAP;
+               ctx->display_flags = PAT_REF_MAP;
        else
-               appctx->ctx.map.display_flags = PAT_REF_ACL;
+               ctx->display_flags = PAT_REF_ACL;
 
        /* Expect two parameters: map name and key. */
        if (!*args[2] || !*args[3]) {
-               if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+               if (ctx->display_flags == PAT_REF_MAP)
                        return cli_err(appctx, "This command expects two parameters: map identifier and key.\n");
                else
                        return cli_err(appctx, "This command expects two parameters: ACL identifier and key.\n");
        }
 
        /* Lookup the reference in the maps. */
-       appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
-       if (!appctx->ctx.map.ref ||
-           !(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags))
+       ctx->ref = pat_ref_lookup_ref(args[2]);
+       if (!ctx->ref ||
+           !(ctx->ref->flags & ctx->display_flags))
                return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
 
        /* If the entry identifier start with a '#', it is considered as
@@ -955,25 +987,25 @@ static int cli_parse_del_map(char **args, char *payload, struct appctx *appctx,
                        return cli_err(appctx, "Malformed identifier. Please use #<id> or <file>.\n");
 
                /* Try to delete the entry. */
-               HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-               if (!pat_ref_delete_by_id(appctx->ctx.map.ref, ref)) {
-                       HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+               if (!pat_ref_delete_by_id(ctx->ref, ref)) {
+                       HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                        /* The entry is not found, send message. */
                        return cli_err(appctx, "Key not found.\n");
                }
-               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
        }
        else {
                /* Else, use the entry identifier as pattern
                 * string and try to delete the entry.
                 */
-               HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-               if (!pat_ref_delete(appctx->ctx.map.ref, args[3])) {
-                       HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+               if (!pat_ref_delete(ctx->ref, args[3])) {
+                       HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
                        /* The entry is not found, send message. */
                        return cli_err(appctx, "Key not found.\n");
                }
-               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
        }
 
        /* The deletion is done, send message. */
@@ -987,11 +1019,12 @@ static int cli_parse_del_map(char **args, char *payload, struct appctx *appctx,
  */
 static int cli_io_handler_clear_map(struct appctx *appctx)
 {
+       struct show_map_ctx *ctx = appctx->svcctx;
        int finished;
 
-       HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-       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);
+       HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+       finished = pat_ref_purge_range(ctx->ref, appctx->ctx.cli.i0, appctx->ctx.cli.i1, 100);
+       HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
 
        if (!finished) {
                /* let's come back later */
@@ -1007,14 +1040,16 @@ static int cli_io_handler_clear_map(struct appctx *appctx)
  */
 static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct show_map_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
        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;
+                       ctx->display_flags = PAT_REF_MAP;
                else
-                       appctx->ctx.map.display_flags = PAT_REF_ACL;
+                       ctx->display_flags = PAT_REF_ACL;
 
                /* For both "map" and "acl" we may have an optional generation
                 * number specified using a "@" character before the pattern
@@ -1027,17 +1062,17 @@ static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx
 
                /* no parameter */
                if (!*args[2]) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Missing map identifier.\n");
                        else
                                return cli_err(appctx, "Missing ACL identifier.\n");
                }
 
                /* lookup into the refs and check the map flag */
-               appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
-               if (!appctx->ctx.map.ref ||
-                   !(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags)) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+               ctx->ref = pat_ref_lookup_ref(args[2]);
+               if (!ctx->ref ||
+                   !(ctx->ref->flags & ctx->display_flags)) {
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
                        else
                                return cli_err(appctx, "Unknown ACL identifier. Please use #<id> or <file>.\n");
@@ -1047,7 +1082,7 @@ static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx
                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;
+                       appctx->ctx.cli.i1 = appctx->ctx.cli.i0 = ctx->ref->curr_gen;
 
                /* delegate the clearing to the I/O handler which can yield */
                return 0;
@@ -1061,6 +1096,8 @@ static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx
  */
 static int cli_parse_commit_map(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct show_map_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
        if (strcmp(args[1], "map") == 0 || strcmp(args[1], "acl") == 0) {
                const char *gen = NULL;
                uint genid;
@@ -1068,9 +1105,9 @@ static int cli_parse_commit_map(char **args, char *payload, struct appctx *appct
 
                /* Set ACL or MAP flags. */
                if (args[1][0] == 'm')
-                       appctx->ctx.map.display_flags = PAT_REF_MAP;
+                       ctx->display_flags = PAT_REF_MAP;
                else
-                       appctx->ctx.map.display_flags = PAT_REF_ACL;
+                       ctx->display_flags = PAT_REF_ACL;
 
                if (*args[2] != '@')
                        return cli_err(appctx, "Missing version number.\n");
@@ -1086,29 +1123,29 @@ static int cli_parse_commit_map(char **args, char *payload, struct appctx *appct
 
                /* no parameter */
                if (!*args[3]) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Missing map identifier.\n");
                        else
                                return cli_err(appctx, "Missing ACL identifier.\n");
                }
 
                /* lookup into the refs and check the map flag */
-               appctx->ctx.map.ref = pat_ref_lookup_ref(args[3]);
-               if (!appctx->ctx.map.ref ||
-                   !(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags)) {
-                       if (appctx->ctx.map.display_flags == PAT_REF_MAP)
+               ctx->ref = pat_ref_lookup_ref(args[3]);
+               if (!ctx->ref ||
+                   !(ctx->ref->flags & ctx->display_flags)) {
+                       if (ctx->display_flags == PAT_REF_MAP)
                                return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
                        else
                                return cli_err(appctx, "Unknown ACL identifier. Please use #<id> or <file>.\n");
                }
 
-               HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
-               if (genid - (appctx->ctx.map.ref->curr_gen + 1) <
-                   appctx->ctx.map.ref->next_gen - appctx->ctx.map.ref->curr_gen)
-                       ret = pat_ref_commit(appctx->ctx.map.ref, genid);
+               HA_SPIN_LOCK(PATREF_LOCK, &ctx->ref->lock);
+               if (genid - (ctx->ref->curr_gen + 1) <
+                   ctx->ref->next_gen - ctx->ref->curr_gen)
+                       ret = pat_ref_commit(ctx->ref, genid);
                else
                        ret = 1;
-               HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ctx->ref->lock);
 
                if (ret != 0)
                        return cli_err(appctx, "Version number out of range.\n");