mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-19 18:28:33 +00:00
MEDIUM: applet: Add support for async appctx startup on a thread subset
It is now possible to start an appctx on a thread subset. Some controls were added here and there. It is forbidden to start a backend appctx on another thread than the local one. If a frontend appctx is started on another thread or a thread subset, the applet .init callback function must be defined. This callback function is responsible to finalize the appctx startup. It can be performed synchornously. In this case, the appctx is started on the local thread. It is not really useful but it is valid. Or it can be performed asynchronously. In this case, .init callback function is called when the appctx is woken up for the first time. When this happens, the appctx affinity is set to the current thread to be able to start the session and the stream.
This commit is contained in:
parent
6095d57701
commit
d9c1d33fa1
@ -64,6 +64,13 @@ static inline struct appctx *appctx_new_anywhere(struct applet *applet, struct c
|
||||
*/
|
||||
static inline int appctx_init(struct appctx *appctx)
|
||||
{
|
||||
/* Set appctx affinity to the current thread. Because, after this call,
|
||||
* the appctx will be fully initialized. The session and the stream will
|
||||
* eventually be created. The affinity must be set now !
|
||||
*/
|
||||
BUG_ON((appctx->t->thread_mask & tid_bit) == 0);
|
||||
task_set_affinity(appctx->t, tid_bit);
|
||||
|
||||
if (appctx->applet->init)
|
||||
return appctx->applet->init(appctx);
|
||||
return 0;
|
||||
|
26
src/applet.c
26
src/applet.c
@ -35,8 +35,8 @@ struct appctx *appctx_new(struct applet *applet, struct cs_endpoint *endp, unsig
|
||||
{
|
||||
struct appctx *appctx;
|
||||
|
||||
/* Disable the feature for now ! */
|
||||
BUG_ON(thread_mask != tid_bit);
|
||||
/* Backend appctx cannot be started on another thread than the local one */
|
||||
BUG_ON(thread_mask != tid_bit && endp);
|
||||
|
||||
appctx = pool_zalloc(pool_head_appctx);
|
||||
if (unlikely(!appctx))
|
||||
@ -91,7 +91,10 @@ int appctx_finalize_startup(struct appctx *appctx, struct proxy *px, struct buff
|
||||
{
|
||||
struct session *sess;
|
||||
|
||||
BUG_ON(appctx->sess || !(appctx->endp->flags & CS_EP_ORPHAN));
|
||||
/* async startup is only possible for frontend appctx. Thus for orphan
|
||||
* appctx. Because no backend appctx can be orphan.
|
||||
*/
|
||||
BUG_ON(!(appctx->endp->flags & CS_EP_ORPHAN));
|
||||
|
||||
sess = session_new(px, NULL, &appctx->obj_type);
|
||||
if (!sess)
|
||||
@ -188,7 +191,7 @@ int appctx_buf_available(void *arg)
|
||||
struct task *task_run_applet(struct task *t, void *context, unsigned int state)
|
||||
{
|
||||
struct appctx *app = context;
|
||||
struct conn_stream *cs = appctx_cs(app);
|
||||
struct conn_stream *cs;
|
||||
unsigned int rate;
|
||||
size_t count;
|
||||
|
||||
@ -197,6 +200,21 @@ struct task *task_run_applet(struct task *t, void *context, unsigned int state)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (app->endp->flags & CS_EP_ORPHAN) {
|
||||
/* Finalize init of orphan appctx. .init callback function must
|
||||
* be defined and it must finalize appctx startup.
|
||||
*/
|
||||
BUG_ON(!app->applet->init);
|
||||
|
||||
if (appctx_init(app) == -1) {
|
||||
appctx_free_on_early_error(app);
|
||||
return NULL;
|
||||
}
|
||||
BUG_ON(!app->sess || !appctx_cs(app) || !appctx_strm(app));
|
||||
}
|
||||
|
||||
cs = appctx_cs(app);
|
||||
|
||||
/* We always pretend the applet can't get and doesn't want to
|
||||
* put, it's up to it to change this if needed. This ensures
|
||||
* that one applet which ignores any event will not spin.
|
||||
|
Loading…
Reference in New Issue
Block a user