]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: proxy: create a tree to store proxies by name
authorWilly Tarreau <w@1wt.eu>
Sat, 15 Mar 2014 06:22:35 +0000 (07:22 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 15 Mar 2014 06:48:35 +0000 (07:48 +0100)
Large configurations can take time to parse when thousands of backends
are in use. Let's store all the proxies in trees.

findproxy_mode() has been modified to use the tree for lookups, which
has divided the parsing time by about 2.5. But many lookups are still
present at many places and need to be dealt with.

include/proto/proxy.h
include/types/proxy.h
src/cfgparse.c
src/proxy.c

index 4a4b2857f1b088abe18e86294327d2bcf98939c3..116c00a16cf837f756f4dc61cfa139aa9ffc46fd 100644 (file)
 #include <types/listener.h>
 #include <proto/freq_ctr.h>
 
+extern struct proxy *proxy;
+extern struct eb_root used_proxy_id;   /* list of proxy IDs in use */
+extern unsigned int error_snapshot_id;  /* global ID assigned to each error then incremented */
+extern struct eb_root proxy_by_name;    /* tree of proxies sorted by name */
+
 int start_proxies(int verbose);
 struct task *manage_proxy(struct task *t);
 void soft_stop(void);
@@ -42,6 +47,7 @@ int  session_set_backend(struct session *s, struct proxy *be);
 
 const char *proxy_cap_str(int cap);
 const char *proxy_mode_str(int mode);
+void proxy_store_name(struct proxy *px);
 struct proxy *findproxy_mode(const char *name, int mode, int cap);
 struct proxy *findproxy(const char *name, int cap);
 struct server *findserver(const struct proxy *px, const char *name);
index af2a3abd3d698b5b547d8379226e85fd1772f555..1a778bd9110c5b1496dddb5046ffaff5580a090c 100644 (file)
@@ -35,6 +35,7 @@
 #include <common/sessionhash.h>
 #include <common/tools.h>
 #include <eb32tree.h>
+#include <ebistree.h>
 
 #include <types/acl.h>
 #include <types/backend.h>
@@ -363,6 +364,7 @@ struct proxy {
                struct list bind;               /* list of bind settings */
                struct list listeners;          /* list of listeners belonging to this frontend */
                struct arg_list args;           /* sample arg list that need to be resolved */
+               struct ebpt_node by_name;       /* proxies are stored sorted by name here */
                char *logformat_string;         /* log format string */
                char *lfs_file;                 /* file name where the logformat string appears (strdup) */
                int   lfs_line;                 /* file name where the logformat string appears */
@@ -423,10 +425,6 @@ struct redirect_rule {
        char *cookie_str;
 };
 
-extern struct proxy *proxy;
-extern struct eb_root used_proxy_id;   /* list of proxy IDs in use */
-extern unsigned int error_snapshot_id;  /* global ID assigned to each error then incremented */
-
 #endif /* _TYPES_PROXY_H */
 
 /*
index f13b9679d102c6beeac350424d2de190ee9b5ffb..ceaa96e4a9c77772abdd45dfe251fa9f54b25029 100644 (file)
@@ -1826,6 +1826,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                curproxy->last_change = now.tv_sec;
                curproxy->id = strdup(args[1]);
                curproxy->cap = rc;
+               proxy_store_name(curproxy);
 
                /* parse the listener address if any */
                if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
index ef0f63de1f466f9cecc94d24f96b5d9094e2717a..3cbc1b4ac2483fb8c32605035832d8e136b4c0b4 100644 (file)
@@ -44,6 +44,7 @@
 int listeners; /* # of proxy listeners, set by cfgparse */
 struct proxy *proxy  = NULL;   /* list of all existing proxies */
 struct eb_root used_proxy_id = EB_ROOT;        /* list of proxy IDs in use */
+struct eb_root proxy_by_name = EB_ROOT; /* tree of proxies sorted by name */
 unsigned int error_snapshot_id = 0;     /* global ID assigned to each error then incremented */
 
 /*
@@ -278,6 +279,15 @@ static int proxy_parse_rate_limit(char **args, int section, struct proxy *proxy,
        return retval;
 }
 
+/* This function inserts proxy <px> into the tree of known proxies. The proxy's
+ * name is used as the storing key so it must already have been initialized.
+ */
+void proxy_store_name(struct proxy *px)
+{
+       px->conf.by_name.key = px->id;
+       ebis_insert(&proxy_by_name, &px->conf.by_name);
+}
+
 /*
  * This function finds a proxy with matching name, mode and with satisfying
  * capabilities. It also checks if there are more matching proxies with
@@ -287,9 +297,15 @@ static int proxy_parse_rate_limit(char **args, int section, struct proxy *proxy,
 struct proxy *findproxy_mode(const char *name, int mode, int cap) {
 
        struct proxy *curproxy, *target = NULL;
+       struct ebpt_node *node;
 
-       for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
-               if ((curproxy->cap & cap)!=cap || strcmp(curproxy->id, name))
+       for (node = ebis_lookup(&proxy_by_name, name); node; node = ebpt_next(node)) {
+               curproxy = container_of(node, struct proxy, conf.by_name);
+
+               if (strcmp(curproxy->id, name) != 0)
+                       break;
+
+               if ((curproxy->cap & cap) != cap)
                        continue;
 
                if (curproxy->mode != mode &&