MEDIUM: proxy: store the default proxies in a tree by name
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.
diff --git a/include/haproxy/proxy.h b/include/haproxy/proxy.h
index b4b04c5..a08ea52 100644
--- a/include/haproxy/proxy.h
+++ b/include/haproxy/proxy.h
@@ -59,6 +59,7 @@
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,
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index 3c252d2..a87358a 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -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 @@
{
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 @@
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 @@
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) {
diff --git a/src/haproxy.c b/src/haproxy.c
index 69ddb90..dc194c9 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -1963,6 +1963,9 @@
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;
diff --git a/src/proxy.c b/src/proxy.c
index e703041..96fc176 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -1179,6 +1179,17 @@
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