mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-05-04 20:46:11 +02:00
MINOR: proxy: simplify defaults proxies list storage
Defaults proxies instance are stored in a global name tree. When there is a name conflict and the older entry cannot be simply discarded as it is already referenced, the older entry is instead removed from the name tree and inserted into the orphaned list. The purpose of the orphaned list was to guarantee that any remaining unreferenced defaults are purged either on postparsing or deinit. However, this is in fact completely useless. Indeed on postparsing, orphaned entries are always referenced. On deinit instead, defaults are already freed along the cleanup of all frontend/backend instances clean up, thanks to their refcounting. This patch streamlines this by removing orphaned list. Instead, a defaults section is inserted into a new global defaults_list during their whole lifetime. This is not strictly necessary but it ensures that defaults instances can still be accessed easily in the future if needed even if not present in the name tree. On deinit, a BUG_ON() is added to ensure that defaults_list is indeed emptied. Another benefit from this patch is to simplify the defaults deletion procedure. Orphaned simple list is replaced by a proper double linked list implementation, so a single LIST_DELETE() is now performed. This will be notably useful as defaults may be removed at runtime in the future if backends deletion at runtime is implemented.
This commit is contained in:
parent
434e979046
commit
848e0cd052
@ -316,6 +316,7 @@ struct proxy {
|
||||
unsigned long last_change; /* internal use only: last time the proxy state was changed */
|
||||
|
||||
struct list global_list; /* list member for global proxy list */
|
||||
struct list el; /* attach point in various list - currently used only on defaults_list for defaults section */
|
||||
|
||||
unsigned int maxconn; /* max # of active streams on the frontend */
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ extern struct list proxies;
|
||||
extern struct ceb_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 ceb_root *proxy_by_name; /* tree of proxies sorted by name */
|
||||
extern struct list defaults_list; /* all defaults proxies list */
|
||||
|
||||
extern const struct cfg_opt cfg_opts[];
|
||||
extern const struct cfg_opt cfg_opts2[];
|
||||
|
||||
@ -569,6 +569,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
}
|
||||
|
||||
if (rc & PR_CAP_DEF) {
|
||||
LIST_APPEND(&defaults_list, &curproxy->el);
|
||||
/* last and current proxies must be updated to this one */
|
||||
curr_defproxy = last_defproxy = curproxy;
|
||||
} else {
|
||||
|
||||
@ -2742,8 +2742,10 @@ void deinit(void)
|
||||
* they are respectively cleaned up in sink_deinit() and deinit_log_forward()
|
||||
*/
|
||||
|
||||
/* destroy all referenced defaults proxies */
|
||||
defaults_px_destroy_all_unref();
|
||||
/* All proxies are removed now, so every defaults should also be freed
|
||||
* when their refcount reached zero.
|
||||
*/
|
||||
BUG_ON(!LIST_ISEMPTY(&defaults_list));
|
||||
|
||||
userlist_free(userlist);
|
||||
|
||||
|
||||
45
src/proxy.c
45
src/proxy.c
@ -64,7 +64,7 @@ struct list proxies = LIST_HEAD_INIT(proxies); /* list of all proxies */
|
||||
struct ceb_root *used_proxy_id = NULL; /* list of proxy IDs in use */
|
||||
struct ceb_root *proxy_by_name = NULL; /* tree of proxies sorted by name */
|
||||
struct ceb_root *defproxy_by_name = NULL; /* tree of default proxies sorted by name (dups possible) */
|
||||
struct proxy *orphaned_default_proxies = NULL; /* deleted ones with refcount != 0 */
|
||||
struct list defaults_list = LIST_HEAD_INIT(defaults_list); /* list of all defaults proxies */
|
||||
unsigned int error_snapshot_id = 0; /* global ID assigned to each error then incremented */
|
||||
|
||||
/* CLI context used during "show servers {state|conn}" */
|
||||
@ -1500,6 +1500,7 @@ void init_new_proxy(struct proxy *p)
|
||||
memset(p, 0, sizeof(struct proxy));
|
||||
p->obj_type = OBJ_TYPE_PROXY;
|
||||
LIST_INIT(&p->global_list);
|
||||
LIST_INIT(&p->el);
|
||||
LIST_INIT(&p->acl);
|
||||
LIST_INIT(&p->http_req_rules);
|
||||
LIST_INIT(&p->http_res_rules);
|
||||
@ -1628,29 +1629,11 @@ static void defaults_px_free(struct proxy *defproxy)
|
||||
*/
|
||||
void defaults_px_destroy(struct proxy *px)
|
||||
{
|
||||
struct proxy *prev;
|
||||
|
||||
BUG_ON(!(px->cap & PR_CAP_DEF));
|
||||
BUG_ON(px->conf.refcount != 0);
|
||||
|
||||
cebis_item_delete(&defproxy_by_name, conf.name_node, id, px);
|
||||
|
||||
/* If orphaned defaults list is not empty, it may contain <px> instance.
|
||||
* In this case it is necessary to manually remove it from the list.
|
||||
*/
|
||||
if (orphaned_default_proxies) {
|
||||
if (orphaned_default_proxies == px) {
|
||||
orphaned_default_proxies = px->next;
|
||||
}
|
||||
else {
|
||||
for (prev = orphaned_default_proxies;
|
||||
prev && prev->next != px; prev = prev->next)
|
||||
;
|
||||
if (prev)
|
||||
prev->next = px->next;
|
||||
}
|
||||
px->next = NULL;
|
||||
}
|
||||
LIST_DELETE(&px->el);
|
||||
|
||||
defaults_px_free(px);
|
||||
free(px);
|
||||
@ -1669,35 +1652,19 @@ void defaults_px_destroy_all_unref(void)
|
||||
if (!px->conf.refcount)
|
||||
defaults_px_destroy(px);
|
||||
}
|
||||
|
||||
px = orphaned_default_proxies;
|
||||
while (px) {
|
||||
BUG_ON(!(px->cap & PR_CAP_DEF));
|
||||
nx = px->next;
|
||||
if (!px->conf.refcount)
|
||||
defaults_px_destroy(px);
|
||||
px = nx;
|
||||
}
|
||||
}
|
||||
|
||||
/* Removes <px> defaults from the name tree. This operation is useful when a
|
||||
* section is made invisible by a newer instance with the same name. If <px> is
|
||||
* not referenced it is freed immediately, else it is moved in defaults
|
||||
* orphaned list.
|
||||
* not referenced it is freed immediately, else it is kept in defaults_list.
|
||||
*/
|
||||
void defaults_px_detach(struct proxy *px)
|
||||
{
|
||||
BUG_ON(!(px->cap & PR_CAP_DEF));
|
||||
|
||||
cebis_item_delete(&defproxy_by_name, conf.name_node, id, px);
|
||||
if (px->conf.refcount) {
|
||||
/* still referenced just append it to the orphaned list */
|
||||
px->next = orphaned_default_proxies;
|
||||
orphaned_default_proxies = px;
|
||||
}
|
||||
else {
|
||||
if (!px->conf.refcount)
|
||||
defaults_px_destroy(px);
|
||||
}
|
||||
/* If not destroyed, <px> can still be accessed in <defaults_list>. */
|
||||
}
|
||||
|
||||
/* Add a reference on the default proxy <defpx> for the proxy <px> Nothing is
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user