struct proxy *be; /* default backend, or NULL if none set */
char *name; /* default backend name during config parse */
} defbe;
+ struct proxy *defpx; /* default proxy used to init this one (may be NULL) */
struct list acl; /* ACL declared on this proxy */
struct list http_req_rules; /* HTTP request rules: allow/deny/... */
struct list http_res_rules; /* HTTP response rules: allow/deny/... */
struct list listeners; /* list of listeners belonging to this frontend */
struct list errors; /* list of all custom error files */
struct arg_list args; /* sample arg list that need to be resolved */
+ unsigned int refcount; /* refcount on this proxy (only used for default proxy for now) */
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) */
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(void);
+void proxy_destroy_all_unref_defaults(void);
+void proxy_ref_defaults(struct proxy *px, struct proxy *defpx);
+void proxy_unref_defaults(struct proxy *px);
struct proxy *alloc_new_proxy(const char *name, unsigned int cap,
char **errmsg);
struct proxy *parse_new_proxy(const char *name, unsigned int cap,
ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
}
- /* defaults sections are not needed anymore */
- proxy_destroy_all_defaults();
+ /* destroy unreferenced defaults proxies */
+ proxy_destroy_all_unref_defaults();
+
err_code |= check_config_validity();
for (px = proxies_list; px; px = px->next) {
free_proxy(p0);
}/* end while(p) */
+ /* destroy all referenced defaults proxies */
+ proxy_destroy_all_unref_defaults();
+
while (ua) {
struct stat_scope *scope, *scopep;
if (!p)
return;
+ proxy_unref_defaults(p);
free(p->conf.file);
free(p->id);
free(p->cookie_name);
return;
if (!(px->cap & PR_CAP_DEF))
return;
+ BUG_ON(px->conf.refcount != 0);
ebpt_delete(&px->conf.by_name);
proxy_free_defaults(px);
free(px);
}
-void proxy_destroy_all_defaults()
+/* delete all unreferenced default proxies. A default proxy is unreferenced if
+ * its refcount is equal to zero.
+ */
+void proxy_destroy_all_unref_defaults()
{
struct ebpt_node *n;
- while ((n = ebpt_first(&defproxy_by_name))) {
+ n = ebpt_first(&defproxy_by_name);
+ while (n) {
struct proxy *px = container_of(n, struct proxy, conf.by_name);
BUG_ON(!(px->cap & PR_CAP_DEF));
- proxy_destroy_defaults(px);
+ n = ebpt_next(n);
+ if (!px->conf.refcount)
+ proxy_destroy_defaults(px);
}
}
+/* Add a reference on the default proxy <defpx> for the proxy <px> Nothing is
+ * done if <px> already references <defpx>. Otherwise, the default proxy
+ * refcount is incremented by one. For now, this operation is not thread safe
+ * and is perform during init stage only.
+ */
+void proxy_ref_defaults(struct proxy *px, struct proxy *defpx)
+{
+ if (px->defpx == defpx)
+ return;
+ BUG_ON(px->defpx != NULL);
+ px->defpx = defpx;
+ defpx->conf.refcount++;
+}
+
+/* proxy <px> removes its reference on its default proxy. The default proxy
+ * refcount is decremented by one. If it was the last reference, the
+ * corresponding default proxy is destroyed. For now this operation is not
+ * thread safe and is performed during deinit staged only.
+*/
+void proxy_unref_defaults(struct proxy *px)
+{
+ if (px->defpx == NULL)
+ return;
+ if (!--px->defpx->conf.refcount)
+ proxy_destroy_defaults(px->defpx);
+ px->defpx = NULL;
+}
+
/* Allocates a new proxy <name> of type <cap>.
* Returns the proxy instance on success. On error, NULL is returned.
*/