mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-05-04 12:41:00 +02:00
MINOR: proxy: add refcount to proxies
Implement refcount notion into proxy structure. The objective is to be able to increment refcount on proxy to prevent its deletion temporarily. This is similar to the server refcount : "del backend" is not blocked and will remove the targetted instance from the global proxies_list. However, the final free operation is delayed until the refcount is null. As stated above, the API is similar to servers. Proxies are initialized with a refcount of 1. Refcount can be incremented via proxy_take(). When no longer useful, refcount is decremented via proxy_drop() which replaces the older free_proxy(). Deinit is only performed once refcount is null. This commit also defines flag PR_FL_DELETED. It is set when a proxy instance has been removed via a "del backend" CLI command. This should serve as indication to modules which may still have a refcount on the target proxy so that they can release it as soon as possible. Note that this new refcount is completely ignored for a default proxy instance. For them, proxy_take() is pure noop. Free is immediately performed on first proxy_drop() invokation.
This commit is contained in:
parent
ebbdfc5915
commit
f3127df74d
@ -247,6 +247,7 @@ enum PR_SRV_STATE_FILE {
|
||||
#define PR_FL_PAUSED 0x00000020 /* The proxy was paused at run time (reversible) */
|
||||
#define PR_FL_CHECKED 0x00000040 /* The proxy configuration was fully checked (including postparsing checks) */
|
||||
#define PR_FL_BE_UNPUBLISHED 0x00000080 /* The proxy cannot be targetted by content switching rules */
|
||||
#define PR_FL_DELETED 0x00000100 /* Proxy has been deleted and must be manipulated with care */
|
||||
|
||||
struct stream;
|
||||
|
||||
@ -508,6 +509,7 @@ struct proxy {
|
||||
|
||||
struct guid_node guid; /* GUID global tree node */
|
||||
struct mt_list watcher_list; /* list of elems which currently references this proxy instance (currently only used with backends) */
|
||||
uint refcount; /* refcount to keep proxy from being deleted during runtime */
|
||||
|
||||
EXTRA_COUNTERS(extra_counters_fe);
|
||||
EXTRA_COUNTERS(extra_counters_be);
|
||||
|
||||
@ -58,7 +58,7 @@ void stop_proxy(struct proxy *p);
|
||||
int stream_set_backend(struct stream *s, struct proxy *be);
|
||||
|
||||
void deinit_proxy(struct proxy *p);
|
||||
void free_proxy(struct proxy *p);
|
||||
void proxy_drop(struct proxy *p);
|
||||
const char *proxy_cap_str(int cap);
|
||||
const char *proxy_mode_str(int mode);
|
||||
enum pr_mode str_to_proxy_mode(const char *mode);
|
||||
@ -82,6 +82,7 @@ void proxy_unref_defaults(struct proxy *px);
|
||||
int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char **errmsg);
|
||||
struct proxy *alloc_new_proxy(const char *name, unsigned int cap,
|
||||
char **errmsg);
|
||||
void proxy_take(struct proxy *px);
|
||||
struct proxy *parse_new_proxy(const char *name, unsigned int cap,
|
||||
const char *file, int linenum,
|
||||
const struct proxy *defproxy);
|
||||
|
||||
@ -2814,7 +2814,7 @@ void deinit(void)
|
||||
while (p) {
|
||||
p0 = p;
|
||||
p = p->next;
|
||||
free_proxy(p0);
|
||||
proxy_drop(p0);
|
||||
}/* end while(p) */
|
||||
|
||||
/* we don't need to free sink_proxies_list nor cfg_log_forward proxies since
|
||||
|
||||
@ -14726,7 +14726,7 @@ static void hlua_deinit()
|
||||
lua_close(hlua_states[thr]);
|
||||
}
|
||||
|
||||
free_proxy(socket_proxy);
|
||||
proxy_drop(socket_proxy);
|
||||
}
|
||||
|
||||
REGISTER_POST_DEINIT(hlua_deinit);
|
||||
|
||||
@ -1214,7 +1214,7 @@ err:
|
||||
if (err_code & ERR_CODE) {
|
||||
ha_alert("httpclient: cannot initialize: %s\n", errmsg);
|
||||
free(errmsg);
|
||||
free_proxy(px);
|
||||
proxy_drop(px);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -3739,7 +3739,7 @@ void deinit_log_forward()
|
||||
while (p) {
|
||||
p0 = p;
|
||||
p = p->next;
|
||||
free_proxy(p0);
|
||||
proxy_drop(p0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
29
src/proxy.c
29
src/proxy.c
@ -456,9 +456,19 @@ void deinit_proxy(struct proxy *p)
|
||||
proxy_unref_defaults(p);
|
||||
}
|
||||
|
||||
/* deinit and free <p> proxy */
|
||||
void free_proxy(struct proxy *p)
|
||||
/* Decrement <p> refcount and free it if null. For a default proxy instance,
|
||||
* refcount is ignored and free is immediately performed.
|
||||
*/
|
||||
void proxy_drop(struct proxy *p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (!(p->cap & PR_CAP_DEF)) {
|
||||
if (HA_ATOMIC_SUB_FETCH(&p->refcount, 1))
|
||||
return;
|
||||
}
|
||||
|
||||
deinit_proxy(p);
|
||||
ha_free(&p);
|
||||
}
|
||||
@ -3211,6 +3221,8 @@ struct proxy *alloc_new_proxy(const char *name, unsigned int cap, char **errmsg)
|
||||
if (!setup_new_proxy(curproxy, name, cap, errmsg))
|
||||
goto fail;
|
||||
|
||||
proxy_take(curproxy);
|
||||
|
||||
done:
|
||||
return curproxy;
|
||||
|
||||
@ -3225,6 +3237,13 @@ struct proxy *alloc_new_proxy(const char *name, unsigned int cap, char **errmsg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Increment <px> refcount. Does nothing for a default proxy instance. */
|
||||
void proxy_take(struct proxy *px)
|
||||
{
|
||||
if (!(px->cap & PR_CAP_DEF))
|
||||
HA_ATOMIC_INC(&px->refcount);
|
||||
}
|
||||
|
||||
/* post-check for proxies */
|
||||
static int proxy_postcheck(struct proxy *px)
|
||||
{
|
||||
@ -4955,8 +4974,8 @@ static int cli_parse_add_backend(char **args, char *payload, struct appctx *appc
|
||||
return 1;
|
||||
|
||||
err:
|
||||
/* free_proxy() ensures any potential refcounting on defpx is decremented. */
|
||||
free_proxy(px);
|
||||
/* This ensures any potential refcounting on defpx is decremented. */
|
||||
proxy_drop(px);
|
||||
thread_release();
|
||||
|
||||
if (msg) {
|
||||
@ -5053,6 +5072,8 @@ static int cli_parse_delete_backend(char **args, char *payload, struct appctx *a
|
||||
goto out;
|
||||
}
|
||||
|
||||
px->flags |= PR_FL_DELETED;
|
||||
|
||||
thread_release();
|
||||
|
||||
ha_notice("Backend deleted.\n");
|
||||
|
||||
@ -2637,7 +2637,7 @@ static void resolvers_destroy(struct resolvers *resolvers)
|
||||
resolv_free_resolution(res);
|
||||
}
|
||||
|
||||
free_proxy(resolvers->px);
|
||||
proxy_drop(resolvers->px);
|
||||
free(resolvers->id);
|
||||
free((char *)resolvers->conf.file);
|
||||
task_destroy(resolvers->t);
|
||||
@ -3586,7 +3586,7 @@ out:
|
||||
err_free_conf_file:
|
||||
ha_free((void **)&r->conf.file);
|
||||
err_free_p:
|
||||
free_proxy(p);
|
||||
proxy_drop(p);
|
||||
err_free_r:
|
||||
ha_free(&r);
|
||||
return err_code;
|
||||
|
||||
@ -818,7 +818,7 @@ static void sink_free(struct sink *sink)
|
||||
}
|
||||
LIST_DEL_INIT(&sink->sink_list); // remove from parent list
|
||||
task_destroy(sink->forward_task);
|
||||
free_proxy(sink->forward_px);
|
||||
proxy_drop(sink->forward_px);
|
||||
ha_free(&sink->name);
|
||||
ha_free(&sink->desc);
|
||||
while (sink->sft) {
|
||||
@ -866,7 +866,7 @@ static struct sink *sink_new_ringbuf(const char *id, const char *description,
|
||||
return sink;
|
||||
|
||||
err:
|
||||
free_proxy(p);
|
||||
proxy_drop(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user