mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-18 19:50:54 +00:00
MEDIUM: listeners: implement protocol level ->suspend/resume() calls
Now we have ->suspend() and ->resume() for listeners at the protocol level. This means that it now becomes possible for a protocol to redefine its own way to suspend and resume. The default functions are provided for TCP, UDP and unix, and they are pass-through to the receiver equivalent as it used to be till now. Nothing was defined for sockpair since it does not need to suspend/resume during reloads, hence it will succeed.
This commit is contained in:
parent
7b2febde1d
commit
e03204c8e1
@ -130,6 +130,25 @@ void listener_release(struct listener *l);
|
|||||||
* still bound. This must be used under the listener's lock.
|
* still bound. This must be used under the listener's lock.
|
||||||
*/
|
*/
|
||||||
void default_unbind_listener(struct listener *listener);
|
void default_unbind_listener(struct listener *listener);
|
||||||
|
|
||||||
|
/* default function called to suspend a listener: it simply passes the call to
|
||||||
|
* the underlying receiver. This is find for most socket-based protocols. This
|
||||||
|
* must be called under the listener's lock. It will return non-zero on success,
|
||||||
|
* 0 on failure. If no receiver-level suspend is provided, the operation is
|
||||||
|
* assumed to succeed.
|
||||||
|
*/
|
||||||
|
int default_suspend_listener(struct listener *l);
|
||||||
|
|
||||||
|
/* Tries to resume a suspended listener, and returns non-zero on success or
|
||||||
|
* zero on failure. On certain errors, an alert or a warning might be displayed.
|
||||||
|
* It must be called with the listener's lock held. Depending on the listener's
|
||||||
|
* state and protocol, a listen() call might be used to resume operations, or a
|
||||||
|
* call to the receiver's resume() function might be used as well. This is
|
||||||
|
* suitable as a default function for TCP and UDP. This must be called with the
|
||||||
|
* listener's lock held.
|
||||||
|
*/
|
||||||
|
int default_resume_listener(struct listener *l);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Registers the bind keyword list <kwl> as a list of valid keywords for next
|
* Registers the bind keyword list <kwl> as a list of valid keywords for next
|
||||||
* parsing sessions.
|
* parsing sessions.
|
||||||
|
@ -92,6 +92,8 @@ struct protocol {
|
|||||||
void (*enable)(struct listener *l); /* enable receipt of new connections */
|
void (*enable)(struct listener *l); /* enable receipt of new connections */
|
||||||
void (*disable)(struct listener *l); /* disable receipt of new connections */
|
void (*disable)(struct listener *l); /* disable receipt of new connections */
|
||||||
void (*unbind)(struct listener *l); /* unbind the listener and possibly its receiver */
|
void (*unbind)(struct listener *l); /* unbind the listener and possibly its receiver */
|
||||||
|
int (*suspend)(struct listener *l); /* try to suspend the listener */
|
||||||
|
int (*resume)(struct listener *l); /* try to resume a suspended listener */
|
||||||
|
|
||||||
/* functions acting on the receiver */
|
/* functions acting on the receiver */
|
||||||
void (*rx_enable)(struct receiver *rx); /* enable receiving on the receiver */
|
void (*rx_enable)(struct receiver *rx); /* enable receiving on the receiver */
|
||||||
|
101
src/listener.c
101
src/listener.c
@ -358,6 +358,65 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli)
|
|||||||
HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock);
|
HA_SPIN_UNLOCK(PROXY_LOCK, &px->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* default function called to suspend a listener: it simply passes the call to
|
||||||
|
* the underlying receiver. This is find for most socket-based protocols. This
|
||||||
|
* must be called under the listener's lock. It will return non-zero on success,
|
||||||
|
* 0 on failure. If no receiver-level suspend is provided, the operation is
|
||||||
|
* assumed to succeed.
|
||||||
|
*/
|
||||||
|
int default_suspend_listener(struct listener *l)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
if (!l->rx.proto->rx_suspend)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ret = l->rx.proto->rx_suspend(&l->rx);
|
||||||
|
return ret > 0 ? ret : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tries to resume a suspended listener, and returns non-zero on success or
|
||||||
|
* zero on failure. On certain errors, an alert or a warning might be displayed.
|
||||||
|
* It must be called with the listener's lock held. Depending on the listener's
|
||||||
|
* state and protocol, a listen() call might be used to resume operations, or a
|
||||||
|
* call to the receiver's resume() function might be used as well. This is
|
||||||
|
* suitable as a default function for TCP and UDP. This must be called with the
|
||||||
|
* listener's lock held.
|
||||||
|
*/
|
||||||
|
int default_resume_listener(struct listener *l)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
if (l->state == LI_ASSIGNED) {
|
||||||
|
char msg[100];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = l->rx.proto->listen(l, msg, sizeof(msg));
|
||||||
|
if (err & ERR_ALERT)
|
||||||
|
ha_alert("Resuming listener: %s\n", msg);
|
||||||
|
else if (err & ERR_WARN)
|
||||||
|
ha_warning("Resuming listener: %s\n", msg);
|
||||||
|
|
||||||
|
if (err & (ERR_FATAL | ERR_ABORT)) {
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->state < LI_PAUSED) {
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->state == LI_PAUSED && l->rx.proto->rx_resume &&
|
||||||
|
l->rx.proto->rx_resume(&l->rx) <= 0)
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function tries to temporarily disable a listener, depending on the OS
|
/* This function tries to temporarily disable a listener, depending on the OS
|
||||||
* capabilities. Linux unbinds the listen socket after a SHUT_RD, and ignores
|
* capabilities. Linux unbinds the listen socket after a SHUT_RD, and ignores
|
||||||
* SHUT_WR. Solaris refuses either shutdown(). OpenBSD ignores SHUT_RD but
|
* SHUT_WR. Solaris refuses either shutdown(). OpenBSD ignores SHUT_RD but
|
||||||
@ -379,18 +438,8 @@ int pause_listener(struct listener *l)
|
|||||||
if (l->state <= LI_PAUSED)
|
if (l->state <= LI_PAUSED)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (l->rx.proto->rx_suspend) {
|
if (l->rx.proto->suspend)
|
||||||
/* Returns < 0 in case of failure, 0 if the listener
|
ret = l->rx.proto->suspend(l);
|
||||||
* was totally stopped, or > 0 if correctly paused.
|
|
||||||
*/
|
|
||||||
ret = l->rx.proto->rx_suspend(&l->rx);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
ret = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MT_LIST_DEL(&l->wait_queue);
|
MT_LIST_DEL(&l->wait_queue);
|
||||||
|
|
||||||
@ -436,32 +485,8 @@ int resume_listener(struct listener *l)
|
|||||||
if (l->state == LI_READY)
|
if (l->state == LI_READY)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (l->state == LI_ASSIGNED) {
|
if (l->rx.proto->resume)
|
||||||
char msg[100];
|
ret = l->rx.proto->resume(l);
|
||||||
int err;
|
|
||||||
|
|
||||||
err = l->rx.proto->listen(l, msg, sizeof(msg));
|
|
||||||
if (err & ERR_ALERT)
|
|
||||||
ha_alert("Resuming listener: %s\n", msg);
|
|
||||||
else if (err & ERR_WARN)
|
|
||||||
ha_warning("Resuming listener: %s\n", msg);
|
|
||||||
|
|
||||||
if (err & (ERR_FATAL | ERR_ABORT)) {
|
|
||||||
ret = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l->state < LI_PAUSED) {
|
|
||||||
ret = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l->state == LI_PAUSED && l->rx.proto->rx_resume &&
|
|
||||||
l->rx.proto->rx_resume(&l->rx) <= 0) {
|
|
||||||
ret = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l->maxconn && l->nbconn >= l->maxconn) {
|
if (l->maxconn && l->nbconn >= l->maxconn) {
|
||||||
l->rx.proto->disable(l);
|
l->rx.proto->disable(l);
|
||||||
|
@ -65,6 +65,8 @@ static struct protocol proto_tcpv4 = {
|
|||||||
.enable = tcp_enable_listener,
|
.enable = tcp_enable_listener,
|
||||||
.disable = tcp_disable_listener,
|
.disable = tcp_disable_listener,
|
||||||
.unbind = default_unbind_listener,
|
.unbind = default_unbind_listener,
|
||||||
|
.suspend = default_suspend_listener,
|
||||||
|
.resume = default_resume_listener,
|
||||||
.rx_enable = sock_enable,
|
.rx_enable = sock_enable,
|
||||||
.rx_disable = sock_disable,
|
.rx_disable = sock_disable,
|
||||||
.rx_unbind = sock_unbind,
|
.rx_unbind = sock_unbind,
|
||||||
@ -91,6 +93,8 @@ static struct protocol proto_tcpv6 = {
|
|||||||
.enable = tcp_enable_listener,
|
.enable = tcp_enable_listener,
|
||||||
.disable = tcp_disable_listener,
|
.disable = tcp_disable_listener,
|
||||||
.unbind = default_unbind_listener,
|
.unbind = default_unbind_listener,
|
||||||
|
.suspend = default_suspend_listener,
|
||||||
|
.resume = default_resume_listener,
|
||||||
.rx_enable = sock_enable,
|
.rx_enable = sock_enable,
|
||||||
.rx_disable = sock_disable,
|
.rx_disable = sock_disable,
|
||||||
.rx_unbind = sock_unbind,
|
.rx_unbind = sock_unbind,
|
||||||
|
@ -61,6 +61,8 @@ static struct protocol proto_udp4 = {
|
|||||||
.enable = udp_enable_listener,
|
.enable = udp_enable_listener,
|
||||||
.disable = udp_disable_listener,
|
.disable = udp_disable_listener,
|
||||||
.unbind = default_unbind_listener,
|
.unbind = default_unbind_listener,
|
||||||
|
.suspend = default_suspend_listener,
|
||||||
|
.resume = default_resume_listener,
|
||||||
.rx_enable = sock_enable,
|
.rx_enable = sock_enable,
|
||||||
.rx_disable = sock_disable,
|
.rx_disable = sock_disable,
|
||||||
.rx_unbind = sock_unbind,
|
.rx_unbind = sock_unbind,
|
||||||
@ -85,6 +87,8 @@ static struct protocol proto_udp6 = {
|
|||||||
.enable = udp_enable_listener,
|
.enable = udp_enable_listener,
|
||||||
.disable = udp_disable_listener,
|
.disable = udp_disable_listener,
|
||||||
.unbind = default_unbind_listener,
|
.unbind = default_unbind_listener,
|
||||||
|
.suspend = default_suspend_listener,
|
||||||
|
.resume = default_resume_listener,
|
||||||
.rx_enable = sock_enable,
|
.rx_enable = sock_enable,
|
||||||
.rx_disable = sock_disable,
|
.rx_disable = sock_disable,
|
||||||
.rx_unbind = sock_unbind,
|
.rx_unbind = sock_unbind,
|
||||||
|
@ -60,6 +60,7 @@ static struct protocol proto_unix = {
|
|||||||
.enable = uxst_enable_listener,
|
.enable = uxst_enable_listener,
|
||||||
.disable = uxst_disable_listener,
|
.disable = uxst_disable_listener,
|
||||||
.unbind = default_unbind_listener,
|
.unbind = default_unbind_listener,
|
||||||
|
.suspend = default_suspend_listener,
|
||||||
.rx_enable = sock_enable,
|
.rx_enable = sock_enable,
|
||||||
.rx_disable = sock_disable,
|
.rx_disable = sock_disable,
|
||||||
.rx_unbind = sock_unbind,
|
.rx_unbind = sock_unbind,
|
||||||
|
Loading…
Reference in New Issue
Block a user