]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: proxy: store the default proxies in a tree by name
authorWilly Tarreau <w@1wt.eu>
Fri, 12 Feb 2021 13:08:31 +0000 (14:08 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 12 Feb 2021 15:23:46 +0000 (16:23 +0100)
Now default proxies are stored into a dedicated tree, sorted by name.
Only unnamed entries are not kept upon new section creation. The very
first call to cfg_parse_listen() will automatically allocate a dummy
defaults section which corresponds to the previous static one, since
the code requires to have one at a few places.

The first immediately visible benefit is that it allows to reuse
alloc_new_proxy() to allocate a defaults section instead of doing it by
hand. And the secret goal is to allow to keep multiple named defaults
section in memory to reuse them from various proxies.

include/haproxy/proxy.h
src/cfgparse-listen.c
src/haproxy.c
src/proxy.c

index b4b04c5590fd0a26e1038ce58fabe2d0ba5039a8..a08ea521f519e57df4e9f85ab8c7f91e8b7f20c2 100644 (file)
@@ -59,6 +59,7 @@ void init_new_proxy(struct proxy *p);
 void proxy_preset_defaults(struct proxy *defproxy);
 void proxy_free_defaults(struct proxy *defproxy);
 void proxy_destroy_defaults(struct proxy *px);
+void proxy_destroy_all_defaults();
 struct proxy *alloc_new_proxy(const char *name, unsigned int cap, const char *file, int linenum,
                               const struct proxy *defproxy, char **errmsg);
 int get_backend_server(const char *bk_name, const char *sv_name,
index 3c252d2bb54280d407d26a09897da1b3ac897e44..a87358a76b3de71509276ebadfd35fe92333417c 100644 (file)
@@ -34,8 +34,6 @@
 #include <haproxy/uri_auth.h>
 
 
-static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
-
 /* Report a warning if a rule is placed after a 'tcp-request session' rule.
  * Return 1 if the warning has been emitted, otherwise 0.
  */
@@ -173,6 +171,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
 {
        static struct proxy *curproxy = NULL;
        static struct proxy *curr_defproxy = NULL;
+       static struct proxy *last_defproxy = NULL;
        const char *err;
        int rc;
        unsigned val;
@@ -181,27 +180,33 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
        char *errmsg = NULL;
        struct bind_conf *bind_conf;
 
-       if (defproxy.obj_type != OBJ_TYPE_PROXY) {
-               /* defproxy not initialized yet */
-               init_new_proxy(&defproxy);
-               proxy_preset_defaults(&defproxy);
+       if (!last_defproxy) {
+               /* we need a default proxy and none was created yet */
+               last_defproxy = alloc_new_proxy("", PR_CAP_DEF|PR_CAP_LISTEN, "INIT", 0, NULL, &errmsg);
+               curr_defproxy = last_defproxy;
+               if (!last_defproxy) {
+                       ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
+                       err_code |= ERR_ALERT | ERR_ABORT;
+                       goto out;
+               }
        }
 
-       if (!curr_defproxy)
-               curr_defproxy = &defproxy;
-
        if (strcmp(args[0], "listen") == 0)
                rc = PR_CAP_LISTEN;
        else if (strcmp(args[0], "frontend") == 0)
                rc = PR_CAP_FE;
        else if (strcmp(args[0], "backend") == 0)
                rc = PR_CAP_BE;
-       else if (strcmp(args[0], "defaults") == 0)
-               rc = PR_CAP_DEF;
+       else if (strcmp(args[0], "defaults") == 0) {
+               /* "defaults" must first delete the last no-name defaults if any */
+               proxy_destroy_defaults(proxy_find_by_name("", PR_CAP_DEF, 0));
+               curr_defproxy = NULL;
+               rc = PR_CAP_DEF | PR_CAP_LISTEN;
+       }
        else
                rc = PR_CAP_NONE;
 
-       if (rc & PR_CAP_LISTEN) {  /* new proxy */
+       if ((rc & PR_CAP_LISTEN) && !(rc & PR_CAP_DEF)) {  /* new proxy */
                if (!*args[1]) {
                        ha_alert("parsing [%s:%d] : '%s' expects an <id> argument\n",
                                 file, linenum, args[0]);
@@ -237,34 +242,24 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                                ha_alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
                        goto out;
                }
+       }
 
+       if (rc & PR_CAP_LISTEN) {  /* new proxy or defaults section */
                curproxy = alloc_new_proxy(args[1], rc, file, linenum, curr_defproxy, &errmsg);
                if (!curproxy) {
-                       /* message already printed by alloc_new_proxy() */
                        ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
                        err_code |= ERR_ALERT | ERR_ABORT;
                        goto out;
                }
-               curproxy->next = proxies_list;
-               proxies_list = curproxy;
 
-               goto out;
-       }
-       else if (strcmp(args[0], "defaults") == 0) {  /* use this one to assign default values */
-               if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
-                       err_code |= ERR_ABORT;
-                       goto out;
+               if (rc & PR_CAP_DEF) {
+                       /* last and current proxies must be updated to this one */
+                       curr_defproxy = last_defproxy = curproxy;
+               } else {
+                       /* regular proxies are in a list */
+                       curproxy->next = proxies_list;
+                       proxies_list = curproxy;
                }
-
-               /* let's first free previous defaults */
-               proxy_free_defaults(curr_defproxy);
-               init_new_proxy(curr_defproxy);
-               proxy_preset_defaults(curr_defproxy);
-               curproxy = curr_defproxy;
-               curproxy->id = strdup(args[1]); // may be empty
-               curproxy->conf.args.file = curproxy->conf.file = strdup(file);
-               curproxy->conf.args.line = curproxy->conf.line = linenum;
-               defproxy.cap = PR_CAP_DEF | PR_CAP_LISTEN; /* all caps for now */
                goto out;
        }
        else if (curproxy == NULL) {
index 69ddb903561767a5796dade40576f390ba42deb5..dc194c9431e5a50b8f93e9a4f1d1d115d4e00c4a 100644 (file)
@@ -1963,6 +1963,9 @@ static void init(int argc, char **argv)
                           global.nbproc);
        }
 
+       /* defaults sections are not needed anymore */
+       proxy_destroy_all_defaults();
+
        err_code |= check_config_validity();
        for (px = proxies_list; px; px = px->next) {
                struct server *srv;
index e7030415d00e269de8c55c0713d72799250e5be0..96fc1765fe542aa1fa39d275a7d0855cb687d48e 100644 (file)
@@ -1179,6 +1179,17 @@ void proxy_destroy_defaults(struct proxy *px)
        free(px);
 }
 
+void proxy_destroy_all_defaults()
+{
+       struct ebpt_node *n;
+
+       while ((n = ebpt_first(&defproxy_by_name))) {
+               struct proxy *px = container_of(n, struct proxy, conf.by_name);
+               BUG_ON(!(px->cap & PR_CAP_DEF));
+               proxy_destroy_defaults(px);
+       }
+}
+
 /* Allocates a new proxy <name> of type <cap> found at position <file:linenum>,
  * preset it from the defaults of <defproxy> and returns it. Un case of error,
  * an alert is printed and NULL is returned. If <errmsg> is not NULL, an error