struct list global_list; /* list member for global proxy list */
struct list el; /* attach point in various list
+ * - <main_proxies> for non internal instance
* - <cfg_log_forward> for log forwarder
* - <sink_proxies_list> for sink
* - <defaults_list> for defaults section
#include <haproxy/ticks.h>
#include <haproxy/thread.h>
-extern struct proxy *proxies_list;
+extern struct list main_proxies;
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 */
*/
static inline void main_proxies_register(struct proxy *px)
{
- px->next = proxies_list;
- proxies_list = px;
+ LIST_INSERT(&main_proxies, &px->el);
}
/* Returns first entry in main proxies list or NULL if empty. */
static inline struct proxy *main_proxies_first(void)
{
- return proxies_list;
+ if (LIST_ISEMPTY(&main_proxies))
+ return NULL;
+ return LIST_ELEM(main_proxies.n, struct proxy *, el);
}
/* Returns first entry in main proxies list unless <px> is already set. This is
*/
static inline struct proxy *main_proxies_cond_first(struct proxy *px)
{
- if (!px)
- px = proxies_list;
+ if (!px && !LIST_ISEMPTY(&main_proxies))
+ px = LIST_ELEM(main_proxies.n, struct proxy *, el);
return px;
}
/* Return next entry after <px> in main proxies list or NULL if reaching end of list. */
static inline struct proxy *main_proxies_next(const struct proxy *px)
{
- return px->next;
+ if (px->el.n == &main_proxies)
+ return NULL;
+ return LIST_ELEM(px->el.n, struct proxy *, el);
}
#endif /* _HAPROXY_PROXY_H */
/* Find all references for this cache in the existing filters
* (over all proxies) and reference it in matching filters.
*/
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
struct flt_conf *fconf;
struct cache_flt_conf *cconf;
struct proxy *px;
struct server *srv;
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
for (srv = px->srv; srv; srv = srv->next) {
srv_diag_cookies(ret, srv, &cookies_tree);
srv_diag_check_reuse(ret, srv, px);
struct proxy *next;
struct list *list = (struct list *)head;
- if (head == &cfg_log_forward || head == &sink_proxies_list) {
+ if (head == &main_proxies || head == &cfg_log_forward || head == &sink_proxies_list) {
next = cur ?
LIST_ELEM(cur->el.n, struct proxy *, el) :
LIST_ELEM(list->n, struct proxy *, el);
*/
int check_config_validity()
{
+ struct list tmp_list = LIST_HEAD_INIT(tmp_list);
int cfgerr = 0, ret;
- struct proxy *defpx;
+ struct proxy *defpx, *old;
void *init_proxies_list = NULL;
struct stktable *t;
struct server *newsrv = NULL;
goto out;
/* first, we will invert the proxy list order */
- curproxy = NULL;
- while (proxies_list) {
- struct proxy *next;
-
- next = proxies_list->next;
- proxies_list->next = curproxy;
- curproxy = proxies_list;
- if (!next)
- break;
- proxies_list = next;
+ list_for_each_entry_safe(curproxy, old, &main_proxies, el) {
+ LIST_DELETE(&curproxy->el);
+ LIST_INSERT(&tmp_list, &curproxy->el);
}
+ LIST_SPLICE(&main_proxies, &tmp_list);
/*
* we must finish to initialize certain things on the servers,
curproxy = NULL;
/* starting to initialize the main proxies list */
- init_proxies_list = proxies_list;
+ init_proxies_list = &main_proxies;
init_proxies_list_stage1:
while ((curproxy = _get_next_proxy(init_proxies_list, curproxy))) {
* We have just initialized the main proxies list
* we must also configure the log-forward proxies list
*/
- if (init_proxies_list == proxies_list) {
+ if (init_proxies_list == &main_proxies) {
init_proxies_list = &cfg_log_forward;
goto init_proxies_list_stage1;
}
curproxy = NULL;
/* starting to initialize the main proxies list */
- init_proxies_list = proxies_list;
+ init_proxies_list = &main_proxies;
init_proxies_list_stage2:
while ((curproxy = _get_next_proxy(init_proxies_list, curproxy))) {
* We have just initialized the main proxies list
* we must also configure the log-forward proxies list
*/
- if (init_proxies_list == proxies_list) {
+ if (init_proxies_list == &main_proxies) {
init_proxies_list = &cfg_log_forward;
goto init_proxies_list_stage2;
}
* Recount currently required checks.
*/
- for (curproxy=proxies_list; curproxy; curproxy=curproxy->next) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
int optnum;
for (optnum = 0; cfg_opts[optnum].name; optnum++)
* be done earlier because the data size may be discovered while parsing
* other proxies.
*/
- for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
if ((curproxy->flags & PR_FL_DISABLED) || !curproxy->table)
continue;
/* Update server_state_file_name to backend name if backend is supposed to use
* a server-state file locally defined and none has been provided */
- for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
curproxy->server_state_file_name == NULL)
curproxy->server_state_file_name = strdup(curproxy->id);
* a shorter interval will start independently and will not dictate
* too short an interval for all others.
*/
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
for (s = px->srv; s; s = s->next) {
if ((px->options2 & PR_O2_USE_SBUF_CHECK) &&
(s->check.tcpcheck->rs && s->check.tcpcheck->rs->flags & TCPCHK_RULES_MAY_USE_SBUF))
* by the number of servers, weighted by the server's position in the
* list.
*/
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
if ((px->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
if (init_pid_list()) {
ha_alert("Starting [%s] check: out of memory.\n", px->id);
struct tgroup_ctx *tgroup_ctx; // pointer to ha_tgroup_ctx
struct thread_ctx *thread_ctx; // pointer to ha_thread_ctx
struct list *pools; // pointer to the head of the pools list
- struct proxy **proxies; // pointer to the head of the proxies list
+ struct list *proxies; // pointer to the head of the proxies list
struct global *global; // pointer to the struct global
struct fdtab **fdtab; // pointer to the fdtab array
struct activity *activity; // pointer to the activity[] per-thread array
post_mortem.tgroup_ctx = ha_tgroup_ctx;
post_mortem.thread_ctx = ha_thread_ctx;
post_mortem.pools = &pools;
- post_mortem.proxies = &proxies_list;
+ post_mortem.proxies = &main_proxies;
post_mortem.global = &global;
post_mortem.fdtab = &fdtab;
post_mortem.activity = activity;
struct server *srv;
int err_code = 0;
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
struct fcgi_flt_conf *fcgi_conf = find_px_fcgi_conf(px);
int nb_fcgi_srv = 0;
struct proxy *px;
int err_code = ERR_NONE;
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
continue;
struct proxy *px;
int err_code = 0;
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
continue;
{
struct proxy *px;
- for (px = proxies_list; px; px = px->next)
+ list_for_each_entry(px, &main_proxies, el)
flt_deinit_per_thread(px);
}
*/
static void sig_dump_state(struct sig_handler *sh)
{
- struct proxy *p = proxies_list;
+ struct proxy *p;
ha_warning("SIGHUP received, dumping servers states.\n");
- while (p) {
+ list_for_each_entry(p, &main_proxies, el) {
struct server *s = p->srv;
send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
}
ha_warning("%s\n", trash.area);
send_log(p, LOG_NOTICE, "%s\n", trash.area);
-
- p = p->next;
}
}
/* Preload internal counters. */
apply_stats_file();
- for (px = proxies_list; px; px = px->next)
+ list_for_each_entry(px, &main_proxies, el)
srv_compute_all_admin_states(px);
/* Apply servers' configured address */
if (pr->peers_fe)
break;
- for (px = proxies_list; px; px = px->next)
+ list_for_each_entry(px, &main_proxies, el) {
if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
break;
+ }
if (!px) {
/* We may only have log-forward section */
global.node = strdup(hostname);
/* stop disabled proxies */
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
stop_proxy(px);
}
void deinit(void)
{
- struct proxy *p = proxies_list, *p0;
+ struct proxy *p, *p0;
struct cfgfile *cfg, *cfg_tmp;
struct logger *log, *logb;
struct build_opts_str *bol, *bolb;
}
deinit_signals();
- while (p) {
- p0 = p;
- p = p->next;
- proxy_drop(p0);
- }/* end while(p) */
+ list_for_each_entry_safe(p, p0, &main_proxies, el)
+ proxy_drop(p);
/* we don't need to free sink_proxies_list nor cfg_log_forward proxies since
* they are respectively cleaned up in sink_deinit() and deinit_log_forward()
if (!(global.tune.options & GTUNE_USE_SPLICE) || !global.maxpipes)
return;
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
if ((px->cap & PR_CAP_FE) && !(px->flags & PR_FL_DISABLED) && px->stream_new_from_sc == hstream_new) {
haterm_used = 1;
break;
int pipes;
int max;
- for (cur = proxies_list; cur; cur = cur->next) {
+ list_for_each_entry(cur, &main_proxies, el) {
if (cur->options2 & (PR_O2_SPLIC_ANY)) {
if (cur->cap & PR_CAP_FE) {
max = cur->maxconn;
/* global log directives */
err_code |= postresolve_logger_list(NULL, &global.loggers, NULL, NULL);
/* proxy log directives */
- for (px = proxies_list; px; px = px->next)
+ list_for_each_entry(px, &main_proxies, el)
err_code |= postresolve_logger_list(px, &px->loggers, "proxy", px->id);
/* log-forward log directives */
list_for_each_entry(px, &cfg_log_forward, el)
mworker_on_new_child_failure(exitpid, status);
/* Detach all listeners */
- for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
list_for_each_entry_safe(l, l_next, &curproxy->conf.listeners, by_fe) {
if ((l->rx.fd == child->ipc_fd[0]) || (l->rx.fd == child->ipc_fd[1])) {
unbind_listener(l);
}
/* main proxies cleanup */
- for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
int listen_in_master = 0;
list_for_each_entry_safe(l, l_next, &curproxy->conf.listeners, by_fe) {
__decl_spinlock(proxies_del_lock);
int listeners; /* # of proxy listeners, set by cfgparse */
-struct proxy *proxies_list = NULL; /* list of main proxies */
-struct list proxies = LIST_HEAD_INIT(proxies); /* list of all proxies */
+
+/* List of non-default and non-internal proxies, except mworker and cli_fe which are stored in it.
+ * Used for check_config_validity() post init and most runtime operations (stats, ...).
+ */
+struct list main_proxies = LIST_HEAD_INIT(main_proxies);
+
+/* List of all proxies, except defaults.
+ * Currently only used for post_proxy_check_fct and post_server_check_fct post init.
+ */
+struct list proxies = LIST_HEAD_INIT(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) */
ha_warning("soft-stop running for too long, performing a hard-stop.\n");
send_log(NULL, LOG_WARNING, "soft-stop running for too long, performing a hard-stop.\n");
- p = proxies_list;
- while (p) {
+ list_for_each_entry(p, &main_proxies, el) {
if ((p->cap & PR_CAP_FE) && (p->feconn > 0)) {
ha_warning("Proxy %s hard-stopped (%d remaining conns will be closed).\n",
p->id, p->feconn);
send_log(p, LOG_WARNING, "Proxy %s hard-stopped (%d remaining conns will be closed).\n",
p->id, p->feconn);
}
- p = p->next;
}
thread_isolate();
thread_release();
/* Loop on proxies to stop backends */
- p = proxies_list;
- while (p) {
+ list_for_each_entry(p, &main_proxies, el) {
HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock);
proxy_cond_disable(p);
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock);
- p = p->next;
}
/* signal zero is used to broadcast the "stopping" event */
struct proxy *curproxy;
struct switching_rule *swrule1, *swrule2;
- for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
if (curproxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
continue;
/* automatically compute fullconn if not set. We must not do it in the
* loop above because cross-references are not yet fully resolved.
*/
- for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
if (curproxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
continue;
*/
static int cli_parse_add_backend(char **args, char *payload, struct appctx *appctx, void *private)
{
- struct proxy *px, *defpx, *next;
+ struct proxy *px, *defpx;
struct post_proxy_check_fct *ppcf;
const char *be_name, *def_name, *guid = NULL, *err;
char *msg = NULL;
proxy_index_id(px);
dynpx_next_id = px->uuid;
- if (!proxies_list) {
- proxies_list = px;
- }
- else {
- for (next = proxies_list; next->next; next = next->next)
- ;
- next->next = px;
- }
- px->next = NULL;
+ LIST_APPEND(&main_proxies, &px->el);
thread_release();
static int cli_parse_delete_backend(char **args, char *payload, struct appctx *appctx, void *private)
{
struct watcher *px_watch;
- struct proxy *px, *prev;
+ struct proxy *px;
const char *msg;
char *be_name;
int ret;
ceb32_item_delete(&used_proxy_id, conf.uuid_node, uuid, px);
cebis_item_delete(&proxy_by_name, conf.name_node, id, px);
- /* Detach backend from global proxies_list. */
- if (proxies_list == px) {
- proxies_list = px->next;
- }
- else {
- for (prev = proxies_list->next; prev && prev->next != px; prev = prev->next)
- ;
- BUG_ON(!prev); /* Proxy instance not found in global list ? */
- prev->next = px->next;
- }
+ /* Detach backend from global main_proxies. */
+ LIST_DELETE(&px->el);
px->flags |= PR_FL_DELETED;
task_wakeup(t, TASK_WOKEN_INIT);
}
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
struct server *srv;
if (px->flags & PR_FL_DISABLED) {
struct proxy *curproxy;
int return_code = 0;
- curproxy = proxies_list;
- while (curproxy) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
struct server *srv;
/* servers are in backend only */
if (!(curproxy->cap & PR_CAP_BE) || (curproxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED)))
- goto srv_init_addr_next;
+ continue;
for (srv = curproxy->srv; srv; srv = srv->next) {
set_usermsgs_ctx(srv->conf.file, srv->conf.line, &srv->obj_type);
return_code |= srv_iterate_initaddr(srv);
reset_usermsgs_ctx();
}
-
- srv_init_addr_next:
- curproxy = curproxy->next;
}
return return_code;
no_globalfile:
/* parse all proxies and load states form tree (global file) or from local file */
- for (curproxy = proxies_list; curproxy != NULL; curproxy = curproxy->next) {
+ list_for_each_entry(curproxy, &main_proxies, el) {
struct eb_root local_state_tree = EB_ROOT_UNIQUE;
/* Must be an enabled backend with at least a server */
if (*args[cur_arg+1] == '\0')
return cli_err(appctx, "'-f' requires a frontend name!\n");
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
/* only check the frontends */
if (!(px->cap & PR_CAP_FE))
struct listener *li;
struct stats_module *mod;
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
if (clrall) {
memset(&px->be_counters, 0, sizeof(px->be_counters));
memset(&px->fe_counters, 0, sizeof(px->fe_counters));
if (!mod->clearable && !clrall)
continue;
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
enum stats_domain_px_cap mod_cap = stats_px_get_cap(mod->domain_flags);
if (px->cap & PR_CAP_FE && mod_cap & STATS_PX_CAP_FE) {
i += offset;
}
- for (px = proxies_list; px; px = px->next) {
+ list_for_each_entry(px, &main_proxies, el) {
if (!stats_allocate_proxy_counters(px)) {
ha_alert("stats: cannot allocate all counters for proxy statistics\n");
err_code |= ERR_ALERT | ERR_FATAL;