void (*destroy_srv)(struct server *srv); /* destroy a server context */
int (*get_alpn)(const struct connection *conn, void *xprt_ctx, const char **str, int *len); /* get application layer name */
int (*takeover)(struct connection *conn, void *xprt_ctx, int orig_tid); /* Let the xprt know the fd have been taken over */
+ void (*set_idle)(struct connection *conn, void *xprt_ctx); /* notify the xprt that the connection becomes idle. implies set_used. */
+ void (*set_used)(struct connection *conn, void *xprt_ctx); /* notify the xprt that the connection leaves idle. implies set_idle. */
char name[8]; /* transport layer name, zero-terminated */
int (*subscribe)(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es); /* Subscribe <es> to events, such as "being able to send" */
int (*unsubscribe)(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es); /* Unsubscribe <es> from events */
return 0;
}
+/* notify the next xprt that the connection is about to become idle and that it
+ * may be stolen at any time after the function returns and that any tasklet in
+ * the chain must be careful before dereferencing its context.
+ */
+static inline void xprt_set_idle(struct connection *conn, const struct xprt_ops *xprt, void *xprt_ctx)
+{
+ if (xprt->set_idle)
+ xprt->set_idle(conn, conn->xprt_ctx);
+}
+
+/* notify the next xprt that the connection is not idle anymore and that it may
+ * not be stolen before the next xprt_set_idle().
+ */
+static inline void xprt_set_used(struct connection *conn, const struct xprt_ops *xprt, void *xprt_ctx)
+{
+ if (xprt->set_used)
+ xprt->set_used(conn, conn->xprt_ctx);
+}
+
static inline int conn_get_alpn(const struct connection *conn, const char **str, int *len)
{
if (!conn_xprt_ready(conn) || !conn->xprt->get_alpn)
/* the connection is not idle anymore, let's mark this */
HA_ATOMIC_AND(&fconn->wait_event.tasklet->state, ~TASK_F_USR1);
+ xprt_set_used(conn, conn->xprt, conn->xprt_ctx);
TRACE_LEAVE(FCGI_EV_FSTRM_NEW, conn, fstrm);
return cs;
* that the handler needs to check it under the idle conns lock.
*/
HA_ATOMIC_OR(&fconn->wait_event.tasklet->state, TASK_F_USR1);
+ xprt_set_idle(fconn->conn, fconn->conn->xprt, fconn->conn->xprt_ctx);
+
if (!srv_add_to_idle_list(objt_server(fconn->conn->target), fconn->conn, 1)) {
/* The server doesn't want it, let's kill the connection right away */
fconn->conn->mux->destroy(fconn);
/* the connection is not idle anymore, let's mark this */
HA_ATOMIC_AND(&h1c->wait_event.tasklet->state, ~TASK_F_USR1);
+ xprt_set_used(conn, conn->xprt, conn->xprt_ctx);
TRACE_LEAVE(H1_EV_STRM_NEW, conn, h1s);
return cs;
*/
HA_ATOMIC_OR(&h1c->wait_event.tasklet->state, TASK_F_USR1);
h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
+ xprt_set_idle(h1c->conn, h1c->conn->xprt, h1c->conn->xprt_ctx);
+
if (!srv_add_to_idle_list(objt_server(h1c->conn->target), h1c->conn, is_not_first)) {
/* The server doesn't want it, let's kill the connection right away */
h1c->conn->mux->destroy(h1c);
/* the connection is not idle anymore, let's mark this */
HA_ATOMIC_AND(&h2c->wait_event.tasklet->state, ~TASK_F_USR1);
+ xprt_set_used(h2c->conn, h2c->conn->xprt, h2c->conn->xprt_ctx);
TRACE_LEAVE(H2_EV_H2S_NEW, conn, h2s);
return cs;
* that the handler needs to check it under the idle conns lock.
*/
HA_ATOMIC_OR(&h2c->wait_event.tasklet->state, TASK_F_USR1);
+ xprt_set_idle(h2c->conn, h2c->conn->xprt, h2c->conn->xprt_ctx);
+
if (!srv_add_to_idle_list(objt_server(h2c->conn->target), h2c->conn, 1)) {
/* The server doesn't want it, let's kill the connection right away */
h2c->conn->mux->destroy(h2c);