From 413e903a22231f7e19efcd23a832e7928bcfb8b6 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 7 Jul 2025 15:33:40 +0200 Subject: [PATCH] MEDIUM: server: switch conf.name to cebis_tree This is used to index the server name and it contains a copy of the pointer to the server's name in . Changing that for a ceb_node placed just before saves 32 bytes to the struct server, which remains 3968 bytes large due to alignment. The proxy struct shrinks by 8 bytes to 3144. It's worth noting that the current way duplicate names are handled remains based on the previous mechanism where dups were permitted. Ideally we should now reject them during insertion and use unique key trees instead. --- include/haproxy/proxy-t.h | 2 +- include/haproxy/server-t.h | 3 ++- src/cfgparse.c | 7 ++++--- src/server.c | 23 +++++++---------------- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index db9526a8a..1bf0008cd 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -463,7 +463,7 @@ struct proxy { int line; /* line where the section appears */ struct eb_root used_listener_id;/* list of listener IDs in use */ struct eb_root used_server_id; /* list of server IDs in use */ - struct eb_root used_server_name; /* list of server names in use */ + struct ceb_root *used_server_name; /* list of server names in use */ struct list bind; /* list of bind settings */ struct list listeners; /* list of listeners belonging to this frontend */ struct list errors; /* list of all custom error files */ diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index fe5e4d78e..f55488d33 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -368,6 +368,7 @@ struct server { unsigned long last_change; /* internal use only (not for stats purpose): last time the server state was changed, doesn't change often, not updated atomically on purpose */ char *id; /* just for identification */ + uint32_t rid; /* revision: if id has been reused for a new server, rid won't match */ unsigned iweight,uweight, cur_eweight; /* initial weight, user-specified weight, and effective weight */ unsigned wscore; /* weight score, used during srv map computation */ @@ -510,7 +511,7 @@ struct server { struct { const char *file; /* file where the section appears */ struct eb32_node id; /* place in the tree of used IDs */ - struct ebpt_node name; /* place in the tree of used names */ + struct ceb_node name_node; /* place in the tree of used names, indexes above, not unique, indexed in px->used_server_name */ int line; /* line where the section appears */ } conf; /* config information */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 0bd29feb0..8e25c9ef4 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -36,6 +36,8 @@ #include #include +#include + #include #include #include @@ -3702,12 +3704,11 @@ out_uri_auth_compat: /* Note: internal servers are not always registered and * they do not conflict. */ - if (!newsrv->conf.name.node.leaf_p) + if (!ceb_intree(&newsrv->conf.name_node)) continue; for (other_srv = newsrv; - (other_srv = container_of_safe(ebpt_prev_dup(&other_srv->conf.name), - struct server, conf.name)); ) { + (other_srv = cebis_item_prev_dup(&curproxy->conf.used_server_name, conf.name_node, id, other_srv)); ) { ha_alert("parsing [%s:%d] : %s '%s', another server named '%s' was already defined at line %d, please use distinct names.\n", newsrv->conf.file, newsrv->conf.line, proxy_type_str(curproxy), curproxy->id, diff --git a/src/server.c b/src/server.c index b8dcc2bdc..a9dad40aa 100644 --- a/src/server.c +++ b/src/server.c @@ -3207,7 +3207,7 @@ struct server *srv_drop(struct server *srv) //BUG_ON(ceb_intree(&srv->addr_node) || // srv->idle_node.node.leaf_p || // srv->conf.id.node.leaf_p || - // srv->conf.name.node.leaf_p); + // ceb_intree(&srv->name_node)); guid_remove(&srv->guid); @@ -3359,8 +3359,7 @@ static int _srv_parse_tmpl_init(struct server *srv, struct proxy *px) /* Set the first server's ID. */ _srv_parse_set_id_from_prefix(srv, srv->tmpl_info.prefix, srv->tmpl_info.nb_low); - srv->conf.name.key = srv->id; - ebis_insert(&curproxy->conf.used_server_name, &srv->conf.name); + cebis_item_insert(&curproxy->conf.used_server_name, conf.name_node, id, srv); /* then create other servers from this one */ for (i = srv->tmpl_info.nb_low + 1; i <= srv->tmpl_info.nb_high; i++) { @@ -3384,8 +3383,7 @@ static int _srv_parse_tmpl_init(struct server *srv, struct proxy *px) /* Set this new server ID. */ _srv_parse_set_id_from_prefix(newsrv, srv->tmpl_info.prefix, i); - newsrv->conf.name.key = newsrv->id; - ebis_insert(&curproxy->conf.used_server_name, &newsrv->conf.name); + cebis_item_insert(&curproxy->conf.used_server_name, conf.name_node, id, newsrv); } return i - srv->tmpl_info.nb_low; @@ -3993,8 +3991,7 @@ int parse_server(const char *file, int linenum, char **args, _srv_parse_tmpl_init(newsrv, curproxy); } else if (!(parse_flags & SRV_PARSE_DEFAULT_SERVER)) { - newsrv->conf.name.key = newsrv->id; - ebis_insert(&curproxy->conf.used_server_name, &newsrv->conf.name); + cebis_item_insert(&curproxy->conf.used_server_name, conf.name_node, id, newsrv); } /* If the server id is fixed, insert it in the proxy used_id tree. @@ -4042,15 +4039,10 @@ struct server *server_find_by_id_unique(struct proxy *bk, int id, uint32_t rid) */ struct server *server_find_by_name(struct proxy *px, const char *name) { - struct ebpt_node *node; - struct server *cursrv; - if (!px) return NULL; - node = ebis_lookup(&px->conf.used_server_name, name); - cursrv = node ? container_of(node, struct server, conf.name) : NULL; - return cursrv; + return cebis_item_lookup(&px->conf.used_server_name, conf.name_node, id, name, struct server); } /* @@ -6244,11 +6236,10 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct srv->conf.id.key = srv->puid = next_id; } - srv->conf.name.key = srv->id; /* insert the server in the backend trees */ eb32_insert(&be->conf.used_server_id, &srv->conf.id); - ebis_insert(&be->conf.used_server_name, &srv->conf.name); + cebis_item_insert(&be->conf.used_server_name, conf.name_node, id, srv); /* addr_key could be NULL if FQDN resolution is postponed (ie: add server from cli) */ if (srv->addr_key) cebuis_item_insert(&be->used_server_addr, addr_node, addr_key, srv); @@ -6467,7 +6458,7 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap /* remove srv from addr_node tree */ eb32_delete(&srv->conf.id); - ebpt_delete(&srv->conf.name); + cebis_item_delete(&be->conf.used_server_name, conf.name_node, id, srv); cebuis_item_delete(&be->used_server_addr, addr_node, addr_key, srv); /* remove srv from idle_node tree for idle conn cleanup */