mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-19 04:00:46 +00:00
MINOR: connection: add flag CO_FL_WILL_UPDATE to indicate when updates are granted
In transport-layer functions (snd_buf/rcv_buf), it's very problematic never to know if polling changes made to the connection will be propagated or not. This has led to some conn_cond_update_polling() calls being placed at a few places to cover both the cases where the function is called from the upper layer and when it's called from the lower layer. With the arrival of the MUX, this becomes even more complicated, as the upper layer will not have to manipulate anything from the connection layer directly and will not have to push such updates directly either. But the snd_buf functions will need to see their updates committed when called from upper layers. The solution here is to introduce a connection flag set by the connection handler (and possibly any other similar place) indicating that the caller is committed to applying such changes on return. This way, the called functions will be able to apply such changes by themselves before leaving when the flag is not set, and the upper layer will not have to care about that anymore.
This commit is contained in:
parent
bc97cc4fd1
commit
916e12dcfb
@ -167,11 +167,13 @@ void conn_update_sock_polling(struct connection *c);
|
||||
void conn_update_xprt_polling(struct connection *c);
|
||||
|
||||
/* Refresh the connection's polling flags from its file descriptor status.
|
||||
* This should be called at the beginning of a connection handler.
|
||||
* This should be called at the beginning of a connection handler. It does
|
||||
* nothing if CO_FL_WILL_UPDATE is present, indicating that an upper caller
|
||||
* has already done it.
|
||||
*/
|
||||
static inline void conn_refresh_polling_flags(struct connection *conn)
|
||||
{
|
||||
if (conn_ctrl_ready(conn)) {
|
||||
if (conn_ctrl_ready(conn) && !(conn->flags & CO_FL_WILL_UPDATE)) {
|
||||
unsigned int flags = conn->flags;
|
||||
|
||||
flags &= ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA | CO_FL_WAIT_ROOM);
|
||||
@ -230,32 +232,38 @@ static inline unsigned int conn_sock_polling_changes(const struct connection *c)
|
||||
}
|
||||
|
||||
/* Automatically updates polling on connection <c> depending on the XPRT flags
|
||||
* if no handshake is in progress.
|
||||
* if no handshake is in progress. It does nothing if CO_FL_WILL_UPDATE is
|
||||
* present, indicating that an upper caller is going to do it again later.
|
||||
*/
|
||||
static inline void conn_cond_update_xprt_polling(struct connection *c)
|
||||
{
|
||||
if (!(c->flags & CO_FL_POLL_SOCK) && conn_xprt_polling_changes(c))
|
||||
conn_update_xprt_polling(c);
|
||||
if (!(c->flags & CO_FL_WILL_UPDATE))
|
||||
if (!(c->flags & CO_FL_POLL_SOCK) && conn_xprt_polling_changes(c))
|
||||
conn_update_xprt_polling(c);
|
||||
}
|
||||
|
||||
/* Automatically updates polling on connection <c> depending on the SOCK flags
|
||||
* if a handshake is in progress.
|
||||
* if a handshake is in progress. It does nothing if CO_FL_WILL_UPDATE is
|
||||
* present, indicating that an upper caller is going to do it again later.
|
||||
*/
|
||||
static inline void conn_cond_update_sock_polling(struct connection *c)
|
||||
{
|
||||
if ((c->flags & CO_FL_POLL_SOCK) && conn_sock_polling_changes(c))
|
||||
conn_update_sock_polling(c);
|
||||
if (!(c->flags & CO_FL_WILL_UPDATE))
|
||||
if ((c->flags & CO_FL_POLL_SOCK) && conn_sock_polling_changes(c))
|
||||
conn_update_sock_polling(c);
|
||||
}
|
||||
|
||||
/* Stop all polling on the fd. This might be used when an error is encountered
|
||||
* for example.
|
||||
* for example. It does not propage the change to the fd layer if
|
||||
* CO_FL_WILL_UPDATE is present, indicating that an upper caller is going to do
|
||||
* it later.
|
||||
*/
|
||||
static inline void conn_stop_polling(struct connection *c)
|
||||
{
|
||||
c->flags &= ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA |
|
||||
CO_FL_SOCK_RD_ENA | CO_FL_SOCK_WR_ENA |
|
||||
CO_FL_XPRT_RD_ENA | CO_FL_XPRT_WR_ENA);
|
||||
if (conn_ctrl_ready(c))
|
||||
if (!(c->flags & CO_FL_WILL_UPDATE) && conn_ctrl_ready(c))
|
||||
fd_stop_both(c->handle.fd);
|
||||
}
|
||||
|
||||
@ -263,15 +271,19 @@ static inline void conn_stop_polling(struct connection *c)
|
||||
* SOCK flags, and on whether a handshake is in progress or not. This may be
|
||||
* called at any moment when there is a doubt about the effectiveness of the
|
||||
* polling state, for instance when entering or leaving the handshake state.
|
||||
* It does nothing if CO_FL_WILL_UPDATE is present, indicating that an upper
|
||||
* caller is going to do it again later.
|
||||
*/
|
||||
static inline void conn_cond_update_polling(struct connection *c)
|
||||
{
|
||||
if (unlikely(c->flags & CO_FL_ERROR))
|
||||
conn_stop_polling(c);
|
||||
else if (!(c->flags & CO_FL_POLL_SOCK) && conn_xprt_polling_changes(c))
|
||||
conn_update_xprt_polling(c);
|
||||
else if ((c->flags & CO_FL_POLL_SOCK) && conn_sock_polling_changes(c))
|
||||
conn_update_sock_polling(c);
|
||||
else if (!(c->flags & CO_FL_WILL_UPDATE)) {
|
||||
if (!(c->flags & CO_FL_POLL_SOCK) && conn_xprt_polling_changes(c))
|
||||
conn_update_xprt_polling(c);
|
||||
else if ((c->flags & CO_FL_POLL_SOCK) && conn_sock_polling_changes(c))
|
||||
conn_update_sock_polling(c);
|
||||
}
|
||||
}
|
||||
|
||||
/***** Event manipulation primitives for use by DATA I/O callbacks *****/
|
||||
|
@ -83,7 +83,7 @@ enum {
|
||||
CO_FL_CTRL_READY = 0x00000100, /* FD was registered, fd_delete() needed */
|
||||
CO_FL_XPRT_READY = 0x00000200, /* xprt_init() done, xprt_close() needed */
|
||||
|
||||
/* unused : 0x00000400 */
|
||||
CO_FL_WILL_UPDATE = 0x00000400, /* the conn handler will take care of updating the polling */
|
||||
|
||||
/* This flag is used by data layers to indicate they had to stop
|
||||
* receiving data because a buffer was full. The connection handler
|
||||
|
@ -49,6 +49,8 @@ void conn_fd_handler(int fd)
|
||||
return;
|
||||
|
||||
conn_refresh_polling_flags(conn);
|
||||
conn->flags |= CO_FL_WILL_UPDATE;
|
||||
|
||||
flags = conn->flags & ~CO_FL_ERROR; /* ensure to call the wake handler upon error */
|
||||
|
||||
process_handshake:
|
||||
@ -174,6 +176,7 @@ void conn_fd_handler(int fd)
|
||||
fdtab[fd].ev &= FD_POLL_STICKY;
|
||||
|
||||
/* commit polling changes */
|
||||
conn->flags &= ~CO_FL_WILL_UPDATE;
|
||||
conn_cond_update_polling(conn);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user